diff --git a/docs/sbbsunix.txt b/docs/sbbsunix.txt
index 4937934489cbc76dee6c396b8b29ef2631e1f5c6..784621c85b10e5e7cc89bcd12b1e3d9ff1f115d9 100644
--- a/docs/sbbsunix.txt
+++ b/docs/sbbsunix.txt
@@ -2,7 +2,7 @@ Synchronet for Unix
 -=-=-=-=-=-=-=-=-=-
 
 Created: Mar 15, 2002
-Updated: Apr 12, 2002
+Updated: Mar 15, 2002
 
 By: Rob Swindell
 http://www.synchro.net
@@ -61,8 +61,6 @@ A. Yes, but it will be optional.
 Step-by-step Instructions
 =========================
 
-Note: These instructions assume you are already logged in as 'root'.
-
 1. Get and build the current source code:
 
    A. Create the Synchronet BBS directory on your file system:
@@ -81,7 +79,6 @@ Note: These instructions assume you are already logged in as 'root'.
       cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co xtrn
       cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/sbbs3
       cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/uifc
-	  cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/xpdev
       cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/libdialog
       cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/mozilla
       (this last one may take a while as it includes pre-compiled libraries)
@@ -90,14 +87,14 @@ Note: These instructions assume you are already logged in as 'root'.
       cd /sbbs/src/sbbs3
 
    E. Build the main executable (and utilities):
-      gmake
+      gmake -f Makefile.gnu
       (there *should* be no warnings or errors)
 
    F. Change to this directory:
       cd /sbbs/src/sbbs3/scfg
 
    G. Build the Synchronet configuration utility (SCFG):
-      gmake
+      gmake -f Makefile.gnu
 
    H. Congratulate yourself on a job well-done.
 
@@ -114,13 +111,13 @@ Note: These instructions assume you are already logged in as 'root'.
       /sbbs/src/sbbs3/gcc.linux.exe.debug/fixsmb
       /sbbs/src/sbbs3/gcc.linux.exe.debug/smbutil
       /sbbs/src/sbbs3/gcc.linux.exe.debug/sbbs
-      /sbbs/src/sbbs3/scfg/gcc.linux.debug/scfg
-      /sbbs/src/sbbs3/scfg/gcc.linux.debug/scfghelp.ixb
-      /sbbs/src/sbbs3/scfg/gcc.linux.debug/scfghelp.dat
+      /sbbs/src/sbbs3/scfg/gcc.linux.exe.debug/scfg
+      /sbbs/src/sbbs3/scfg/gcc.linux.exe.debug/scfghelp.ixb
+      /sbbs/src/sbbs3/scfg/gcc.linux.exe.debug/scfghelp.dat
       (the paths will be different for FreeBSD or release builds)
 
    C. Build the required Baja {tm} modules:
-      gmake
+      gmake -f Makefile.gnu
 
 
 3. Prepare the "xtrn" directory:
@@ -131,12 +128,28 @@ Note: These instructions assume you are already logged in as 'root'.
    B. Build Synchronet Blackjack:
       gmake -f Makefile.gnu
 
-   C. Change to this dircectory:
+   C. Create the platform sub-directories:
+      mkdir win32
+      mkdir linux (or freebsd)
+
+   D. Move the executables:
+      mv sbl.exe win32
+      mv sbl linux (or freebsd)
+
+   E. Change to this dircectory:
       cd /sbbs/xtrn/sbl
 
-   D. Build Synchronet BBS List:
+   F. Build Synchronet BBS List:
       gmake -f Makefile.gnu
 
+   G. Create the platform sub-directories:
+      mkdir win32
+      mkdir linux (or freebsd)
+
+   H. Move the executables:
+      mv sbj.exe win32
+      mv sbj linux (or freebsd)
+
 
 4. Configure the BBS:
 
@@ -192,7 +205,7 @@ Note: These instructions assume you are already logged in as 'root'.
       Name                            Synchronet BBS List
       Internal Code                   SBL
       Start-up Directory              ../xtrn/sbl
-      Command Line                    sbl%.
+      Command Line                    %?/sbl
       Clean-up Command Line
       Execution Cost                  None
       Access Requirements
@@ -210,7 +223,7 @@ Note: These instructions assume you are already logged in as 'root'.
       Name                            Synchronet Blackjack!
       Internal Code                   SBJ
       Start-up Directory              ../xtrn/sbj
-      Command Line                    sbj%. /l
+      Command Line                    %?/sbj /l
       Clean-up Command Line
       Execution Cost                  None
       Access Requirements
diff --git a/exec/newslink.js b/exec/newslink.js
deleted file mode 100644
index ac2daa149fe17a2387840e9711cc35bb07332215..0000000000000000000000000000000000000000
--- a/exec/newslink.js
+++ /dev/null
@@ -1,453 +0,0 @@
-// newslink.js
-
-// Synchronet Newsgroup Link/Gateway Module
-
-// Configuration file (in ctrl/newslink.cfg) format:
-
-// ;this line is a comment
-// server	servername
-// port		TCP port number (defaults to 119)
-// user		username (optional)
-// pass		password (optional)
-// area		subboard (internal code) newsgroup
-// ...
-
-const VERSION="1.00 Beta"
-
-printf("Synchronet NewsLink session started (v%s)", VERSION);
-
-var tearline = format("--- Synchronet NewsLink v%s\r\n",VERSION);
-var tagline	=  format(" *  %s - %s - telnet://%s\r\n"
-					  ,system.name,system.location,system.inetaddr);
-var antispam = format("remove-%s-this."
-					  ,random(50000).toString(36));
-
-var cfg_fname = system.ctrl_dir + "newslink.cfg";
-
-load("sbbsdefs.js");
-
-var debug = false;
-var reset_import_ptrs = false;		// Reset import pointers, import all messages
-var update_import_ptrs = false;		// Update import pointers, don't import anything
-var reset_export_ptrs = false;		// Reset export pointers, export all messages
-var update_export_ptrs = false;		// Update export pointers, don't export anything
-var email_addresses = true;			// Include e-mail addresses in headers
-
-// Parse arguments
-for(i=0;i<argc;i++) {
-	if(argv[i].toLowerCase()=="-d")			// debug
-		debug = true;
-	else if(argv[i].toLowerCase()=="-ri")	// reset import pointers (import all)
-		reset_import_ptrs = true;
-	else if(argv[i].toLowerCase()=="-ui")	// update import pointers (import none)
-		update_import_ptrs = true;
-	else if(argv[i].toLowerCase()=="-re")	// reset export pointers (export all)
-		reset_export_ptrs = true;
-	else if(argv[i].toLowerCase()=="-ue")	// update export pointers (export none)
-		update_export_ptrs = true;
-	else if(argv[i].toLowerCase()=="-ne")	// no e-mail addresses
-		email_addresses = false;
-	else if(argv[i].toLowerCase()=="-nm")	// no mangling of e-mail addresses
-		antispam = "";
-	else
-		cfg_fname = argv[i];
-}
-
-// Write a string to the server socket
-function write(str)
-{
-	socket.send(str);
-}
-
-function writeln(str)
-{
-	if(debug)
-		printf("cmd: %s",str);
-	write(str + "\r\n");
-}
-
-function readln(str)
-{
-	rsp = socket.readln();
-	if(debug)
-		printf("rsp: %s",rsp);
-	return(rsp);
-}
-
-var server;
-var port=119;
-var username;
-var password;
-area = new Array();
-
-/******************************/
-/* Read/Parse the Config File */
-/******************************/
-
-cfg_file = new File(cfg_fname);
-if(!cfg_file.open("r")) {
-	printf("!Error %d opening %s",errno,cfg_fname);
-	delete cfg_file;
-	exit();
-}
-
-while(!cfg_file.eof) {
-	line = cfg_file.readln();
-	if(line==null || line[0] == ';' || !line.length)
-		continue;
-	str=line.split(/\s+/);
-	switch(str[0].toLowerCase()) {
-		case "server":
-			server=str[1];
-			break;
-		case "port":
-			port=Number(str[1]);
-			break;
-		case "user":
-			username=str[1];
-			break;
-		case "pass":
-			password=str[1];
-			break;
-		case "area":
-			area.push(str);
-			break;
-		default:
-			printf("!UNRECOGNIZED configuration keyword: %s",str[0]);
-			break;
-	}
-}
-delete cfg_file;
-
-printf("server: %s",server);
-if(debug) {
-	printf("username: %s",username);
-	printf("password: %s",password);
-}
-printf("%ld areas",area.length);
-
-if(server==undefined || !server.length) {
-	printf("!No news server specified");
-	exit();
-}
-
-printf("Connecting to %s port %d ...",server,port);
-socket = new Socket();
-//socket.debug=true;
-if(!socket.connect(server,port)) {
-	printf("!Error %d connecting to %s port %d"
-		,socket.last_error,server,port);
-	delete socket;
-	exit();
-}
-printf("Connected");
-readln();
-
-writeln("slave");
-readln();
-
-if(username!=undefined && username.length) {
-	printf("Authenticating...");
-	writeln(format("AUTHINFO USER %s",username));
-	readln();
-	if(password!=undefined && password.length) {
-		writeln(format("AUTHINFO PASS %s",password));
-		rsp = readln();
-		if(rsp==null || rsp[0]!='2') {
-			printf("!Authentication failure: %s", rsp);
-			delete socket;
-			exit();
-		}
-	}
-	printf("Authenticated");
-}
-
-/******************************/
-/* Export and Import Messages */
-/******************************/
-var exported=0;
-var imported=0;
-
-printf("Scanning %lu message bases...",area.length);
-for(i in area) {
-	
-	if(!socket.is_connected) {
-		printf("Disconnected");
-		break;
-	}
-
-//	printf("%s",area[i].toString());
-	
-	sub = area[i][1];
-	newsgroup = area[i][2];
-	printf("sub: %s, newsgroup: %s",sub,newsgroup);
-	msgbase = new MsgBase(sub);
-	if(msgbase == null) {
-		printf("!ERROR opening msgbase: %s",sub);
-		continue;
-	}
-
-	/*********************/
-	/* Read Pointer File */
-	/*********************/
-	export_ptr = 0;
-	import_ptr = 0;
-	ptr_fname = msgbase.file + ".snl";
-	ptr_file = new File(ptr_fname);
-	if(ptr_file.open("rb")) {
-		export_ptr = ptr_file.readBin();
-		printf("%s export ptr: %ld",sub,export_ptr);
-		import_ptr = ptr_file.readBin();
-		printf("%s import ptr: %ld",sub,import_ptr);
-	}
-	ptr_file.close();
-
-	if(reset_export_ptrs)
-		ptr = 0;
-	else if(update_export_ptrs)
-		ptr = msgbase.last_msg;
-	else 
-		ptr = export_ptr;
-
-	if(ptr < msgbase.first_msg)
-		ptr = msgbase.first_msg;
-	else
-		ptr++;
-
-	/*************************/
-	/* EXPORT Local Messages */
-	/*************************/
-	for(;socket.is_connected && ptr<=msgbase.last_msg;ptr++) {
-		hdr = msgbase.get_msg_header(false,ptr);
-		if(hdr == null)
-			continue;
-		if(hdr.attr&MSG_DELETE)	/* marked for deletion */
-			continue;
-		if(hdr.attr&MSG_MODERATED && !(hdr.attr&MSG_VALIDATED))
-			continue;
-		if(hdr.attr&MSG_PRIVATE)/* no private messages on NNTP */
-			continue;
-		if(hdr.from_net_type==NET_INTERNET)	/* no dupe loop */
-			continue;
-
-		body = msgbase.get_msg_body(false, ptr
-				,true	/* remove ctrl-a codes */
-				,true	/* include tails */);
-		if(body == null) {
-			printf("!FAILED to read message number %ld",ptr);
-			continue;
-		}
-		body = ascii_str(body);
-		body += tearline;
-		body += tagline;
-
-		if(0) 
-			writeln(format("IHAVE %s",hdr.id));
-		else
-			writeln("POST");
-
-		rsp = readln();
-		if(rsp==null || rsp[0]!='3') {
-			printf("!POST failure: %s",rsp);
-			break;
-		}
-
-		if(!email_addresses)
-			writeln(format("From: %s@%s",hdr.from,newsgroup));
-		else if(hdr.from.indexOf('@')!=-1)
-			writeln(format("From: %s%s",antispam,hdr.from));
-		else if(hdr.from_net_type && hdr.from_net_addr!=null) {
-			if(hdr.from_net_addr.indexOf('@')!=-1)
-				writeln(format("From: \"%s\" <%s%s>"
-					,hdr.from
-					,antispam,hdr.from_net_addr));
-			else
-				writeln(format("From: \"%s\" <%s%s@%s%s>"
-					,hdr.from
-					,antispam,hdr.from
-					,antispam,hdr.from_net_addr));
-		}
-		else if(hdr.from.indexOf(' ')>0)
-			writeln(format("From: \"%s\" <\"%s%s\"@%s%s>"
-				,hdr.from
-				,antispam,hdr.from
-				,antispam,system.inetaddr));
-		else
-			writeln(format("From: \"%s\" <%s%s@%s%s>"
-				,hdr.from
-				,antispam,hdr.from
-				,antispam,system.inetaddr));
-		writeln("To: " + hdr.to);
-		writeln("X-Comment-To: " + hdr.to);
-		writeln("Subject: " + hdr.subject);
-		writeln("Message-ID: " + hdr.id);
-		writeln("Date: " + hdr.date);
-		writeln("References: " + hdr.reply_id);
-		writeln("Newsgroups: " + newsgroup);
-		writeln("");
-		if(hdr.to.toLowerCase()!="all") {
-			writeln("  To: " + hdr.to);
-		}
-		write(body);
-		writeln(".");
-		rsp = readln();
-		if(rsp==null || rsp[0]!='2') {
-			printf("!POST failure: %s",rsp);
-			break;
-		}
-		printf("Exported message %lu to newsgroup: %s",ptr,newsgroup);
-		exported++;
-	}
-	if(ptr > msgbase.last_msg)
-		ptr = msgbase.last_msg;
-	export_ptr = ptr;
-
-	/***************************/
-	/* IMPORT Network Messages */
-	/***************************/	
-
-	writeln(format("GROUP %s",newsgroup));
-	rsp = readln();
-	if(rsp==null || rsp[0]!='2') {
-		printf("!GROUP %s failure: %s",newsgroup,rsp);
-		delete ptr_file;
-		delete msgbase;
-		continue;
-	}
-	str = rsp.split(' ');
-
-	first_msg = Number(str[2]);
-	last_msg = Number(str[3]);
-
-	if(reset_import_ptrs)
-		ptr = 0;
-	else if(update_import_ptrs)
-		ptr = last_msg;
-	else
-		ptr = import_ptr;
-
-	printf("%s import ptr: %ld, last_msg: %ld",newsgroup,ptr,last_msg);
-
-	if(ptr < first_msg)
-		ptr = first_msg;
-	else {
-		if(ptr > last_msg)
-			ptr = last_msg;
-		ptr++;
-	}
-	for(;socket.is_connected && ptr<=last_msg;ptr++) {
-		writeln(format("ARTICLE %lu",ptr));
-		rsp = readln();
-		if(rsp==null || rsp[0]!='2') {
-			printf("!ARTICLE %lu failure: %s",ptr,rsp);
-			continue;
-		}
-		body=format("\1n\1b\1hFrom Newsgroup\1n\1b: \1h\1c%s\1n\r\n\r\n",newsgroup);
-		header=true;
-		var hdr=new Object();
-		while(socket.is_connected) {
-
-			line = socket.recvline(512 /*maxlen*/, 300 /*timeout*/);
-
-			if(line==null) {
-				printf("!TIMEOUT waiting for text line");
-				break;
-			}
-
-			//printf("msgtxt: %s",line);
-
-			if(line==".") {
-//				printf("End of message text");
-				break;
-			}
-			if(line=="" && header) {
-				header=false;
-				continue;
-			}
-
-			if(!header) {	/* Body text, append to 'body' */
-				if(line.charAt(0)=='.')
-					line=line.slice(1);		// Skip prepended dots
-				body += line;
-				body += "\r\n";
-				continue;
-			}
-			//printf(line);
-
-			/* Parse header lines */
-			if((sp=line.indexOf(':'))==-1)
-				continue;
-
-			data=line.slice(sp+1);
-			while(data.charAt(0)==' ')	// skip prepended spaces
-				data=data.slice(1);
-
-			line=line.substr(0,sp);
-			while(line.charAt(0)==' ')	// skip prepended spaces
-				line=line.slice(1);
-
-			switch(line.toLowerCase()) {
-				case "to":
-				case "apparently-to":
-				case "x-comment-to":
-					hdr.to=data;
-					break;
-				case "from":
-					hdr.from=data;
-					break;
-				case "date":
-					hdr.date=data;
-					break;
-				case "subject":
-					hdr.subject=data;
-					break;
-				case "message-id":
-					hdr.id=data;
-					break;
-				case "references":
-					hdr.reply_id=data;
-					break;
-			}
-		}
-		if(hdr.id.indexOf('@' + system.inetaddr)!=-1)	// avoid dupe loop
-			continue;
-		if(system.trashcan("subject",hdr.subject)) {
-			printf("!BLOCKED subject: %s",hdr.subject);
-			var reason = format("Blocked subject (%s)",hdr.subject);
-			system.spamlog("NNTP",reason,hdr.from,server,hdr.to);
-			continue;
-		}
-
-		hdr.from_net_type=NET_INTERNET;
-//		hdr.from_net_addr=hdr.from;
-		body += tearline;
-		if(msgbase.save_msg(hdr,body)) {
-			printf("Message %lu imported into %s",ptr,sub);
-			imported++;
-		}
-	}
-	if(ptr > last_msg)
-		ptr = last_msg;
-	import_ptr = ptr;
-
-	/* Save Pointers */
-	if(!ptr_file.open("wb"))
-		printf("!ERROR %d creating/opening %s",errno,ptr_fname);
-	else {
-		ptr_file.writeBin(export_ptr);
-		ptr_file.writeBin(import_ptr);
-		ptr_file.close();
-	}
-	delete ptr_file;
-	delete msgbase;
-}
-
-writeln("quit");
-readln();
-
-delete socket;
-
-printf("Synchronet NewsLink session complete (%lu exported, %lu imported)"
-	   ,exported, imported);
-
-/* End of newslink.js */
diff --git a/exec/tone/battle.ton b/exec/tone/battle.ton
deleted file mode 100644
index b100c4690675f37a69cc5ee73f6942a41ea2dc50..0000000000000000000000000000000000000000
--- a/exec/tone/battle.ton
+++ /dev/null
@@ -1,32 +0,0 @@
-: Battle Hymn of Republic  |
-t  2
-s  5
-v Mine \
-f4 133
-v eyes \
-f4 160
-v have \
-f4 100
-v seen \
-f4 160
-v the \
-D4 100
-v glor\
-d4 160
-v y \
-f4 100
-v of \
-A4 160
-v the \
-c5 100
-v com\
-d5 160
-v ing \
-d5 100
-v of \
-d5 160
-v the \
-c5 100
-v lord.\
-A4 200
-v
\ No newline at end of file
diff --git a/exec/tone/bouree.ton b/exec/tone/bouree.ton
deleted file mode 100644
index 7e9ac3b7d77725e94003042eae780415b304f316..0000000000000000000000000000000000000000
--- a/exec/tone/bouree.ton
+++ /dev/null
@@ -1,21 +0,0 @@
-: Bouree                   |
-t  2
-b3 80
-c4 80
-d4 160
-g3 80
-F3 80
-g3 160
-g4 160
-F4 160 
-e4 80
-F4 80
-d4 160
-a3 80
-b3 80
-c4 160
-F3 80
-e3 80
-F3 160
-d4 160
-b3 160
diff --git a/exec/tone/buffgals.ton b/exec/tone/buffgals.ton
deleted file mode 100644
index 179146650f787fb21a8a5289fc653b1b774437eb..0000000000000000000000000000000000000000
--- a/exec/tone/buffgals.ton
+++ /dev/null
@@ -1,22 +0,0 @@
-: Buffalo Gals             |
-s  5
-c3 100
-c3 100
-c3 200
-e3 200
-g3 100
-g3 100
-a3 133
-g3 200
-g3 133
-e3 200
-r 200
-g3 133
-f3 200
-f3 133
-d3 200
-r 200
-a3 133
-g3 200
-g3 133
-e3 200
diff --git a/exec/tone/camptown.ton b/exec/tone/camptown.ton
deleted file mode 100644
index 9d0b4205975f34a91072dea77787cf180e34f1c1..0000000000000000000000000000000000000000
--- a/exec/tone/camptown.ton
+++ /dev/null
@@ -1,22 +0,0 @@
-: Camptown Races           |
-s  5
-t  2
-a3 100
-a3 100
-F3 100
-a3 100
-b3 100
-a3 100
-F3 200
-F3 100
-e3 300
-F3 100
-e3 200
-r 15
-a3 100
-a3 100
-F3 100 
-a3 100
-b3 100
-a3 100
-F3 200
diff --git a/exec/tone/clown.ton b/exec/tone/clown.ton
deleted file mode 100644
index 956ab30aab8c366d41308907abbc28f236e2f834..0000000000000000000000000000000000000000
--- a/exec/tone/clown.ton
+++ /dev/null
@@ -1,33 +0,0 @@
-t 200
-c5 2
-p -.50
-b4 2
-p -.50
-A4 1
-p -.50
-b4 1
-p -.50
-A4 1
-p -.50
-a4 1
-p -.50
-G4 2
-p -.50
-g4 2
-p -.50
-F4 2
-p -.50
-g4 1
-p -.10
-g4 1
-p -.10
-g4 1
-p -.10
-g4 1
-p -.10
-g4 1
-p -.10
-g4 1
-p -.10
-g4 1
-
diff --git a/exec/tone/ent.ton b/exec/tone/ent.ton
deleted file mode 100644
index da3eea3f71f7fa8124c35321405e829b43e37fe4..0000000000000000000000000000000000000000
--- a/exec/tone/ent.ton
+++ /dev/null
@@ -1,299 +0,0 @@
-: Now we're going to set-up and play a song
-
-Visual		The Entertainer
-
-pitch	323.50	All commands can be abreviated with just one character
-t	200
-s	10
-:r	 10	 Rest before we begin
-
-:intro
-
-o	6
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-g	1
-r	1
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-g	1
-r	1
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-a	1
-G	1
-g	2
-r	2
-
-g5	1
-r	1
-
-: begin
-o	5
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3	1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-r	1
-
-a4	1
-g4	1
-F4	1
-a4	1
-c5	1
-e5	2
-d5	1
-c5	1
-b4	1
-d5	1
-
-r	1
-g3	1
-r	1
-a3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r       1
-
-c	1
-d	1
-e	1
-c	1
-d	1
-e       2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e	2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e       2
-b4	1
-d	2
-c       1
-
-r	1
-g3	1
-r	1
-a3	1
-r       1
-
-: repeat
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3	1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-r	1
-
-a4	1
-g4	1
-F4	1
-a4	1
-c5	1
-e5	2
-d5	1
-c5	1
-b4	1
-d5	1
-
-r	1
-g3	1
-r	1
-a3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r       1
-
-c	1
-d	1
-e	1
-c	1
-d	1
-e       2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e	2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e       2
-b4	1
-d	2
-c       1
-
-r	1
-g3	1
-r	1
-c3	1
-
diff --git a/exec/tone/example.ton b/exec/tone/example.ton
deleted file mode 100644
index e3ec4579fd2ac7b777d0cecd35d2c54c07643c45..0000000000000000000000000000000000000000
--- a/exec/tone/example.ton
+++ /dev/null
@@ -1,539 +0,0 @@
-: Example TONE (.TON) file
-  All lines starting with non-alphanumeric characters are ignored.
-
-: We're going to set the timer count value (in milliseconds).  The first word
-  of the line must begin with a 'T' (not case sensitive).  Following the 'T'
-  word (or letter) must be some amount of white space (tabs or space) then
-  a number to use for the timer count value.  The default timer count value
-  is 1 millisecond.
-
-Time 		200
-
-: The colons you see at the beginning of the comment paragraphs are not
-  necessary.  They are only used to visually separate comments from tone 
-  command lines.  A space, tab, or any other non-alphanumeric character would
-  work just as well.
-
-: Now we're going to display some text on the monitor using the 'V' (visual)
-  command.  The first word of the line must begin with a 'V' (not case 
-  sensitive).  Some amount of white space must follow the 'V' word (or letter)
-  then text to be displayed to the user.  If you do not wish a new line to be
-  automatically displayed, append a backslash (\) to the end of the line.
-
-Visual		This is the beginning of our example TONE file.
-Visual		This text will be displayed on the same line as \
-Visual		this text.
-
-: Now we're going to play some tones. Tones may be specified by note letter 
-  (and optional octave number) or exact frequency (in Hz).  We'll begin with
-  a natural 'a' (440Hz) for 1 second (1000 milliseconds).  Tone lines have two
-  parameters, the note (or exact frequency) and duration (in time counts).
-  Since our time counter value is now 200, we will need a time count of 5 to
-  produce a 1 second duration (5 counts multiplied by 200 milliseconds equals 
-  1 second.)
-
-a 5
-
-: The note is still playing right now and will continue to play until we make
-  another tone, give a rest command, or give a quit command. 
-
-: Notice that we used a lower case 'a'. Note letters ARE case sensitive. Lower
-  case notes are naturals and upper case notes are sharps.
-
-: Now we're going to specify the same note by specifying the exact frequency
-  (in HZ) of 440, for the same duration.
-
-440 5
-
-: There will be no audible change caused by the above command because we were
-  already hearing the same frequency. What you will hear is a 2 second 'a',
-  unaware that we actually played two 1 second 'a's.
-
-: To stop the note from sounding, we are now going to give a rest command.
-  Rest commands can be specified with a word starting with the letter 'R'
-  (not case sensitive) or by specifying a frequency of 0.  Some amount of
-  white space must follow, then a duration (in time counts).  The following
-  rest command is specifying 1 second of silence.
-
-Rest 5
-
-: To produce an automatic sound-off or pause between notes, we must specify
-  a stacato duration (in milliseconds).  This helps the listener to distinguish
-  between notes played of the same frequency.  If you do not specify a stacato
-  duration, the result is legato (smooth transition between notes). 
-
-: The stacato command must begin with the 'S' character (not case sensitive)
-  followed by white space then the duration (in milliseconds).  The default 
-  duration is 0 (disabled).
-  
-Stacato 10
-
-: To play notes from octaves other than the default octave (4), you can either
-  change the current default octave (with the Octave command) or specify the
-  octave with the note.  To play a low C for 1 second, we will use the
-  following command:
-
-c1 5
-
-: When we don't specify the octave number, the default octave is used.  To
-  change the default octave number, we can use the following command:
-
-Octave 3
-
-Visual		Now we will play a C major scale (octave 3):
-
-c 2		Comments can follow any command (except Visual)
-d 2
-e 2
-f 2
-g 2
-a 2
-b 2
-
-: To adjust the current default octave, we can use the plus (+) and minus
-  (-) symbols:
-
-Octave +1
-
-Visual		Another C major scale (now in octave 4).
-
-c 2
-d 2
-e 2
-f 2
-g 2
-a 2
-b 2
-
-Visual		Rest a little
-
-Rest 5
-
-: When specifying notes, the sounded frequency is based on a default pitch for
-  middle C.  The default starts at 523.50Hz but can be adjusted with the Pitch
-  command.  This is useful for created de-tuning or bend effects.  The Pitch
-  command can be used to specify a default pitch or adjust the current default
-  pitch up (+) or down (-).
-
-Visual		Now for a pitch variation example.
-
-: Lower timer count value and disable stacto for a smooth transition between
-  pitches
-
-Time 40
-Stacato 0
-
-: Starting at a3 and ascend gradually.
-
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10 	Kind of repetitive, huh?
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-a3 1
-p  +.10
-
-: Now descend quickly
-
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-a3 1
-p  -1.0
-
-: Now we're going to set-up and play a song
-
-Visual		The Entertainer
-
-pitch	323.50	All commands can be abreviated with just one character
-t	200
-s	10
-r	10	Rest before we begin
-
-:intro
-
-o	6
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-g	1
-r	1
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-g	1
-r	1
-
-d	1
-e	1
-c	1
-o      -1
-a	2
-b	1
-a	1
-G	1
-g	2
-r	2
-
-g5	1
-r	1
-
-: begin
-o	5
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3	1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-r	1
-
-a4	1
-g4	1
-F4	1
-a4	1
-c5	1
-e5	2
-d5	1
-c5	1
-b4	1
-d5	1
-
-r	1
-g3	1
-r	1
-a3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r       1
-
-c	1
-d	1
-e	1
-c	1
-d	1
-e       2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e	2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e       2
-b4	1
-d	2
-c       1
-
-r	1
-g3	1
-r	1
-a3	1
-r       1
-
-: repeat
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3	1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-r	1
-
-a4	1
-g4	1
-F4	1
-a4	1
-c5	1
-e5	2
-d5	1
-c5	1
-b4	1
-d5	1
-
-r	1
-g3	1
-r	1
-a3	1
-r	1
-
-d4	1
-D4	1
-e4	1
-c5	2
-e4	1
-c5	2
-e4	1
-c5      3
-
-a3	1
-r	1
-g3      1
-
-c	1
-d	1
-D	1
-e	1
-c	1
-d	1
-e	2
-b4	1
-d	2
-c	1
-
-r	1
-
-g3	1
-r	1
-g3	1
-r       1
-
-c	1
-d	1
-e	1
-c	1
-d	1
-e       2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e	2
-
-c	1
-d	1
-c	1
-e	1
-c	1
-d	1
-e       2
-b4	1
-d	2
-c       1
-
-r	1
-g3	1
-r	1
-c3	1
-
-
diff --git a/exec/tone/funeral.ton b/exec/tone/funeral.ton
deleted file mode 100644
index 4fc170cd211c557a1871ac1a5f20b6d912a77368..0000000000000000000000000000000000000000
--- a/exec/tone/funeral.ton
+++ /dev/null
@@ -1,14 +0,0 @@
-: Funeral March-Marionette |
-t  2
-s  10
-a2 93
-d3 93
-r 70
-d3 93
-d3 93
-C3 93
-b2 93
-C3 93
-r 70
-d3 93
-e3 93
diff --git a/exec/tone/furelise.ton b/exec/tone/furelise.ton
deleted file mode 100644
index 8eeda90f2c07b0d35223cde807fce0509026dc4d..0000000000000000000000000000000000000000
--- a/exec/tone/furelise.ton
+++ /dev/null
@@ -1,20 +0,0 @@
-: Fur Elise                |
-t  2
-s  5
-e4 133
-D4 133
-e4 133
-b3 133
-d4 133
-c4 133
-a3 200
-r 100
-c3 133
-e3 133
-a3 133
-b3 200
-r 100
-e3 133
-G2 133
-b3 133
-c4 200
diff --git a/exec/tone/goodnite.ton b/exec/tone/goodnite.ton
deleted file mode 100644
index e42405d592f8806bb794ca238447ba0db12ffe3b..0000000000000000000000000000000000000000
--- a/exec/tone/goodnite.ton
+++ /dev/null
@@ -1,22 +0,0 @@
-: Good-night, Ladies       |
-s  5
-e4 420
-c4 420
-g3 140
-c4 840
-r 210
-e4 420
-c4 420
-d4 140
-d4 840
-r 210
-e4 420
-c4 420
-f4 140
-f4 840
-f4 140
-e4 280
-c4 140
-d4 280
-b3 140
-c4 840
diff --git a/exec/tone/hatdance.ton b/exec/tone/hatdance.ton
deleted file mode 100644
index 9ed6d6db7ae3e1d603141512313276cc3e7dfd11..0000000000000000000000000000000000000000
--- a/exec/tone/hatdance.ton
+++ /dev/null
@@ -1,17 +0,0 @@
-: Mexican Hat Dance        |
-d3 160
-F3 160
-r 120
-d3 160
-F3 160
-r 120
-d3 160
-F3 320
-r 240
-d3 160
-F3 160
-G3 160
-F3 160
-f3 320
-F3 160
-G3 240
diff --git a/exec/tone/humor.ton b/exec/tone/humor.ton
deleted file mode 100644
index e2f612ddc6bd1fb508efe6e52b71c1b0d5d38132..0000000000000000000000000000000000000000
--- a/exec/tone/humor.ton
+++ /dev/null
@@ -1,18 +0,0 @@
-: Humoresque               |
-s  5
-g2 210
-a2 140
-g2 210
-a2 140
-b2 210
-d3 140
-e3 210
-d3 140
-g3 210
-F3 140
-a3 210
-g3 140
-F3 210
-a3 140
-g3 210
-e3 210
diff --git a/exec/tone/jeanie.ton b/exec/tone/jeanie.ton
deleted file mode 100644
index 8cea3248c5d21075ab9539d7b706b5d94ab59cc8..0000000000000000000000000000000000000000
--- a/exec/tone/jeanie.ton
+++ /dev/null
@@ -1,14 +0,0 @@
-: Jeanie with Light Brown  |
-t  2
-s  5
-d4 200
-c4 300
-a3 100
-A3 100
-a3 100
-g3 100
-f3 100
-a3 200
-c3 100
-d3 100
-f3 300
diff --git a/exec/tone/la_cuca.ton b/exec/tone/la_cuca.ton
deleted file mode 100644
index 954127d5ed17b378a364f880f5c74a967214dacc..0000000000000000000000000000000000000000
--- a/exec/tone/la_cuca.ton
+++ /dev/null
@@ -1,21 +0,0 @@
-: La Cucaracha             |
-s  10
-d3 133
-d3 133
-d3 133
-g3 400
-b3 200
-r 100
-d3 133
-d3 133
-d3 133
-g3 400
-b3 200
-r 200
-g3 133
-g3 133
-F3 133
-F3 133
-e3 133
-e3 133
-d3 400
diff --git a/exec/tone/maplerag.ton b/exec/tone/maplerag.ton
deleted file mode 100644
index 9db8f29dd3a7060b48f847e76f515088fd7a82de..0000000000000000000000000000000000000000
--- a/exec/tone/maplerag.ton
+++ /dev/null
@@ -1,24 +0,0 @@
-: Maple Leaf Rag           |
-t  2
-s  2
-b3 80
-d4 80
-g3 80
-b3 80
-d4 160
-F3 80
-d4 80
-F3 80
-a3 80
-d4 240
-r  80
-b3 80
-d4 80
-g3 80
-b3 80
-d4 160
-F3 80
-d4 80
-F3 80
-a3 80
-d4 240
diff --git a/exec/tone/march.ton b/exec/tone/march.ton
deleted file mode 100644
index f22e3cb844dc437fb6d485c335a2e63c762600dd..0000000000000000000000000000000000000000
--- a/exec/tone/march.ton
+++ /dev/null
@@ -1,21 +0,0 @@
-: March - Nutcracker Suite |
-s  5
-t  2
-d4 200
-d4  70
-d4  70
-d4  70
-e4 200
-e4 200
-F4 200
-d4 200
-e4 400
-d4 200
-d4  70
-d4  70
-d4  70
-e4 200
-e4 200
-F4 200
-d4 200
-e4 266
diff --git a/exec/tone/mary.ton b/exec/tone/mary.ton
deleted file mode 100644
index e36108d0881014408e60ac500c4fb2fc2f2bb671..0000000000000000000000000000000000000000
--- a/exec/tone/mary.ton
+++ /dev/null
@@ -1,57 +0,0 @@
-: Mary had a little lamb
-s 50
-v  Mar\
-e4 500
-v  y \
-d4 100
-v  had \ 
-c4 300
-v  a \
-d4 300
-v  lit\
-e4 300
-v  tle \
-e4 300
-v  lamb, \
-e4 800
-v  lit\
-d4 300
-v  tle \
-d4 300
-v  lamb, \  
-d4 800
-v  lit\
-e4 300
-v  tle \
-g4 300
-v  lamb.\
-g4 800
-v
-
-v  Mar\
-e4 500
-v  y \
-d4 100
-v  had \  
-c4 300
-v  a \
-d4 300
-v  lit\
-e4 300
-v  tle \
-e4 300
-v  lamb, \ 
-e4 300
-v  her \
-e4 300
-v  fleece \
-d4 300
-v  was \
-d4 300
-v  white \
-e4 300
-v  as \
-d4 300
-v  snow.\
-c4 1000
-v
diff --git a/exec/tone/mountai.ton b/exec/tone/mountai.ton
deleted file mode 100644
index e5e5a9a1784dbdc2f293abc3d41ac0ba86a17e0f..0000000000000000000000000000000000000000
--- a/exec/tone/mountai.ton
+++ /dev/null
@@ -1,14 +0,0 @@
-: Comin' round the mountain|
-t  2
-s  5
-d3 106
-e3 106
-g3 106
-g3 106
-g3 106
-g3 106
-e3 106
-d3 106
-b2 106
-d3 106
-g3 320
diff --git a/exec/tone/sakura.ton b/exec/tone/sakura.ton
deleted file mode 100644
index f785f956f4e020cce6dfc26228caec09b089891c..0000000000000000000000000000000000000000
--- a/exec/tone/sakura.ton
+++ /dev/null
@@ -1,17 +0,0 @@
-: Sakura                   |
-s  10
-t  2
-a2 140
-a2 140
-b2 280
-a2 140
-a2 140
-b2 280
-a2 140
-b2 140
-c3 140
-b2 140
-a2 140
-b2 70
-a2 70
-f2 280
diff --git a/exec/tone/sleeping.ton b/exec/tone/sleeping.ton
deleted file mode 100644
index fcd520d2fe395386f0bf8d8fa8b0f763376d129b..0000000000000000000000000000000000000000
--- a/exec/tone/sleeping.ton
+++ /dev/null
@@ -1,42 +0,0 @@
-: Are You Sleeping?        |
-t  2
-s  1
-g3 200
-a3 200
-b3 200
-g3 200
-g3 200
-a3 200
-b3 200
-g3 200
-b3 200
-c4 200
-d4 390
-r  10
-b3 200
-c4 200
-d4 390
-r  10
-d4 100
-e4 100
-d4 100
-c4 100
-b3 200
-g3 190
-r  10
-
-d4 100
-e4 100
-d4 100
-c4 100
-b3 200
-g3 190
-r  10
-
-g3 200
-d3 200
-g3 400
-
-g3 200
-d3 200
-g3 400
diff --git a/exec/tone/susanna.ton b/exec/tone/susanna.ton
deleted file mode 100644
index 526756a0e441a6c9de6db4c03ae7972680177df2..0000000000000000000000000000000000000000
--- a/exec/tone/susanna.ton
+++ /dev/null
@@ -1,18 +0,0 @@
-: Oh! Susanna              |
-t  2
-s  5
-g3 100
-a3 100
-b3 133
-d4 133
-d4 133
-e4 133
-d4 133
-b3 133
-g3 160
-a3 100
-b3 133
-b3 133
-a3 133
-g3 133
-a3 200
diff --git a/exec/tone/swinglow.ton b/exec/tone/swinglow.ton
deleted file mode 100644
index 733377797f9d8ebb30237b8801cd0a62c84d2254..0000000000000000000000000000000000000000
--- a/exec/tone/swinglow.ton
+++ /dev/null
@@ -1,17 +0,0 @@
-: Swing low, Sweet Chariot |
-t  3
-s  10
-a2 140
-f2 280
-a2 140
-f2 186
-f2 93
-d2 93
-c2 186
-f2 93
-f2 93
-f2 93
-f2 93
-a2 93
-c3 93
-c3 140
diff --git a/exec/tone/symph_40.ton b/exec/tone/symph_40.ton
deleted file mode 100644
index 361ae2c464fc1fb88634be39a51a74432f7e8ca4..0000000000000000000000000000000000000000
--- a/exec/tone/symph_40.ton
+++ /dev/null
@@ -1,23 +0,0 @@
-: Symphony #40             |
-t  2
-s  10
-D3 110
-d3 110
-d3 132
-D3 110
-d3 110
-d3 132
-D3 110
-d3 110
-d3 132
-A3 110
-r 82
-A3 110
-a3 110
-g3 132
-g3 110
-f3 110
-D3 132
-D3 110
-d3 110
-c3 132
diff --git a/exec/tone/tdc.ton b/exec/tone/tdc.ton
deleted file mode 100644
index 68979d4dc39cddfd7bcdbeb3026b87fff910623e..0000000000000000000000000000000000000000
--- a/exec/tone/tdc.ton
+++ /dev/null
@@ -1,190 +0,0 @@
-: Twelve days of Christmas
-
-Stacato 5
-Timing	80
-Rest	8
-v	On \
-c4	2
-v	the \
-c4	2
-v	twelfth \
-c4   	4
-v	day \
-f4   	2
-v	of \
-f4   	2
-v	Christ\
-f4   	4
-v	mas \
-e4   	2
-v	my \
-f4   	2
-v	true \
-g4   	2
-v	love \
-a4   	2
-v	gave \
-A4   	2
-v	to \
-g4   	2
-v	me\
-a4   	4
-Rest 	4
-v
-
-v	Twelve \
-c5	2
-v	De\
-c5	2
-v	scrip\
-g4	2
-v	tor \
-a4	2
-v	Type\
-A4	2
-v	-Codes,\
-g4	4
-v
-
-v	E\
-g4	2
-v	lev\
-c5	2
-v	en \
-c5	2
-v	Point\
-g4	2
-v	ers \
-a4   	2
-v	Point\
-A4   	2
-v	ing,\
-g4   	2
-v
-
-v	Ten \
-c5   	4
-v	Pipe\
-g4   	2
-v	lines \ 
-a4   	2
-v	Pip\
-A4   	2
-v	ing,\
-g4   	2
-v
-
-v	Nine \
-c5   	4
-v	Page \
-g4   	2
-v	Frames \
-a4   	2
-v	Pag\
-A4   	2
-v	ing,\
-g4   	2
-v
-
-v	Eight \
-c5	4
-v	Bits \
-g4	2
-v	A\
-a4	2
-v	'Shift\
-A4	2
-v	ing,\
-g4	2
-v
-
-v	Sev\
-c5	2
-v	en \
-c5	2
-v	Swans \
-g4	2
-v	A\
-a4	2
-v	'Swim\
-A4	2
-v	ming,\
-g4	2
-v
-
-v	Six \
-c5	4
-v	Sig\
-g4	2
-v	nals \
-a4	2
-v	Pend\
-A4	2
-v	ing,\
-g4	2
-v
-
-v	FIVE \
-c5	8
-v	TRAP \
-d5	4
-b4	4
-v	GATES!\
-c5	8
-a3	2
-g3	2
-a3	2
-A3	2
-v
-
-v	Four \
-c5	2
-A4	2
-v	Far \
-a4	2
-g4	2
-v	Calls,\
-f4	4
-v
-
-v	Three \
-A4	4
-v	Short \
-d4	4
-v	Jumps,\
-f4	4
-v
-
-v	Two \
-g4	2
-f4	2
-v	Tur\
-e4	2
-v	tle \
-d4	2
-v	Doves,\
-c4	4
-v
-
-v	And \
-a4	2
-v	a \
-A4   	2
-v	Task State \
-c5   	4
-v	Seg\
-d5   	2
-v	ment \
-A4   	2
-v	with \
-a4   	2
-v	a \
-f4   	2
-v	Bit \
-g4   	4
-v	Map\
-f4   	8
-Rest 	4
-v	.\
-f2   	3
-v
diff --git a/exec/tone/trapeze.ton b/exec/tone/trapeze.ton
deleted file mode 100644
index 3312e678912f30c1ced64f86ea3fc9b8a3625942..0000000000000000000000000000000000000000
--- a/exec/tone/trapeze.ton
+++ /dev/null
@@ -1,21 +0,0 @@
-: Man on Flying Trapeze    |
-s  5
-f3 220
-f3 220
-A3 220
-c4 220
-d4 220
-D4 220
-d4 220
-d4 220
-c4 220
-g3 220
-c4 440
-e3 220
-f3 220
-a3 220
-A3 220
-c4 220
-d4 220
-c4 220
-A3 440
diff --git a/exec/tone/weasel.ton b/exec/tone/weasel.ton
deleted file mode 100644
index f5215e9bc066a8c77dc3cdf88f718a25f0a6e0be..0000000000000000000000000000000000000000
--- a/exec/tone/weasel.ton
+++ /dev/null
@@ -1,17 +0,0 @@
-: Pop! Goes the Weasel     |
-s  1
-g2 200
-g2 133
-a2 200
-a2 133
-b2 133
-d3 100
-b2 133
-g2 200
-d2 133
-g2 200
-g2 133
-a2 200
-a2 133
-b2 266
-g2 200
diff --git a/exec/tone/yankee.ton b/exec/tone/yankee.ton
deleted file mode 100644
index 2ba754fc80e6c8f9da07e25af1479f3e8c7c2884..0000000000000000000000000000000000000000
--- a/exec/tone/yankee.ton
+++ /dev/null
@@ -1,15 +0,0 @@
-: Yankee Doodle            |
-c3 220
-c3 220
-d3 220
-e3 220
-c3 220
-e3 220
-d3 220
-g2 220
-c3 220
-c3 220
-d3 220
-e3 220
-c3 440
-b2 220
diff --git a/node1/node.cnf b/node1/node.cnf
deleted file mode 100644
index a5a4342bbb16cda5e4c84b5c42155d6669878302..0000000000000000000000000000000000000000
Binary files a/node1/node.cnf and /dev/null differ
diff --git a/node1/sbbs.bat b/node1/sbbs.bat
deleted file mode 100755
index aa2b0bd10adacadaf9222632ddb674ad6fcbe6ec..0000000000000000000000000000000000000000
--- a/node1/sbbs.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node1/sbbs.cmd b/node1/sbbs.cmd
deleted file mode 100755
index e791768435e128dac61cb42ec97742894e9621d2..0000000000000000000000000000000000000000
--- a/node1/sbbs.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs4os2 %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node1/scfg.bat b/node1/scfg.bat
deleted file mode 100755
index b406a1245efe037742d9442ae2d240a43e4a1659..0000000000000000000000000000000000000000
--- a/node1/scfg.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node1/scfg.cmd b/node1/scfg.cmd
deleted file mode 100755
index 7b1905b433f8e60a4b87430bab3ff1c14e46320f..0000000000000000000000000000000000000000
--- a/node1/scfg.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg4os2 ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node2/node.cnf b/node2/node.cnf
deleted file mode 100644
index a5a4342bbb16cda5e4c84b5c42155d6669878302..0000000000000000000000000000000000000000
Binary files a/node2/node.cnf and /dev/null differ
diff --git a/node2/sbbs.bat b/node2/sbbs.bat
deleted file mode 100755
index aa2b0bd10adacadaf9222632ddb674ad6fcbe6ec..0000000000000000000000000000000000000000
--- a/node2/sbbs.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node2/sbbs.cmd b/node2/sbbs.cmd
deleted file mode 100755
index e791768435e128dac61cb42ec97742894e9621d2..0000000000000000000000000000000000000000
--- a/node2/sbbs.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs4os2 %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node2/scfg.bat b/node2/scfg.bat
deleted file mode 100755
index b406a1245efe037742d9442ae2d240a43e4a1659..0000000000000000000000000000000000000000
--- a/node2/scfg.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node2/scfg.cmd b/node2/scfg.cmd
deleted file mode 100755
index 7b1905b433f8e60a4b87430bab3ff1c14e46320f..0000000000000000000000000000000000000000
--- a/node2/scfg.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg4os2 ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node3/node.cnf b/node3/node.cnf
deleted file mode 100644
index a5a4342bbb16cda5e4c84b5c42155d6669878302..0000000000000000000000000000000000000000
Binary files a/node3/node.cnf and /dev/null differ
diff --git a/node3/sbbs.bat b/node3/sbbs.bat
deleted file mode 100755
index aa2b0bd10adacadaf9222632ddb674ad6fcbe6ec..0000000000000000000000000000000000000000
--- a/node3/sbbs.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node3/sbbs.cmd b/node3/sbbs.cmd
deleted file mode 100755
index e791768435e128dac61cb42ec97742894e9621d2..0000000000000000000000000000000000000000
--- a/node3/sbbs.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs4os2 %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node3/scfg.bat b/node3/scfg.bat
deleted file mode 100755
index b406a1245efe037742d9442ae2d240a43e4a1659..0000000000000000000000000000000000000000
--- a/node3/scfg.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node3/scfg.cmd b/node3/scfg.cmd
deleted file mode 100755
index 7b1905b433f8e60a4b87430bab3ff1c14e46320f..0000000000000000000000000000000000000000
--- a/node3/scfg.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg4os2 ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node4/node.cnf b/node4/node.cnf
deleted file mode 100644
index a5a4342bbb16cda5e4c84b5c42155d6669878302..0000000000000000000000000000000000000000
Binary files a/node4/node.cnf and /dev/null differ
diff --git a/node4/sbbs.bat b/node4/sbbs.bat
deleted file mode 100755
index aa2b0bd10adacadaf9222632ddb674ad6fcbe6ec..0000000000000000000000000000000000000000
--- a/node4/sbbs.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node4/sbbs.cmd b/node4/sbbs.cmd
deleted file mode 100755
index e791768435e128dac61cb42ec97742894e9621d2..0000000000000000000000000000000000000000
--- a/node4/sbbs.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\sbbs4os2 %1 %2 %3 %4 %5
\ No newline at end of file
diff --git a/node4/scfg.bat b/node4/scfg.bat
deleted file mode 100755
index b406a1245efe037742d9442ae2d240a43e4a1659..0000000000000000000000000000000000000000
--- a/node4/scfg.bat
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/node4/scfg.cmd b/node4/scfg.cmd
deleted file mode 100755
index 7b1905b433f8e60a4b87430bab3ff1c14e46320f..0000000000000000000000000000000000000000
--- a/node4/scfg.cmd
+++ /dev/null
@@ -1 +0,0 @@
-@..\exec\scfg4os2 ..\ctrl %1 %2 %3
\ No newline at end of file
diff --git a/src/cleanall.bat b/src/cleanall.bat
deleted file mode 100755
index acefc679cd9a98e28ac1b56f6af58eb38d345956..0000000000000000000000000000000000000000
--- a/src/cleanall.bat
+++ /dev/null
@@ -1,96 +0,0 @@
-@echo off
-rem
-rem Deletes all intermediate files for Synchronet projects - Rob Swindell
-rem
-echo y | del stp\*.obj > nul
-echo y | del stp\*.map > nul
-echo y | del stp\*.exe > nul
-echo y | del tone\*.obj > nul
-echo y | del tone\*.map > nul
-echo y | del tone\*.exe > nul
-echo y | del sbbs\dos > nul
-echo y | del sbbs\os2 > nul
-echo y | del sbbs\w32 > nul
-echo y | del sbbs\addfiles\dos > nul
-echo y | del sbbs\addfiles\dosx > nul
-echo y | del sbbs\addfiles\nt > nul
-echo y | del sbbs\addfiles\os2 > nul
-echo y | del sbbs\allusers\*.obj > nul
-echo y | del sbbs\allusers\*.map > nul
-echo y | del sbbs\allusers\*.exe > nul
-echo y | del sbbs\baja\*.obj > nul
-echo y | del sbbs\baja\*.map > nul
-echo y | del sbbs\baja\*.exe > nul
-echo y | del sbbs\dcdwatch\*.obj > nul
-echo y | del sbbs\dcdwatch\*.map > nul
-echo y | del sbbs\dcdwatch\*.exe > nul
-echo y | del sbbs\delfiles\dos > nul
-echo y | del sbbs\delfiles\dosx > nul
-echo y | del sbbs\delfiles\nt > nul
-echo y | del sbbs\delfiles\os2 > nul
-echo y | del sbbs\dstsedit\*.obj > nul
-echo y | del sbbs\dstsedit\*.map > nul
-echo y | del sbbs\dstsedit\*.exe > nul
-echo y | del sbbs\dupefind\dos > nul
-echo y | del sbbs\dupefind\dosx > nul
-echo y | del sbbs\dupefind\nt > nul
-echo y | del sbbs\dupefind\os2 > nul
-echo y | del sbbs\echo\*.obj > nul
-echo y | del sbbs\echo\*.map > nul
-echo y | del sbbs\echo\*.exe > nul
-echo y | del sbbs\echo\dos > nul
-echo y | del sbbs\echo\dos4G > nul
-echo y | del sbbs\echo\nt > nul
-echo y | del sbbs\echo\os2 > nul
-echo y | del sbbs\execsbbs\dos > nul
-echo y | del sbbs\execsbbs\os2 > nul
-echo y | del sbbs\filelist\dos > nul
-echo y | del sbbs\filelist\dosx > nul
-echo y | del sbbs\filelist\nt > nul
-echo y | del sbbs\filelist\os2 > nul
-echo y | del sbbs\install\dos > nul
-echo y | del sbbs\install\os2 > nul
-echo y | del sbbs\mlabels\*.obj > nul
-echo y | del sbbs\mlabels\*.map > nul
-echo y | del sbbs\mlabels\*.exe > nul
-echo y | del sbbs\node\dos > nul
-echo y | del sbbs\node\os2 > nul
-echo y | del sbbs\qwknodes\*.obj > nul
-echo y | del sbbs\qwknodes\*.map > nul
-echo y | del sbbs\qwknodes\*.exe > nul
-echo y | del sbbs\sbl\*.obj > nul
-echo y | del sbbs\sbl\*.map > nul
-echo y | del sbbs\sbl\*.exe > nul
-echo y | del sbbs\sbj\*.obj > nul
-echo y | del sbbs\sbj\*.map > nul
-echo y | del sbbs\sbj\*.exe > nul
-echo y | del sbbs\scb\*.obj > nul
-echo y | del sbbs\scb\*.map > nul
-echo y | del sbbs\scb\*.exe > nul
-echo y | del sbbs\scfg\dos > nul
-echo y | del sbbs\scfg\dos32 > nul
-echo y | del sbbs\scfg\os2 > nul
-echo y | del sbbs\slog\dos > nul
-echo y | del sbbs\slog\os2 > nul
-echo y | del sbbs\smb\chksmb\dos > nul
-echo y | del sbbs\smb\chksmb\os2 > nul
-echo y | del sbbs\smb\fixsmb\dos > nul
-echo y | del sbbs\smb\fixsmb\os2 > nul
-echo y | del sbbs\smb\smbutil\dos > nul
-echo y | del sbbs\smb\smbutil\dos4G > nul
-echo y | del sbbs\smb\smbutil\nt > nul
-echo y | del sbbs\smb\smbutil\os2 > nul
-echo y | del sbbs\smbactiv\dos > nul
-echo y | del sbbs\smbactiv\dosx > nul
-echo y | del sbbs\smbactiv\nt > nul
-echo y | del sbbs\smbactiv\os2 > nul
-echo y | del sbbs\smm\*.obj > nul
-echo y | del sbbs\smm\*.map > nul
-echo y | del sbbs\smm\*.exe > nul
-echo y | del sbbs\uti\*.obj > nul
-echo y | del sbbs\uti\*.map > nul
-echo y | del sbbs\uti\*.exe > nul
-echo y | del sbbs\execdos\*.obj > nul
-echo y | del sbbs\execdos\*.map > nul
-echo y | del sbbs\execdos\*.exe > nul
-
diff --git a/src/makeall.bat b/src/makeall.bat
deleted file mode 100755
index b73207ac5821e016c16b1eca0c1342053d311601..0000000000000000000000000000000000000000
--- a/src/makeall.bat
+++ /dev/null
@@ -1,121 +0,0 @@
-@echo off
-rem
-rem Makes all Borland for DOS Synchronet projects - April 1997 Rob Swindell
-rem
-cd sbbs
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-make -DW32 %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd scfg
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-make -DDOS32 %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\addfiles
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\allusers
-call make.bat %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\baja
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\delfiles
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\dstsedit
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\dupefind
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\echo
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\execdos
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\execsbbs
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\filelist
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\install
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\mlabels
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\node
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\qwknodes
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\sbj
-make %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\sbl
-make %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-call makeio.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\scb
-make %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-make -fscbcfg.mak %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\slog
-call make.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\smb
-cd chksmb
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\fixsmb
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\smbutil
-make -fmakefile.bc %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..
-cd ..\smbactiv
-make -fmakefile.bc %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\smm
-make %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-make -fsmmcfg.mak %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-call makeio.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-call makephot.bat  %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-call makeutil.batn %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\uti
-make %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-rem
-rem Non-Synchronet specific stuff
-rem
-cd ..\
-cd ..\tone
-call make.bat %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-cd ..\stp
-call make.bat %1 %2 %3 %4 %5 
-if errorlevel 1 goto err
-rem
-rem End of makes
-rem
-cd ..
-goto end
-:err
-rem Error occurred
-echo.
-echo There was an error!
-echo.
-:end
diff --git a/src/makeall.cmd b/src/makeall.cmd
deleted file mode 100755
index bff08dcdc7efc1e42fcf8dda708c849557078c59..0000000000000000000000000000000000000000
--- a/src/makeall.cmd
+++ /dev/null
@@ -1,63 +0,0 @@
-@echo off
-rem
-rem Makes all Borland for OS/2 Synchronet projects - April 1997 Rob Swindell
-rem
-cd sbbs
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd scfg
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\addfiles
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\baja
-call make.cmd %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\delfiles
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\dupefind
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\echo
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\execsbbs
-call make.cmd %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\filelist
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\install
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\node
-call make.cmd %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\slog
-call make.cmd %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\smb
-cd chksmb
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\fixsmb
-make %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\smbutil
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..
-cd ..\smbactiv
-make -fmakefile.bc %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-rem End of makes
-cd ..\..
-goto end
-:err
-rem Error occurred
-echo.
-echo There was an error!
-echo.
-:end
diff --git a/src/odoors/DOOR.CFG b/src/odoors/DOOR.CFG
deleted file mode 100644
index b68fd752b132167093a78cbe086fa24607a73d5d..0000000000000000000000000000000000000000
--- a/src/odoors/DOOR.CFG
+++ /dev/null
@@ -1,341 +0,0 @@
-; DOOR.CFG - Sample OpenDoors door configuration file
-;
-; This configuration file can be used by the sysop to customize an OpenDoors
-; door for use on their own system. The information in this file is NOT usually
-; needed, and the file can be left as is, or even erased, without effecting the
-; door's performance. OpenDoors is designed to run on almost any BBS system
-; automatically, without requiring anything but to the door's .EXE file.
-; However, there are many cases where the sysop may wish to customize a door's
-; operation using this configuration file. The configuration file system is
-; provided to allow the customization of options such as paging hours, maximum
-; time permitted within the door, etc., and to allow OpenDoors doors to be run
-; under even the most non-typical BBS setups.
-;
-; Any text following a semi-colon (;), and blank lines, are ignored.
-;
-;------------------------------------------------------------------------------
-;
-;  BBS system directory. Indicates where the door information file (drop file)
-;  can be found. Remove the semi-colon (;) to activate this option.
-;
-;BBSDir    C:\BBS
-;
-;------------------------------------------------------------------------------
-;
-;  The door's working directory. This is where the door's system files are
-;  located. Remove the semi-colon (;) to activate this option.
-;
-;DoorDir    C:\BBS\MYDOOR
-;
-;------------------------------------------------------------------------------
-;
-;  Local mode override. Forces door to always operate in local test mode.
-;  Remove the semi-colon (;) to activate this option. When this mode is
-;  activated, no door information file is required and default settings are
-;  used for the user's name, location, etc.
-;
-;LocalMode
-;
-;------------------------------------------------------------------------------
-;
-;  Door personality setting. This setting selects one of a number of sysop
-;  interface personalities. Each personality setting emulates the status line
-;  format and sysop function keys of a particular BBS package. Valid
-;  personality settings are:
-;
-;                     Standard            (OpenDoors style, simplified from RA)
-;                     PCBoard
-;                     RemoteAccess
-;                     Wildcat
-;
-Personality    Standard
-;
-;------------------------------------------------------------------------------
-;
-;  Log File options. "LogFileName" specifies filename (path optional) where the
-;  door should record log information. To disable the log file altogether,
-;  remove the semi-colon (;) from the "DisableLogging" line.
-;
-;LogFileName    DOOR.LOG
-;DisableLogging
-;
-;------------------------------------------------------------------------------
-;
-;  BBS node number that door is running on. Only used if OpenDoors is unable
-;  to determine the node number by some other means.
-;
-Node    1
-;
-;------------------------------------------------------------------------------
-;
-;  Sysop paging hours. Sysop paging will be permitted beginning at the start
-;  time, up until, but not including, the end time. Times should be in 24-hour
-;  format. To disable paging on a particular day, set the paging start and end
-;  times to the same time. To make paging always available, set the start time
-;  to 0:00 and the end time to 23:59.
-;
-;                      Start Time    End Time
-SundayPagingHours         9:00        22:00
-MondayPagingHours         8:30        22:00
-TuesdayPagingHours        8:30        22:00
-WednesdayPagingHours      8:30        22:00
-ThursdayPagingHours       8:30        22:00
-FridayPagingHours         8:30        22:00
-SaturdayPagingHours       9:00        22:00
-;
-;------------------------------------------------------------------------------
-;
-;  Duration of sysop page. Value indicates the number of beeps that compose the
-;  sysop page alarm, with one beep sounded per second.
-;
-PageDuration    10
-;
-;------------------------------------------------------------------------------
-;
-;  Maximum length of time a user is permitted to access the door. If the user's
-;  total remaining time on the BBS is less than this value, the user will only
-;  be permitted to access the door for this shorter length of time. This option
-;  may be disabled by placing a semi-colon (;) at the beginning of the line.
-;  When this option is disabled, the user will be permitted to use the full
-;  of their remaining time on the BBS within the door.
-;
-;MaximumDoorTime    15
-;
-;------------------------------------------------------------------------------
-;
-;  Inactivity timeout. Specifies the maximum number of seconds that may elapse
-;  without the user pressing any key, before the user will be automatically
-;  disconnected. A value of 0 disables inactivity timeouts.
-;
-InactivityTimeout    200
-;
-;------------------------------------------------------------------------------
-;
-;  Name of the sysop. OpenDoors can usually determine the sysop's name from the
-;  information passed to the door by the BBS. However, some BBS software does
-;  not supply this information to doors. In such cases, if the sysop's name is
-;  required by the door, it may be supplied here. Remove the semi-colon (;) to
-;  activate this option.
-;
-;SysopName    The Sysop
-;
-;------------------------------------------------------------------------------
-;
-;  Name of the BBS. OpenDoors can usually determine the name of the BBS from
-;  the information passed to the door by the BBS. However, some BBS software
-;  does not supply this information to door programs. In such cases, if the
-;  name of the BBS is needed by the door, it may be supplied here. Remove the
-;  semi-colon (;) to activate this option.
-;
-;SystemName    Unnamed BBS
-;
-;------------------------------------------------------------------------------
-;
-;  Door colour options. These options specify the various text colours that
-;  will be used by the door if ANSI or AVATAR graphics modes are available.
-;  Colours are specified in the format:
-;
-;         {Bright} {Flashing} [Foreground Colour] on [Background Colour]
-;
-;  Where foreground and background colours are one of:
-;
-;         Black
-;         Blue
-;         Green
-;         Cyan
-;         Red
-;         Magenta
-;         Yellow / Brown
-;         White / Grey
-;
-;  Note that some of these options (such as those that pertain to files
-;  listings) are not used for all doors.
-;
-ChatUserColour               Bright white on black
-ChatSysopColour              Bright red on black
-FileListTitleColour          Bright yellow on black
-FileListNameColour           Bright yellow on black
-FileListSizeColour           Bright magenta on black
-FileListDescriptionColour    Cyan on black
-FileListOfflineColour        Bright red on black
-PagePromptColour             Bright white on black
-PopupMenuTitleColour         Bright white on grey
-PopupMenuBorderColour        Black on grey
-PopupMenuTextColour          Black on grey
-PopupMenuKeyColour           Red on grey
-PopupMenuHighlightColour     Grey on black
-PopupMenuHighKeyColour       Red on black
-;
-;------------------------------------------------------------------------------
-;
-;  Memory swapping options. These options are generally not needed, but can be
-;  used to customize OpenDoor's swapping behaviour. "SwappingDir" can be used
-;  to specify which directory or directories should be used for swapping.
-;  Multiple directory paths can be seperated using a semi-colon.
-;  "SwappingNoEMS" can be used to prevent any swapping from being done to EMS
-;  memory, and "SwappingDisable" can be used to disable memory swapping
-;  altogether. Remove the semi-colon (;) to activate any of these options.
-;
-;SwappingDir    C:\
-;SwappingNoEMS
-;SwappingDisable
-;
-;------------------------------------------------------------------------------
-;
-;  Serial port options. These options are generally not needed, as these
-;  settings can usually be determined from the BBS door information file.
-;  "LockedBPS" specifies the the BPS rate at which the door should communicate
-;  with the modem. "SerialPort" specifies the port port number that the modem
-;  is connected to. Unless you have reassigned the port numbers through your
-;  FOSSIL drive, port 0 corresponds to COM1, port 1 corresponds to COM2, and
-;  so on. Remove the semi-colon (;) to activate either of these options.
-;
-;LockedBPS    38400
-;SerialPort    0
-;
-;
-;  Under DOS, a FOSSIL driver is normally used for serial I/O if one is
-;  available. If a FOSSIL driver has not been loaded, the door communicates
-;  directly with the modem. Removing the semi-colon (;) from the "NoFossil"
-;  option causes the door to always communicate directly with the modem,
-;  bypassing any FOSSIL driver.
-;
-;NoFossil
-;
-;------------------------------------------------------------------------------
-;
-;  The following options only apply for the MS-DOS version of this program,
-;  and only if a FOSSIL driver is NOT being used for serial communications.
-;  If a FOSSIL driver IS being used, these options are normally set on the
-;  FOSSIL driver command line. Under Windows, these options are set in the
-;  control panel.
-;
-;  Hexidecimal address of the serial port. This address can usually be
-;  determined automatically for ports COM1, COM2, COM3, and COM4, and is
-;  normally only required for ports COM5 and higher. Remove the semi-colon
-;  (;) to activate this option.
-;
-;PortAddress 2F8
-;
-;
-;  Interrupt request line that the serial port is using. May be any IRQ line
-;  from 1 to 15. By default, IRQ line 4 is used for ports COM1: and COM3:,
-;  while IRQ line 3 is used for all other ports. Remove the semi-colon (;)
-;  to activate this option.
-;
-;PortIRQ 4
-;
-;
-;  Serial I/O buffer sizes. "ReceiveBuffer" specifies the number of bytes in
-;  the serial I/O receive buffer. You may want to increase this buffer size
-;  if you find that characters being sent from the user's modem are being lost.
-;  "TransmitBuffer" specifies the number of bytes in the serial I/O transmit
-;  buffer. You may want to increase this buffer size for improved performance
-;  in some multitasking environments. A transmit buffer size smaller than 3072
-;  bytes is not recommended.
-;
-ReceiveBuffer 256
-TransmitBuffer 3072
-;
-;
-;  UART FIFO buffers. Normally, OpenDoors will use 16550A UART FIFO buffers
-;  if they are available. You can prevent OpenDoors from using the FIFO
-;  buffers, even if they are available, by removing the semi-colon before
-;  the "NoFIFO" keyword. The "FIFOTriggerSize" specifies how many characters
-;  may be placed in the FIFO buffers before an serial I/O interrupt is
-;  envoked. Valid values are 1, 4, 8 and 14 bytes. The default value is 4
-;  bytes.
-;
-;NoFIFO
-FIFOTriggerSize 4
-;
-;------------------------------------------------------------------------------
-;
-;  The following options control if and how the Windows version of this program
-;  disables DTR response by the modem prior to exiting. Normally, the sequence
-;  of modem commands specified by DisableDTR is sent before exiting, to prevent
-;  the modem from hanging up. To disable this feature, remove the semi-colon
-;  (;) at the beginning of the NoDTRDisable line.
-;
-;  DisableDTR specifies a series of commands to be sent to the modem, and
-;  responses to be received by the modem. Each command and response is
-;  separated by a space. A tilde (~) character denotes a one second pause, and
-;  a pipe (|) denotes a CR.
-;
-;NoDTRDisable
-DisableDTR ~+++ OK AT&D0| OK ATO|
-;
-;------------------------------------------------------------------------------
-;
-;  Custom door information file support. OpenDoors automatically recognizes
-;  most door information file (drop file) formats, including DORINFO?.DEF,
-;  EXITINFO.BBS, DOOR.SYS, SFDOORS.DAT, CALLINFO.BBS and CHAIN.TXT. However,
-;  to permit OpenDoors doors to operate on BBS systems that produce a different
-;  format file, you may define a custom door information file format. A custom
-;  door information file format is defined using the "CustomFileName" command,
-;  followed by one or more lines beginning with the "CustomFileLine" command.
-;
-;  The "CustomFileName" option specifies the filename used to distinguish this
-;  file format from other file formats. This filename should not include a
-;  path. To specify the path where the door information file is located, use
-;  the BBSDir setting, near the beginning of this file. If the filename of the
-;  custom format is the same as that of one of the built-in formats, the custom
-;  format will override the built-in format.
-;
-;  The actual format of the custom file is specified using a number of lines
-;  that begin with the keyword "CustomFileLine". Each of these lines will
-;  correspond to a single line in the door information file, with the option
-;  following the "CustomFileLine" keyword specifying the information that can
-;  be found on that line. This can be one of the following keywords:
-;
-;                    Ignore - Causes the next line in the door information
-;                             file to be ignored. Use on lines for which none
-;                             of the options below apply.
-;                   ComPort - COM? port the modem is connected to
-;                             (0 indicates local mode)
-;                FossilPort - Fossil port number the modem is connected to
-;                  ModemBPS - BPS rate at which to communicate with modem
-;                             (0 or non-numerical value indicates local mode)
-;                 LocalMode - 1, T or Y if door is operating in local mode
-;                  UserName - Full name of the user
-;             UserFirstName - First name(s) of the user
-;              UserLastName - Last name of the user
-;                     Alias - The user's psuedonym / handle
-;                 HoursLeft - Hours user has left online
-;               MinutesLeft - Minutes user has left online, or time left online
-;                             in format hh:mm
-;               SecondsLeft - Seconds user has left online, or time left online
-;                             in format hh:mm:ss or format mm:ss
-;                             (If more than one of the above time options are
-;                             used, the user time left is taken to be the total
-;                             of all of these values.)
-;                      ANSI - 1, T, Y or G for ANSI graphics mode
-;                    AVATAR - 1, T or Y for AVATAR graphics mode
-;                       RIP - 1, T or Y for RIP graphics mode
-;               PagePausing - 1, T or Y if user wishes a pause at end of screen
-;              ScreenLength - Number of lines on user's screen
-;            ScreenClearing - 1, T or Y if screen clearing mode is on
-;                  Security - The user's security level / access level
-;                      City - City the user is calling from
-;                      Node - Node number user is connected to
-;                 SysopName - Full name of the sysop
-;            SysopFirstName - The sysop's first name(s)
-;             SysopLastName - The sysop's last name
-;                SystemName - Name of the BBS
-;
-;
-CustomFileName    EXAMPLE.DEF                     ; Same format as DORINFO?.DEF
-CustomFileLine    SystemName
-CustomFileLine    SysopFirstName
-CustomFileLine    SysopLastName
-CustomFileLine    ComPort
-CustomFileLine    ModemBPS
-CustomFileLine    Ignore
-CustomFileLine    UserFirstName
-CustomFileLine    UserLastName
-CustomFileLine    City
-CustomFileLine    ANSI
-CustomFileLine    Security
-CustomFileLine    MinutesLeft
-;
-;------------------------------------------------------------------------------
diff --git a/src/odoors/DORINFO1.DEF b/src/odoors/DORINFO1.DEF
deleted file mode 100644
index 32be55548455175366e99f8a3954b40743bed1bb..0000000000000000000000000000000000000000
--- a/src/odoors/DORINFO1.DEF
+++ /dev/null
@@ -1,12 +0,0 @@
-TEST BBS
-THE
-SYSOP
-COM0
-0 BAUD,N,8,1
-0
-TEST
-USER
-UNKNOWN LOCATION
-1
-10
-60
diff --git a/src/odoors/DOS.mak b/src/odoors/DOS.mak
deleted file mode 100644
index 314f35c8ad35005a9288cf28cda8653343cc8dfe..0000000000000000000000000000000000000000
--- a/src/odoors/DOS.mak
+++ /dev/null
@@ -1,422 +0,0 @@
-#  OpenDoors 6.10
-#  (C) Copyright 1991 - 1997 by Brian Pirie. All Rights Reserved.
-#
-#
-#         File: DOS.mak
-#
-#  Description: Makefile used to build the MS-DOS OpenDoors libraries from
-#               the sources. Usage is described below.
-#
-#    Revisions: Date          Ver   Who  Change
-#               ---------------------------------------------------------------
-#               Oct 13, 1994  6.00  BP   New file header format.
-#               Oct 13, 1994  6.00  BP   Made directories configurable.
-#               Oct 13, 1994  6.00  BP   Erase tlib-created backup file.
-#               Oct 14, 1994  6.00  BP   Added ODGen.h dependencies.
-#               Oct 14, 1994  6.00  BP   Added ODPlat.c module.
-#               Oct 31, 1994  6.00  BP   Added headers dependency constant.
-#               Nov 01, 1994  6.00  BP   Added ODUtil.c module.
-#               Dec 31, 1994  6.00  BP   Added -B option for Borland Cs.
-#               Jan 01, 1995  6.00  BP   Added ODKrnl.c, ODKrnl.h.
-#               Jan 29, 1995  6.00  BP   Added ODCmdLn.c.
-#               Nov 16, 1995  6.00  BP   Added ODInQue.c, and new headers.
-#               Nov 21, 1995  6.00  BP   Created ODInit1.c, ODInit2.c.
-#               Dec 02, 1995  6.00  BP   Added ODRes.h
-#               Dec 02, 1995  6.00  BP   Added ODFrame.c, ODFrame.h.
-#               Dec 02, 1995  6.00  BP   Added ODStat.h, ODSwap.h.
-#               Dec 04, 1995  6.00  BP   Changes for building Win32 version.
-#               Dec 05, 1995  6.00  BP   Split into makefiles for each platform
-#               Dec 07, 1995  6.00  BP   Added ODEdit.c.
-#               Jan 04, 1996  6.00  BP   Added ODGetIn.c.
-#               Feb 09, 1996  6.00  BP   Renamed ODInit?.* to ODInEx?.*
-#               Feb 19, 1996  6.00  BP   Changed version number to 6.00.
-#               Mar 03, 1996  6.10  BP   Begin version 6.10.
-#
-###############################################################################
-#
-# USAGE INFORMATION
-#
-###############################################################################
-#
-# Command Line:   make -fDOS.mak -DTARGET=?
-#                     or
-#                 nmake -fDOS.mak "TARGET=?"
-#
-# Where:  "TARGET=?"   - Specifies which version of the library should be
-#                        built. TARGET can be set to:
-#
-#                             t - MS-DOS version, tiny memory model
-#                             s - MS-DOS version, small memory model
-#                             c - MS-DOS version, compact memory model
-#                             m - MS-DOS version, medium memory model
-#                             l - MS-DOS version, large memory model
-#                             h - MS-DOS version, huge memory model
-#
-#                        Setting must be in lower case for Borland compilers,
-#                        uppercase for Microsoft compilers.
-#
-###############################################################################
-#
-# CONFIGURATION
-#
-# Customize this section of the makefile to provide the relevant information
-# for your compiler, assembler (if any) and build environment.
-#
-###############################################################################
-# Compiler executable file name. Use:
-#
-#                  tcc - For Borland Turbo C and Turbo C++
-#                  bcc - For Borland C++
-#                   cl - For Microsoft compilers
-#
-CC=tcc
-#
-#------------------------------------------------------------------------------
-#
-# Assembler executable file name. Use:
-#
-#                 tasm - For Turbo Assembler
-#                 masm - For Microsoft Macro Assembler
-#
-AS=tasm
-#
-#------------------------------------------------------------------------------
-#
-# Library managment utility. Use:
-#
-#                 tlib - For Borland compilers
-#                  lib - For Microsoft compilers
-#
-LIB=tlib
-#
-#------------------------------------------------------------------------------
-#
-# MS-DOS compiler command-line flags. Use:
-#
-#   -m$(TARGET) -c -O -G -Z -d -B  - For Borland compilers including Turbo C
-#          /a$(TARGET) /c /nologo  - For Microsoft compilers
-#
-CFLAGS=-m$(TARGET) -c -O -G -Z -d -Ic:\progra~1\tc\include
-#
-#------------------------------------------------------------------------------
-#
-# Assembler command-line flags.
-#
-AFLAGS=/mx
-ADEFLCODE=/dLCODE
-ADEFLDATA=/dLDATA
-#
-#------------------------------------------------------------------------------
-#
-# Output directories. customize for your own preferences. Note that trailing
-# backslash (\) characters are required.
-#
-SOURCEDIR=.\                                               # Comments required
-ODHEADERDIR=.\                                             # in order to
-OBJDIR=..\obj\                                             # avoid line
-LIBDIR=..\lib\                                             # concatentation
-#
-###############################################################################
-#
-# DEPENDENCIES
-#
-# You won't normally have to change anything after this point in this makefile.
-#
-###############################################################################
-#
-# Define primary target.
-#
-all: $(LIBDIR)ODoor$(TARGET).lib
-#
-#------------------------------------------------------------------------------
-#
-# Name of all headers.
-#
-HEADERS= $(HEADERDIR)ODCom.h\
-         $(HEADERDIR)ODCore.h\
-         $(HEADERDIR)ODFrame.h\
-         $(HEADERDIR)ODGen.h\
-         $(HEADERDIR)ODInEx.h\
-         $(HEADERDIR)ODInQue.h\
-         $(HEADERDIR)ODKrnl.h\
-         $(HEADERDIR)ODPlat.h\
-         $(HEADERDIR)ODRes.h\
-         $(HEADERDIR)ODScrn.h\
-         $(HEADERDIR)ODStat.h\
-         $(HEADERDIR)ODSwap.h\
-         $(HEADERDIR)ODTypes.h\
-         $(HEADERDIR)ODUtil.h\
-         $(HEADERDIR)OpenDoor.h
-#
-#------------------------------------------------------------------------------
-#
-# Build from C sources.
-#
-$(OBJDIR)odauto$(TARGET).obj : $(SOURCEDIR)odauto.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odauto.c
-   command /c erase $(OBJDIR)odauto$(TARGET).obj
-   move odauto.obj $(OBJDIR)odauto$(TARGET).obj
-
-$(OBJDIR)odblock$(TARGET).obj : $(SOURCEDIR)odblock.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odblock.c
-   command /c erase $(OBJDIR)odblock$(TARGET).obj
-   move odblock.obj $(OBJDIR)odblock$(TARGET).obj
-
-$(OBJDIR)odcfile$(TARGET).obj : $(SOURCEDIR)odcfile.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcfile.c
-   command /c erase $(OBJDIR)odcfile$(TARGET).obj
-   move odcfile.obj $(OBJDIR)odcfile$(TARGET).obj
-
-$(OBJDIR)odcmdln$(TARGET).obj : $(SOURCEDIR)odcmdln.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcmdln.c
-   command /c erase $(OBJDIR)odcmdln$(TARGET).obj
-   move odcmdln.obj $(OBJDIR)odcmdln$(TARGET).obj
-
-$(OBJDIR)odcom$(TARGET).obj : $(SOURCEDIR)odcom.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcom.c
-   command /c erase $(OBJDIR)odcom$(TARGET).obj
-   move odcom.obj $(OBJDIR)odcom$(TARGET).obj
-
-$(OBJDIR)odcore$(TARGET).obj : $(SOURCEDIR)odcore.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcore.c
-   command /c erase $(OBJDIR)odcore$(TARGET).obj
-   move odcore.obj $(OBJDIR)odcore$(TARGET).obj
-
-$(OBJDIR)oddrbox$(TARGET).obj : $(SOURCEDIR)oddrbox.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)oddrbox.c
-   command /c erase $(OBJDIR)oddrbox$(TARGET).obj
-   move oddrbox.obj $(OBJDIR)oddrbox$(TARGET).obj
-
-$(OBJDIR)odedit$(TARGET).obj : $(SOURCEDIR)odedit.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odedit.c
-   command /c erase $(OBJDIR)odedit$(TARGET).obj
-   move odedit.obj $(OBJDIR)odedit$(TARGET).obj
-
-$(OBJDIR)odedstr$(TARGET).obj : $(SOURCEDIR)odedstr.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odedstr.c
-   command /c erase $(OBJDIR)odedstr$(TARGET).obj
-   move odedstr.obj $(OBJDIR)odedstr$(TARGET).obj
-
-$(OBJDIR)odemu$(TARGET).obj : $(SOURCEDIR)odemu.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odemu.c
-   command /c erase $(OBJDIR)odemu$(TARGET).obj
-   move odemu.obj $(OBJDIR)odemu$(TARGET).obj
-
-$(OBJDIR)odgetin$(TARGET).obj : $(SOURCEDIR)odgetin.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odgetin.c
-   command /c erase $(OBJDIR)odgetin$(TARGET).obj
-   move odgetin.obj $(OBJDIR)odgetin$(TARGET).obj
-
-$(OBJDIR)odgraph$(TARGET).obj : $(SOURCEDIR)odgraph.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odgraph.c
-   command /c erase $(OBJDIR)odgraph$(TARGET).obj
-   move odgraph.obj $(OBJDIR)odgraph$(TARGET).obj
-
-$(OBJDIR)odinex1$(TARGET).obj : $(SOURCEDIR)odinex1.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinex1.c
-   command /c erase $(OBJDIR)odinex1$(TARGET).obj
-   move odinex1.obj $(OBJDIR)odinex1$(TARGET).obj
-
-$(OBJDIR)odinex2$(TARGET).obj : $(SOURCEDIR)odinex2.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinex2.c
-   command /c erase $(OBJDIR)odinex2$(TARGET).obj
-   move odinex2.obj $(OBJDIR)odinex2$(TARGET).obj
-
-$(OBJDIR)odinque$(TARGET).obj : $(SOURCEDIR)odinque.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinque.c
-   command /c erase $(OBJDIR)odinque$(TARGET).obj
-   move odinque.obj $(OBJDIR)odinque$(TARGET).obj
-
-$(OBJDIR)odkrnl$(TARGET).obj : $(SOURCEDIR)odkrnl.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odkrnl.c
-   command /c erase $(OBJDIR)odkrnl$(TARGET).obj
-   move odkrnl.obj $(OBJDIR)odkrnl$(TARGET).obj
-
-$(OBJDIR)odlist$(TARGET).obj : $(SOURCEDIR)odlist.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odlist.c
-   command /c erase $(OBJDIR)odlist$(TARGET).obj
-   move odlist.obj $(OBJDIR)odlist$(TARGET).obj
-
-$(OBJDIR)odlog$(TARGET).obj : $(SOURCEDIR)odlog.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odlog.c
-   command /c erase $(OBJDIR)odlog$(TARGET).obj
-   move odlog.obj $(OBJDIR)odlog$(TARGET).obj
-
-$(OBJDIR)odmulti$(TARGET).obj : $(SOURCEDIR)odmulti.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odmulti.c
-   command /c erase $(OBJDIR)odmulti$(TARGET).obj
-   move odmulti.obj $(OBJDIR)odmulti$(TARGET).obj
-
-$(OBJDIR)odplat$(TARGET).obj : $(SOURCEDIR)odplat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odplat.c
-   command /c erase $(OBJDIR)odplat$(TARGET).obj
-   move odplat.obj $(OBJDIR)odplat$(TARGET).obj
-
-$(OBJDIR)odpcb$(TARGET).obj : $(SOURCEDIR)odpcb.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odpcb.c
-   command /c erase $(OBJDIR)odpcb$(TARGET).obj
-   move odpcb.obj $(OBJDIR)odpcb$(TARGET).obj
-
-$(OBJDIR)odpopup$(TARGET).obj : $(SOURCEDIR)odpopup.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odpopup.c
-   command /c erase $(OBJDIR)odpopup$(TARGET).obj
-   move odpopup.obj $(OBJDIR)odpopup$(TARGET).obj
-
-$(OBJDIR)odprntf$(TARGET).obj : $(SOURCEDIR)odprntf.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odprntf.c
-   command /c erase $(OBJDIR)odprntf$(TARGET).obj
-   move odprntf.obj $(OBJDIR)odprntf$(TARGET).obj
-
-$(OBJDIR)odra$(TARGET).obj : $(SOURCEDIR)odra.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odra.c
-   command /c erase $(OBJDIR)odra$(TARGET).obj
-   move odra.obj $(OBJDIR)odra$(TARGET).obj
-
-$(OBJDIR)odscrn$(TARGET).obj : $(SOURCEDIR)odscrn.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odscrn.c
-   command /c erase $(OBJDIR)odscrn$(TARGET).obj
-   move odscrn.obj $(OBJDIR)odscrn$(TARGET).obj
-
-$(OBJDIR)odspawn$(TARGET).obj : $(SOURCEDIR)odspawn.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odspawn.c
-   command /c erase $(OBJDIR)odspawn$(TARGET).obj
-   move odspawn.obj $(OBJDIR)odspawn$(TARGET).obj
-
-$(OBJDIR)odstand$(TARGET).obj : $(SOURCEDIR)odstand.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odstand.c
-   command /c erase $(OBJDIR)odstand$(TARGET).obj
-   move odstand.obj $(OBJDIR)odstand$(TARGET).obj
-
-$(OBJDIR)odstat$(TARGET).obj : $(SOURCEDIR)odstat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odstat.c
-   command /c erase $(OBJDIR)odstat$(TARGET).obj
-   move odstat.obj $(OBJDIR)odstat$(TARGET).obj
-
-$(OBJDIR)odsys$(TARGET).obj : $(SOURCEDIR)odsys.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odsys.c
-   command /c erase $(OBJDIR)odsys$(TARGET).obj
-   move odsys.obj $(OBJDIR)odsys$(TARGET).obj
-
-$(OBJDIR)odutil$(TARGET).obj : $(SOURCEDIR)odutil.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odutil.c
-   command /c erase $(OBJDIR)odutil$(TARGET).obj
-   move odutil.obj $(OBJDIR)odutil$(TARGET).obj
-
-$(OBJDIR)odwcat$(TARGET).obj : $(SOURCEDIR)odwcat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odwcat.c
-   command /c erase $(OBJDIR)odwcat$(TARGET).obj
-   move odwcat.obj $(OBJDIR)odwcat$(TARGET).obj
-
-$(OBJDIR)odwin$(TARGET).obj : $(SOURCEDIR)odwin.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odwin.c
-   command /c erase $(OBJDIR)odwin$(TARGET).obj
-   move odwin.obj $(OBJDIR)odwin$(TARGET).obj
-#
-#------------------------------------------------------------------------------
-#
-# Build from assembly sources.
-#
-$(OBJDIR)odswapt.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswapt.obj
-   move odswap.obj $(OBJDIR)odswapt.obj
-
-$(OBJDIR)odswaps.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswaps.obj
-   move odswap.obj $(OBJDIR)odswaps.obj
-
-$(OBJDIR)odswapc.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(ADEFLDATA) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswapc.obj
-   move odswap.obj $(OBJDIR)odswapc.obj
-
-$(OBJDIR)odswapm.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(ADEFLCODE) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswapm.obj
-   move odswap.obj $(OBJDIR)odswapm.obj
-
-$(OBJDIR)odswapl.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(ADEFLDATA) $(ADEFLCODE) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswapl.obj
-   move odswap.obj $(OBJDIR)odswapl.obj
-
-$(OBJDIR)odswaph.obj : $(SOURCEDIR)odswap.asm
-   $(AS) $(AFLAGS) $(ADEFLDATA) $(ADEFLCODE) $(SOURCEDIR)odswap.asm
-   command /c erase $(OBJDIR)odswaph.obj
-   move odswap.obj $(OBJDIR)odswaph.obj
-#
-#------------------------------------------------------------------------------
-#
-# Build library from objects.
-#
-OBJECTS= $(OBJDIR)odauto$(TARGET).obj\
-         $(OBJDIR)odblock$(TARGET).obj\
-         $(OBJDIR)odcfile$(TARGET).obj\
-         $(OBJDIR)odcmdln$(TARGET).obj\
-         $(OBJDIR)odcom$(TARGET).obj\
-         $(OBJDIR)odcore$(TARGET).obj\
-         $(OBJDIR)oddrbox$(TARGET).obj\
-         $(OBJDIR)odedit$(TARGET).obj\
-         $(OBJDIR)odedstr$(TARGET).obj\
-         $(OBJDIR)odemu$(TARGET).obj\
-         $(OBJDIR)odgetin$(TARGET).obj\
-         $(OBJDIR)odgraph$(TARGET).obj\
-         $(OBJDIR)odinex1$(TARGET).obj\
-         $(OBJDIR)odinex2$(TARGET).obj\
-         $(OBJDIR)odinque$(TARGET).obj\
-         $(OBJDIR)odkrnl$(TARGET).obj\
-         $(OBJDIR)odlist$(TARGET).obj\
-         $(OBJDIR)odlog$(TARGET).obj\
-         $(OBJDIR)odmulti$(TARGET).obj\
-         $(OBJDIR)odplat$(TARGET).obj\
-         $(OBJDIR)odpcb$(TARGET).obj\
-         $(OBJDIR)odpopup$(TARGET).obj\
-         $(OBJDIR)odprntf$(TARGET).obj\
-         $(OBJDIR)odra$(TARGET).obj\
-         $(OBJDIR)odscrn$(TARGET).obj\
-         $(OBJDIR)odspawn$(TARGET).obj\
-         $(OBJDIR)odstand$(TARGET).obj\
-         $(OBJDIR)odstat$(TARGET).obj\
-         $(OBJDIR)odswap$(TARGET).obj\
-         $(OBJDIR)odsys$(TARGET).obj\
-         $(OBJDIR)odutil$(TARGET).obj\
-         $(OBJDIR)odwcat$(TARGET).obj\
-         $(OBJDIR)odwin$(TARGET).obj
-$(LIBDIR)odoor$(TARGET).lib : $(OBJECTS)
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odauto$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odblock$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odcfile$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odcmdln$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odcom$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odcore$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)oddrbox$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odedit$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odedstr$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odemu$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odgetin$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odgraph$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odinex1$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odinex2$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odinque$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odkrnl$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odlist$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odlog$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odmulti$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odplat$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odpcb$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odpopup$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odprntf$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odra$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odscrn$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odspawn$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odstand$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odstat$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odswap$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odsys$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odutil$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odwcat$(TARGET).obj
-   $(LIB) $(LIBDIR)odoor$(TARGET).lib -+$(OBJDIR)odwin$(TARGET).obj
-   erase $(LIBDIR)odoor$(TARGET).bak
-#
-#------------------------------------------------------------------------------
diff --git a/src/odoors/FILE_ID.DIZ b/src/odoors/FILE_ID.DIZ
deleted file mode 100644
index 9fbef744d53520b820551ea5deebba88254742a0..0000000000000000000000000000000000000000
--- a/src/odoors/FILE_ID.DIZ
+++ /dev/null
@@ -1,17 +0,0 @@
-OpenDoors 6.21 C/C++ door programming toolkit
-OpenDoors is an advanced, easy to use library
-for writing online software such as BBS doors
-
-Includes full source code and DLL for the 
-native-Win32 version. v6.2x modifications by 
-Rob Swindell (www.synchro.net) add support for 
-TCP socket (Telnet) connections and Door32.sys!
-
-OpenDoors transparently interfaces with most
-BBS systems, automatically displays output on
-both local and remote screens, creates ANSI/
-AVATAR/RIP control sequences, and provides a
-sysop interface with commands for chat, time
-adjustment, disconnecting, etc. 
-http://www.attcanada.net/~pirie/opendoors.html
-(C) 1991-2001 Brian Pirie
diff --git a/src/odoors/ODApp.ico b/src/odoors/ODApp.ico
deleted file mode 100644
index 3192ae1411d92a412de4eee079679cf9b4a39072..0000000000000000000000000000000000000000
Binary files a/src/odoors/ODApp.ico and /dev/null differ
diff --git a/src/odoors/ODAuto.c b/src/odoors/ODAuto.c
deleted file mode 100644
index 649ed153ad9c643d4515f6e2e6df2feaee2f91b5..0000000000000000000000000000000000000000
--- a/src/odoors/ODAuto.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODAuto.c
- *
- * Description: Implements od_autodetect() for automatic detection of
- *              terminal emulation supported by remote system.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 14, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Use new millisecond timer functions.
- *              Nov 12, 1995  6.00  BP   32-bit portability.
- *              Nov 13, 1995  6.00  BP   Fixed non-functioning RIP autodetect.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <ctype.h>
-
-#include "OpenDoor.h"
-#include "ODTypes.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODCore.h"
-#include "ODKrnl.h"
-
-
-/* Private function prototypes. */
-static char ODWaitNoCase(char *pszWaitFor, tODMilliSec WaitTime);
-
-
-/* Number of attempts and timeout values for testing each terminal emulation */
-/* protocol.                                                                 */
-#define ANSI_TRIES      1
-#define ANSI_WAIT       660                         /* Time in milliseconds. */
-#define RIP_TRIES       1
-#define RIP_WAIT        660                         /* Time in milliseconds. */
-
-/* Strings to use for autodetection. */
-#define ANSI_QUERY      "\x1b[6n\r    \r"
-#define ANSI_RESPONSE   "\x1b["
-#define RIP_QUERY       "\r\x1b[!\r   \r"
-#define RIP_RESPONSE    "RIP"
-
-/* Maximum number of characters to match with _waitnocase(). */
-#define MATCH_LEN       3
-
-
-/* ----------------------------------------------------------------------------
- * od_autodetect()
- *
- * Determines the terminal emulation capabilities of the remote communications
- * software, when possible. Turns on ANSI and/or RIP modes if they are
- * supported by the remote system.
- *
- * Parameters: nFlags - Currently unused.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_autodetect(INT nFlags)
-{
-   INT nCount;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_autodetect()");
-
-   /* Initialize OpenDoors if it hasn't aready been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Temporary code that will be optimized out, which prevents a compiler   */
-   /* warning from being generated for the currently unused flags parameter. */
-   (void)nFlags;
-
-   /* If operating in local mode, turn on ANSI mode, but not RIP. */
-   if(od_control.baud == 0)
-   {
-      od_control.user_ansi = TRUE;
-      OD_API_EXIT();
-      return;
-   }
-
-   /* If user_ansi is not set, attempt to determine ANSI capabilities. */
-   if(!od_control.user_ansi)
-   {
-      /* Clear inbound keyboard buffer. */
-      od_clear_keybuffer();
-
-      /* Try twice to test ANSI capabilities. */
-      for(nCount = 0; nCount < ANSI_TRIES; ++nCount)
-      {
-         /* Send a string that an ANSI capable terminal will usually */
-         /* respond to. */
-         od_disp(ANSI_QUERY, strlen(ANSI_QUERY), FALSE);
-
-         /* Wait for response expected from an ANSI terminal, for up to */
-         /* 12/18.2 second. */
-         if(ODWaitNoCase(ANSI_RESPONSE, ANSI_WAIT))
-         {
-            /* If expected sequence was received, turn on ANSI mode and */
-            /* exit the loop. */
-            od_control.user_ansi = TRUE;
-            break;
-         }
-      }
-      od_clear_keybuffer();
-   }
-
-   /* If user_rip is not set, attempt to determine RIP capabilities. */
-   if(!od_control.user_rip)
-   {
-      /* Clear inbound keyboard buffer. */
-      od_clear_keybuffer();
-
-      /* Try twice to test RIP capabilities. */
-      for(nCount = 0; nCount < RIP_TRIES; ++nCount)
-      {
-         /* Send a string that a RIP capable terminal will usually */
-         /* respond to. */
-         od_disp(RIP_QUERY, strlen(RIP_QUERY), FALSE);
-
-         /* Wait for response expected from a RIP terminal. */
-         if(ODWaitNoCase(RIP_RESPONSE, RIP_WAIT))
-         {
-            /* If expected sequence was received, turn on RIP mode and */
-            /* exit the loop. */
-            od_control.user_rip = TRUE;
-            break;
-         }
-      }
-      od_clear_keybuffer();
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODWaitNoCase()                                      *** PRIVATE FUNCTION ***
- *
- * Waits up to the specified maximum time for a specified string to be sent
- * from the remote system. String matching is not case sensitive.
- *
- * Parameters: pszWaitFor - String to wait for.
- *
- *             WaitTime   - Maximum time, in milliseconds, to wait.
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-static char ODWaitNoCase(char *pszWaitFor, tODMilliSec WaitTime)
-{
-   tODTimer Timer;
-   char szReceived[MATCH_LEN + 1];
-   int nCount;
-   char chReceived;
-   int nMatchChars = MIN(MATCH_LEN, strlen(pszWaitFor));
-
-   ASSERT(pszWaitFor != NULL);
-   ASSERT(strlen(pszWaitFor) != 0);
-   ASSERT(WaitTime >= 0);
-
-   ODTimerStart(&Timer, WaitTime);
-
-   for(nCount = 0; nCount <= MATCH_LEN; ++nCount)
-   {
-      szReceived[nCount] = '\0';
-   }
-
-   do
-   {
-      if((chReceived = od_get_key(FALSE)) != 0)
-      {
-         for(nCount = 0; nCount < MATCH_LEN - 1; ++ nCount)
-         {
-            szReceived[nCount] = szReceived[nCount + 1];
-         }
-         szReceived[MATCH_LEN - 1] = chReceived;
-
-         if(strnicmp(szReceived + (MATCH_LEN - nMatchChars), pszWaitFor,
-            nMatchChars) == 0)
-         {
-            return(TRUE);
-         }
-      }
-   } while(!ODTimerElapsed(&Timer));
-
-   return(FALSE);
-}
diff --git a/src/odoors/ODBlock.c b/src/odoors/ODBlock.c
deleted file mode 100644
index 32bfd6b8a63a24d19f696a1b364d8680e36a8336..0000000000000000000000000000000000000000
--- a/src/odoors/ODBlock.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODBlock.c
- *
- * Description: Implements the text block manipulation functions.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODKrnl.h"
-
-
-/* Set to TRUE when od_puttext() should leave the cursor in its original */
-/* position */
-static BOOL bScrollAction = TRUE;
-
-
-
-/* ----------------------------------------------------------------------------
- * od_puttext()
- *
- * Displays the contents of the buffer passed in block. Leaves cursor in
- * original position, unless bScrollAction is FALSE. Leaves colour at
- * original value.
- *
- * Parameters: nLeft   - Column number of left edge of block of text to
- *                       transfer, where 1 is the leftmost column of the
- *                       screen.
- *
- *             nTop    - Row number of the top edge of block of text to
- *                       to transfer, where 1 is the top row of the screen.
- *
- *             nRight  - Column number of the right edge of block.
- *
- *             nBottom - Row number of bottom edge of block.
- *
- *             pBlock  - Pointer to buffer that has been filled in the format
- *                       used by od_gettext().
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_puttext(INT nLeft, INT nTop, INT nRight, INT nBottom,
-   void *pBlock)
-{
-   INT nRowLength = nRight - nLeft +1;
-   INT nRowBytes = nRowLength * 2;
-   char *pchTest;
-   char *pchMemory;
-   char *pBuffer;
-   char *pchScreenBlock;
-   INT nBlockRow = 0;
-   INT nOutRow;
-   INT nOutColour = 999;
-   INT nOutColumn, nCheckColumn;
-   char *pchMemBlock;
-   INT nMoveCost = od_control.user_avatar ? 4 : 7;
-   BYTE btMaxRight, btMaxBottom;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_puttext()");
-
-   /* Ensure that OpenDoors is initialized before proceeding. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Get current display setting profile. */
-   ODScrnGetTextInfo(&ODTextInfo);
-
-   /* Calculate the maximum values for bottom and right of block. */
-   btMaxRight=ODTextInfo.winright-ODTextInfo.winleft+1;
-   btMaxBottom=ODTextInfo.winbottom-ODTextInfo.wintop+1;
-
-   /* Check that parameters seem reasonable. */
-   if(nLeft<1 || nTop<1 || nRight>btMaxRight || nBottom>btMaxBottom
-      || nTop > nBottom || nLeft > nRight || pBlock==NULL)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Ensure that ANSI and/or AVATAR mode is available. */
-   if(!od_control.user_ansi && !od_control.user_avatar)
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* If OpenDoors is operating in remote mode. */
-   if(od_control.baud != 0)
-   {
-      /* Allocate temporary buffer to store original screen contents while */
-      /* buffer paste is being performed.                                  */
-      if((pBuffer=malloc(nRowBytes*(nBottom-nTop+1)))==NULL)
-      {
-         od_control.od_error = ERR_MEMORY;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      /* Get current screen contents of area to be pasted into, storing */
-      /* into the temporary buffer.                                     */
-      if(!ODScrnGetText((BYTE)nLeft, (BYTE)nTop, (BYTE)nRight, (BYTE)nBottom,
-         pBuffer))
-      {
-         od_control.od_error = ERR_PARAMETER;
-         free(pBuffer);
-         OD_API_EXIT();
-         return(FALSE);
-      }
-   }
-
-   /* Display the block to be pasted on the local screen. */
-   if(!ODScrnPutText((BYTE)nLeft, (BYTE)nTop, (BYTE)nRight, (BYTE)nBottom,
-      pBlock))
-   {
-      od_control.od_error = ERR_PARAMETER;
-      free(pBuffer);
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* If operating in remote mode. */
-   if(od_control.baud != 0)
-   {
-      /* Loop for each line in the buffer to be pasted */
-      for(nOutRow=nTop;nOutRow<=nBottom;++nOutRow,++nBlockRow)
-      {
-         /* Setup pointer to beginning of line of original screen contents. */
-         pchScreenBlock=(char *)pBuffer+(nRowBytes*nBlockRow);
-
-         /* Setup pointer to beginning of line of block to be displayed. */
-         pchMemBlock=(char *)pBlock+(nRowBytes*nBlockRow);
-
-         /* Loop for each column on this line. */
-         for(nOutColumn=0;nOutColumn<nRowLength;)
-         {
-            /* Loop from this character onwards, counting number of */
-            /* characters that don't need to be changed. */
-            nCheckColumn=nOutColumn;
-            pchMemory=((char *)pchMemBlock)+(nCheckColumn<<1);
-            pchTest=((char *)pchScreenBlock)+(nCheckColumn<<1);
-            for(;nCheckColumn<nRowLength;++nCheckColumn)
-            {
-               if(od_control.od_full_put) break;
-
-               /* If both buffers have space characters. */
-               if(*pchMemory==*pchTest && (*pchTest==' ' || *pchTest=='\0'))
-               {
-                  /* If colours differ, then stop comparison loop. */
-                  if((pchTest[1]&0x70) != (pchMemory[1]&0x70))
-                  {
-                     break;
-                  }
-               }
-
-               /* If both have different character and colour attributes. */
-               else if(*((int *)pchTest) != *((int *)pchMemory))
-               {
-                  /* Then stop comparison loop now. */
-                  break;
-               }
-
-               /* Increment source and background pointers by two bytes. */
-               pchTest+=2;
-               pchMemory+=2;
-            }
-
-            /* If no futher text to change on this line. */
-            if(nCheckColumn==nRowLength)
-            {
-               /* Move to the next line. */
-               goto next_line;
-            }
-
-            /* If this is the first text to be displayed on this line. */
-            if(nOutColumn == 0)
-            {
-               /* Move the cursor to the first text to be changed on line. */
-               nOutColumn = nCheckColumn;
-
-               /* If AVATAR mode is available. */
-               if(od_control.user_avatar)
-               {
-                  /* Send the avatar cursor positioning command. */
-                  szODWorkString[0]=22;
-                  szODWorkString[1]=8;
-                  szODWorkString[2]=nOutRow;
-                  szODWorkString[3]=nLeft+nOutColumn;
-                  od_disp(szODWorkString,4,FALSE);
-               }
-               else
-               {
-                  /* Otherwise, send the ANSI cursor positioning command. */
-                  sprintf(szODWorkString,"x[%d;%dH",nOutRow,nLeft + nOutColumn);
-                  szODWorkString[0]=27;
-                  od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-               }
-            }
-
-            /* If the number of characters after current cursor position  */
-            /* which must be changed, is greater than the number of       */
-            /* characters required to reposition the cursor on this line, */
-            /* then move the cursor to skip unchanged characters.         */
-            else if((nCheckColumn-nOutColumn)>nMoveCost)
-            {
-               nOutColumn=nCheckColumn;
-               /* If AVATAR mode is available. */
-               if(od_control.user_avatar)
-               {
-                  /* Advance cursor appropriate number of characters */
-                  /* using the AVATAR cursor position command.       */
-                  szODWorkString[0]=22;
-                  szODWorkString[1]=8;
-                  szODWorkString[2]=nOutRow;
-                  szODWorkString[3]=nLeft+nOutColumn;
-                  od_disp(szODWorkString,4,FALSE);
-               }
-               else
-               {
-                  /* Otherwise, advance cursor appropriate number of      */
-                  /* characters using the ANSI cursor position command.   */
-                  sprintf(szODWorkString,"x[%d;%dH",nOutRow,nLeft + nOutColumn);
-                  szODWorkString[0]=27;
-                  od_disp(szODWorkString,strlen(szODWorkString),FALSE);
-               }
-            }
-
-            /* Output text for the number of characters found to be */
-            /* different.                                           */
-            pchTest=(char *)&pchMemBlock[nOutColumn*2];
-            for(;nOutColumn<=nCheckColumn;++nOutColumn)
-            {
-               if(pchTest[1] != nOutColour)
-               {
-                  od_set_attrib(nOutColour=pchTest[1]);
-               }
-               od_disp(pchTest,1,FALSE);
-               pchTest++;
-               pchTest++;
-            }
-         }
-next_line:
-         ;
-      }
-
-      /* If not disabled, update cursor position. */
-      if(bScrollAction)
-      {
-         od_set_cursor(ODTextInfo.cury,ODTextInfo.curx);
-      }
-
-      /* Deallocate temporary buffer. */
-      free(pBuffer);
-   }
-
-   /* Restore the original display attribute. */
-   od_set_attrib(ODTextInfo.attribute);
-
-   /* Return with success. */
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_gettext()
- *
- * Retrieves text from the screen (based on what is current displayed on the
- * local display), storing it in the buffer provided by the caller.
- *
- * Parameters: nLeft   - Column number of left edge of block of text to
- *                       transfer, where 1 is the leftmost column of the
- *                       screen.
- *
- *             nTop    - Row number of the top edge of block of text to
- *                       to transfer, where 1 is the top row of the screen.
- *
- *             nRight  - Column number of the right edge of block.
- *
- *             nBottom - Row number of bottom edge of block.
- *
- *             pBlock  - Pointer to buffer large enough to hold two bytes
- *                       for each character in the block.
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_gettext(INT nLeft, INT nTop, INT nRight, INT nBottom,
-   void *pBlock)
-{
-   BYTE btMaxRight, btMaxBottom;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_gettext()");
-
-   /* Initialize OpenDoors if not already done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   ODScrnGetTextInfo(&ODTextInfo);
-
-   btMaxRight=ODTextInfo.winright-ODTextInfo.winleft+1;
-   btMaxBottom=ODTextInfo.winbottom-ODTextInfo.wintop+1;
-   if(nLeft<1 || nTop<1 || nRight>btMaxRight || nBottom>btMaxBottom || !pBlock)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   if(!od_control.user_ansi && !od_control.user_avatar)
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   OD_API_EXIT();
-   return(ODScrnGetText((BYTE)nLeft, (BYTE)nTop, (BYTE)nRight, (BYTE)nBottom,
-      pBlock));
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_scroll()
- *
- * Scrolls the specified area of the screen by the specified number of
- * lines, in either the up or down directions. The cursor is left at its
- * original locaiton, and the display attribute is left at its original
- * setting. New lines are created in the current display colour.
- *
- * Parameters: nLeft     - Column number of left edge of area to scroll, where
- *                         1 is the leftmost column of the screen.
- *
- *             nTop      - Row number of the top edge of the area to scroll,
- *                         where 1 is the top row of the screen.
- *
- *             nRight    - Column number of the right edge of area to scroll.
- *
- *             nBottom   - Row number of bottom edge of area to scroll.
- *
- *             nDistance - Number of lines to scroll the text. A value of 0
- *                         has no effect on the specified area, a positive
- *                         value moves the text upwards (leaving blank lines
- *                         at the bottom of the specified area), while a
- *                         negative value moves the text upwards. If the
- *                         distance is equal to the number of lines in the
- *                         area, then the entire area is cleared.
- *
- *             nFlags    - Bitwise-or (|) of SCROLL_* flags. SCROLL_NORMAL
- *                         is the default. SCROLL_NO_CLEAR does not clear
- *                         the new area at the top/bottom of the scroll
- *                         region if doing so would be slower.
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_scroll(INT nLeft, INT nTop, INT nRight, INT nBottom,
-   INT nDistance, WORD nFlags)
-{
-   BYTE btWidth, btHeight;
-   BYTE btCount;
-   BYTE btFirst, btLast;
-   char szAVTSeq[7];
-   void *pBlock;
-   char szBlank[81];
-   BYTE btKeepHeight;
-   BYTE btMaxRight;
-   BYTE btMaxBottom;
-   tODScrnTextInfo TextState;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_scroll()");
-
-   /* Ensure that OpenDoors has been initialized before proceeding. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Get current display setting information. */
-   ODScrnGetTextInfo(&TextState);
-
-   /* Determine the height and width of the area to be scrolled. */
-   btWidth=nRight-nLeft+1;
-   btHeight=nBottom-nTop+1;
-
-   /* Determine the number of lines currently in the area that will still */
-   /* be visible after scrolling.                                         */
-   btKeepHeight=btHeight-((nDistance>=0) ? nDistance : -nDistance);
-
-   /* Determine the maximum bottom and left coordinates of an area to be */
-   /* scrolled.                                                          */
-   btMaxRight=TextState.winright-TextState.winleft+1;
-   btMaxBottom=TextState.winbottom-TextState.wintop+1;
-
-   /* Check that parameters are valid. */
-   if(nLeft<1 || nTop<1 || nRight>btMaxRight || nBottom>btMaxBottom ||
-      nLeft > nRight || nTop > nBottom)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Check that ANSI or AVATAR graphics mode is available. */
-   if(!od_control.user_ansi && !od_control.user_avatar)
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* If distance to be scrolled is 0, then we are finished already and */
-   /* can return immediately.                                           */
-   if(nDistance == 0)
-   {
-      OD_API_EXIT();
-      return(TRUE);
-   }
-
-   /* If distance is positive, then we are moving text upwards. */
-   if(nDistance>0)
-   {
-      /* Ensure that distance is not greater than size of scrolled area. */
-      if(nDistance>btHeight)
-      {
-         nDistance=btHeight;
-      }
-
-      /* Calculate first and last line to be moved. */
-      btFirst=nBottom-(nDistance-1);
-      btLast=nBottom;
-   }
-
-   /* If distance is negative, then we are moving text downwards. */
-   else /* if(nDistance<0) */
-   {
-      /* Ensure that distance is not greater than size of scrolled area. */
-      if(nDistance<-btHeight)
-      {
-         nDistance=-btHeight;
-      }
-
-      /* Calculate first and last line to be moved. */
-      btFirst=nTop;
-      btLast=nTop-nDistance-1;
-   }
-
-   /* If AVATAR mode is available */
-   if(od_control.user_avatar)
-   {
-      /* Generate AVATAR sequence which causes the remote terminal to */
-      /* scroll an area of its screen.                                */
-      szAVTSeq[0]=22;
-
-      /* If scrolling text upwards. */
-      if(nDistance>0)
-      {
-         /* Specify control sequence for scrolling upwards. */
-         szAVTSeq[1]=10;
-         szAVTSeq[2]=nDistance;
-
-         /* Move text appropriate direction on local screen. */
-         ODScrnCopyText((BYTE)nLeft, (BYTE)(nTop + nDistance), (BYTE)nRight,
-            (BYTE)nBottom, (BYTE)nLeft, (BYTE)nTop);
-      }
-      /* If scrolling text downwards. */
-      else /* if(disatnce<0) */
-      {
-         /* Specify control sequence for scrolling downwards. */
-         szAVTSeq[1]=11;
-         szAVTSeq[2]=-nDistance;
-
-         /* Move text appropriate direction on local screen. */
-         ODScrnCopyText((BYTE)nLeft, (BYTE)nTop, (BYTE)nRight,
-            (BYTE)(nBottom + nDistance), (BYTE)nLeft, (BYTE)(nTop - nDistance));
-      }
-
-      /* Specify area to be scrolled to the AVATAR terminal. */
-      szAVTSeq[3]=nTop;
-      szAVTSeq[4]=nLeft;
-      szAVTSeq[5]=nBottom;
-      szAVTSeq[6]=nRight;
-
-      /* Send the control sequence to the AVATAR terminal. */
-      od_disp(szAVTSeq,7,FALSE);
-
-      /* Generate string containing a blank line of text. */
-      for(btCount=0;btCount<btWidth;++btCount) szBlank[btCount]=' ';
-      szBlank[btCount]='\0';
-
-      /* Blank-out lines that will no longer be visiable. */
-      for(;btFirst<=btLast;++btFirst)
-      {
-         ODScrnSetCursorPos((BYTE)nLeft, btFirst);
-         ODScrnDisplayString(szBlank);
-      }
-
-      /* Reset cursor position on local display. */
-      ODScrnSetCursorPos(TextState.curx,TextState.cury);
-   }
-
-   /* Otherwise, we are using ANSI mode. */
-   else /* if(od_control.user_ansi) */
-   {
-      /* If any of the original text will still be available after */
-      /* scrolling.                                                */
-      if(btKeepHeight>0)
-      {
-         /* Allocate some temporary memory to hold text to be "got". */
-         if((pBlock=malloc(btKeepHeight*btWidth*2))==NULL)
-         {
-            /* If memory allocation failed, then scrolling fails. */
-            od_control.od_error = ERR_MEMORY;
-            OD_API_EXIT();
-            return(FALSE);
-         }
-
-         /* If we are scrolling text upwards. */
-         if(nDistance > 0)
-         {
-            /* Move text that will still be visible, using od_gettext() */
-            /* and od_puttext().                                        */
-            od_gettext(nLeft,nTop+nDistance,nRight,nBottom,pBlock);
-            bScrollAction=FALSE;
-            od_puttext(nLeft,nTop,nRight,nBottom-nDistance,pBlock);
-            bScrollAction=TRUE;
-         }
-
-         /* If we are scrolling text downwards. */
-         else /* if(nDistance < 0) */
-         {
-            /* Move text that will still be visible, using od_gettext() */
-            /* and od_puttext().                                        */
-            od_gettext(nLeft,nTop,nRight,nBottom+nDistance,pBlock);
-            bScrollAction=FALSE;
-            od_puttext(nLeft,nTop-nDistance,nRight,nBottom,pBlock);
-            bScrollAction=TRUE;
-         }
-
-         /* Deallocate temporary memory block. */
-         free(pBlock);
-      }
-
-      /* If new area clearing has not been disabled. */
-      if(!(nFlags&SCROLL_NO_CLEAR))
-      {
-         /* Loop for lines that should be blank. */
-         for(;btFirst<=btLast;++btFirst)
-         {
-            /* Move cursor to the beginning of this line. */
-            od_set_cursor(btFirst,nLeft);
-
-            /* If right boarder of area to be scrolled is the edge of the */
-            /* screen, then we can use a quick control sequence to clear  */
-            /* the rest of the line. Call od_clr_line() to do this.       */
-            if(nRight == 80)
-            {
-               od_clr_line();
-            }
-
-            /* If right boarder of area to be scrolled is not at the edge */
-            /* of the screen, then each line must be manually erased, by  */
-            /* sending the appropriate number of blanks (spaces).         */
-            else /* if(right != 80) */
-            {
-               od_repeat(' ',btWidth);
-            }
-         }
-      }
-
-      /* Reset the cursor to its original position. */
-      od_set_cursor(TextState.cury,TextState.curx);
-   }
-
-   /* Return with success */
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_save_screen()
- *
- * Stores the contents of the entire screen into a buffer, along with
- * the current cursor location and display colour. Supports all display
- * modes.
- *
- * Parameters: pBuffer - Pointer to a buffer of at least 4004 bytes in size,
- *                       where the information on the current screen state
- *                       will be stored.
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_save_screen(void *pBuffer)
-{
-   char btHeight;
-   tODScrnTextInfo TextState;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_save_screen()");
-
-   /* Ensure that OpenDoors is initialized before proceeding. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check parameters and current output window size. */
-   ODScrnGetTextInfo(&TextState);
-   if(TextState.winleft!=1 || TextState.winright!=80 || !pBuffer)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Store current cursor location in buffer. */
-   ((char *)pBuffer)[0]=TextState.curx;
-   ((char *)pBuffer)[1]=TextState.cury;
-
-   /* Store current display colour in buffer. */
-   ((char *)pBuffer)[2]=TextState.attribute;
-
-   /* Store height of buffer stored. */
-   ((char *)pBuffer)[3]=btHeight=TextState.winbottom-TextState.wintop+1;
-
-   /* Store screen contents using local screen gettext() function. */
-   OD_API_EXIT();
-   return(ODScrnGetText(1,1,80,btHeight,(char *)pBuffer+4));
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_restore_screen()
- *
- * Restores the screen contents, along with the current text colour and cursor
- * location, as previously stored by od_save_screen().
- *
- * Parameters: pBuffer - Pointer to buffer which was filled by a previous call
- *                       to od_save_screen().
- *
- *     Return: TRUE on success, FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_restore_screen(void *pBuffer)
-{
-   char *pch;
-   char btPos;
-   char chLast;
-   char *pchTextBuffer;
-   char btHeight;
-   int nToReturn=TRUE;
-   tODScrnTextInfo TextState;
-   char btLine;
-   char btDistance=0;
-   char btCursorRow;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_restore_screen()");
-
-   /* Ensure that OpenDoors is initialized before proceeding. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check parameters and current output window size. */
-   ODScrnGetTextInfo(&TextState);
-   if(TextState.winleft!=1 || TextState.winright!=80 || !pBuffer)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Determine current window height were text will be restored. */
-   btHeight=TextState.winbottom-TextState.wintop+1;
-
-   /* If current display window height is too small for entire buffer */
-   /* to be re-displayed.                                             */
-   if(btHeight<((char *)pBuffer)[3])
-   {
-      /* Then we will always display as much of the END of the buffer */
-      /* as possible.                                                 */
-      btDistance = btHeight - ((char *)pBuffer)[3];
-   }
-   else if(btHeight > ((char *)pBuffer)[3])
-   {
-      /* Otherwise, ensure that we don't try to display more lines that */
-      /* are in the buffer.                                             */
-      btHeight=((char *)pBuffer)[3];
-   }
-
-   /* Clear the remote and local screens. */
-   od_clr_scr();
-
-   /* If ANSI or AVATAR modes are available. */
-   if(od_control.user_avatar || od_control.user_ansi)
-   {
-      /* Then we can efficiently display the buffer using od_puttext(). */
-      bScrollAction=FALSE;
-      nToReturn=od_puttext(1,1,80,btHeight,(char *)pBuffer+(4+((int)btDistance*160)));
-      bScrollAction=TRUE;
-
-      /* Restore original cursor location. */
-      od_set_cursor(((char *)pBuffer)[1],((char *)pBuffer)[0]);
-
-      /* Restore original display attribute. */
-      od_set_attrib(((char *)pBuffer)[2]);
-   }
-
-   /* If we are operating in ASCII mode. */
-   else /* if (!od_control.od_avatar && !od_control.caller_ansi) */
-   {
-      /* Then the buffer is displayed one line at a time, beginning  */
-      /* at the top of the screen, up to the saved cusrsor location. */
-
-      /* Set pointer to beginning of buffer to be displayed. */
-      pchTextBuffer=(char *)pBuffer+4;
-
-      /* Get final cursor row number. */
-      btCursorRow=((char *)pBuffer)[1];
-
-      /* Loop for each line in the buffer. */
-      for(btLine=1;btLine<=btHeight;++btLine)
-      {
-         /* Set pointer to last character of line. */
-         pch=(char *)pchTextBuffer+158;
-
-         /* Loop backwards until a non-blank character is found, or we */
-         /* reach the beginning of the line.                           */
-         for(chLast=80;chLast>1;)
-         {
-            /* If this is a blank character. */
-            if(*pch==32 || *pch==0)
-            {
-               /* Move to previous character. */
-               --chLast;
-               pch-=2;
-            }
-
-            /* If this is not a blank character, then stop looping. */
-            else
-            {
-               break;
-            }
-         }
-
-         /* If this is the line on which the cursor resides. */
-         if(btLine==btCursorRow)
-         {
-            /* If last non-blank character of line is at or past the final */
-            /* cursor location, then we backup the last character to be    */
-            /* displayed to the cursor before the final cursor position.   */
-            /* This code could be improved to be able to display text on   */
-            /* the entire cursor line by displaying the entire line,       */
-            /* sending a C/R, and redisplaying first portion of line to    */
-            /* end up with the cursor in the desired position.             */
-            if(chLast>=((char *)pBuffer)[0])
-            {
-               chLast=((char *)pBuffer)[0]-1;
-            }
-         }
-
-         /* Display all characters on this line */
-         pch = (char *)pchTextBuffer;
-         for(btPos=1;btPos<=chLast;++btPos)
-         {
-            od_putch(*pch);
-            pch+=2;
-         }
-
-         /* If this is the row where the cursor should be left, then we */
-         /* stop displaying now.                                        */
-         if(btLine==btCursorRow)
-         {
-            break;
-         }
-
-         /* If cursor hasn't been wrapped, then we should send a C/R - */
-         /* L/F sequence.                                              */
-         if(chLast != 80)
-         {
-            od_disp_str("\n\r");
-            pchTextBuffer+=160;
-         }
-      }
-   }
-
-   /* Return with the appropriate success/failure status. */
-   OD_API_EXIT();
-   return(nToReturn);
-}
diff --git a/src/odoors/ODCFile.c b/src/odoors/ODCFile.c
deleted file mode 100644
index 2f5a793874ccc65a59f6a74008671b6c82a8a370..0000000000000000000000000000000000000000
--- a/src/odoors/ODCFile.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCFile.c
- *
- * Description: Implements the configuration file sub-system.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Nov 11, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 01, 1996  6.00  BP   Added DisableDTR and NoDTRDisable.
- *              Jan 19, 1996  6.00  BP   Display error if config file not found
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODInEx.h"
-#include "ODUtil.h"
-
-
-/* Internal private variables */
-static WORD awTimeVal[3];
-static BYTE btTimeNumVals;
-
-
-/* Local functions. */
-static WORD ODCfgGetWordDecimal(char *pszConfigText);
-static DWORD ODCfgGetDWordDecimal(char *pszConfigText);
-static WORD ODCfgGetWordHex(char *pszConfigText);
-static void ODCfgGetNextTime(char **ppchConfigText);
-static BOOL ODCfgIsTrue(char *pszConfigText);
-
-
-/* ----------------------------------------------------------------------------
- * ODConfigInit()
- *
- * Called to perform OpenDoors initialization when the configuration file
- * system is being used. This function is called from the normal od_init(),
- * and also uses the normal od_init() to perform base initialization after
- * the configuration file has been read, but before certain configuration
- * settings are set in od_control.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL ODConfigInit(void)
-{
-   void (*custom_line_function)(char *keyword, char *options)
-      = od_control.config_function;
-   char *pchConfigText;
-   WORD wCurrent;
-   INT nConfigOption;
-   BOOL bConfigFileRequired = TRUE;
-   static FILE *pfConfigFile;
-   static FILE *pfCustomDropFile = NULL;
-   static char szConfigLine[257];
-   static char szToken[33];
-   static char szTempString[256];
-   static char szWorkDir[80];
-   static BOOL bWorkDirSet = FALSE;
-   static time_t nUnixTime;
-   static struct tm *TimeBlock;
-   static INT16 nPageStart;
-   static INT16 nPageEnd;
-   static BOOL bPageSet = FALSE;
-   static BOOL bInactivitySet = FALSE;
-   static INT16 nInactivity;
-   static char *pszWork;
-   static BOOL bPageLengthSet = FALSE;
-   static BYTE btPageLength;
-   static char *apszFileNames[1];
-
-   bIsCallbackActive = TRUE;
-
-   nUnixTime = time(NULL);
-   TimeBlock = localtime(&nUnixTime);
-
-   /* Use default configuration file filename if none has been specified. */
-   if(od_control.od_config_filename == NULL)
-   {
-      od_control.od_config_filename = "door.cfg";
-      bConfigFileRequired = FALSE;
-   }
-
-   if((pfConfigFile = fopen(od_control.od_config_filename, "rt")) == NULL)
-   {
-      if(strchr(od_control.od_config_filename, '\\') != NULL
-         || strchr(od_control.od_config_filename, ':') != NULL)
-      {
-         wCurrent = strlen(od_control.od_config_filename);
-         pchConfigText = (char *)od_control.od_config_filename + (wCurrent - 1);
-         while(wCurrent > 0)
-         {
-            if(*pchConfigText == '\\' || *pchConfigText == ':')
-            {
-               strcpy(szConfigLine, (char *)pchConfigText + 1);
-               pfConfigFile = fopen(szConfigLine, "rt");
-               break;
-            }
-
-            --pchConfigText;
-            --wCurrent;
-         }
-      }
-      else
-      {
-         strcpy(szConfigLine, od_control.od_config_filename);
-      }
-   }
-
-   /* If we were able to open the configuration file. */
-   if(pfConfigFile != NULL)
-   {
-      /* Get configuration file strings in upper case. */
-      for(wCurrent = 0; wCurrent < TEXT_SIZE; ++wCurrent)
-      {
-         strupr(od_config_text[wCurrent]);
-      }
-      for(wCurrent = 0; wCurrent < LINES_SIZE; ++wCurrent)
-      {
-         strupr(od_config_lines[wCurrent]);
-      }
-
-      for(;;)
-      {
-         /* Read the next line from the configuration file. */
-         if(fgets(szConfigLine, 257, pfConfigFile) == NULL) break;
-
-         /* Ignore all of line after comments or CR/LF char. */
-         pchConfigText = (char *)szConfigLine;
-         while(*pchConfigText)
-         {
-            if(*pchConfigText == '\n' || *pchConfigText == '\r'
-               || *pchConfigText == ';')
-            {
-               *pchConfigText = '\0';
-               break;
-            }
-            ++pchConfigText;
-         }
-
-         /* Search for beginning of first token on line. */
-         pchConfigText = (char *)szConfigLine;
-         while(*pchConfigText
-            && (*pchConfigText == ' ' || *pchConfigText == '\t'))
-         {
-            ++pchConfigText;
-         }
-         if(!*pchConfigText) continue;
-
-         /* Get first token from line. */
-         wCurrent = 0;
-         while(*pchConfigText
-            && !(*pchConfigText == ' ' || *pchConfigText == '\t'))
-         {
-            if(wCurrent < 32) szToken[wCurrent++] = *pchConfigText;
-            ++pchConfigText;
-         }
-         if(wCurrent <= 32)
-         {
-            szToken[wCurrent] = '\0';
-         }
-         else
-         {
-            szToken[32] = '\0';
-         }
-         strupr(szToken);
-
-         /* Find beginning of configuration option parameters */
-         while(*pchConfigText && (*pchConfigText == ' '
-            || *pchConfigText == '\t'))
-         {
-            ++pchConfigText;
-         }
-
-         /* Trim trailing spaces from setting string. */
-         for(wCurrent = strlen(pchConfigText) - 1; wCurrent > 0; --wCurrent)
-         {
-            if(pchConfigText[wCurrent] == ' '
-               || pchConfigText[wCurrent] == '\t')
-            {
-               pchConfigText[wCurrent] = '\0';
-            }
-            else
-            {
-               break;
-            }
-         }
-
-
-         for(wCurrent = 0; wCurrent < TEXT_SIZE; ++wCurrent)
-         {
-            if(strcmp(szToken, od_config_text[wCurrent]) == 0)
-            {
-               switch(wCurrent)
-               {
-                  case 0:
-                     wODNodeNumber = ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 1:
-                     strcpy(od_control.info_path,pchConfigText);
-                     break;
-
-                  case 2:
-                     if(pchConfigText[strlen(pchConfigText) - 1] == '\\'
-                        && pchConfigText[strlen(pchConfigText) - 2] != ':'
-                        && strlen(pchConfigText) > 1)
-                     {
-                        pchConfigText[strlen(pchConfigText) - 1] = '\0';
-                     }
-
-                     szOriginalDir = (char *)malloc(256);
-                     if(szOriginalDir != NULL)
-                     {
-                        ODDirGetCurrent(szOriginalDir, 256);
-                     }
-
-                     strcpy(szWorkDir, pchConfigText);
-                     bWorkDirSet = TRUE;
-                     break;
-
-                  case 3:
-                     strcpy(od_control.od_logfile_name, pchConfigText);
-                     break;
-
-                  case 4:
-                     od_control.od_logfile_disable = TRUE;
-                     break;
-
-                  case 5:
-                  case 6:
-                  case 7:
-                  case 8:
-                  case 9:
-                  case 10:
-                  case 11:
-                      if((wCurrent - 5) == (WORD)TimeBlock->tm_wday)
-                      {
-                         ODCfgGetNextTime((char **)&pchConfigText);
-                         nPageStart = awTimeVal[0] * 60 + awTimeVal[1];
-                         ODCfgGetNextTime((char **)&pchConfigText);
-                         nPageEnd = awTimeVal[0] * 60 + awTimeVal[1];
-                         bPageSet = TRUE;
-                      }
-                     break;
-
-                  case 12:
-                     od_control.od_maxtime = ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 13:
-                     bSysopNameSet = TRUE;
-                     strncpy((char *)&szForcedSysopName, pchConfigText, 39);
-                     szForcedSysopName[39] = '\0';
-                     break;
-
-                  case 14:
-                     bSystemNameSet = TRUE;
-                     strncpy((char *)&szForcedSystemName, pchConfigText, 39);
-                     szForcedSystemName[39] = '\0';
-                     break;
-
-                  case 15:
-                     od_control.od_swapping_disable = TRUE;
-                     break;
-
-                  case 16:
-                     strncpy(od_control.od_swapping_path, pchConfigText, 79);
-                     od_control.od_swapping_path[79] = '\0';
-                     break;
-
-                  case 17:
-                     od_control.od_swapping_noems = TRUE;
-                     break;
-
-                  case 18:
-                     dwForcedBPS = ODCfgGetDWordDecimal(pchConfigText);
-                     break;
-
-                  case 19:
-                     nForcedPort = ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 20:
-                     if(pfCustomDropFile == NULL && !od_control.od_force_local)
-                     {
-                        apszFileNames[0] = (char *)pchConfigText;
-                        if(ODSearchForDropFile(apszFileNames, 1, szTempString,
-                           NULL) != -1)
-                        {
-                           if((pfCustomDropFile = fopen(szTempString, "rt"))
-                              != NULL)
-                           {
-                              od_control.od_info_type = CUSTOM;
-                              od_control.user_attribute = 0x06;
-                              od_control.user_screen_length = 23;
-                              od_control.user_ansi = TRUE;
-                              od_control.user_rip = FALSE;
-                              od_control.user_avatar = FALSE;
-                              od_control.od_page_pausing = TRUE;
-                              od_control.od_page_len = 15;
-                              od_control.user_timelimit = 0;
-                              strcpy(od_control.user_name, "Unknown User");
-                              strcpy(od_control.user_location,
-                                 "Unknown Location");
-                              od_control.user_security = 1;
-                           }
-                        }
-                     }
-                     break;
-
-                  case 21:
-                     if(pfCustomDropFile != NULL)
-                     {
-                        if(fgets(szTempString, 255, pfCustomDropFile)!=NULL)
-                        {
-                           if(szTempString[strlen(szTempString) - 1] == '\n')
-                           {
-                              szTempString[strlen(szTempString) - 1] = '\0';
-                           }
-                           else
-                           {
-                              INT ch;
-                              do
-                              {
-                                 ch = fgetc(pfCustomDropFile);
-                              } while(ch != '\n' && ch != EOF);
-                           }
-
-                           strupr(pchConfigText);
-
-                           for(nConfigOption = 0; nConfigOption < LINES_SIZE;
-                              ++nConfigOption)
-                           {
-                              if(strcmp(pchConfigText,
-                                 od_config_lines[nConfigOption]) == 0)
-                              {
-                                 switch(nConfigOption)
-                                 {
-                                    case 1:
-                                       od_control.port =
-                                          ODCfgGetWordDecimal(szTempString) - 1;
-                                       break;
-
-                                    case 2:
-                                       od_control.port =
-                                          ODCfgGetWordDecimal(szTempString);
-                                       break;
-
-                                    case 3:
-                                       od_control.baud =
-                                          ODCfgGetWordDecimal(szTempString);
-                                       break;
-
-                                    case 4:
-                                       if(ODCfgIsTrue(szTempString))
-                                       {
-                                          od_control.baud = 0;
-                                       }
-                                       break;
-
-                                    case 5:
-                                    case 6:
-                                       ODStringToName(szTempString);
-                                       strncpy(od_control.user_name,
-                                          szTempString, 34);
-                                       od_control.user_name[34] = '\0';
-                                       break;
-
-                                    case 7:
-                                       strcat(od_control.user_name, " ");
-                                       ODStringToName(szTempString);
-                                       strncat(od_control.user_name,
-                                          szTempString,
-                                          35 - strlen(od_control.user_name));
-                                       od_control.user_name[35] = '\0';
-                                       break;
-
-                                    case 8:
-                                       ODStringToName(szTempString);
-                                       strncpy(od_control.user_handle,
-                                          szTempString, 35);
-                                       od_control.user_handle[35] = '\0';
-                                       break;
-
-                                    case 9:
-                                       pszWork = (char *)szTempString;
-                                       ODCfgGetNextTime((char **)&pszWork);
-                                       od_control.user_timelimit += 
-                                          (awTimeVal[0] * 60);
-                                       break;
-
-                                    case 10:
-                                       pszWork = (char *)szTempString;
-                                       ODCfgGetNextTime((char **)&pszWork);
-                                       if(btTimeNumVals <= 1)
-                                       {
-                                          od_control.user_timelimit +=
-                                             awTimeVal[0];
-                                       }
-                                       else
-                                       {
-                                          od_control.user_timelimit +=
-                                             awTimeVal[1] + (awTimeVal[0] * 60);
-                                       }
-                                       break;
-
-                                    case 11:
-                                       pszWork = (char *)szTempString;
-                                       ODCfgGetNextTime((char **)&pszWork);
-                                       if(btTimeNumVals <= 1)
-                                       {
-                                          od_control.user_timelimit +=
-                                             awTimeVal[0] / 60;
-                                       }
-                                       else if(btTimeNumVals == 2)
-                                       {
-                                          od_control.user_timelimit +=
-                                             (awTimeVal[1] / 60) + awTimeVal[0];
-                                       }
-                                       else
-                                       {
-                                          od_control.user_timelimit +=
-                                             (awTimeVal[2] / 60) + awTimeVal[1]
-                                             + (awTimeVal[0] * 60);
-                                       }
-                                       break;
-
-                                    case 12:
-                                       od_control.user_ansi =
-                                          ODCfgIsTrue(szTempString);
-                                       break;
-
-                                    case 13:
-                                       od_control.user_avatar =
-                                          ODCfgIsTrue(szTempString);
-                                       break;
-
-                                    case 14:
-                                       od_control.od_page_pausing =
-                                          ODCfgIsTrue(szTempString);
-                                       break;
-
-                                    case 15:
-                                       od_control.user_screen_length =
-                                          ODCfgGetWordDecimal(szTempString);
-                                       break;
-
-                                    case 16:
-                                       if(ODCfgIsTrue(szTempString))
-                                        {
-                                           od_control.user_attribute |= 0x02;
-                                        }
-                                       else
-                                        {
-                                           od_control.user_attribute &=~ 0x02;
-                                        }
-                                       break;
-
-                                    case 17:
-                                       od_control.user_security =
-                                          ODCfgGetWordDecimal(szTempString);
-                                       break;
-
-                                    case 18:
-                                       ODStringToName(szTempString);
-                                       strncpy(od_control.user_location,
-                                          szTempString, 25);
-                                       od_control.user_location[25] = '\0';
-                                       break;
-
-                                    case 19:
-                                       wODNodeNumber =
-                                          ODCfgGetWordDecimal(szTempString);
-                                       break;
-
-                                    case 20:
-                                    case 21:
-                                       ODStringToName(szTempString);
-                                       strncpy(od_control.sysop_name,
-                                          szTempString, 38);
-                                       od_control.sysop_name[38] = '\0';
-                                       break;
-
-                                    case 22:
-                                       strcat(od_control.sysop_name, " ");
-                                       ODStringToName(szTempString);
-                                       strncat(od_control.sysop_name,
-                                          szTempString,
-                                          39 - strlen(od_control.system_name));
-                                       od_control.sysop_name[39] = '\0';
-                                       break;
-
-                                    case 23:
-                                       strncpy(od_control.system_name,
-                                          szTempString, 39);
-                                       od_control.system_name[39] = '\0';
-                                       break;
-
-                                    case 24:
-                                       od_control.user_rip =
-                                          ODCfgIsTrue(szTempString);
-                                 }
-                              }
-                           }
-                        }
-                     }
-                     break;
-
-                  case 22:
-                     bInactivitySet = TRUE;
-                     nInactivity = ODCfgGetWordDecimal(pchConfigText);
-                     if(nInactivity < 0) nInactivity = 0;
-                     break;
-
-                  case 23:
-                     btPageLength = (BYTE)ODCfgGetWordDecimal(pchConfigText);
-                     bPageLengthSet = TRUE;
-                     break;
-
-                  case 24:
-                     od_control.od_chat_color2 = 
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 25:
-                     od_control.od_chat_color1 =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 26:
-                     od_control.od_list_title_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 27:
-                     od_control.od_list_name_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 28:
-                     od_control.od_list_size_col = 
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 29:
-                     od_control.od_list_comment_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 30:
-                     od_control.od_list_offline_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 31:
-                     strncpy(szDesiredPersonality, pchConfigText, 32);
-                     szDesiredPersonality[32] = '\0';
-                     break;
-
-                  case 32:
-                     /* "NoFossil" */
-                     od_control.od_no_fossil = TRUE;
-                     break;
-
-                  case 33:
-                     /* "PortAddress" */
-                     od_control.od_com_address = ODCfgGetWordHex(pchConfigText);
-                     break;
-
-                  case 34:
-                     /* "PortIRQ" */
-                     od_control.od_com_irq =
-                        (char)ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 35:
-                     /* "ReceiveBuffer" */
-                     od_control.od_com_rx_buf =
-                        ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 36:
-                     /* "TransmitBuffer" */
-                     od_control.od_com_tx_buf =
-                        ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 37:
-                     /* "PagePromptColour" */
-                     od_control.od_continue_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 38:
-                     /* "LocalMode" */
-                     od_control.od_force_local = TRUE;
-                     break;
-
-                  case 39:
-                     /* "PopupMenuTitleColour" */
-                     od_control.od_menu_title_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 40:
-                     /* "PopupMenuBorderColour" */
-                     od_control.od_menu_border_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 41:
-                     /* "PopupMenuTextColour" */
-                     od_control.od_menu_text_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 42:
-                     /* "PopupMenuKeyColour" */
-                     od_control.od_menu_key_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 43:
-                     /* "PopupMenuHighlightColour" */
-                     od_control.od_menu_highlight_col =
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 44:
-                     /* "PopupMenuHighKeyColour" */
-                     od_control.od_menu_highkey_col = 
-                        od_color_config(pchConfigText);
-                     break;
-
-                  case 45:
-                     /* "NoFIFO" */
-                     od_control.od_com_no_fifo = TRUE;
-                     break;
-
-                  case 46:
-                     /* "FIFOTriggerSize" */
-                     od_control.od_com_fifo_trigger =
-                        (BYTE)ODCfgGetWordDecimal(pchConfigText);
-                     break;
-
-                  case 47:
-                     /* "DisableDTR" */
-                     ODStringCopy(od_control.od_disable_dtr, pchConfigText,
-                        sizeof(od_control.od_disable_dtr));
-                     break;
-
-                  case 48:
-                     /* "NoDTRDisable" */
-                     od_control.od_disable |= DIS_DTR_DISABLE;
-                     break;
-               }
-            }
-         }
-
-         /* Check if command is a programmer customized option. */
-         if(wCurrent >= TEXT_SIZE && custom_line_function != NULL)
-         {
-            (*custom_line_function)((char *)&szToken, pchConfigText);
-         }
-      }
-
-      /* Close the configuration file. */
-      fclose(pfConfigFile);}
-   else
-   {
-      if(bConfigFileRequired)
-      {
-         od_control.od_error = ERR_FILEOPEN;
-         ODInitError("Unable to access configuration file.");
-         exit(od_control.od_errorlevel[1]);
-      }
-   }
-
-   /* Close custom door info file */
-   if(pfCustomDropFile != NULL)
-   {
-      fclose(pfCustomDropFile);
-   }
-
-   bIsCallbackActive = FALSE;
-
-   /* Carry out normal OpenDoors initialization. */
-   bCalledFromConfig = TRUE;
-   od_init();
-   bCalledFromConfig = FALSE;
-
-   /* Update any settings that need to be updated. */
-   if(bPageSet)
-   {
-      od_control.od_pagestartmin = nPageStart;
-      od_control.od_pageendmin = nPageEnd;
-   }
-
-   if(bInactivitySet && nInactivity != 0)
-   {
-      od_control.od_inactivity = nInactivity;
-   }
-
-   if(bSysopNameSet)
-   {
-      strcpy((char *)&od_control.sysop_name, (char *)&szForcedSysopName);
-   }
-
-   if(bSystemNameSet)
-   {
-      strcpy((char *)&od_control.system_name, (char *)&szForcedSystemName);
-   }
-
-   if(bPageLengthSet)
-   {
-      od_control.od_page_len = btPageLength;
-   }
-
-   if(bWorkDirSet)
-   {
-      ODDirChangeCurrent(szWorkDir);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODCfgGetWordDecimal()                               *** PRIVATE FUNCTION ***
- *
- * Obtains the value of the next decimal number in the provided string, in the
- * form of a WORD (16 bit value).
- *
- * Parameters: pszConfigText - String to examine.
- *
- *     Return: The first number obtained from the string.
- */
-static WORD ODCfgGetWordDecimal(char *pszConfigText)
-{
-   ASSERT(pszConfigText != NULL);
-
-   /* Skip any initial non-numerical characters. */
-   while(*pszConfigText && (*pszConfigText < '0' || *pszConfigText > '9'))
-   {
-      ++pszConfigText;
-   }
-
-   /* Return value of number. */
-   return(atoi(pszConfigText));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODCfgGetDWordDecimal()                              *** PRIVATE FUNCTION ***
- *
- * Obtains the value of the next decimal number in the provided string, in the
- * form of a DWORD (32 bit value).
- *
- * Parameters: pszConfigText - String to examine.
- *
- *     Return: The first number obtained from the string.
- */
-static DWORD ODCfgGetDWordDecimal(char *pszConfigText)
-{                                
-   ASSERT(pszConfigText != NULL);
-
-   /* Skip any initial non-numerical characters. */
-   while(*pszConfigText && (*pszConfigText < '0' || *pszConfigText > '9'))
-   {
-      ++pszConfigText;
-   }
-
-   /* Return value of number. */
-   return(atol(pszConfigText));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODCfgGetWordHex()                                   *** PRIVATE FUNCTION ***
- *
- * Obtains the value of the next hexidecimal number in the provided string, in
- * the form of a WORD (16 bit value).
- *
- * Parameters: pszConfigText - String to examine.
- *
- *     Return: The first number obtained from the string.
- */
-static WORD ODCfgGetWordHex(char *pszConfigText)
-{
-   WORD wToReturn;
-
-   ASSERT(pszConfigText != NULL);
-
-   /* Skip any initial non-hexidecimal characters. */
-   while(*pszConfigText && (*pszConfigText < '0' || *pszConfigText > '9')
-      && (toupper(*pszConfigText) < 'A' || toupper(*pszConfigText) > 'F'))
-   {
-      ++pszConfigText;
-   }
-
-   sscanf(pszConfigText, "%x", &wToReturn);
-
-   return(wToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODCfgGetNextTime()                                  *** PRIVATE FUNCTION ***
- *
- * Obtains the next time from a string, updating the string pointer to point to
- * the position in the string after the end of the time. The time information
- * is stored in the btTimeNumVals and awTimeVal private global variables.
- *
- * Parameters: ppchConfigText - Pointer to character pointer to the string,
- *                              which is to be updated.
- *
- *     Return: void
- */
-static void ODCfgGetNextTime(char **ppchConfigText)
-{
-   char *pchConfigText = (char *)(*ppchConfigText);
-
-   ASSERT(ppchConfigText != NULL);
-   ASSERT(*ppchConfigText != NULL);
-
-   btTimeNumVals = 0;
-   awTimeVal[0] = 0;
-   awTimeVal[1] = 0;
-   awTimeVal[2] = 0;
-
-
-   while(*pchConfigText && (*pchConfigText == ' ' || *pchConfigText == '\t'))
-   {
-      ++pchConfigText;
-   }
-
-
-   while(*pchConfigText && btTimeNumVals < 3)
-   {
-      if(*pchConfigText < '0' || *pchConfigText > '9') break;
-      awTimeVal[btTimeNumVals++] = atoi(pchConfigText);
-      while(*pchConfigText && *pchConfigText >= '0' && *pchConfigText <= '9')
-      {
-         ++pchConfigText;
-      }
-      if(*pchConfigText == ':' || *pchConfigText == '.' || *pchConfigText == ','
-         || *pchConfigText == ';')
-      {
-         ++pchConfigText;
-      }
-   }
-
-   *ppchConfigText = (char *)pchConfigText;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODCfgIsTrue()                                       *** PRIVATE FUNCTION ***
- *
- * Determines whether the specified string represents a TRUE or FALSE value.
- * For example "Yes", "TRUE", "Y" and "1" all represent TRUE values, while
- * "No", "FALSE", "N" and "0" all represent FALSE values.
- *
- * Parameters: pszConfigText - String to examine.
- *
- *     Return: The Boolean value represented by the string.
- */
-static BOOL ODCfgIsTrue(char *pszConfigText)
-{
-   ASSERT(pszConfigText != NULL);
-
-   while(*pszConfigText && (*pszConfigText == ' ' || *pszConfigText == '\t'))
-   {
-      ++pszConfigText;
-   }
-
-   switch(*pszConfigText)
-   {
-      case '1':
-      case 't':
-      case 'T':
-      case 'y':
-      case 'Y':
-      case 'g':
-      case 'G':
-         return(TRUE);
-   }
-
-   return(FALSE);
-}
diff --git a/src/odoors/ODCmdLn.c b/src/odoors/ODCmdLn.c
deleted file mode 100644
index 7ce22c9430037368c36f51d19b9a131516378eed..0000000000000000000000000000000000000000
--- a/src/odoors/ODCmdLn.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCmdLn.c
- *
- * Description: Implementation of od_parse_cmd_line() function, which
- *              parses standard command-line parameters for OpenDors programs.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Jan 29, 1995  6.00  BP   Created.
- *              Aug 19, 1995  6.00  BP   Cleaned up indentations.
- *              Nov 12, 1995  6.00  BP   32-bit portability.
- *              Nov 12, 1995  6.00  BP   Added -CONFIG parameter.
- *              Dec 21, 1995  6.00  BP   Added -HANDLE parameter.
- *              Dec 24, 1995  6.00  BP   puts() -> printf().
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Recognize -D for -DROPFILE.
- *              Jan 03, 1996  6.00  BP   Parameters must begin with - or /.
- *              Feb 06, 1996  6.00  BP   Added -SILENT for od_silent_mode.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 20, 1996  6.00  BP   Added bParsedCmdLine.
- *              Feb 21, 1996  6.00  BP   Make cmd line options overriding.
- *              Feb 25, 1996  6.00  BP   Fix -P COMx.
- *              Feb 27, 1996  6.00  BP   Add -P COMx to command line help.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Apr 08, 1996  6.10  BP   Added command-line parsing callbacks.
- *					 Apr 24, 2002  6.22  RS   Added -SOCKET parameter.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#include "OpenDoor.h"
-#include "ODPlat.h"
-#include "ODCore.h"
-#include "ODInEx.h"
-
-
-/* Maximum number of command-line arguments. Any additional arguments will */
-/* simply be ignored.                                                      */
-#define MAX_ARGS 32
-
-/* Size of temporary string that will hold any options following custom      */
-/* command-line keywords that are passed to the client application's handler */
-/* function.                                                                 */
-#define CUSTOM_OPTION_SIZE 80
-
-/* Command-line parameter identifiers. */
-typedef enum
-{
-   kParamConfigFile,
-   kParamLocal,
-   kParamBPS,
-   kParamPort,
-   kParamNode,
-   kParamHelp,
-   kParamPersonality,
-   kParamMaxTime,
-   kParamAddress,
-   kParamIRQ,
-   kParamNoFOSSIL,
-   kParamNoFIFO,
-   kParamDropFile,
-   kParamUserName,
-   kParamTimeLeft,
-   kParamSecurity,
-   kParamLocation,
-   kParamGraphics,
-   kParamBBSName,
-   kParamPortHandle,
-   kParamSocketDescriptor,
-   kParamSilentMode,
-   kParamOption,
-   kParamUnknown
-} tCommandLineParameter;
-
-
-/* Private function prototypes. */
-static void ODAdvanceToNextArg(INT *pnCurrentArg, INT nArgCount,
-   char *pszOption);
-static void ODGetNextArgName(INT *pnCurrentArg, INT nArgCount,
-   char *papszArguments[], char *pszString, size_t nStringSize);
-static tCommandLineParameter ODGetCommandLineParameter(char *pszArgument);
-
-
-/* Private variables. */
-#define CONFIG_FILENAME_SIZE 80
-static char szConfigFilename[CONFIG_FILENAME_SIZE];
-
-
-/* ----------------------------------------------------------------------------
- * od_parse_cmd_line()
- *
- * Function to parse an OpenDoors program's command-line, interpreting
- * standard command-line parameters. This is one of the few OpenDoors APIs
- * that will not automatically initialize OpenDoors if it hasn't already
- * been done. This is because od_parse_cmd_line() performs setup that must
- * be done prior to OpenDoors initialization.
- *
- * Parameters: FOR NON-WIN32 VERSIONS:
- *
- *             nArgCount      - Number of command line arguments, as passed to
- *                              main() in argc.
- *
- *             papszArguments - Pointer to array of pointers to string
- *                              arguments, as passed to main() in argv. The
- *                              first element of this array (usually the
- *                              full path and filename of the executable)
- *                              is ignored.
- *
- *             FOR WIN32 VERSION:
- *
- *             pszCmdLine     - Pointer to the command line string, as passed
- *                              to WinMain().
- *
- *     Return: void
- */
-#ifdef ODPLAT_WIN32
-ODAPIDEF void ODCALL od_parse_cmd_line(LPSTR pszCmdLine)
-#else /* !ODPLAT_WIN32 */
-ODAPIDEF void ODCALL od_parse_cmd_line(INT nArgCount, char *papszArguments[])
-#endif /* !ODPLAT_WIN32 */
-{
-   char *pszCurrentArg;
-   INT nCurrentArg;
-   INT n;
-#ifdef ODPLAT_WIN32
-   INT nArgCount;
-   char *papszArguments[MAX_ARGS];
-   char *pszCmdLineCopy;
-   char *pchCurrent
-#endif /* ODPLAT_WIN32 */
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_parse_cmd_line()");
-
-#ifdef ODPLAT_WIN32
-   /* Attempt to allocate space for a copy of the command line. */
-   pszCmdLineCopy = malloc(strlen(pszCmdLine) + 1);
-   if(pszCmdLineCopy == NULL)
-   {
-      od_control.od_error = ERR_MEMORY;
-      return;
-   }
-
-   /* Copy the command line text into our working copy. */
-   strcpy(pszCmdLineCopy, pszCmdLine);
-
-   /* Loop, building papszArguments and nArgCount. */
-   pchCurrent = pszCmdLineCopy;
-   for(nArgCount = 0; nArgCount < MAX_ARGS && *pchCurrent != '\0'; ++nArgCount)
-   {
-      /* Store address of the next command line argument. */
-      papszArguments[nArgCount] = pchCurrent;
-
-      /* Skip forward to the next white space. */
-      while(*pchCurrent != '\0' && !isspace(*pchCurrent))
-      {
-         ++pchCurrent;
-      }
-
-      /* Replace white space characters with '\0' string terminators, until */
-      /* we reach the next command line argument, or the end of the string. */
-      while(*pchCurrent != '\0' && isspace(*pchCurrent))
-      {
-         *pchCurrent = '\0';
-         ++pchCurrent;
-      }
-   }
-#endif /* ODPLAT_WIN32 */
-
-#ifndef ODPLAT_WIN32
-   /* Check validity of parameters. */
-   if(papszArguments == NULL)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      return;
-   }
-#endif /* !ODPLAT_WIN32 */
-
-   /* Record that od_parse_cmd_line() has been called. */
-   bParsedCmdLine = TRUE;
-
-   /* Initialize variables that are not initialized in od_init() if */
-   /* od_parse_cmd_line is specified.                               */
-   od_control.user_ansi = TRUE;
-   od_control.user_timelimit = 60;
-
-#ifdef ODPLAT_WIN32
-   for(nCurrentArg = 0; nCurrentArg < nArgCount; ++nCurrentArg)
-#else /* !ODPLAT_WIN32 */
-   for(nCurrentArg = 1; nCurrentArg < nArgCount; ++nCurrentArg)
-#endif /* !ODPLAT_WIN32 */
-   {
-      pszCurrentArg = papszArguments[nCurrentArg];
-
-      switch(ODGetCommandLineParameter(pszCurrentArg))
-      {
-         case kParamConfigFile:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            strncpy(szConfigFilename, papszArguments[nCurrentArg],
-               sizeof(szConfigFilename) - 1);
-            szConfigFilename[sizeof(szConfigFilename) - 1] = '\0';
-            od_control.od_config_filename = szConfigFilename;
-            break;
-
-         case kParamLocal:
-            od_control.od_force_local = TRUE;
-            break;
-
-         case kParamBPS:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.baud = atol(papszArguments[nCurrentArg]);
-            wPreSetInfo |= PRESET_BPS;
-            break;
-
-         case kParamPort:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            if(strnicmp(papszArguments[nCurrentArg], "COM", 3) == 0)
-            {
-               od_control.port = atoi(papszArguments[nCurrentArg] + 3) - 1;
-            }
-            else
-            {
-               od_control.port = atoi(papszArguments[nCurrentArg]);
-            }
-            wPreSetInfo |= PRESET_PORT;
-            break;
-
-         case kParamHelp:
-            if(od_control.od_cmd_line_help_func != NULL)
-            {
-               (*od_control.od_cmd_line_help_func)();
-               exit(0);
-            }
-
-#ifdef ODPLAT_WIN32
-            sprintf(szODWorkString, "%s Command Line Options",
-               strlen(od_control.od_prog_name) > 0 ? od_control.od_prog_name
-               : OD_VER_SHORTNAME);
-            if(od_control.od_cmd_line_help != NULL)
-            {
-               MessageBox(NULL, od_control.od_cmd_line_help, szODWorkString,
-                  MB_ICONINFORMATION | MB_OK);
-            }
-            else
-            {
-               MessageBox(NULL,
-                  "(Note that some options can be overriden by configuration or drop files.)\n"
-                  "\n"
-                  "-C x or -CONFIG x\t- Specfies configuration filename.\n"
-                  "-L or -LOCAL\t- Causes door to operate in local mode, without requiring a drop file.\n"
-                  "-D or -DROPFILE x\t- Door information file directory and/or filename.\n"
-                  "-N x or -NODE x\t- Sets the node number to use.\n"
-                  "-B x or -BPS x\t- Sets the serial port <---> modem bps (baud) rate to use.\n"
-                  "-P x or -PORT x\t- Sets serial port to use. For COM1: use -P 0 or -P COM1, for COM2: use -P 1 or -P COM2, etc.\n"
-                  "-HANDLE x\t- Provides an already open serial port handle.\n"
-						"-SOCKET x\t- Provides an already open TCP/IP socket descriptor.\n"
-                  "-SILENT\t\t- Operate in silent mode, with no local display.\n"
-                  "-MAXTIME x\t- Sets the maximum number of minutes that user will be permitted to access the door.\n"
-                  "-G or -GRAPHICS\t- Unless followed by 0 or N, turns on ANSI display mode.\n"
-                  "-BBSNAME x\t- Name of BBS.\n"
-                  "-USERNAME x\t- Name of user who is currently online.\n"
-                  "-TIMELEFT x\t- User's time remaining online.\n"
-                  "-SECURITY x\t- User's security level.\n"
-                  "-LOCATION x\t- Location from which user is calling.\n"
-                  "-?, -H or -HELP\t- Displays command-line help and exits.",
-                  szODWorkString, MB_ICONINFORMATION | MB_OK);
-            }
-#else /* !ODPLAT_WIN32 */
-            printf("AVALIABLE COMMAND LINE OPTIONS ");
-            if(od_control.od_cmd_line_help != NULL)
-            {
-               printf(od_control.od_cmd_line_help);
-            }
-            else
-            {
-               printf("(Some can be overriden by config/drop file)\n");
-               printf(" -C or -CONFIG    - Specfies configuration filename.\n");
-               printf(" -L or -LOCAL     - Causes door to operate in local mode, without requiring a\n");
-               printf("                    door information (drop) file.\n");
-               printf(" -D or -DROPFILE  - Door information file directory and/or filename.\n");
-               printf(" -N x or -NODE x  - Sets the node number to use.\n");
-               printf(" -B x or -BPS x   - Sets the serial port <---> modem bps (baud) rate to use.\n");
-               printf(" -P x or -PORT x  - Sets serial port to use. For COM1: use -P 0 or -P COM1, for\n");
-               printf("                    COM2: use -P 1 or -P COM2, etc.\n");
-               printf(" -ADDRESS x       - Sets serial port address in HEXIDECIMAL (if no FOSSIL).\n");
-               printf(" -IRQ x           - Sets the serial port IRQ line (if FOSSIL is not used).\n");
-               printf(" -NOFOSSIL        - Disables use of FOSSIL driver, even if available.\n");
-               printf(" -NOFIFO          - Disables use of 16550 FIFO buffers (only if no FOSSIL).\n");
-               printf(" -MAXTIME x       - Sets the maximum number of minutes that any user will be\n");
-               printf("                    permitted to access the door, regardless of time left.\n");
-               printf(" -SILENT          - Operate in silent mode, with no local display.\n");
-               printf(" -G or -GRAPHICS  - Unless followed by 0 or N, turns on ANSI display mode.\n");
-               printf(" -BBSNAME x       - Name of BBS.\n");
-               printf(" -USERNAME x      - Name of user who is currently online.\n");
-               printf(" -TIMELEFT x      - User's time remaining online.\n");
-               printf(" -SECURITY x      - User's security level.\n");
-               printf(" -LOCATION x      - Location from which user is calling.\n");
-               printf(" -?, -H or -HELP  - Displays command-line help and exits.\n");
-            }
-#endif /* !ODPLAT_WIN32 */
-            exit(1);
-            break;
-
-         case kParamNode:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.od_node = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamMaxTime:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.od_maxtime = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamAddress:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.od_com_address =
-               (WORD)strtol(papszArguments[nCurrentArg], NULL, 16);
-            break;
-
-         case kParamIRQ:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.od_com_irq = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamNoFOSSIL:
-            od_control.od_no_fossil = TRUE;
-            break;
-
-         case kParamNoFIFO:
-            od_control.od_com_no_fifo = TRUE;
-            break;
-
-         case kParamDropFile:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            strncpy(od_control.info_path, papszArguments[nCurrentArg],
-               sizeof(od_control.info_path) - 1);
-            od_control.info_path[sizeof(od_control.info_path) - 1] = '\0';
-            break;
-
-         case kParamUserName:
-            ODGetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-            od_control.user_name, sizeof(od_control.user_name));
-            break;
-
-         case kParamTimeLeft:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.user_timelimit = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamSecurity:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.user_security = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamLocation:
-            ODGetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-            od_control.user_location, sizeof(od_control.user_location));
-            break;
-
-         case kParamGraphics:
-            n = nCurrentArg;
-            if(++n < nArgCount)
-            {
-               if(atoi(papszArguments[n]) == 0 ||
-                  stricmp(papszArguments[n], "N") == 0)
-               {
-                  od_control.user_ansi = FALSE;
-                  ++nCurrentArg;
-                  break;
-               }
-            }
-            od_control.user_ansi = TRUE;
-            break;
-
-         case kParamBBSName:
-            ODGetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-               od_control.system_name, sizeof(od_control.system_name));
-            break;
-
-         case kParamSocketDescriptor:
-				od_control.od_use_socket = TRUE;
-				/* fall through */
-
-         case kParamPortHandle:
-            ODAdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-            od_control.od_open_handle = atoi(papszArguments[nCurrentArg]);
-            break;
-
-         case kParamSilentMode:
-            od_control.od_silent_mode = TRUE;
-            break;
-
-         case kParamUnknown:
-            /* If the client application provided a custom command line   */
-            /* handler function, then pass this unrecognized command-line */
-            /* parameter and any options to that callback function.       */
-            if(od_control.od_cmd_line_handler != NULL)
-            {
-               char szCustomOptions[CUSTOM_OPTION_SIZE];
-               ODGetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-                  szCustomOptions, sizeof(szCustomOptions));
-               (*od_control.od_cmd_line_handler)(pszCurrentArg,
-                  szCustomOptions);
-            }
-            break;
-      }
-   }
-
-#ifdef ODPLAT_WIN32
-   free(pszCmdLineCopy);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODAdvanceToNextArg()                                *** PRIVATE FUNCTION ***
- *
- * Moves to the argument for a particular command line option.
- *
- * Parameters: pnCurrentArg - Pointer to current argument number.
- *
- *             nArgCount    - Total number of arguments available.
- *
- *             pszOption    - Pointer to command line option name.
- *
- *     Return: void
- */
-static void ODAdvanceToNextArg(INT *pnCurrentArg, INT nArgCount,
-   char *pszOption)
-{
-   ASSERT(pnCurrentArg != NULL);
-   ASSERT(pszOption != NULL);
-
-   if(++*pnCurrentArg >= nArgCount)
-   {
-      printf("Missing parameter for option: %s\n", pszOption);
-      exit(1);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODGetNextArgName()                                  *** PRIVATE FUNCTION ***
- *
- * Obtains a multi-word name from command-line.
- *
- * Parameters: pnCurrentArg   - Pointer to integer storing current argument
- *                              number.
- *
- *             nArgCount      - The total number of command-line argument
- *
- *             papszArguments - Pointer to array of pointers to string
- *                              arguments, as passed to main() in argv.
- *
- *             pszString      - Pointer to string in which name will string
- *                              be stored.
- *
- *             nStringSize    - Size of the string.
- *
- *     Return: void
- */
-static void ODGetNextArgName(INT *pnCurrentArg, INT nArgCount,
-   char *papszArguments[], char *pszString, size_t nStringSize)
-{
-   BOOL bFirst = TRUE;
-
-   ASSERT(pnCurrentArg != NULL);
-   ASSERT(papszArguments != NULL);
-   ASSERT(pszString != NULL);
-   ASSERT(nStringSize > 0);
-
-   if((*pnCurrentArg) + 1 >= nArgCount)
-   {
-      printf("Missing parameter for option: %s\n",
-         papszArguments[(*pnCurrentArg) - 1]);
-      exit(1);
-   }
-
-   pszString[0] = '\0';
-
-   while(++*pnCurrentArg < nArgCount)
-   {
-      if(ODGetCommandLineParameter(papszArguments[*pnCurrentArg])
-         != kParamOption)
-      {
-         --*pnCurrentArg;
-         break;
-      }
-
-      if(strlen(pszString) >= nStringSize - 1)
-      {
-         break;
-      }
-
-      if(!bFirst)
-      {
-         strcat(pszString, " ");
-      }
-
-      strncat(pszString, papszArguments[*pnCurrentArg],
-         strlen(pszString) - nStringSize - 1);
-      pszString[nStringSize - 1] = '\0';
-
-      bFirst = FALSE;
-   }
-
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODGetCommandLineParameter()                         *** PRIVATE FUNCTION ***
- *
- * Determines which command-line option, if any, is specified by an argument
- * string.
- *
- * Parameters: pszArgument - Pointer to string containing raw command-line
- *                           argument.
- *
- *     Return: A tCommandLineParameter, identifying which command-line option,
- *             if any, matches the argument string.
- */
-static tCommandLineParameter ODGetCommandLineParameter(char *pszArgument)
-{
-   ASSERT(pszArgument != NULL);
-
-   if(*pszArgument == '-' || *pszArgument == '/')
-   {
-      ++pszArgument;
-   }
-   else
-   {
-      return(kParamOption);
-   }
-
-   if(stricmp(pszArgument, "C") == 0
-      || stricmp(pszArgument, "CONFIG") == 0
-      || stricmp(pszArgument, "CONFIGFILE") == 0
-      || stricmp(pszArgument, "CFGFILE") == 0
-      || stricmp(pszArgument, "CFG") == 0)
-   {
-      return(kParamConfigFile);
-   }
-   else if(stricmp(pszArgument, "L") == 0
-      || stricmp(pszArgument, "LOCAL") == 0)
-   {
-      return(kParamLocal);
-   }
-   else if(stricmp(pszArgument, "B") == 0
-      || stricmp(pszArgument, "BPS") == 0
-      || stricmp(pszArgument, "BAUD") == 0)
-   {
-      return(kParamBPS);
-   }
-   else if(stricmp(pszArgument, "P") == 0
-      || stricmp(pszArgument, "PORT") == 0)
-   {
-      return(kParamPort);
-   }
-   else if(stricmp(pszArgument, "N") == 0
-      || stricmp(pszArgument, "NODE") == 0)
-   {
-      return(kParamNode);
-   }
-   else if(stricmp(pszArgument, "?") == 0
-      || stricmp(pszArgument, "H") == 0
-      || stricmp(pszArgument, "HELP") == 0)
-   {
-      return(kParamHelp);
-   }
-   else if(stricmp(pszArgument, "PERSONALITY") == 0)
-   {
-      return(kParamPersonality);
-   }
-   else if(stricmp(pszArgument, "MAXTIME") == 0)
-   {
-      return(kParamMaxTime);
-   }
-   else if(stricmp(pszArgument, "ADDRESS") == 0)
-   {
-      return(kParamAddress);
-   }
-   else if(stricmp(pszArgument, "IRQ") == 0)
-   {
-      return(kParamIRQ);
-   }
-   else if(stricmp(pszArgument, "NOFOSSIL") == 0)
-   {
-      return(kParamNoFOSSIL);
-   }
-   else if(stricmp(pszArgument, "NOFIFO") == 0)
-   {
-      return(kParamNoFIFO);
-   }
-   else if(stricmp(pszArgument, "DROPFILE") == 0 ||
-      stricmp(pszArgument, "D") == 0)
-   {
-      return(kParamDropFile);
-   }
-   else if(stricmp(pszArgument, "USERNAME") == 0)
-   {
-      return(kParamUserName);
-   }
-   else if(stricmp(pszArgument, "TIMELEFT") == 0)
-   {
-      return(kParamTimeLeft);
-   }
-   else if(stricmp(pszArgument, "SECURITY") == 0)
-   {
-      return(kParamSecurity);
-   }
-   else if(stricmp(pszArgument, "LOCATION") == 0)
-   {
-      return(kParamLocation);
-   }
-   else if(stricmp(pszArgument, "GRAPHICS") == 0
-      || stricmp(pszArgument, "G") == 0)
-   {
-      return(kParamGraphics);
-   }
-   else if(stricmp(pszArgument, "BBSNAME") == 0)
-   {
-      return(kParamBBSName);
-   }
-   else if(stricmp(pszArgument, "HANDLE") == 0)
-   {
-      return(kParamPortHandle);
-   }
-   else if(stricmp(pszArgument, "SOCKET") == 0)
-   {
-      return(kParamSocketDescriptor);
-   }
-   else if(stricmp(pszArgument, "SILENT") == 0)
-   {
-      return(kParamSilentMode);
-   }
-   else
-   {
-      return(kParamUnknown);
-   }
-}
diff --git a/src/odoors/ODCom.c b/src/odoors/ODCom.c
deleted file mode 100644
index 2e0a93f9fc6f8c542ca4512c3fde48521a2a82bf..0000000000000000000000000000000000000000
--- a/src/odoors/ODCom.c
+++ /dev/null
@@ -1,3429 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCom.c
- *
- * Description: Generic serial I/O routines, provide a single interface to
- *              serial ports on any platform.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 20, 1994  6.00  BP   Handle BIOS missing port addrs.
- *              Oct 20, 1994  6.00  BP   Standardized coding style.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Dec 07, 1994  6.00  BP   Support for RTS/CTS flow control.
- *              Dec 10, 1994  6.00  BP   Allow word frmt setting for intern I/O
- *              Dec 13, 1994  6.00  BP   Remove include of dir.h.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Jan 01, 1995  6.00  BP   Integrate in Win32 code.
- *              Jan 01, 1995  6.00  BP   Add FLOW_DEFAULT setting.
- *              Jan 01, 1995  6.00  BP   Added ODComWaitEvent().
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 21, 1995  6.00  BP   Ported to Win32.
- *              Dec 21, 1995  6.00  BP   Add ability to use already open port.
- *              Jan 09, 1996  6.00  BP   Supply actual in/out buffer size used.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Initial support for Door32 interface.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Jan 13, 1997  6.10  BP   Fixes for Door32 support.
- *              Oct 19, 2001  6.20  RS   Added TCP/IP socket (telnet) support.
- *              Oct 22, 2001  6.21  RS   Fixed disconnected socket detection.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODCom.h"
-#include "ODUtil.h"
-
-
-/* The following define determines whether serial port function should */
-/* ASSERT or return an error code on programmer erorrs (e.g. invalid   */
-/* parameters.                                                         */
-#define ASSERT_ON_INVALID_CALLS
-
-/* The following code defines the VERIFY_CALL() macro, which maps to an */
-/* ASSERT if ASSERT_ON_INVALID_CALLS is defined. Otherwise, this macro  */
-/* maps to a test which will return an error code to the caller.        */
-#ifdef ASSERT_ON_INVALID_CALLS
-#define VERIFY_CALL(x) ASSERT(x)
-#else /* !ASSERT_ON_INVALID_CALLS */
-#define VERIFY_CALL(x) if(x) return(kODRCInvalidCall)
-#endif /* !ASSERT_ON_INVALID_CALLS */
-
-
-/* The following defines determine which serial I/O mechanisms should be */
-/* supported.                                                            */
-
-/* Serial I/O mechanisms supported under MS-DOS version. */
-#ifdef ODPLAT_DOS
-#define INCLUDE_FOSSIL_COM                      /* INT 14h FOSSIL-based I/O. */
-#define INCLUDE_UART_COM                   /* Internal interrupt driven I/O. */
-#endif /* ODPLAT_DOS */
-
-/* Serial I/O mechanisms supported under Win32 version. */
-#ifdef ODPLAT_WIN32
-#define INCLUDE_WIN32_COM                           /* Win32 API serial I/O. */
-#define INCLUDE_DOOR32_COM                          /* Door32 I/O interface. */
-#define INCLUDE_SOCKET_COM                          /* TCP/IP socket I/O.    */
-#endif /* ODPLAT_WIN32 */
-
-
-/* Include "windows.h" for Win32-API based serial I/O. */
-#ifdef INCLUDE_WIN32_COM
-#include "windows.h"
-#endif /* INCLUDE_WIN32_COM */
-
-#if defined(_WIN32) && defined(INCLUDE_SOCKET_COM)
-	#include <winsock.h>
-	static WSADATA WSAData;		/* WinSock data */
-#endif
-
-/* ========================================================================= */
-/* Serial port object structure.                                             */
-/* ========================================================================= */
-
-/* Win32-API serial I/O implementation requires current timeout setting */
-/* status variable in serial port object structure.                     */
-#ifdef INCLUDE_WIN32_COM
-typedef enum
-{
-   kNotSet,
-   kBlocking,
-   kNonBlocking
-} tReadTimeoutState;
-#endif /* INCLUDE_WIN32_COM */
-
-/* Structure associated with each serial port handle. */
-typedef struct
-{
-   BOOL bIsOpen;
-   BOOL bUsingClientsHandle;
-   BYTE btFlowControlSetting;
-   long lSpeed;
-   BYTE btPort;
-   int nPortAddress;
-   BYTE btIRQLevel;
-   BYTE btWordFormat;
-   int nReceiveBufferSize;
-   int nTransmitBufferSize;
-   BYTE btFIFOSetting;
-   tComMethod Method;
-   void (*pfIdleCallback)(void);
-#ifdef INCLUDE_WIN32_COM
-   HANDLE hCommDev;
-   tReadTimeoutState ReadTimeoutState;
-#endif /* INCLUDE_WIN32_COM */
-#ifdef INCLUDE_DOOR32_COM
-   HINSTANCE hinstDoor32DLL;
-   BOOL (WINAPI *pfDoorInitialize)(void);
-   BOOL (WINAPI *pfDoorShutdown)(void);
-   BOOL (WINAPI *pfDoorWrite)(const BYTE *pbData, DWORD dwSize);
-   DWORD (WINAPI *pfDoorRead)(BYTE *pbData, DWORD dwSize);
-   HANDLE (WINAPI *pfDoorGetAvailableEventHandle)(void);
-   HANDLE (WINAPI *pfDoorGetOfflineEventHandle)(void);
-#endif /* INCLUDE_DOOR32_COM */
-#ifdef INCLUDE_SOCKET_COM
-	SOCKET	socket;
-#endif
-} tPortInfo;
-
-
-/* ========================================================================= */
-/* Internal interrupt-driven serial I/O specific defintions & functions.     */
-/* ========================================================================= */
-
-#ifdef INCLUDE_UART_COM
-
-/* Private function prototypes, used by internal UART async serial I/O. */
-static void ODComSetVect(BYTE btVector, void (INTERRUPT far *pfISR)(void));
-static void (INTERRUPT far *ODComGetVect(BYTE btVector))(void);
-static void INTERRUPT ODComInternalISR();
-static BOOL ODComInternalTXReady(void);
-static void ODComInternalResetRX(void);
-static void ODComInternalResetTX(void);
-
-
-/* Offsets of UART registers. */
-#define TXBUFF  0                       /* Transmit buffer register. */
-#define RXBUFF  0                       /* Receive buffer register. */
-#define DLLSB   0                       /* Divisor latch LS byte. */
-#define DLMSB   1                       /* Divisor latch MS byte. */
-#define IER     1                       /* Interrupt enable register. */
-#define IIR     2                       /* Interrupt ID register. */
-#define LCR     3                       /* Line control register. */
-#define MCR     4                       /* Modem control register. */
-#define LSR     5                       /* Line status register. */
-#define MSR     6                       /* Modem status register. */
-
-/* FIFO control register bits. */
-#define FE      0x01                    /* FIFO enable. */
-#define RR      0x02                    /* FIFO receive buffer reset. */
-#define TR      0x04                    /* FIFO transmit buffer reset. */
-#define FTS_1   0x00                    /* FIFO trigger size 1 byte. */
-#define FTS_4   0x40                    /* FIFO trigger size 4 bytes. */
-#define FTS_8   0x80                    /* FIFO trigger size 8 bytes. */
-#define FTS_14  0xc0                    /* FIFO trigger size 14 bytes. */
-
-/* Modem control register (MCR) bits. */
-#define DTR     0x01                    /* Data terminal ready. */
-#define NOT_DTR 0xfe                    /* All bits other than DTR. */
-#define RTS     0x02                    /* Request to send. */
-#define NOT_RTS 0xfd                    /* All bits other than RTS. */
-#define OUT1    0x04                    /* Output #1. */
-#define OUT2    0x08                    /* Output #2. */
-#define LPBK    0x10                    /* Loopback mode bit. */
-
-/* Modem status register (MSR) bits. */
-#define DCTS    0x01                    /* Delta clear to send. */
-#define DDSR    0x02                    /* Delta data set ready. */
-#define TERI    0x04                    /* Trailing edge ring indicator. */
-#define DRLSD   0x08                    /* Delta Rx line signal detect. */
-#define CTS     0x10                    /* Clear to send. */
-#define DSR     0x20                    /* Data set ready. */
-#define RI      0x40                    /* Ring indicator. */
-#define RLSD    0x80                    /* Receive line signal detect. */
-
-/* Line control register (LCR) bits. */
-#define DATA5   0x00                    /* 5 Data bits. */
-#define DATA6   0x01                    /* 6 Data bits. */
-#define DATA7   0x02                    /* 7 Data bits. */
-#define DATA8   0x03                    /* 8 Data bits. */
-
-#define STOP1   0x00                    /* 1 Stop bit. */
-#define STOP2   0x04                    /* 2 Stop bits. */
-
-#define NOPAR   0x00                    /* No parity. */
-#define ODDPAR  0x08                    /* Odd parity. */
-#define EVNPAR  0x18                    /* Even parity. */
-#define STKPAR  0x28                    /* Sticky parity. */
-#define ZROPAR  0x38                    /* Zero parity. */
-
-#define DLATCH  0x80                    /* Baud rate divisor latch. */
-#define NOT_DL  0x7f                    /* Turns off divisor latch. */
-
-/* Line status register (LSR) bits. */
-#define RDR     0x01                    /* Receive data ready. */
-#define ERRS    0x1E                    /* All the error bits. */
-#define TXR     0x20                    /* Transmitter ready. */
-
-/* Interrupt enable register (IER) bits. */
-#define DR      0x01                    /* Data ready. */
-#define THRE    0x02                    /* Transmit holding register empty. */
-#define RLS     0x04                    /* Receive line status. */
-#define MS      0x08                    /* Modem status. */
-
-/* Flow control receive buffer limits. */
-#define RECEIVE_LOW_NUM     1           /* Numerator for low water mark. */
-#define RECEIVE_LOW_DENOM   4           /* Denominator for low water mark. */
-#define RECEIVE_HIGH_NUM    3           /* Numerator for high water mark. */
-#define RECEIVE_HIGH_DENOM  4           /* Denominator for high water mark. */
-
-
-/* Built-in async serial I/O global variables. */
-
-/* These variabes are shared throughout the functions that handle the      */
-/* built-in UART-base serial I/O, including the interrupt service routine. */
-/* Since only one copy of these variables exist, the built-in serial I/O   */
-/* routines may only be used to access one port at a time.                 */
-
-/* Default port addresses. */
-/* First 4 addresses are standard addresses used for PC/AT COM1 thru COM4. */
-/* Second 4 addresses are PS/2 standard addresses used for COM5 thru COM8. */
-static int anDefaultPortAddr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8,
-                                  0x4220, 0x4228, 0x5220, 0x5228};
-
-/* UART address variables. */
-static int nDataRegAddr;                /* Data register address. */
-static int nIntEnableRegAddr;           /* Interrupt enable register. */
-static int nIntIDRegAddr;               /* Interrupt ID register address. */
-static int nLineCtrlRegAddr;            /* Line control register address. */
-static int nModemCtrlRegAddr;           /* Modem control register address. */
-static int nLineStatusRegAddr;          /* Line status register address. */
-static int nModemStatusRegAddr;         /* Modem status register address. */
-
-/* General variables. */
-static BYTE btIntVector;                /* Interrupt vector number for port. */
-static char btI8259Bit;                 /* 8259 bit mask. */
-static char btI8259Mask;                /* Copy as it was before open. */
-static int nI8259MaskRegAddr;           /* Address of i8259 mask register. */
-static int nI8259EndOfIntRegAddr;       /* Address of i8259 EOI register. */
-static int nI8259MasterEndOfIntRegAddr; /* Address of master PIC EOI reg. */
-static char btOldIntEnableReg;          /* Original IER contents. */
-static char btOldModemCtrlReg;          /* Original MCR contents. */
-static void (INTERRUPT far *pfOldISR)();/* Original ISR routine for IRQ. */
-static char bUsingFIFO = FALSE;         /* Are we using 16550 FIFOs? */
-static unsigned char btBaseFIFOCtrl;    /* FIFO control register byte. */
-
-
-/* Transmit queue variables. */
-static int nTXQueueSize;                /* Actual size of transmit queue. */
-static char *pbtTXQueue;                /* Pointer to transmit queue. */
-static int nTXInIndex;                  /* Location to store next byte. */
-static int nTXOutIndex;                 /* Location to get next byte. */
-static int nTXChars;                    /* Count of characters in queue. */
-
-/*  Receive queue variables. */
-static int nRXQueueSize;                /* Actual size of receive queue. */
-static char *pbtRXQueue;                /* Pointer to receive queue. */
-static int nRXInIndex;                  /* Location to store next byte. */
-static int nRXOutIndex;                 /* Location to retrieve next byte. */
-static int nRXChars;                    /* Count of characters in queue. */
-
-/* Flow control variables. */
-static int nRXHighWaterMark;            /* High water mark for queue size. */
-static int nRXLowWaterMark;             /* Low water mark for queue size. */
-static BYTE btFlowControl;              /* Flow control method. */
-static BOOL bStopTrans;                 /* Flag set to stop transmitting. */
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetVect()                                      *** PRIVATE FUNCTION ***
- *
- * Sets the function to be called for the specified interrupt level.
- *
- * Parameters: btVector - Interrupt vector level, a value from 0 to 255.
- *
- *             pfISR    - Pointer to the ISR function to be called.
- *
- *     Return: void
- */
-static void ODComSetVect(BYTE btVector, void (INTERRUPT far *pfISR)(void))
-{
-   ASM   push ds
-   ASM   mov ah, 0x25
-   ASM   mov al, btVector
-   ASM   lds dx, pfISR
-   ASM   int 0x21
-   ASM   pop ds
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComGetVect()                                      *** PRIVATE FUNCTION ***
- *
- * Returns the address of the function that is currently called for the
- * specified interrupt level.
- *
- * Parameters: btVector - Interrupt vector level, a value from 0 to 255.
- *
- *     Return: A pointer to the code that is currently executed on an interrupt
- *             of the speceified level.
- */
-static void (INTERRUPT far *ODComGetVect(BYTE btVector))(void)
-{
-   void (INTERRUPT far *pfISR)(void);
-
-   ASM   push es
-   ASM   mov ah, 0x35
-   ASM   mov al, btVector
-   ASM   int 0x21
-   ASM   mov word ptr pfISR, bx
-   ASM   mov word ptr [pfISR+2], bx
-   ASM   pop es
-
-   return(pfISR);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComInternalTXReady()                              *** PRIVATE FUNCTION ***
- *
- * Returns TRUE if the internal serial I/O transmit buffer is not full.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static BOOL ODComInternalTXReady(void)
-{
-   /* Return TRUE if tx_chars is less than total tx buffer size. */
-   return(nTXChars < nTXQueueSize);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComInternalResetTX()                              *** PRIVATE FUNCTION ***
- *
- * Clears transmit buffer used by internal serial I/O routines.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODComInternalResetTX(void)
-{
-   /* Disable interrupts. */
-   ASM cli
-
-   /* If we are using 16550A FIFO buffers, then clear the FIFO transmit */
-   /* buffer.                                                           */
-   if(bUsingFIFO)
-   {
-      ASM mov al, btBaseFIFOCtrl
-      ASM or al, TR
-      ASM mov dx, nIntIDRegAddr
-      ASM out dx, al
-   }
-
-   /* Reset start, end and total count of characters in buffer      */
-   /* If buffer is still empty on next transmit interrupt, transmit */
-   /* interrupts will be turned off.                                */
-   nTXChars = nTXInIndex = nTXOutIndex = 0;
-
-   /* Re-enable interrupts. */
-   ASM sti
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComInternalResetRX()                              *** PRIVATE FUNCTION ***
- *
- * Clears receive buffer used by internal serial I/O routines.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODComInternalResetRX(void)
-{
-   /* Disable interrupts. */
-   ASM cli
-
-   /* If we are using 16550A FIFO buffers, then clear the FIFO receive */
-   /* buffer.                                                          */
-   if(bUsingFIFO)
-   {
-      ASM mov al, btBaseFIFOCtrl
-      ASM or al, RR
-      ASM mov dx, nIntIDRegAddr
-      ASM out dx, al
-   }
-
-   /* Reset start, end and total count of characters in buffer           */
-   /* On the next receive interrupt, data will be added at the beginning */
-   /* of the buffer.                                                     */
-   nRXChars = nRXInIndex = nRXOutIndex = 0;
-
-   /* Re-enable interrupts. */
-   ASM sti
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComInternalISR()                                  *** PRIVATE FUNCTION ***
- *
- * Interrupt service routine for internal UART-based serial I/O.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void INTERRUPT ODComInternalISR()
-{
-   char btIIR;
-   BYTE btTemp;
-
-   /* Loop until there are no more pending operations to perform with the */
-   /* UART. */
-   for(;;)
-   {
-      /* While bit 0 of the UART IIR is 0, there remains pending operations. */
-      /* Read IIR. */
-      ASM mov dx, nIntIDRegAddr
-      ASM in al, dx
-      ASM mov btIIR, al
-
-      /* If IIR bit 0 is set, then UART processing is finished.             */
-      if(btIIR & 0x01) break;
-
-      /* Bits 1 and 2 of the IIR register identify the type of operation */
-      /* to be performed with the UART.                                  */
-
-      /* Switch on bits 1 and 2 of IIR register. */
-      switch(btIIR & 0x06)
-      {
-         case 0x00:
-            /* Operation: modem status has changed. */
-
-            /* Read modem status register. */
-            ASM mov dx, nModemStatusRegAddr
-            ASM in al, dx
-            ASM mov btTemp, al
-
-            /* We only care about the modem status register if we are */
-            /* using RTS/CTS flow control, and the CTS register has  */
-            /* changed.                                               */
-            if((btFlowControl & FLOW_RTSCTS) && (btTemp & DCTS))
-            {
-               if(btTemp & CTS)
-               {
-                  /* If CTS has gone high, then re-enable transmission. */
-                  bStopTrans = FALSE;
-
-                  /* Restart transmission if there is anything in the */
-                  /* transmit buffer.                                 */
-                  if(nTXChars > 0)
-                  {
-                     /* Enable transmit interrupt. */
-                     ASM mov dx, nIntEnableRegAddr
-                     ASM in al, dx
-                     ASM or al, THRE
-                     ASM out dx, al
-                  }
-               }
-               else
-               {
-                  /* If CTS has gone low, then stop transmitting. */
-                  bStopTrans = TRUE;
-               }
-            }
-
-            break;
-
-         case 0x02:
-            /* Operation: room in transmit register/FIFO. */
-            /* Check whether we can send further characters to transmit. */
-            if(nTXChars <= 0 || bStopTrans)
-            {
-               /* If we cannot send more characters, then turn off */
-               /* transmit interrupts.                             */
-               ASM mov dx, nIntEnableRegAddr
-               ASM in al, dx
-               ASM and al, 0xfd
-               ASM out dx, al
-            }
-            else
-            {
-               /* If we still have characters to transmit ... */
-
-               /* Check line status register to determine whether transmit  */
-               /* register/FIFO truly has room. Some UARTs trigger transmit */
-               /* interrupts before the character has been tranmistted,     */
-               /* causing transmitted characters to be lost.                */
-               ASM mov dx, nLineStatusRegAddr
-               ASM in al, dx
-               ASM mov btTemp, al
-
-               if(btTemp & TXR)
-               {
-                  /* There is room in the transmit register/FIFO. */
-
-                  /* Get next character to transmit. */
-                  btTemp = pbtTXQueue[nTXOutIndex++];
-
-                  /* Write character to UART data register. */
-                  ASM mov dx, nDataRegAddr
-                  ASM mov al, btTemp
-                  ASM out dx, al
-
-                  /* Wrap-around transmit buffer pointer, if needed. */
-                  if (nTXOutIndex == nTXQueueSize)
-                  {
-                     nTXOutIndex = 0;
-                  }
-
-                  /* Decrease count of characters in transmit buffer. */
-                  nTXChars--;
-               }
-            }
-            break;
-
-         case 0x04:
-            /* Operation: Receive Data. */
-
-            /* Get character from receive buffer ASAP. */
-            ASM mov dx, nDataRegAddr
-            ASM in al, dx
-            ASM mov btTemp, al
-
-            /* If receive buffer is above high water mark. */
-            if(nRXChars >= nRXHighWaterMark)
-            {
-               /* If we are using flow control, then stop sender from */
-               /* sending.                                            */
-               if(btFlowControl & FLOW_RTSCTS)
-               {
-                  /* If using RTS/CTS flow control, then lower RTS line. */
-                  ASM mov dx, nModemCtrlRegAddr
-                  ASM in al, dx
-                  ASM and al, NOT_RTS
-                  ASM out dx, al
-               }
-            }
-
-            /* If there is room in receive buffer. */
-            if(nRXChars < nRXQueueSize)
-            {
-               /* Store the new character in the receive buffer. */
-               pbtRXQueue[nRXInIndex++] = btTemp;
-
-               /* Wrap-around buffer index, if needed. */
-               if (nRXInIndex == nRXQueueSize)
-                  nRXInIndex = 0;
-
-               /* Increment count of characters in the buffer. */
-               nRXChars++;
-            }
-            break;
-
-         case 0x06:
-            /* Operation: Change in line status register. */
-
-            /* We just read the register to move on to further operations. */
-            ASM mov dx, nLineStatusRegAddr
-            ASM in al, dx
-            break;
-      }
-   }
-
-   /* Send end of interrupt to interrupt controller(s). */
-   ASM mov dx, nI8259EndOfIntRegAddr
-   ASM mov al, 0x20
-   ASM out dx, al
-
-   if(nI8259MasterEndOfIntRegAddr != 0)
-   {
-      ASM mov dx, nI8259MasterEndOfIntRegAddr
-      ASM mov al, 0x20
-      ASM out dx, al
-   }
-}
-#endif /* INCLUDE_UART_COM */
-
-
-
-/* ========================================================================= */
-/* Win32-API base serial I/O specific functions.                             */
-/* ========================================================================= */
-
-#ifdef INCLUDE_WIN32_COM
-
-/* Function prototypes. */
-static tODResult ODComWin32SetReadTimeouts(tPortInfo *pPortInfo,
-   tReadTimeoutState RequiredTimeoutState);
-
-
-/* ----------------------------------------------------------------------------
- * ODComWin32SetReadTimeouts()                         *** PRIVATE FUNCTION ***
- *
- * Ensures that read timeout state is set appropriately.
- *
- * Parameters: pPortInfo            - Pointer to serial port handle structure.
- *
- *             RequiredTimeoutState - Timeout state that should be set.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-static tODResult ODComWin32SetReadTimeouts(tPortInfo *pPortInfo,
-   tReadTimeoutState RequiredTimeoutState)
-{
-   ASSERT(pPortInfo != NULL);
-
-   /* If timeout state must be changed ... */
-   if(RequiredTimeoutState != pPortInfo->ReadTimeoutState)
-   {
-      COMMTIMEOUTS CommTimeouts;
-
-      /* Obtain current timeout settings. */
-      if(!GetCommTimeouts(pPortInfo->hCommDev, &CommTimeouts))
-      {
-         return(kODRCGeneralFailure);
-      }
-
-      /* Setup timeout setting structure appropriately. */
-      switch(RequiredTimeoutState)
-      {
-         case kBlocking:
-            CommTimeouts.ReadIntervalTimeout = 0;
-            CommTimeouts.ReadTotalTimeoutMultiplier = 0;
-            CommTimeouts.ReadTotalTimeoutConstant = 0;
-            break;
-         case kNonBlocking:
-            CommTimeouts.ReadIntervalTimeout = INFINITE;
-            CommTimeouts.ReadTotalTimeoutMultiplier = 0;
-            CommTimeouts.ReadTotalTimeoutConstant = 0;
-            break;
-         default:
-            ASSERT(FALSE);
-      }
-
-      /* Write settings. */
-      if(!SetCommTimeouts(pPortInfo->hCommDev, &CommTimeouts))
-      {
-         return(kODRCGeneralFailure);
-      }
-
-      /* Record current read timeout setting state for subsequent */
-      /* calls to this function.                                  */
-      pPortInfo->ReadTimeoutState = RequiredTimeoutState;
-   }
-
-   return(kODRCSuccess);
-}
-
-#endif /* INCLUDE_WIN32_COM */
-
-
-
-/* ========================================================================= */
-/* Implementation of generic serial I/O functions.                           */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODComAlloc()
- *
- * Allocates a serial port handle, which can be passed to other ODCom...()
- * functions.
- *
- * Parameters: phPort - Pointer to serial port handle.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComAlloc(tPortHandle *phPort)
-{
-   tPortInfo *pPortInfo;
-
-   VERIFY_CALL(phPort != NULL);
-
-   /* Attempt to allocate a serial port information structure. */
-   pPortInfo = malloc(sizeof(tPortInfo));
-
-   /* If memory allocation failed, return with failure. */
-   if(pPortInfo == NULL)
-   {
-      *phPort = ODPTR2HANDLE(NULL, tPortInfo);
-      return(kODRCNoMemory);
-   }
-
-   /* Initialize serial port information structure. */
-   pPortInfo->bIsOpen = FALSE;
-   pPortInfo->bUsingClientsHandle = FALSE;
-   pPortInfo->btFlowControlSetting = FLOW_DEFAULT;
-   pPortInfo->lSpeed = SPEED_UNSPECIFIED;
-   pPortInfo->btWordFormat = ODPARITY_NONE | DATABITS_EIGHT | STOP_ONE;
-   pPortInfo->nReceiveBufferSize = 1024;
-   pPortInfo->nTransmitBufferSize = 1024;
-   pPortInfo->btFIFOSetting = FIFO_ENABLE | FIFO_TRIGGER_8;
-   pPortInfo->Method = kComMethodUnspecified;
-   pPortInfo->pfIdleCallback = NULL;
-
-   /* Convert serial port information structure pointer to a handle. */
-   *phPort = ODPTR2HANDLE(pPortInfo, tPortInfo);
-
-   /* Set default port number. */
-   ODComSetPort(*phPort, 0);
-
-#if defined(INCLUDE_SOCKET_COM) && defined(_WINSOCKAPI_)
-	WSAStartup(MAKEWORD(1,1), &WSAData);
-#endif
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComFree()
- *
- * Deallocates a serial port handle that is no longer required.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComFree(tPortHandle hPort)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   /* Deallocate port information structure. */
-   free(pPortInfo);
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetIdleFunction()
- *
- * Sets function to call when serial I/O module is idle, or NULL for none.
- *
- * Parameters: hPort      - Handle to a serial port object.
- *
- *             pfCallback - Pointer to function to call when idle.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetIdleFunction(tPortHandle hPort,
-   void (*pfCallback)(void))
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->pfIdleCallback = pfCallback;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetFlowControl()
- *
- * Sets the flow control method(s) to use. If this function is not called,
- * RTS/CTS flow control is used by default. This function should not be
- * called while the port is open.
- *
- * Parameters: hPort                - Handle to a serial port object.
- *
- *             btFlowControlSetting - One or more FLOW_* settings, joined
- *                                    by bitwise-or (|) operators. If
- *                                    FLOW_DEFAULT is included, all other
- *                                    settings are ignored, and the default
- *                                    settings for this serial I/O method
- *                                    are used.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetFlowControl(tPortHandle hPort, BYTE btFlowControlSetting)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->btFlowControlSetting = btFlowControlSetting;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetSpeed()
- *
- * Sets the serial port BPS (baud) rate to use. Depending upon the serial I/O
- * method being used, this setting may be controlled by the user's system
- * configuration, in which case the value passed to this function wil have
- * no effect. A setting of SPEED_UNSPECIFIED, indicates that the serial port
- * speed should not be changed, if it is possible not to do so with the serial
- * I/O method being used. This function cannot be called while the port is
- * open.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *             lSpeed - A valid BPS rate, or SPEED_UNSPECIFIED.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetSpeed(tPortHandle hPort, long lSpeed)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->lSpeed = lSpeed;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetPort()
- *
- * Sets the serial port number to be associated with this port handle. This
- * function cannot be called while the port is open. Calling this function
- * also sets the IRQ line number and serial port address to their defaults
- * for this port number, if this values can be set for the serial I/O method
- * being used.
- *
- * Parameters: hPort  - Handle to a serial port object.
- *
- *             btPort - Serial port identification, where 0 typically
- *                      corresponds to COM1, 1 to COM2, and so on.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetPort(tPortHandle hPort, BYTE btPort)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   /* Store port number in port information structure. */
-   pPortInfo->btPort = btPort;
-
-
-#ifdef INCLUDE_UART_COM
-   /* Get default address for this port number, if possible. */
-   pPortInfo->nPortAddress = 0;
-
-   if(btPort < 4)
-   {
-      /* Get port address from BIOS data area. */
-      pPortInfo->nPortAddress = *(((int far *)0x400) + btPort);
-   }
-
-   /* If port address is still unknown, and we know the default */
-   /* address, then use that address. */
-   if(pPortInfo->nPortAddress == 0
-      && btPort < DIM(anDefaultPortAddr))
-   {
-      pPortInfo->nPortAddress = anDefaultPortAddr[btPort];
-   }
-
-
-   /* Set default IRQ number for this port number. */
-
-   /* Ports 0 and 2 (COM1:, COM3:) default to IRQ 4, all others */
-   /* default to IRQ 3. */
-   if(btPort == 0 || btPort == 2)
-   {
-      pPortInfo->btIRQLevel = 4;
-   }
-   else
-   {
-      pPortInfo->btIRQLevel = 3;
-   }
-#endif /* INCLUDE_UART_COM */
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetPortAddress()
- *
- * Sets address of the serial port, if it can be set for the serial I/O method
- * being used. This function cannot be called when the port is open.
- *
- * Parameters: hPort        - Handle to a serial port object.
- *
- *             nPortAddress - Address of serial port.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetPortAddress(tPortHandle hPort, int nPortAddress)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->nPortAddress = nPortAddress;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetIRQ()
- *
- * Sets the IRQ line associated with this serial port, if applicable for the
- * serial I/O method being used. This function cannot be called while the port
- * is open.
- *
- * Parameters: hPort      - Handle to a serial port object.
- *
- *             btIRQLevel - A number from 1 to 15, specifying the IRQ line that
- *                          the serial port is wired to.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetIRQ(tPortHandle hPort, BYTE btIRQLevel)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->btIRQLevel = btIRQLevel;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetWordFormat()
- *
- * Determine the word format (number of data bits, stop bits and parity bits)
- * to use, if it can be set for the serial I/O method being used. If this
- * function is not called, N81 word format is used. This function can only
- * be called when the port is not open.
- *
- * Parameters: hPort        - Handle to a serial port object.
- *
- *             btWordFormat - Bitwise-or (|) of PARITY_*, STOP_* and DATABITS_*
- *                            settings which determine the word format to use.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetWordFormat(tPortHandle hPort, BYTE btWordFormat)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->btWordFormat = btWordFormat;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetRXBuf()
- *
- * Sets the desired size of the receive buffer, if possible for the
- * serial I/O method being used. Note that for some serial I/O methods, this
- * buffer size is fixed, controlled by the user's system configuration.
- * No error is generated when this function is called when such serial I/O
- * methods will be used - in this case this setting will simply have no effect.
- * This function cannot be called while the port is open.
- *
- * Parameters: hPort              - Handle to a serial port object.
- *
- *             nReceiveBufferSize - Number of bytes in the receive buffer.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetRXBuf(tPortHandle hPort, int nReceiveBufferSize)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->nReceiveBufferSize = nReceiveBufferSize;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetTXBuf()
- *
- * Sets the desired size of the transmit buffer, if possible for the
- * serial I/O method being used. Note that for some serial I/O methods, this
- * buffer size is fixed, controlled by the user's system configuration.
- * No error is generated when this function is called when such serial I/O
- * methods will be used - in this case this setting will simply have no effect.
- * This function cannot be called while the port is open.
- *
- * Parameters: hPort               - Handle to a serial port object.
- *
- *             nTransmitBufferSize - Number of bytes in the transmit buffer.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetTXBuf(tPortHandle hPort, int nTransmitBufferSize)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->nTransmitBufferSize = nTransmitBufferSize;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetFIFO()
- *
- * Enables or disables use of the UART FIFO buffers (if applicable), and also
- * sets the FIFO trigger level. This function cannot be called while the port
- * is open.
- *
- * Parameters: hPort         - Handle to a serial port object.
- *
- *             btFIFOSetting - UART FIFO setting, including FIFO_ENABLE or
- *                             FIDO_DISABLE, and a FIFO_TRIGGER_* setting,
- *                             joined by bitwise-or (|) operators.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetFIFO(tPortHandle hPort, BYTE btFIFOSetting)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->btFIFOSetting = btFIFOSetting;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetPreferredMethod()
- *
- * Sets the method to be used to perform serial I/O.
- *
- * Parameters: hPort  - Handle to a serial port object.
- *
- *             Method - The method to be used for peforming serial I/O,
- *                      or kComMethodUnspecified to have the serial I/O
- *                      routines to automatically choose the method to use.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetPreferredMethod(tPortHandle hPort, tComMethod Method)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   pPortInfo->Method = Method;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComGetMethod()
- *
- * Returns the method being used to perform serial I/O, if this has been
- * determined. You can only assume that this value will be set after
- * ODComOpen() has been called.
- *
- * Parameters: hPort   - Handle to a serial port object.
- *
- *             pMethod - Pointer to a tComMethod, in which function will
- *                       store the method of serial I/O being used, if this
- *                       has been determined.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComGetMethod(tPortHandle hPort, tComMethod *pMethod)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pMethod != NULL);
-
-   *pMethod = pPortInfo->Method;
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComOpen()
- *
- * Initializes serial I/O for appropriate serial I/O mechanism (e.g. FOSSIL
- * driver, internal async I/O, etc.)
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComOpen(tPortHandle hPort)
-{
-#if defined(INCLUDE_FOSSIL_COM) || defined(INCLUDE_UART_COM)
-   unsigned int uDivisor;
-   unsigned long ulQuotient, ulRemainder;
-   BYTE btTemp;
-#endif /* INCLUDE_FOSSIL_COM || INCLUDE_UART_COM */
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   nPort = (int)pPortInfo->btPort;
-
-   /* Ensure that port is not already open. */
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-   /* The following code is used to handle FOSSIL-based serial I/O open */
-   /* operations.                                                       */
-#ifdef INCLUDE_FOSSIL_COM
-   /* If use of FOSSIL driver has not been disabled, then first attempt to */
-   /* use it.                                                              */
-   if(pPortInfo->Method == kComMethodFOSSIL ||
-      pPortInfo->Method == kComMethodUnspecified)
-   {
-      /* Attempt to open port with FOSSIL DRIVER. */
-      ASM    push si
-      ASM    push di
-      ASM    mov ah, 4
-      ASM    mov dx, nPort
-      ASM    mov bx, 0
-      ASM    int 20
-      ASM    pop di
-      ASM    pop si
-      ASM    cmp ax, 6484
-      ASM    je fossil
-      goto no_fossil;
-
-fossil:
-      pPortInfo->Method = kComMethodFOSSIL;
-
-      /* Enable flow control, if applicable. */
-
-      /* Generate flow control setting. All bits in high nibble of flow   */
-      /* control are set to 1, because some FOSSIL driver implementations */
-      /* use the high nibble as a control mask.                           */
-      if(pPortInfo->btFlowControlSetting & FLOW_DEFAULT)
-      {
-         btTemp = FLOW_RTSCTS | 0xf0;
-      }
-      else
-      {
-         btTemp = pPortInfo->btFlowControlSetting | 0xf0;
-      }
-
-      ASM    push si
-      ASM    push di
-      ASM    mov ah, 0x0f
-      ASM    mov al, btTemp
-      ASM    mov dx, nPort
-      ASM    int 20
-      ASM    pop di
-      ASM    pop si
-
-      /* If serial port speed is not to be set, then return now. */
-      if(pPortInfo->lSpeed == SPEED_UNSPECIFIED)
-      {
-         /* Set port state to open. */
-         pPortInfo->bIsOpen = TRUE;
-
-         /* Return with success. */
-         return(kODRCSuccess);
-      }
-
-      /* Set to current baud rate. */
-      switch(pPortInfo->lSpeed)
-      {
-         case 300L:
-            btTemp = 0x40;
-            break;
-         case 600L:
-            btTemp = 0x60;
-            break;
-         case 1200L:
-            btTemp = 0x80;
-            break;
-         case 2400L:
-            btTemp = 0xa0;
-            break;
-         case 4800L:
-            btTemp = 0xc0;
-            break;
-         case 9600L:
-            btTemp = 0xe0;
-            break;
-         case 19200L:
-            btTemp = 0x00;
-            break;
-         case 38400L:
-            btTemp = 0x20;
-            break;
-         default:
-            /* If invalid bps rate, don't change current bps setting. */
-            /* Set port state to open. */
-            pPortInfo->bIsOpen = TRUE;
-
-            /* Return with success. */
-            return(kODRCSuccess);
-      }
-
-      /* Add desired word format parameters to data to be passed to fossil. */
-      btTemp |= pPortInfo->btWordFormat;
-
-      /* Initialize fossil driver. */
-      ASM    push si
-      ASM    push di
-      ASM    mov al, btTemp
-      ASM    mov ah, 0
-      ASM    mov dx, nPort
-      ASM    int 20
-      ASM    pop di
-      ASM    pop si
-
-      /* Set port state to open. */
-      pPortInfo->bIsOpen = TRUE;
-
-      /* Return with success. */
-      return(kODRCSuccess);
-   }
-
-no_fossil:
-#endif /* INCLUDE_FOSSIL_COM */
-
-   /* The following code is used to carry out the serial port I/O open */
-   /* operations if built-in UART-based serial I/O is being used.      */
-#ifdef INCLUDE_UART_COM
-   if(pPortInfo->Method == kComMethodUART ||
-      pPortInfo->Method == kComMethodUnspecified)
-   {
-      /* Set internal serial I/O flow control variable from pre-set */
-      /* flow control options.                                      */
-      if(pPortInfo->btFlowControlSetting & FLOW_DEFAULT)
-      {
-         btFlowControl = FLOW_RTSCTS;
-      }
-      else
-      {
-         btFlowControl = pPortInfo->btFlowControlSetting;
-      }
-
-      /* Store serial I/O method being used. */
-      pPortInfo->Method = kComMethodUART;
-
-      /* Calculate receive buffer high and low water marks for use with */
-      /* flow control. */
-      nRXHighWaterMark = (pPortInfo->nReceiveBufferSize * RECEIVE_HIGH_NUM)
-         / RECEIVE_HIGH_DENOM;
-      nRXLowWaterMark = (pPortInfo->nReceiveBufferSize * RECEIVE_LOW_NUM)
-         / RECEIVE_LOW_DENOM;
-
-      /* Allocate transmit and receive buffers */
-      pbtTXQueue = malloc(nTXQueueSize = pPortInfo->nTransmitBufferSize);
-      pbtRXQueue = malloc(nRXQueueSize = pPortInfo->nReceiveBufferSize);
-
-      if(pbtTXQueue == NULL || pbtRXQueue == NULL)
-      {
-         return(kODRCNoMemory);
-      }
-
-      /* If serial port address is unknown. */
-      if(pPortInfo->nPortAddress == 0)
-      {
-         return(kODRCNoPortAddress);
-      }
-
-      /* Initialize table of UART register port addresses. */
-      nDataRegAddr = pPortInfo->nPortAddress;
-      nIntEnableRegAddr = nDataRegAddr + IER;
-      nIntIDRegAddr = nDataRegAddr + IIR;
-      nLineCtrlRegAddr = nDataRegAddr + LCR;
-      nModemCtrlRegAddr = nDataRegAddr + MCR;
-      nLineStatusRegAddr = nDataRegAddr + LSR;
-      nModemStatusRegAddr = nDataRegAddr + MSR;
-
-
-      /* Store interrupt vector number and PIC interrupt information for */
-      /* the specified IRQ line.                                         */
-      if(pPortInfo->btIRQLevel <= 7)
-      {
-         btIntVector = 0x08 + (pPortInfo->btIRQLevel);
-         btI8259Bit = 1 << (pPortInfo->btIRQLevel);
-         nI8259MaskRegAddr = 0x21;
-         nI8259EndOfIntRegAddr = 0x20;
-         nI8259MasterEndOfIntRegAddr = 0x00;
-      }
-      else
-      {
-         btIntVector = 0x68 + (pPortInfo->btIRQLevel);
-         btI8259Bit = 1 << (pPortInfo->btIRQLevel - 8);
-         nI8259MaskRegAddr = 0xA1;
-         nI8259EndOfIntRegAddr = 0xA0;
-         nI8259MasterEndOfIntRegAddr = 0x20;
-      }
-
-      /* Save original state of UART IER register. */
-      ASM mov dx, nIntEnableRegAddr
-      ASM in al, dx
-      ASM mov btOldIntEnableReg, al
-
-      /* Test that a UART is indeed installed at this port address. */
-      ASM mov dx, nIntEnableRegAddr
-      ASM mov al, 0
-      ASM out dx, al
-
-      ASM mov dx, nIntEnableRegAddr
-      ASM in al, dx
-      ASM mov btTemp, al
-
-      if (btTemp != 0)
-      {
-         return(kODRCNoUART);
-      }
-
-      /* Setup for RTS/CTS flow control, if it is to be used. */
-      if(btFlowControl & FLOW_RTSCTS)
-      {
-         /* Read modem status register. */
-         ASM mov dx, nModemStatusRegAddr
-         ASM in al, dx
-         ASM mov btTemp, al
-
-         /* Enable transmission only if CTS is high. */
-         bStopTrans = !(btTemp & CTS);
-      }
-
-      /* Save original PIC interrupt settings, and temporarily disable */
-      /* interrupts on this IRQ line while we perform initialization.  */
-      ASM cli
-
-      ASM mov dx, nI8259MaskRegAddr
-      ASM in al, dx
-      ASM mov btI8259Mask, al
-      ASM or  al, btI8259Bit
-      ASM out dx, al
-
-      /* Initialize transmit and recieve buffers. */
-      ODComInternalResetTX();
-      ODComInternalResetRX();
-
-      /* Re-enable interrupts. */
-      ASM sti
-
-      /* Save original interrupt vector. */
-      pfOldISR = ODComGetVect(btIntVector);
-
-      /* Set interrupt vector to point to our ISR. */
-#ifdef _MSC_VER
-      ODComSetVect(btIntVector, (void far *)ODComInternalISR);
-#else /* !_MSC_VER */
-      ODComSetVect(btIntVector, ODComInternalISR);
-#endif /* !_MSC_VER */
-
-      /* Set line control register to 8 data bits, no parity bits, 1 stop */
-      /* bit. */
-      btTemp = pPortInfo->btWordFormat;
-      ASM mov dx, nLineCtrlRegAddr
-      ASM mov al, btTemp
-      ASM out dx, al
-
-      /* Save original modem control register. */
-      ASM cli
-
-      ASM mov dx, nModemCtrlRegAddr
-      ASM in al, dx
-      ASM mov btOldModemCtrlReg, al
-
-      /* Keep current DTR setting, and activate RTS. */
-      btTemp = (btOldModemCtrlReg & DTR) | (OUT2 + RTS);
-      ASM mov dx, nModemCtrlRegAddr
-      ASM mov al, btTemp
-      ASM out dx, al
-
-      /* Enable use of 16550A FIFOs, if available. */
-      if(pPortInfo->btFIFOSetting & FIFO_ENABLE)
-      {
-         /* Set FIFO enable bit and trigger size. */
-         btBaseFIFOCtrl = pPortInfo->btFIFOSetting;
-
-         /* Attempt to enable use of FIFO buffers. */
-         ASM mov al, btBaseFIFOCtrl
-         ASM mov dx, nIntIDRegAddr
-         ASM out dx, al
-
-         /* Check whether a 16550A UART is actually present by reading */
-         /* state of FIFO buffer. */
-         ASM mov dx, nIntIDRegAddr
-         ASM in al, dx
-         ASM mov btTemp, al
-
-         bUsingFIFO = btTemp & 0xc0;
-      }
-
-      ASM sti
-
-      /* Enable receive and modem status interrupts on the UART. */
-      ASM mov dx, nIntEnableRegAddr
-      ASM mov al, DR + MS
-      ASM out dx, al
-
-      ASM cli
-
-      ASM mov dx, nI8259MaskRegAddr
-      ASM in al, dx
-      ASM mov ah, btI8259Bit
-      ASM not ah
-      ASM and al, ah
-      ASM out dx, al
-
-      ASM sti
-
-      /* Set baud rate, if possible. */
-
-      /* Calculate baud rate divisor. */
-      if(pPortInfo->lSpeed != SPEED_UNSPECIFIED)
-      {
-         ODDWordDivide(&ulQuotient, &ulRemainder, 115200UL, pPortInfo->lSpeed);
-
-         /* If division results in a remainder, then this is an invalid     */
-         /* baud rate. We only change the UART baud rate if we have a valid */
-         /* rate to set it to. Otherwise, we cross our fingers and proceed  */
-         /* with the currently set UART baud rate.                          */
-         if(ulRemainder == 0L)
-         {
-            uDivisor = (unsigned int)ulQuotient;
-
-            /* Disable interrupts. */
-            ASM cli
-
-            /* Set baud rate divisor latch. */
-            /* The data register now becomes the lower byte of the baud rate */
-            /* divisor, and the interrupt enable register becomes the upper  */
-            /* byte of the divisor.                                          */
-            ASM mov dx, nLineCtrlRegAddr
-            ASM in al, dx
-            ASM or al, DLATCH
-            ASM out dx, al
-
-            /* Write lower byte of baud rate divisor. */
-            ASM mov dx, nDataRegAddr
-            ASM mov ax, uDivisor
-            ASM out dx, al
-
-            /* Write upper byte of baud rate divisor. */
-            ASM mov dx, nIntEnableRegAddr
-            ASM mov al, ah
-            ASM out dx, al
-
-            /* Reset baud rate divisor latch. */
-            ASM mov dx, nLineCtrlRegAddr
-            ASM in al, dx
-            ASM and al, NOT_DL
-            ASM out dx, al
-
-            /* Re-enable interrupts. */
-            ASM sti
-         }
-      }
-
-      /* Remember the serial I/O method that we are using. */
-      pPortInfo->Method = kComMethodUART;
-
-      /* Store port state as open. */
-      pPortInfo->bIsOpen = TRUE;
-
-      /* Return with success. */
-      return(kODRCSuccess);
-   }
-#endif /* INCLUDE_UART_COM */
-
-   /* The following code is used to handle I/O using the Door32 interface. */
-#ifdef INCLUDE_DOOR32_COM
-   if(pPortInfo->Method == kComMethodDoor32 ||
-      pPortInfo->Method == kComMethodUnspecified)
-   {
-      /* Attempt to load the Door32 DLL. */
-      pPortInfo->hinstDoor32DLL = LoadLibrary("DOOR32.DLL");
-      if(pPortInfo->hinstDoor32DLL != NULL)
-      {
-         /* Obtain pointers to required Door32 API function entry points. */
-         pPortInfo->pfDoorInitialize = (BOOL (WINAPI *)(void))
-            GetProcAddress(pPortInfo->hinstDoor32DLL, "DoorInitialize");
-         pPortInfo->pfDoorShutdown = (BOOL (WINAPI *)(void))
-            GetProcAddress(pPortInfo->hinstDoor32DLL, "DoorShutdown");
-         pPortInfo->pfDoorWrite = (BOOL (WINAPI *)(const BYTE *, DWORD))
-            GetProcAddress(pPortInfo->hinstDoor32DLL, "DoorWrite");
-         pPortInfo->pfDoorRead = (DWORD (WINAPI *)(BYTE *, DWORD))
-            GetProcAddress(pPortInfo->hinstDoor32DLL, "DoorRead");
-         pPortInfo->pfDoorGetAvailableEventHandle = (HANDLE (WINAPI *)(void))
-            GetProcAddress(pPortInfo->hinstDoor32DLL,
-            "DoorGetAvailableEventHandle");
-         pPortInfo->pfDoorGetOfflineEventHandle = (HANDLE (WINAPI *)(void))
-            GetProcAddress(pPortInfo->hinstDoor32DLL,
-            "DoorGetOfflineEventHandle");
-
-         /* Check whether we have successfully been able to obtain all the */
-         /* required function entry points.                                */
-         if(pPortInfo->pfDoorInitialize != NULL
-            && pPortInfo->pfDoorShutdown != NULL
-            && pPortInfo->pfDoorWrite != NULL
-            && pPortInfo->pfDoorRead != NULL
-            && pPortInfo->pfDoorGetAvailableEventHandle != NULL
-            && pPortInfo->pfDoorGetOfflineEventHandle != NULL)
-         {
-            if((*pPortInfo->pfDoorInitialize)())
-            {
-               /* Set port state as open. */
-               pPortInfo->bIsOpen = TRUE;
-
-               /* Set serial I/O method. */
-               pPortInfo->Method = kComMethodDoor32;
-
-               /* Return with success. */
-               return(kODRCSuccess);
-            }
-         }
-
-         /* On failure to obtain all Door32 function entry points, unload */
-         /* the Door32 DLL.                                               */
-         FreeLibrary(pPortInfo->hinstDoor32DLL);
-      }
-
-      /* If our attempt to use the Door32 interface failed for any reason, */
-      /* then proceed, attempting to use the Win32 serial I/O interface.   */
-   }
-#endif /* INCLUDE_DOOR32_COM */
-
-   /* The following code is used to handle Win32 API-base serial I/O */
-   /* open operations.                                               */
-#ifdef INCLUDE_WIN32_COM
-   if(pPortInfo->Method == kComMethodWin32 ||
-      pPortInfo->Method == kComMethodUnspecified)
-   {
-      char szDevName[7];
-      DCB dcb;
-
-      /* Generate device name. */
-      sprintf(szDevName, "COM%u", (unsigned)pPortInfo->btPort + 1);
-
-      /* Attempt to create handle for device. */
-      pPortInfo->hCommDev = CreateFile(szDevName, GENERIC_READ | GENERIC_WRITE,
-         0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
-      /* On open failure, return with an error code. */
-      if(pPortInfo->hCommDev == INVALID_HANDLE_VALUE)
-      {
-         return(kODRCGeneralFailure);
-      }
-
-      /* Note that read timeout settings have not been set. */
-      pPortInfo->ReadTimeoutState = kNotSet;
-      
-      /* Call SetupComm() to set queue sizes. */
-      if(!SetupComm(pPortInfo->hCommDev, pPortInfo->nReceiveBufferSize,
-         pPortInfo->nTransmitBufferSize))
-      {
-         CloseHandle(pPortInfo->hCommDev);
-         return(kODRCGeneralFailure);
-      }
-
-      /* Get current port state. */
-      if(!GetCommState(pPortInfo->hCommDev, &dcb))
-      {
-         CloseHandle(pPortInfo->hCommDev);
-         return(kODRCGeneralFailure);
-      }
-
-      /* Fill device control block. */
-
-      /* Set bps rate, if appropriate. */
-      if(pPortInfo->lSpeed != SPEED_UNSPECIFIED)
-      {
-         dcb.BaudRate = pPortInfo->lSpeed;
-      }
-
-      /* Set flow control, if appropriate. */
-      if(!(pPortInfo->btFlowControlSetting & FLOW_DEFAULT))
-      {
-         if(pPortInfo->btFlowControlSetting & FLOW_RTSCTS)
-         {
-            dcb.fOutxCtsFlow = 1;
-            dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
-         }
-         else
-         {
-            dcb.fOutxCtsFlow = 0;
-            dcb.fRtsControl = RTS_CONTROL_ENABLE;
-         }
-      }
-
-      /* Set word size. */
-      if((pPortInfo->btWordFormat & DATABITS_MASK) == DATABITS_FIVE)
-      {
-         dcb.ByteSize = 5;
-      }
-      else if((pPortInfo->btWordFormat & DATABITS_MASK) == DATABITS_SIX)
-      {
-         dcb.ByteSize = 6;
-      }
-      else if((pPortInfo->btWordFormat & DATABITS_MASK) == DATABITS_SEVEN)
-      {
-         dcb.ByteSize = 7;
-      }
-      else if((pPortInfo->btWordFormat & DATABITS_MASK) == DATABITS_EIGHT)
-      {
-         dcb.ByteSize = 8;
-      }
-
-      /* Set parity. */
-      if((pPortInfo->btWordFormat & ODPARITY_MASK) == ODPARITY_NONE)
-      {
-         dcb.Parity = NOPARITY;
-      }
-      else if((pPortInfo->btWordFormat & ODPARITY_MASK) == ODPARITY_ODD)
-      {
-         dcb.Parity = ODDPARITY;
-      }
-      else if((pPortInfo->btWordFormat & ODPARITY_MASK) == ODPARITY_EVEN)
-      {
-         dcb.Parity = EVENPARITY;
-      }
-
-      /* Enable DTR control. */
-      dcb.fDtrControl = DTR_CONTROL_ENABLE;
-
-      /* Set number of stop bits. */
-      if((pPortInfo->btWordFormat & STOP_MASK) == STOP_ONE)
-      {
-         dcb.StopBits = ONESTOPBIT;
-      }
-      else if((pPortInfo->btWordFormat & STOP_MASK) == STOP_ONE_POINT_FIVE)
-      {
-         dcb.StopBits = ONE5STOPBITS;
-      }
-      else if((pPortInfo->btWordFormat & STOP_MASK) == STOP_TWO)
-      {
-         dcb.StopBits = TWOSTOPBITS;
-      }
-
-      /* Set comm state from device control block. */
-      if(!SetCommState(pPortInfo->hCommDev, &dcb))
-      {
-         CloseHandle(pPortInfo->hCommDev);
-         return(kODRCGeneralFailure);
-      }
-
-      /* Store port state as open. */
-      pPortInfo->bIsOpen = TRUE;
-
-      /* Set serial I/O method. */
-      pPortInfo->Method = kComMethodWin32;
-
-      /* Return with success. */
-      return(kODRCSuccess);
-   }
-#endif /* INCLUDE_WIN32_COM */
-
-   /* If we get to this point, then no form of serial I/O could be */
-   /* initialized.                                                 */
-   return(kODRCGeneralFailure);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComOpenFromExistingHandle()
- *
- * Initializes serial I/O using a serial port handle natvie to the current
- * operating system, which has already been opened by another application.
- *
- * Parameters: hPort            - Handle to a serial port object.
- *
- *             dwExistingHandle - Native operating system's handle to an
- *                                already open serial port.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComOpenFromExistingHandle(tPortHandle hPort,
-   DWORD dwExistingHandle)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(!pPortInfo->bIsOpen);
-
-#ifdef INCLUDE_SOCKET_COM
-	if(pPortInfo->Method == kComMethodSocket) {
-
-		pPortInfo->socket = dwExistingHandle;
-
-        pPortInfo->bIsOpen = TRUE;
-
-		return(kODRCSuccess);
-	}
-#endif /* INCLUDE_SOCKET_COM */
-
-#ifdef INCLUDE_WIN32_COM
-
-   /* Store handle to the Win32 handle to the serial port. */
-   pPortInfo->hCommDev = (HANDLE)dwExistingHandle;
-
-   /* Remember that read timeout settings have not been set. */
-   pPortInfo->ReadTimeoutState = kNotSet;
-
-   /* Remember that we are using a handle provided by the client, rather  */
-   /* than one that we opened ourself. This flag prevents the handle from */
-   /* being closed by a call to ODComClose().                             */
-   pPortInfo->bUsingClientsHandle = TRUE;
-
-   /* Remember that the serial port is now open. */
-   pPortInfo->bIsOpen = TRUE;
-
-   return(kODRCSuccess);
-
-#else /* !INCLUDE_WIN32_COM */
-   UNUSED(dwExistingHandle);
-   UNUSED(pPortInfo);
-
-   /* If no form of serial I/O included in this build can use this handle, */
-   /* then return with a failure.                                          */
-   return(kODRCInvalidCall);
-
-#endif /* !INCLUDE_WIN32_COM */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComClose()
- *
- * Closes currently open serial port.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComClose(tPortHandle hPort)
-{
-#ifdef INCLUDE_UART_COM
-   BYTE btTemp;
-#endif /* INCLUDE_UART_COM */
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   /* If we are using the client's handle, then we should not close it. */
-   if(pPortInfo->bUsingClientsHandle)
-   {
-      pPortInfo->bIsOpen = FALSE;
-      return(kODRCSuccess);
-   }
-
-   nPort = (int)pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-         ASM    mov ah, 5
-         ASM    mov dx, nPort
-         ASM    int 20
-         break;
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         /* Reset UART registers to their original values. */
-         ASM mov dx, nModemCtrlRegAddr
-         ASM mov al, btOldModemCtrlReg
-         ASM out dx, al
-         ASM mov dx, nIntEnableRegAddr
-         ASM mov al, btOldIntEnableReg
-         ASM out dx, al
-
-         /* Disable interrupts. */
-         ASM cli
-
-         /* Reset this line's interrupt enable status on the PIC to its */
-         /* original state.                                             */
-         ASM mov dx, nI8259MaskRegAddr
-         ASM in al, dx
-         ASM mov btTemp, al
-
-         btTemp = (btTemp  & ~btI8259Bit) | (btI8259Mask &  btI8259Bit);
-
-         ASM mov dx, nI8259MaskRegAddr
-         ASM mov al, btTemp
-         ASM out dx, al
-
-         /* Re-enable interrupts. */
-         ASM sti
-
-         /* Reset vector to original interrupt handler. */
-#ifdef _MSC_VER
-         ODComSetVect(btIntVector, (void far *)pfOldISR);
-#else /* !_MSC_VER */
-         ODComSetVect(btIntVector, pfOldISR);
-#endif /* !_MSC_VER */
-
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-         CloseHandle(pPortInfo->hCommDev);
-         break;
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorShutdown != NULL);
-         (*pPortInfo->pfDoorShutdown)();
-         ASSERT(pPortInfo->hinstDoor32DLL != NULL);
-         FreeLibrary(pPortInfo->hinstDoor32DLL);
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-         closesocket(pPortInfo->socket);
-         break;
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Store the fact that the port is now closed. */
-   pPortInfo->bIsOpen = FALSE;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComCarrier()
- *
- * Determines whether or not the carrier detect signal is present.
- *
- * Parameters: hPort       - Handle to a serial port object.
- *
- *             pbIsCarrier - Location to store result. Set to TRUE if carrier
- *                           detect signal is high, FALSE if it is low.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComCarrier(tPortHandle hPort, BOOL *pbIsCarrier)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pbIsCarrier != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-      {
-         int to_return;
-
-         ASM    mov ah, 3
-         ASM    mov dx, nPort
-         ASM    int 20
-         ASM    and ax, 128
-         ASM    mov to_return, ax
-
-         *pbIsCarrier = to_return;
-
-         break;
-      }
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-      {
-         BYTE btMSR;
-
-         ASM mov dx, nModemStatusRegAddr
-         ASM in al, dx
-         ASM mov btMSR, al
-
-         *pbIsCarrier = btMSR & RLSD;
-         break;
-      }
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwModemStats;
-
-         /* Get modem status settings. */
-         if(!GetCommModemStatus(pPortInfo->hCommDev, &dwModemStats))
-         {
-            return(kODRCGeneralFailure);
-         }
-
-         *pbIsCarrier = (dwModemStats & MS_RLSD_ON) ? TRUE : FALSE;
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorGetOfflineEventHandle != NULL);
-         *pbIsCarrier = (WaitForSingleObject(
-            (*pPortInfo->pfDoorGetOfflineEventHandle)(),
-            0) != WAIT_OBJECT_0);
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			int		i;
-			char		ch;
-			fd_set	socket_set;
-			struct	timeval tv;
-
-			FD_ZERO(&socket_set);
-			FD_SET(pPortInfo->socket,&socket_set);
-
-			tv.tv_sec=0;
-			tv.tv_usec=0;
-			i=select(pPortInfo->socket+1,&socket_set,NULL,NULL,&tv);
-			if(i==0 
-				|| (i==1 && recv(pPortInfo->socket+1,&ch,1,MSG_PEEK)==1))
-				*pbIsCarrier = TRUE;
-			else
-				*pbIsCarrier = FALSE;
-			break;
-		}
-#endif
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSetDTR()
- *
- * Raises or lowers the DTR signal on the port.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *             bHigh - TRUE to raise DTR, FALSE to lower it.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSetDTR(tPortHandle hPort, BOOL bHigh)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-         ASM    cmp byte ptr bHigh, 0
-         ASM    je lower
-         ASM    mov al, 1
-         ASM    jmp set_dtr
-
-lower:
-         ASM    xor al, al
-
-set_dtr:
-         ASM    mov ah, 6
-         ASM    mov dx, nPort
-         ASM    int 20
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         if(bHigh)
-         {
-            ASM cli
-
-            ASM mov dx, nModemCtrlRegAddr
-            ASM in al, dx
-            ASM or al, DTR
-            ASM out dx, al
-
-            ASM sti
-         }
-         else
-         {
-            ASM cli
-
-            ASM mov dx, nModemCtrlRegAddr
-            ASM in al, dx
-            ASM and al, NOT_DTR
-            ASM out dx, al
-
-            ASM sti
-         }
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-         /* Set DTR line appropriately. */
-         if(!EscapeCommFunction(pPortInfo->hCommDev, bHigh ? SETDTR : CLRDTR))
-         {
-            return(kODRCGeneralFailure);
-         }
-         break;
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         return(kODRCUnsupported);
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-         if(bHigh)
-            return(kODRCUnsupported);
-         closesocket(pPortInfo->socket);
-         break;
-#endif /* INCLUDE_SOCKET_CO */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComOutbound()
- *
- * Determines the number of bytes waiting in the serial port outbound buffer.
- *
- * Parameters: hPort             - Handle to a serial port object.
- *
- *             pnOutboundWaiting - Location where result the number of bytes
- *                                 waiting in the outbound buffer should be
- *                                 stored. Under some I/O methods we can
- *                                 determine whether data is still in the
- *                                 buffer, but not the number of bytes in the
- *                                 buffer. In this situation, this may be set
- *                                 to SIZE_NON_ZERO.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComOutbound(tPortHandle hPort, int *pnOutboundWaiting)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pnOutboundWaiting != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-         ASM    mov ah, 0x03
-         ASM    mov dx, nPort
-         ASM    int 20
-         ASM    and ah, 0x40
-         ASM    jz  still_sending
-         *pnOutboundWaiting = 0;
-         break;
-
-still_sending:
-         *pnOutboundWaiting = SIZE_NON_ZERO;
-         break;
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         *pnOutboundWaiting = (int)nTXChars;
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwErrors;
-         COMSTAT ComStat;
-
-         /* Use ClearCommError() to obtain device status. */
-         if(!ClearCommError(pPortInfo->hCommDev, &dwErrors, &ComStat))
-         {
-            return(kODRCGeneralFailure);
-         }
-
-         /* Set pbIsInbound to TRUE if any bytes are in outbound queue. */
-         *pnOutboundWaiting = (int)ComStat.cbOutQue;
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         /* Door32 doesn't currently support this functionality, so we */
-         /* assume that all sent data is transmitted immediately.      */
-         *pnOutboundWaiting = 0;
-         return(kODRCUnsupported);
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-			*pnOutboundWaiting = 0;
-			return(kODRCUnsupported);
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComClearOutbound()
- *
- * Removes the current contents of the serial port outbound buffer.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComClearOutbound(tPortHandle hPort)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-         ASM    mov ah, 9
-         ASM    mov dx, nPort
-         ASM    int 20
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         ODComInternalResetTX();
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-         if(!PurgeComm(pPortInfo->hCommDev, PURGE_TXCLEAR))
-         {
-            return(kODRCGeneralFailure);
-         }
-         break;
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         return(kODRCUnsupported);
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-			return(kODRCUnsupported);
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComClearInbound()
- *
- * Removes the current contents of the serial port inbound buffer.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComClearInbound(tPortHandle hPort)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-         ASM    mov ah, 10
-         ASM    mov dx, nPort
-         ASM    int 20
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         ODComInternalResetRX();
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-         if(!PurgeComm(pPortInfo->hCommDev, PURGE_RXCLEAR))
-         {
-            return(kODRCGeneralFailure);
-         }
-         break;
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         return(kODRCUnsupported);
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-			return(kODRCUnsupported);
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComInbound()
- *
- * Determines the number of bytes waiting in the serial port inbound buffer.
- *
- * Parameters: hPort            - Handle to a serial port object.
- *
- *             pnInboundWaiting - Location in which to store number of bytes
- *                                waiting in the inbound buffer. Under some
- *                                I/O methods (e.g. FOSSIL driver), we can
- *                                determine whether data is still in the
- *                                buffer, but not the number of bytes in the
- *                                buffer. In this situation, this may be set
- *                                to SIZE_NON_ZERO.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComInbound(tPortHandle hPort, int *pnInboundWaiting)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pnInboundWaiting != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-      {
-         BOOL bDataInBuffer = FALSE;
-
-         ASM    mov ah, 3
-         ASM    mov dx, nPort
-         ASM    push si
-         ASM    push di
-         ASM    int 20
-         ASM    pop di
-         ASM    pop si
-         ASM    and ah, 1
-         ASM    mov bDataInBuffer, ah
-
-         *pnInboundWaiting = bDataInBuffer ? SIZE_NON_ZERO : 0;
-
-         break;
-      }
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         *pnInboundWaiting = (int)nRXChars;
-
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwErrors;
-         COMSTAT ComStat;
-
-         /* Use ClearCommError() to obtain device status. */
-         if(!ClearCommError(pPortInfo->hCommDev, &dwErrors, &ComStat))
-         {
-            return(kODRCGeneralFailure);
-         }
-
-         /* Set pbIsInbound to TRUE if there are any bytes in inbound queue. */
-         *pnInboundWaiting = (int)ComStat.cbInQue;
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorGetAvailableEventHandle != NULL);
-         if(WaitForSingleObject(
-            (*pPortInfo->pfDoorGetAvailableEventHandle)(),
-            0) == WAIT_OBJECT_0)
-         {
-            *pnInboundWaiting = SIZE_NON_ZERO;
-         }
-         else
-         {
-            *pnInboundWaiting = 0;
-         }
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-			if(ioctlsocket(pPortInfo->socket,FIONREAD,pnInboundWaiting) != 0)
-				*pnInboundWaiting = 0;
-			break;
-#endif /* INCLUDE_SOCKET_COM */
-
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComGetByte()
- *
- * Returns a single inbound byte. If there are characters waiting in the
- * inbound buffer, the next character is returned immediately. If bWait is TRUE
- * and no characters are waiting, this function will wait until a character is
- * received (possibly forever, if no characters are ever received).
- *
- * Parameters: hPort   - Handle to a serial port object.
- *
- *             pbtNext - Location to store retrieved byte.
- *
- *             bWait   - If TRUE, function will only return after a character
- *                       has been received. If FALSE, this function will return
- *                       kODRCNothingWaiting if no characters are waiting.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComGetByte(tPortHandle hPort, char *pbtNext, BOOL bWait)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pbtNext != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-      {
-         BYTE btToReturn;
-         int nInboundSize;
-
-         /* If we should not wait for characters if inbound queue is empty. */
-         if(!bWait)
-         {
-            /* Determine whether there are any inbound characterse waiting. */
-            ODComInbound(hPort, &nInboundSize);
-
-            /* If there are no inbound characters waiting, then return */
-            /* without obtaining any characters.                       */
-            if(nInboundSize == 0) return(kODRCNothingWaiting);
-         }
-
-         ASM     mov ah, 2
-         ASM     mov dx, nPort
-         ASM     push si
-         ASM     push di
-         ASM     int 20
-         ASM     pop di
-         ASM     pop si
-         ASM     mov btToReturn, al
-
-         *pbtNext = btToReturn;
-
-         break;
-      }
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         /* If we should not wait for characters if inbound queue is empty. */
-         if(!bWait)
-         {
-            /* If there are no inbound characters waiting, then return */
-            /* without obtaining any characters.                       */
-            if(!nRXChars) return(kODRCNothingWaiting);
-         }
-
-         /* Loop, calling idle function, until next character arrives. */
-         while(!nRXChars)
-         {
-            if(pPortInfo->pfIdleCallback != NULL)
-            {
-               (*pPortInfo->pfIdleCallback)();
-            }
-         }
-
-         /* Disable interrupts. */
-         ASM cli
-
-         /* Get next character from receive queue. */
-         *pbtNext = pbtRXQueue[nRXOutIndex++];
-
-         /* Wrap queue index if needed. */
-         if (nRXOutIndex == nRXQueueSize)
-         {
-            nRXOutIndex = 0;
-         }
-
-         /* Decrement count of total character in the receive queue. */
-         nRXChars--;
-
-         /* Re-enable interrupts. */
-         ASM sti
-
-         /* If receive buffer is below low water mark. */
-         if(nRXChars <= nRXLowWaterMark)
-         {
-            /* If we are using flow control, then stop sender from */
-            /* sending.                                            */
-            if(btFlowControl & FLOW_RTSCTS)
-            {
-               /* If using RTS/CTS flow control, then raise RTS line. */
-               ASM mov dx, nModemCtrlRegAddr
-               ASM in al, dx
-               ASM or al, RTS
-               ASM out dx, al
-            }
-         }
-
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwBytesRead;
-         DWORD dwErrors;
-
-         /* Ensure read timeout state is set appropriately for bWait value. */
-         if(bWait)
-         {
-            ODComWin32SetReadTimeouts(pPortInfo, kBlocking);
-         }
-         else
-         {
-            ODComWin32SetReadTimeouts(pPortInfo, kNonBlocking);
-         }
-
-         /* Perform read operation. */
-         if(!ReadFile(pPortInfo->hCommDev, pbtNext, 1, &dwBytesRead, NULL))
-         {
-            ClearCommError(pPortInfo->hCommDev, &dwErrors, NULL);
-            return(kODRCGeneralFailure);
-         }
-
-         /* Determine whether or not a byte was read. */
-         if(dwBytesRead == 0)
-         {
-            /* If no bytes where read, then this is a general error if bWait */
-            /* is TRUE. If bWait is FALSE, then we should return             */
-            /* waiting kODRCNothingWaiting.                                  */
-            return(bWait ? kODRCGeneralFailure : kODRCNothingWaiting);
-         }
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         if(WaitForSingleObject((*pPortInfo->pfDoorGetAvailableEventHandle)(),
-            bWait ? INFINITE : 0) == WAIT_OBJECT_0)
-         {
-            (*pPortInfo->pfDoorRead)(pbtNext, 1);
-            break;
-         }
-
-         return(bWait ? kODRCGeneralFailure : kODRCNothingWaiting);
-
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			fd_set	socket_set;
-			struct	timeval tv;
-
-			FD_ZERO(&socket_set);
-			FD_SET(pPortInfo->socket,&socket_set);
-
-			tv.tv_sec=0;
-			tv.tv_usec=0;
-
-			if(select(pPortInfo->socket+1,&socket_set,NULL,NULL,bWait ? NULL : &tv) != 1)
-	         return(bWait ? kODRCGeneralFailure : kODRCNothingWaiting);
-
-			if(recv(pPortInfo->socket,pbtNext,1,0) != 1)
-	         return(bWait ? kODRCGeneralFailure : kODRCNothingWaiting);
-
-			break;
-		}
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSendByte()
- *
- * Sends a single byte to the serial port outbound buffer.
- *
- * Parameters: hPort - Handle to a serial port object.
- *
- *             btToSend - The byte to transmit.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSendByte(tPortHandle hPort, BYTE btToSend)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-try_again:
-         ASM    mov ah, 0x0b
-         ASM    mov dx, nPort
-         ASM    mov al, btToSend
-         ASM    int 20
-         ASM    cmp ax, 0
-         ASM    jne keep_going
-
-         /* Call idle function, if any. */
-         if(pPortInfo->pfIdleCallback != NULL)
-         {
-            (*pPortInfo->pfIdleCallback)();
-         }
-
-         goto try_again;
-keep_going:
-         break;
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-         /* Loop, calling idle function, until characters are waiting in */
-         /* the transmit buffer.                                         */
-         while(!ODComInternalTXReady())
-         {
-            /* Call idle function, if any. */
-            if(pPortInfo->pfIdleCallback != NULL)
-            {
-               (*pPortInfo->pfIdleCallback)();
-            }
-         }
-
-         /* Disable interrupts. */
-         ASM cli
-
-         /* Place the character in the queue. */
-         pbtTXQueue[nTXInIndex++] = btToSend;
-
-         /* Wrap transmit queue index, if needed. */
-         if (nTXInIndex == nTXQueueSize)
-         {
-            nTXInIndex = 0;
-         }
-
-         /* Increment count of total characters in the queue. */
-         nTXChars++;
-
-         /* Enable transmit interrupt on the UART. */
-         ASM mov dx, nIntEnableRegAddr
-         ASM in al, dx
-         ASM or al, THRE
-         ASM out dx, al
-
-         ASM sti
-
-         break;
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwErrors;
-         DWORD dwBytesWritten;
-
-         /* Attempt to perform write operation. */
-         if(!WriteFile(pPortInfo->hCommDev, &btToSend, 1, &dwBytesWritten,
-            NULL) || dwBytesWritten != 1)
-         {
-            ClearCommError(pPortInfo->hCommDev, &dwErrors, NULL);
-            return(kODRCGeneralFailure);
-         }
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorWrite != NULL);
-         if(!(*pPortInfo->pfDoorWrite)(&btToSend, 1))
-         {
-            return(kODRCGeneralFailure);
-         }
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			fd_set	socket_set;
-			struct	timeval tv;
-
-			FD_ZERO(&socket_set);
-			FD_SET(pPortInfo->socket,&socket_set);
-
-			tv.tv_sec=0;
-			tv.tv_usec=0;
-
-			if(select(pPortInfo->socket+1,NULL,&socket_set,NULL,&tv) != 1)
-	         return(kODRCGeneralFailure);
-
-			if(send(pPortInfo->socket,&btToSend,1,0) != 1)
-				return(kODRCGeneralFailure);
-			break;
-		}
-#endif /* INCLUDE_SOCKET_COM */
-
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComGetBuffer()
- *
- * Retreives received data into a buffer, filling the buffer with as much data
- * as possible that has been received, returning immediately.
- *
- * Parameters: hPort       - Handle to a serial port object.
- *
- *             pbtBuffer   - Pointer to a contiguous array of bytes.
- *
- *             nSize       - Size of buffer, in bytes. This is the maximum
- *                           number of characters that will be returned.
- *
- *             pnBytesRead - Pointer to an int where function will store the
- *                           number of bytes actually read.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComGetBuffer(tPortHandle hPort, BYTE *pbtBuffer, int nSize,
-   int *pnBytesRead)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pbtBuffer != NULL);
-   VERIFY_CALL(nSize > 0);
-   VERIFY_CALL(pnBytesRead != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-      {
-         int nReceived;
-
-         ASM    push di
-         ASM    mov cx, nSize
-         ASM    mov dx, nPort
-
-
-#ifdef LARGEDATA
-         ASM    les di, pbtBuffer
-#else
-         ASM    mov ax, ds
-         ASM    mov es, ax
-         ASM    mov di, pbtBuffer
-#endif
-
-         ASM    mov ah, 0x18
-         ASM    int 20
-         ASM    pop di
-         ASM    mov nReceived, ax
-
-         *pnBytesRead = nReceived;
-
-         break;
-      }
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-      {
-         int nTransferSize;
-         int nFirstHalfSize;
-         int nSecondHalfSize;
-         char *pbtSource;
-
-         /* Disable interrupts. */
-         ASM cli
-
-         /* Number of bytes to transfer is minimum of buffer size, and */
-         /* number of bytes in receive queue.                          */
-         nTransferSize = MIN(nRXChars, nSize);
-
-         /* First half of transfer is minimum of number of bytes from here */
-         /* to the end of the buffer, and the total transfer size.         */
-         nFirstHalfSize = nRXQueueSize - nRXOutIndex;
-         nFirstHalfSize = MIN(nFirstHalfSize, nTransferSize);
-
-         /* Second half of transfer is remaining bytes, if any. */
-         nSecondHalfSize = nTransferSize - nFirstHalfSize;
-
-         /* Perform first half of transfer. */
-         pbtSource = pbtRXQueue + nRXOutIndex;
-         while(nFirstHalfSize--)
-         {
-            *pbtBuffer++ = *pbtSource++;
-         }
-
-         /* If there is a second half to transfer. */
-         if(nSecondHalfSize)
-         {
-            /* Copy source will begin at beginning of queue. */
-            pbtSource = pbtRXQueue;
-
-            /* Set final queue out index. */
-            nRXOutIndex = nSecondHalfSize;
-
-            /* Perform second half of transfer. */
-            while(nSecondHalfSize--)
-            {
-               *pbtBuffer++ = *pbtSource++;
-            }
-         }
-
-         /* If entire transfer was performed in first half. */
-         else
-         {
-            /* Set final queue out index. */
-            nRXOutIndex += nTransferSize;
-
-            /* Wrap queue out index, if needed. */
-            if(nRXOutIndex == nRXQueueSize) nRXOutIndex = 0;
-         }
-
-         /* Subtract number of bytes retrieved from number of bytes in */
-         /* receive queue.                                             */
-         nRXChars -= nTransferSize;
-
-         /* Return number of bytes copied into buffer. */
-         *pnBytesRead = nTransferSize;
-
-         /* Re-enable interrupts. */
-         ASM sti
-
-         break;
-      }
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwBytesRead;
-         DWORD dwErrors;
-
-         /* Ensure read timeout state is set for non-blocking read */
-         ODComWin32SetReadTimeouts(pPortInfo, kNonBlocking);
-
-         /* Perform read operation. */
-         if(!ReadFile(pPortInfo->hCommDev, pbtBuffer, nSize, &dwBytesRead,
-            NULL))
-         {
-            ClearCommError(pPortInfo->hCommDev, &dwErrors, NULL);
-            return(kODRCGeneralFailure);
-         }
-
-         /* Pass number of bytes read back to caller. */
-         *pnBytesRead = (int)dwBytesRead;
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorRead != NULL);
-         *pnBytesRead = (int)((*pPortInfo->pfDoorRead)(pbtBuffer, nSize));
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			fd_set	socket_set;
-			struct	timeval tv;
-
-			FD_ZERO(&socket_set);
-			FD_SET(pPortInfo->socket,&socket_set);
-
-			tv.tv_sec=0;
-			tv.tv_usec=0;
-
-			if(select(pPortInfo->socket+1,&socket_set,NULL,NULL,&tv) != 1) {
-				*pnBytesRead = 0;
-	         break;
-			}
-
-			*pnBytesRead = recv(pPortInfo->socket,pbtBuffer,nSize,0);
-			break;
-		}
-#endif /* INCLUDE_SOCKET_COM */
-
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComSendBuffer()
- *
- * Sends the contents of an entire buffer to the serial port, waiting until
- * there is enough room in the serial port outbound buffer.
- *
- * Parameters: hPort     - Handle to a serial port object.
- *
- *             pbtBuffer - Pointer to the first byte in the buffer to transmit.
- *
- *             nSize     - Number of bytes to transmit from the buffer.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComSendBuffer(tPortHandle hPort, BYTE *pbtBuffer, int nSize)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-   int nPort;
-
-   VERIFY_CALL(pPortInfo != NULL);
-   VERIFY_CALL(pbtBuffer != NULL);
-   VERIFY_CALL(nSize >= 0);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   nPort = pPortInfo->btPort;
-
-   /* If there are no characters to transmit, then there is no need to */
-   /* proceed further.                                                 */
-   if(nSize == 0)
-   {
-      return(kODRCSuccess);
-   }
-
-   switch(pPortInfo->Method)
-   {
-#ifdef INCLUDE_FOSSIL_COM
-      case kComMethodFOSSIL:
-      {
-         int nCount;
-
-try_again:
-         ASM    push di
-         ASM    mov cx, nSize
-         ASM    mov dx, nPort
-
-
-#ifdef LARGEDATA
-         ASM    les di, pbtBuffer
-#else
-         ASM    mov ax, ds
-         ASM    mov es, ax
-         ASM    mov di, pbtBuffer
-#endif
-
-         ASM    mov ah, 0x19
-         ASM    int 20
-         ASM    pop di
-         ASM    mov nCount, ax
-
-         if(nCount<nSize)
-         {
-            /* Call idle function, if any. */
-            if(pPortInfo->pfIdleCallback != NULL)
-            {
-               (*pPortInfo->pfIdleCallback)();
-            }
-
-            nSize-=nCount;
-            pbtBuffer+=nCount;
-            goto try_again;
-         }
-         break;
-      }
-#endif /* INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_UART_COM
-      case kComMethodUART:
-      {
-         int nTransferSize;
-         int nFirstHalfSize;
-         int nSecondHalfSize;
-         char *pbtDest;
-
-         /* Loop, copying as much of buffer to transmit queue as possible, */
-         /* then waiting for some characters to be transmitted, and copy   */
-         /* more of buffer to transmit queue, until entire buffer has been */
-         /* transferred.                                                   */
-         for(;;)
-         {
-            /* Disable interrupts. */
-            ASM cli
-
-            /* Try to transfer all of buffer if possible. */
-            nTransferSize = nSize;
-
-            /* Adjust number of character to transfer down if there isn't */
-            /* enough space in transmit queue.                            */
-            if(nTransferSize > (nTXQueueSize - nTXChars))
-            {
-               nTransferSize = (nTXQueueSize - nTXChars);
-            }
-
-            /* Block transfer is divided into two segments - everything from */
-            /* current in index to end of queue, and everything from         */
-            /* beginning of queue to end of free space in queue.             */
-
-            /* Calculate size of first half of transfer. */
-            nFirstHalfSize = nTXQueueSize - nTXInIndex;
-            if(nFirstHalfSize > nTransferSize) nFirstHalfSize = nTransferSize;
-
-            /* Calculate size of second half of transfer. */
-            nSecondHalfSize = nTransferSize - nFirstHalfSize;
-
-            /* Transfer characters at current queue in index. */
-            pbtDest = pbtTXQueue + nTXInIndex;
-            while(nFirstHalfSize--)
-            {
-               *pbtDest++ = *pbtBuffer++;
-            }
-
-            /* If there is a second half to transfer. */
-            if(nSecondHalfSize)
-            {
-               /* Copy destination will begin at beginning of queue. */
-               pbtDest = pbtTXQueue;
-
-               /* Set final queue in index. */
-               nTXInIndex = nSecondHalfSize;
-
-               /* Perform second half of transfer. */
-               while(nSecondHalfSize--)
-               {
-                  *pbtDest++ = *pbtBuffer++;
-               }
-            }
-
-            /* If entire transfer was performed in first half. */
-            else
-            {
-               /* Set final queue in index. */
-               nTXInIndex += nTransferSize;
-
-               /* Wrap queue in index if we just happened to fill characters */
-               /* up to end of physical queue. If there was one less         */
-               /* character transferred, no wrap would be necessary, and if  */
-               /* there was one more character to be transferred, transfer   */
-               /* would have to be performed in two halves.                  */
-               if(nTXInIndex == nTXQueueSize) nTXInIndex = 0;
-            }
-
-            /* Update count of total characters in the queue. */
-            nTXChars += nTransferSize;
-
-            /* Enable transmit interrupt on the UART. */
-            ASM mov dx, nIntEnableRegAddr
-            ASM in al, dx
-            ASM or al, THRE
-            ASM out dx, al
-
-            /* Re-enable interrupts. */
-            ASM sti
-
-            /* Adjust count of characters left to transfer down by number of */
-            /* characters transferred.                                       */
-            nSize -= nTransferSize;
-
-            /* If there are no characters left to transfer, then we are */
-            /* done.                                                    */
-            if(nSize == 0) break;
-
-            /* Call idle function, if any. */
-            if(pPortInfo->pfIdleCallback != NULL)
-            {
-               (*pPortInfo->pfIdleCallback)();
-            }
-         }
-         break;
-      }
-#endif /* INCLUDE_UART_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwErrors;
-         DWORD dwBytesWritten;
-
-         /* Attempt to perform write operation. */
-         if(!WriteFile(pPortInfo->hCommDev, pbtBuffer, nSize, &dwBytesWritten,
-            NULL) || dwBytesWritten != (DWORD)nSize)
-         {
-            ClearCommError(pPortInfo->hCommDev, &dwErrors, NULL);
-            return(kODRCGeneralFailure);
-         }
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         ASSERT(pPortInfo->pfDoorWrite != NULL);
-         if(!(*pPortInfo->pfDoorWrite)(pbtBuffer, nSize))
-         {
-            return(kODRCGeneralFailure);
-         }
-         break;
-         return(kODRCUnsupported);
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			fd_set	socket_set;
-			struct	timeval tv;
-
-			FD_ZERO(&socket_set);
-			FD_SET(pPortInfo->socket,&socket_set);
-
-			tv.tv_sec=0;
-			tv.tv_usec=0;
-
-			if(select(pPortInfo->socket+1,NULL,&socket_set,NULL,&tv) != 1)
-	         return(kODRCGeneralFailure);
-
-			if(send(pPortInfo->socket,pbtBuffer,nSize,0) != nSize)
-				return(kODRCGeneralFailure);
-			break;
-		}
-#endif /* INCLUDE_SOCKET_COM */
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODComWaitEvent()
- *
- * Blocks until the specified serial I/O event occurs, or an error condition
- * is encountered.
- *
- * Parameters: hPort - Handle to an open port.
- *
- *             Event - Event type to wait for.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODComWaitEvent(tPortHandle hPort, tComEvent Event)
-{
-   tPortInfo *pPortInfo = ODHANDLE2PTR(hPort, tPortInfo);
-
-   VERIFY_CALL(pPortInfo != NULL);
-
-   VERIFY_CALL(pPortInfo->bIsOpen);
-
-   switch(pPortInfo->Method)
-   {
-#if defined(INCLUDE_UART_COM) || defined(INCLUDE_FOSSIL_COM)
-      case kComMethodFOSSIL:
-      case kComMethodUART:
-         switch(Event)
-         {
-            case kNoCarrier:
-            {
-               BOOL bCarrier;
-               for(;;)
-               {
-                  ODComCarrier(hPort, &bCarrier);
-                  if(!bCarrier) break;
-
-                  if(pPortInfo->pfIdleCallback != NULL)
-                  {
-                     (*pPortInfo->pfIdleCallback)();
-                  }
-               }
-               break;
-            }
-            default:
-               VERIFY_CALL(FALSE);
-         }
-         break;
-#endif /* INCLUDE_UART_COM || INCLUDE_FOSSIL_COM */
-
-#ifdef INCLUDE_WIN32_COM
-      case kComMethodWin32:
-      {
-         DWORD dwEvtMask;
-
-         /* Obtain current event mask. */
-         if(!GetCommMask(pPortInfo->hCommDev, &dwEvtMask))
-         {
-            return(kODRCGeneralFailure);
-         }
-
-         /* Turn on event to be waited for. */
-         switch(Event)
-         {
-            case kNoCarrier:
-               dwEvtMask |= EV_RLSD;
-               break;
-            default:
-               VERIFY_CALL(FALSE);
-         }
-
-         /* Write new event mask. */
-         if(!SetCommMask(pPortInfo->hCommDev, dwEvtMask))
-         {
-            return(kODRCGeneralFailure);
-         }
-
-         /* Wait until event occurs. */
-         for(;;)
-         {
-            /* Block until some event occurs. */
-            if(!WaitCommEvent(pPortInfo->hCommDev, &dwEvtMask, NULL))
-            {
-               return(kODRCGeneralFailure);
-            }
-
-            /* Determine whether this is what we are waiting for. */
-            switch(Event)
-            {
-               case kNoCarrier:
-                  if(dwEvtMask | EV_RLSD)
-                  {
-                     BOOL bCarrier;
-                     ODComCarrier(hPort, &bCarrier);
-                     if(!bCarrier)
-                     {
-                        return(kODRCSuccess);
-                     }
-                  }
-                  break;
-            }
-
-            /* If we get here, the event we are waiting for hasn't occurred */
-            /* yet, so loop and block waiting for next event.               */
-         }
-
-         break;
-      }
-#endif /* INCLUDE_WIN32_COM */
-
-#ifdef INCLUDE_DOOR32_COM
-      case kComMethodDoor32:
-         switch(Event)
-         {
-            case kNoCarrier:
-               ASSERT(pPortInfo->pfDoorGetOfflineEventHandle != NULL);
-               WaitForSingleObject(
-                  (*pPortInfo->pfDoorGetOfflineEventHandle)(), INFINITE);
-               break;
-            default:
-               VERIFY_CALL(FALSE);
-         }
-         break;
-#endif /* INCLUDE_DOOR32_COM */
-
-#ifdef INCLUDE_SOCKET_COM
-      case kComMethodSocket:
-		{
-			if(Event == kNoCarrier)
-			{
-  			/* Wait for socket disconnect */
-				fd_set	socket_set;
-				char		ch;
-
-				while(1) 
-				{
-
-					FD_ZERO(&socket_set);
-					FD_SET(pPortInfo->socket,&socket_set);
-					if(select(pPortInfo->socket+1,&socket_set,NULL,NULL,NULL)
-						==SOCKET_ERROR)
-						break;
-					if(recv(pPortInfo->socket+1,&ch,1,MSG_PEEK)!=1)
-						break;
-				}
-			} 
-			else
-			{
-				VERIFY_CALL(FALSE);
-			}
-			break;
-		}
-#endif /* INCLUDE_SOCKET_COM */
-
-
-      default:
-         /* If we get here, then the current serial I/O method is not */
-         /* handled by this function.                                 */
-         ASSERT(FALSE);
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
diff --git a/src/odoors/ODCom.h b/src/odoors/ODCom.h
deleted file mode 100644
index ccd3a372d5f99bf924d07e0639c35845373f762d..0000000000000000000000000000000000000000
--- a/src/odoors/ODCom.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCom.h
- *
- * Description: Public definitions for serial communications module, which
- *              is implemented in odcom.c
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 21, 1994  6.00  BP   Created.
- *              Jan 01, 1995  6.00  BP   Added ODComWaitEvent().
- *              Dec 21, 1995  6.00  BP   Add ability to use already open port.
- *              Jan 09, 1996  6.00  BP   Supply actual in/out buffer size used.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Initial support for Door32 interface.
- *              Oct 19, 2001  6.20  RS   Added TCP/IP socket (telnet) support.
- */
-
-#ifndef _INC_ODCOM
-#define _INC_ODCOM
-
-/* odtypes.h is needed for definitions of tODHandle, and BOOL. */
-#include "ODTypes.h"
-
-/* Serial I/O handle. */
-typedef tODHandle tPortHandle;
-
-/* Flow Control setting manifest constants. */
-#define FLOW_NONE           0x00
-#define FLOW_RTSCTS         0x02
-#define FLOW_DEFAULT        0x80
-
-/* Parity bit setting manifest constants. */
-#define ODPARITY_NONE         0x00
-#define ODPARITY_ODD          0x08
-#define ODPARITY_EVEN         0x18
-
-#define ODPARITY_MASK         0x18
-
-/* Stop bit setting manifest constants. */
-#define STOP_ONE            0x00
-#define STOP_ONE_POINT_FIVE 0x04                 /* Only with DATABITS_FIVE. */
-#define STOP_TWO            0x04         /* Only if not using DATABITS_FIVE. */
-
-#define STOP_MASK           0x04
-
-/* Character length manifest constants. */
-#define DATABITS_FIVE       0x00
-#define DATABITS_SIX        0x01
-#define DATABITS_SEVEN      0x02
-#define DATABITS_EIGHT      0x03
-
-#define DATABITS_MASK       0x03
-
-/* FIFO setting constants. */
-#define FIFO_DISABLE        0x00
-#define FIFO_ENABLE         0x01
-#define FIFO_TRIGGER_1      0x00
-#define FIFO_TRIGGER_4      0x40
-#define FIFO_TRIGGER_8      0x80
-#define FIFO_TRIGGER_14     0xc0
-
-/* Misc. manifest constants. */
-#define SPEED_UNSPECIFIED   0
-#define SIZE_NON_ZERO       -1
-
-/* Serial I/O method settings. */
-typedef enum
-{
-   kComMethodUnspecified,
-   kComMethodFOSSIL,
-   kComMethodUART,
-   kComMethodWin32,
-   kComMethodDoor32,
-	kComMethodSocket,
-} tComMethod;
-
-/* Serial I/O event types. */
-typedef enum
-{
-   kNoCarrier
-} tComEvent;
-
-/* Serial I/O function prototypes. */
-tODResult ODComAlloc(tPortHandle *phPort);
-tODResult ODComFree(tPortHandle hPort);
-tODResult ODComSetIdleFunction(tPortHandle hPort,
-   void (*pfCallback)(void));
-tODResult ODComSetFlowControl(tPortHandle hPort, BYTE btFlowControlSetting);
-tODResult ODComSetSpeed(tPortHandle hPort, long lSpeed);
-tODResult ODComSetPort(tPortHandle hPort, BYTE btPort);
-tODResult ODComSetIRQ(tPortHandle hPort, BYTE btIRQLevel);
-tODResult ODComSetPortAddress(tPortHandle hPort, int nPortAddress);
-tODResult ODComSetWordFormat(tPortHandle hPort, BYTE btWordFormat);
-tODResult ODComSetRXBuf(tPortHandle hPort, int nReceiveBufferSize);
-tODResult ODComSetTXBuf(tPortHandle hPort, int nTransmitBufferSize);
-tODResult ODComSetFIFO(tPortHandle hPort, BYTE btFIFOSetting);
-tODResult ODComSetPreferredMethod(tPortHandle hPort, tComMethod Method);
-tODResult ODComGetMethod(tPortHandle hPort, tComMethod *pMethod);
-tODResult ODComOpen(tPortHandle hPort);
-tODResult ODComOpenFromExistingHandle(tPortHandle hPort,
-   DWORD dwExistingHandle);
-tODResult ODComClose(tPortHandle hPort);
-tODResult ODComClearInbound(tPortHandle hPort);
-tODResult ODComClearOutbound(tPortHandle hPort);
-tODResult ODComInbound(tPortHandle hPort, int *pnInboundWaiting);
-tODResult ODComOutbound(tPortHandle hPort, int *pnOutboundWaiting);
-tODResult ODComCarrier(tPortHandle hPort, BOOL *pbIsCarrier);
-tODResult ODComSetDTR(tPortHandle hPort, BOOL bHigh);
-tODResult ODComSendByte(tPortHandle hPort, BYTE btToSend);
-tODResult ODComGetByte(tPortHandle hPort, char *pbtNext, BOOL bWait);
-tODResult ODComSendBuffer(tPortHandle hPort, BYTE *pbtBuffer, int nSize);
-tODResult ODComGetBuffer(tPortHandle hPort, BYTE *pbtBuffer, int nSize,
-   int *pnBytesRead);
-tODResult ODComWaitEvent(tPortHandle hPort, tComEvent Event);
-
-#endif /* !_INC_ODCOM */
diff --git a/src/odoors/ODCore.c b/src/odoors/ODCore.c
deleted file mode 100644
index 0d481dfcddff9a8a8e5ff84569d9f4c6f9b66dd2..0000000000000000000000000000000000000000
--- a/src/odoors/ODCore.c
+++ /dev/null
@@ -1,1576 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCore.c
- *
- * Description: Implements the core of OpenDoors, including chat mode
- *              and standard input/output functions that are
- *              used throughout OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 19, 1994  6.00  BP   Changed paging hours logic.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Oct 22, 1994  6.00  BP   Name case conversion /w punct.
- *              Dec 08, 1994  6.00  BP   Allow custom chat mode deactivation.
- *              Dec 09, 1994  6.00  BP   Remove global dir entry structure.
- *              Dec 13, 1994  6.00  BP   Remove include of dir.h.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Dec 31, 1994  6.00  BP   Remove old multitasker definitions.
- *              Jan 01, 1995  6.00  BP   Don't use ODComInbound().
- *              Jan 01, 1995  6.00  BP   _waitdrain() -> ODWaitDrain().
- *              Jan 01, 1995  6.00  BP   Use new millisecond timer functions.
- *              Jan 01, 1995  6.00  BP   Remove od_init() from _remotechar()
- *              Jan 01, 1995  6.00  BP   Split off odkrnl.c from odcore.c
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Moved first_word() to odlist.c
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Create odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Dec 12, 1995  6.00  BP   Added od_set_color().
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 13, 1995  6.00  BP   Moved chat mode code to ODKrnl.h.
- *              Dec 19, 1995  6.00  BP   Request reason for chat outside hours.
- *              Dec 23, 1995  6.00  BP   Allow space to continue at page pause.
- *              Dec 24, 1995  6.00  BP   Added abtGreyBlock.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Use OD_API_VAR_DEFN for od_control.
- *              Jan 04, 1996  6.00  BP   tODInQueueEvent -> tODInputEvent.
- *              Jan 23, 1996  6.00  BP   No od_set_statusline() under Win32.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add ODInQueueGetNextEvent() timeout.
- *              Jan 09, 1996  6.00  BP   ODComOutbound() returns actual size.
- *              Jan 09, 1996  6.00  BP   Reduce kernel calls from od_disp...().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Mar 21, 1996  6.10  BP   Added od_control_get().
- *              Sep 01, 1996  6.10  BP   Update output area on od_set_per...().
- *              Oct 19, 2001  6.20  RS   od_get_key now ignores linefeeds.
- *              Mar 14, 2002  6.22  RS   Fixed od_get_key(bWait=FALSE)
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include <errno.h>
-
-#include "OpenDoor.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODCom.h"
-#include "ODKrnl.h"
-#include "ODScrn.h"
-#include "ODCore.h"
-#include "ODInQue.h"
-#ifdef ODPLAT_WIN32
-#include "ODFrame.h"
-#endif /* ODPLAT_WIN32 */
-
-
-/* GLOBAL VARIABLES SHARED THROUGHOUT OPENDOORS. */
-
-/* Global declaration of the OpenDoors control structure. */
-OD_API_VAR_DEFN tODControl 
-#ifndef _WIN32	/* warning C4229: anachronism used : modifiers on data are ignored */
-OD_GLOBAL_CONV 
-#endif
-od_control;
-
-/* OpenDoors global initialized flag. */
-BOOL bODInitialized = FALSE;
-
-/* Global serial port object handle. */
-tPortHandle hSerialPort;
-
-/* Global input queue object handle. */
-tODInQueueHandle hODInputQueue;
-
-/* Reentrancy control. */
-BOOL bIsCallbackActive = FALSE;
-BOOL bShellChatActive = FALSE;
-
-/* Global working space. */
-char szODWorkString[OD_GLOBAL_WORK_STRING_SIZE];
-
-/* Global instance of the text information structure for general use. */
-tODScrnTextInfo ODTextInfo;
-
-/* Logfile function hooks. */
-BOOL (*pfLogWrite)(INT) = NULL;
-void (*pfLogClose)(INT) = NULL;
-
-/* od_color_config() support for od_printf(). */
-char chColorCheck = 0;
-char *pchColorEndPos;
-
-/* Status line information. */
-BYTE btCurrentStatusLine = STATUS_NONE;
-OD_PERSONALITY_CALLBACK *pfCurrentPersonality = NULL;
-char szDesiredPersonality[33] = "";
-extern SET_PERSONALITY_FUNC *pfSetPersonality = NULL;
-
-/* Commonly used character sequences. */
-char abtBlackBlock[2] = {' ', 0x07};
-char abtGreyBlock[2] = {' ', 0x70};
-char szBackspaceWithDelete[4] = {8, ' ', 8, 0};
-
-/* Current output area on screen. */
-BYTE btOutputTop = 1;
-BYTE btOutputBottom = 23;
-
-
-/* PRIVATE VARIABLES. */
-
-/* Display color varaibles. */
-char bAnyColorChangeYet;
-
-/* Static character sequences. */
-static char szClearScreen[2] = {12, 0};
-
-/* Lookup table to map colors from PC values to ANSI color values. */
-static BYTE abtPCToANSIColorTable[8] = {30, 34, 32, 36, 31, 35, 33, 37};
-
-
-/* LOCAL HELPER FUNCTIONS. */
-static void ODAddANSIParameter(char *szControlSequence, int nParameterValue);
-
-
-/* ----------------------------------------------------------------------------
- * ODWaitDrain()
- *
- * Waits for up to the specified number of milliseconds for the output serial
- * buffer to drain.
- *
- * Parameters: MaxWait - Specifies the maximum number of milliseconds to wait
- *                       before timing out.
- *
- *     Return: void
- */
-void ODWaitDrain(tODMilliSec MaxWait)
-{
-   int nOutboundSize;
-   tODTimer Timer;
-
-   /* If we are operating in local mode, then don't do anything. */
-   if(od_control.baud == 0) return;
-
-   /* Otherwise, start a timer that is set to elapse after the maximum */
-   /* wait period.                                                     */
-   ODTimerStart(&Timer, MaxWait);
-
-   /* Loop until either the outbound buffer is empty, or the */
-   /* timer has elapsed.                                     */
-   for(;;)
-   {
-      /* Check whether any data is in the outbound serial queue. */
-      ODComOutbound(hSerialPort, &nOutboundSize);
-
-      /* If the queue is empty or the timer has elapsed, then stop */
-      /* waiting.                                                  */
-      if(nOutboundSize == 0 || ODTimerElapsed(&Timer)) break;
-
-      /* Otherwise, give other tasks a chance to run. */
-      od_sleep(0);
-
-      /* Give od_kernel() activities a chance to run. */
-      CALL_KERNEL_IF_NEEDED();
-   } 
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_clr_scr()
- *
- * Clears the contents of the local and remote screens, if screen clearing is
- * enabled.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_clr_scr(void)
-{
-   INT16 nOriginalAttrib;
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_clr_scr()");
-
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Don't clear screen if disabled. */
-   if(!od_control.od_always_clear && !(od_control.user_attribute & 2)
-      && (od_control.od_extended_info || od_control.od_info_type == CUSTOM))
-   {
-      OD_API_EXIT();
-      return;
-   }
-
-   if(od_control.user_rip)
-   {
-      od_disp("!|*", 3, FALSE);
-      if(!od_control.od_default_rip_win)
-      {
-         od_disp("!|w0000270M12", 13, FALSE);
-      }
-   }
-
-   /* Send ascii 12 to modem, no local echo. */
-   od_disp(szClearScreen, 1, FALSE);
-
-   /* Clear local window. */
-   ODScrnClear();
-
-   /* Get color set prior to screen clear. */
-   nOriginalAttrib = od_control.od_cur_attrib;
-
-   /* Current color state is unknown. */
-   od_control.od_cur_attrib = -1;
-
-   /* Set color to original value. This gurantees that local and */
-   /* remote systems both have the same current color set.       */
-   od_set_attrib(nOriginalAttrib);
-
-   OD_API_EXIT();
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * od_input_str()
- *
- * Allows the user to input a string up to the specified length, using
- * characters in the specified range. This string input function is designed
- * to be compatible with all terminal types.
- *
- * Parameters: pszInput   - Pointer to string to store input in.
- *
- *             nMaxLength - Maximum number of characters to permit the user
- *                          to input.
- *
- *             chMin      - The minimum character value to permit. This must
- *                          be at least ASCII 32.
- *
- *             chMax      - The maximum character value to permit.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_input_str(char *pszInput, 
-   INT nMaxLength,
-   unsigned char chMin,
-   unsigned char chMax)
-{
-   char chKeyPressed;
-   INT nPosition;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_input_str()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Start at the beginning of the string. */
-   nPosition = 0;
-
-   /* Check that input parameters are valid. */
-   if(pszInput == NULL || nMaxLength < 1 || chMin > chMax)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return;
-   }
-
-   for(;;)
-   {
-      chKeyPressed = od_get_key(TRUE);
-
-      /* If user pressed enter. */
-      if(chKeyPressed == '\r' || chKeyPressed == '\n')
-      {
-         /* Terminate the string. */
-         pszInput[nPosition] = '\0';
-
-         /* Display CR-LF sequence. */
-         od_disp_str("\n\r");
-
-         /* Exit the function. */
-         OD_API_EXIT();
-         return;
-      }
-
-      /* If the user pressed backspace. */
-      else if(chKeyPressed == 8)
-      {
-         /* If we are not currently at the beginning of the string. */
-         if(nPosition > 0)
-         {
-            /* Send backspace sequence. */
-            od_disp_str(szBackspaceWithDelete);
-
-            /* Move current position back by one position in the string. */
-            --nPosition;
-         }
-      }
-
-      /* If this is a valid character to place in the string and we have */
-      /* not reached the maximum size of the string yet.                 */
-      else if(chKeyPressed >= chMin && chKeyPressed <= chMax
-         && nPosition < nMaxLength)
-      {
-         /* Display key that was pressed. */
-         od_putch(chKeyPressed);
-
-         /* Add the entered character to the string and increment our */
-         /* current position in the string.                           */
-         pszInput[nPosition++] = chKeyPressed;
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_clear_keybuffer()
- *
- * Clears any keystrokes from the inbound buffers. Both input from local and
- * remote systems is discarded, by clearing both OpenDoors' common input
- * event queue, and the serial port inbound buffer. This function is called
- * to cause any input by the user prior to the time the function was called
- * to be ignored.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_clear_keybuffer(void)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_clear_keybuffer()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Empty any events in the common input event queue. */
-   ODInQueueEmpty(hODInputQueue);
-
-   /* If we are not operating in local mode ... */
-   if(od_control.baud != 0)
-   {
-      /* ... then remove any items in the serial port inbound buffer. */
-      ODComClearInbound(hSerialPort);
-   }
-
-   /* Call the OpenDoors kernel function. */
-   CALL_KERNEL_IF_NEEDED();
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_get_key()
- *
- * Inputs a single character, optionally waiting for the next character if no
- * character has been received yet. This function returns data received from
- * either the local or remote system, in the order in which it was received.
- *
- * Parameters: bWait - FALSE if od_get_key() should return right away with
- *                     a value of 0 if no characters have been received, or
- *                     TRUE if od_get_key() should wait for the next received
- *                     character.
- *
- *     Return: Character that was received, or 0 if no character is waiting.
- */
-ODAPIDEF char ODCALL od_get_key(BOOL bWait)
-{
-   tODInputEvent InputEvent;
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_get_key()");
-
-   OD_API_ENTRY();
-
-   /* Call the OpenDoors kernel. */
-   CALL_KERNEL_IF_NEEDED();
-
-	do {
-
-	   /* If we aren't supposed to wait for input, then check whether any   */
-	   /* input is waiting in the input queue, and if not return right away */
-	   /* without any data.                                                 */
-	   if(!bWait)
-	   {
-		  if(!ODInQueueWaiting(hODInputQueue))
-		  {
-			 OD_API_EXIT();
-			 return(0);
-		  }
-	   }
-
-		/* Obtain the next character from the input queue. If we get to this */
-		/* point and there is no data waiting in the input queue, then the   */
-		/* ODInQueueGetNextEvent() function will block until a character     */
-		/* is available in the input queue.                                  */
-		ODInQueueGetNextEvent(hODInputQueue, &InputEvent, OD_NO_TIMEOUT);
-
-		/* Only keyboard input events are currently supported by od_get_key(). */
-		ASSERT(InputEvent.EventType == EVENT_CHARACTER);
-
-		/* Update OpenDoors control structure member that records whether the */
-		/* last input came from the local or remote user.                     */
-		od_control.od_last_input = InputEvent.bFromRemote ? 0 : 1;
-
-	} while(InputEvent.chKeyPress == '\n');	/* Ignore line-feed char */
-
-   /* Return the character that was pressed by the user. */
-   OD_API_EXIT();
-   return(InputEvent.chKeyPress);
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * od_carrier()
- *
- * Allows programs to determine the current state of the carrier detect
- * signal when OpenDoors' automatic carrier detection has been disabled.
- *
- * Parameters: none
- *
- *     Return: TRUE if the carrier detct signal is present, FALSE if it
- *             isn't. When operating in local mode, this function always
- *             returns FALSE.
- */
-ODAPIDEF BOOL ODCALL od_carrier(void)
-{
-   BOOL bIsCarrier;
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_carrier()");
-
-   /* If we are operating in local mode, then return FALSE. */
-   if(od_control.baud == 0)
-   {
-      od_control.od_error = ERR_NOREMOTE;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* In remote mode, obtain the current state of the carrier detect signal. */
-   ODComCarrier(hSerialPort, &bIsCarrier);
-
-   /* Return the current state of the carrier detect signal. */
-   OD_API_EXIT();
-   return(bIsCarrier);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_repeat()
- *
- * This function displays the same character the specified number of times on
- * the local and remote screens, using any available optimal control sequences
- * under the current display mode.
- *
- * Parameters: chValue - Character to repeat.
- *
- *             btTimes - Number of times to repeat the character.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_repeat(char chValue, BYTE btTimes)
-{
-   char *pchCurStringPos;
-   BYTE btLeft;
-   char szBuffer[3];
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_repeat()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* If the caller asked to repeat the character 0 times, then we can */
-   /* safely return right away without doing anything.                 */
-   if(btTimes == 0)
-   {
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Generate string of repeat characters. */
-   pchCurStringPos = szODWorkString; 
-   for(btLeft = btTimes; btLeft--;)
-   {
-      *pchCurStringPos++ = chValue;
-   }
-   *pchCurStringPos = '\0';
-
-   /* Display repeated string on local screen. */
-   ODScrnDisplayString(szODWorkString);
-
-   /* If we are operating in AVATAR mode. */
-   if(od_control.user_avatar)
-   {
-      /* Generate the AVATAR control sequence to repeat this character */
-      /* the specified number of times.                                */
-      szBuffer[0] = 25;
-      szBuffer[1] = chValue;
-      szBuffer[2] = btTimes;
-      od_disp(szBuffer, 3, FALSE);
-   }
-
-   /* If AVATAR mode is not available. */
-   else
-   {
-      /* Send the entire repeated string to the remote system. */
-      od_disp(szODWorkString, btTimes, FALSE);
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_page()
- *
- * This function is called when the user wished to page the system operator.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_page(void)
-{
-   INT16 nCount;
-   tODTimer Timer;
-   time_t nUnixTime;
-   struct tm *TimeBlock;
-   INT16 nMinute;
-   BOOL bFailed = FALSE;
-   INT16 nOriginalAttrib;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_page()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Save current display color attribute. */
-   nOriginalAttrib = od_control.od_cur_attrib;
-
-   /* Clear the screen. */
-   od_clr_scr();
-   od_set_attrib(od_control.od_chat_color1);
-
-   /* Ask reason for chat. */
-   od_disp_str(od_control.od_chat_reason);
-   od_set_attrib(od_control.od_chat_color2);
-   od_putch('[');
-
-   /* Use extended ASCII characters if operating in ANSI or AVATAR mode. */
-   if(od_control.user_ansi || od_control.user_avatar)
-   {
-      od_repeat('�',77);
-   }
-   else
-   {
-      od_repeat('-',77);
-   }
-   od_disp_str("]\n\r ");
-   od_input_str(od_control.user_reasonforchat,77,32,255);
-
-   /* If the user did not abort sysop paging by entering a blank reason */
-   /* for chat.                                                         */
-   if(strlen(od_control.user_reasonforchat) != 0)
-   {
-      /* Indicate that the user wants to chat. */
-      od_control.user_wantchat = TRUE;
-#ifdef ODPLAT_WIN32
-      ODFrameUpdateWantChat();
-#endif /* ODPLAT_WIN32 */
-
-      /* Determine whether or not sysop paging should be permitted at */
-      /* the current time.                                            */
-      nUnixTime = time(NULL);
-      TimeBlock = localtime(&nUnixTime);
-      nMinute = (60 * TimeBlock->tm_hour) + TimeBlock->tm_min;
-      if(od_control.od_pagestartmin < od_control.od_pageendmin)
-      {
-         if(nMinute < od_control.od_pagestartmin
-            || nMinute >= od_control.od_pageendmin)
-         {
-            bFailed = TRUE;
-         }
-      }
-      else if(od_control.od_pagestartmin > od_control.od_pageendmin)
-      {
-         if(nMinute < od_control.od_pagestartmin
-            && nMinute >= od_control.od_pageendmin)
-         {
-            bFailed = TRUE;
-         }
-      }
-      else
-      {
-         bFailed = FALSE;
-      }
-
-      /* If paging is set to PAGE_ENABLE, meaning that sysop paging should */
-      /* be permitted regardless of the time of day, then allow paging.    */
-      if(od_control.od_okaytopage == PAGE_ENABLE)
-      {
-         bFailed = FALSE;
-      }
-
-      /* If paging is explicitly disable by PAGE_DISABLE, or the current */
-      /* time of the day is not normally permitted for paging.           */
-      if(od_control.od_okaytopage == PAGE_DISABLE || bFailed)
-      {
-         /* Indicate this to user. */
-         od_disp_str("\n\r");
-         od_disp_str(od_control.od_no_sysop);
-         od_disp_str(od_control.od_press_key);
-         od_get_answer("\x0d\x0a");
-
-         /* Return from this function. */
-         goto cleanup;
-      }
-
-      /* Update status line right away. */
-      bForceStatusUpdate = TRUE;
-      CALL_KERNEL_IF_NEEDED();
-
-      /* Write sysop page information to the logfile, if the log file */
-      /* system is hooked up.                                         */
-      if(pfLogWrite != NULL)
-      {
-         (*pfLogWrite)(8);
-      }
-
-      /* Tell the user that we are now paging the system operator. */
-      od_set_attrib(od_control.od_chat_color1);
-      od_disp_str(od_control.od_paging);
-
-#ifdef OD_TEXTMODE
-      /* Display sysop page status line if it exists and the sysop status */
-      /* line is currently active.                                        */
-      if(od_control.od_page_statusline != -1 && btCurrentStatusLine != 8)
-      {
-         od_set_statusline(od_control.od_page_statusline);
-      }
-#endif /* OD_TEXTMODE */
-
-      /* Increment the total number of times that the user has paged */
-      /* the sysop.                                                  */
-      ++od_control.user_numpages;
-
-      /* Sysop hasn't responded yet. */
-      bChatted=FALSE;
-
-      /* Loop for length of sysop page. */
-      for(nCount = 0; nCount < od_control.od_page_len; ++nCount)
-      {
-         /* Start a timer that is set to elapse in exactly one second. */
-         ODTimerStart(&Timer, 1000);
-
-         /* Display another period character. */
-         od_putch('.');
-
-         /* Abort page if system operator answered */
-         if(bChatted) goto cleanup;
-
-         /* Send beep to local and remote systems. */
-         od_putch('\a');
-
-         /* Check whether system operator has answered after playing beep. */
-         if (bChatted) goto cleanup;
-
-         /* Wait for the timer to elapse, calling od_kernel() so that */
-         /* chat mode will start as soon as the sysop presses the     */
-         /* chat key.                                                 */
-         while(!ODTimerElapsed(&Timer))
-         {
-            CALL_KERNEL_IF_NEEDED();
-         }
-      }
-
-      /* If sysop page time has elapsed without a response from the */
-      /* sysop, then notify the user.                               */
-      od_disp_str(od_control.od_no_response);
-      od_disp_str(od_control.od_press_key);
-      od_get_answer("\x0d\x0a");
-      od_disp_str("\n\r\n\r");
-   }
-
-cleanup:
-   /* Restore original display color attribute. */
-   od_set_attrib(nOriginalAttrib);
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_disp()
- *
- * Function to send one or more character to the remote system, optionally
- * also echoing the same characters to the local screen.
- *
- * Parameters: pachBuffer - Pointer to buffer of characters to send.
- *
- *             nSize      - Number of characters to send from the buffer.
- *
- *             bLocalEcho - TRUE to also echo the characters to the local
- *                          screen, FALSE to just send the characters to the
- *                          remote system.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_disp(char *pachBuffer, INT nSize, BOOL bLocalEcho)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_disp()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Call the OpenDoors kernel, if needed. */
-#ifndef OD_MULTITHREADED
-   if(ODTimerElapsed(&RunKernelTimer))
-   {
-      CALL_KERNEL_IF_NEEDED();
-   }
-#endif /* !OD_MULTITHREADED */
-
-   /* If we are operating in remote mode, then send the buffer to the */
-   /* remote system.                                                  */
-   if(od_control.baud != 0)
-   {
-      ODComSendBuffer(hSerialPort, (BYTE *)pachBuffer, nSize);
-   }
-
-   /* If we are also to display the character on the local screen, then */
-   /* display the buffer on the local screen.                           */
-   if(bLocalEcho)
-   {
-      ODScrnDisplayBuffer(pachBuffer, nSize);
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_disp_str()
- *
- * Displays a string on both the local and remote systems.
- *
- * Parameters: pszToDisplay - Pointer to the string to be displayed.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_disp_str(char *pszToDisplay)
-{
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_disp_str()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Call the OpenDoors kernel, if needed. */
-#ifndef OD_MULTITHREADED
-   if(ODTimerElapsed(&RunKernelTimer))
-   {
-      CALL_KERNEL_IF_NEEDED();
-   }
-#endif /* !OD_MULTITHREADED */
-
-   /* Send the string to the remote system, if we are running in remote mode. */
-   if(od_control.baud != 0)
-   {
-      ODComSendBuffer(hSerialPort, (BYTE *)pszToDisplay, strlen(pszToDisplay));
-   }
-
-   /* Display the screen on the local screen. */
-   ODScrnDisplayString(pszToDisplay);
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_statusline()
- *
- * Switches to one of the available status lines provided by the current
- * personality, or turns off the status line altogether.
- *
- * Parameters: nSetting - Indicates which status line (if any) should be
- *                        activated.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_set_statusline(INT nSetting)
-{
-#ifdef OD_TEXTMODE
-   INT nDistance;
-   BYTE btCount
-#endif /* OD_TEXTMODE */
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_set_statusline()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY()
-
-#ifdef OD_TEXTMODE
-
-   /* If status line is disabled, then don't do anything. */
-   if(!od_control.od_status_on)
-   {
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Ensure that the parameter is within the valid range. */
-   if(nSetting < 0 || nSetting > 8)
-   {
-      nSetting = 0;
-   }
-
-   /* If the specified status line is already active, and status line */
-   /* update isn't being forced, then return without doing anything.  */
-   if(!od_control.od_update_status_now && nSetting == btCurrentStatusLine)
-   {
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Save the current cursor settings. */
-   ODStoreTextInfo();
-
-   /* Reset screen boundary to allow access to the entire screen. */
-   ODScrnSetBoundary(1,1,80,25);
-
-   /* If status line is being turned off. */
-   if(btCurrentStatusLine == STATUS_NONE)
-   {
-      if((nDistance = (INT)ODTextInfo.cury - ( 1 + (INT)btOutputBottom
-         - (INT)btOutputTop)) > 0)
-      {
-         ODScrnCopyText(1, (BYTE)((INT)btOutputTop + nDistance), 80,
-            (BYTE)((INT)btOutputBottom + nDistance), (BYTE)btOutputTop, 1);
-         ODTextInfo.cury = 1 + btOutputBottom - btOutputTop;
-      }
-      else if(ODTextInfo.cury < btOutputTop)
-      {
-         ODTextInfo.cury = btOutputTop;
-         ODScrnCopyText(1, (BYTE)(btOutputTop + 24 - btOutputBottom), 80, 25,
-            btOutputTop, 1);
-      }
-   }
-
-   od_control.od_current_statusline = btCurrentStatusLine = nSetting;
-
-   if(nSetting == 8)
-   {
-      ODScrnSetAttribute(0x07);
-
-      for(btCount = 1; btCount <= 25; ++btCount)
-      {
-         if(btCount < btOutputTop || btCount > btOutputBottom)
-         {
-            if(btCount == 25)
-            {
-               ODScrnPutText(80, 25, 80, 25, abtBlackBlock);
-               ODScrnSetCursorPos(1, 25);
-               ODScrnDisplayString("                                                                               ");
-            }
-            else
-            {
-               ODScrnSetCursorPos(1, 24);
-               ODScrnDisplayString("                                                                                ");
-            }
-         }
-      }
-
-      ODScrnSetAttribute(ODTextInfo.attribute);
-      ODScrnSetCursorPos(ODTextInfo.curx, ODTextInfo.cury);
-   }
-
-   else
-   {
-      ODScrnEnableCaret(FALSE);
-      ODScrnEnableScrolling(FALSE);
-
-      (*pfCurrentPersonality)((BYTE)nSetting);
-
-      ODScrnEnableCaret(TRUE);
-      ODScrnEnableScrolling(TRUE);
-
-      ODScrnSetBoundary(1, btOutputTop, 80, btOutputBottom);
-      ODScrnSetAttribute(ODTextInfo.attribute);
-      ODScrnSetCursorPos(ODTextInfo.curx, ODTextInfo.cury);
-   }
-
-#else /* !OD_TEXTMODE */
-
-   od_control.od_error = ERR_UNSUPPORTED;
-
-#endif /* !OD_TEXTMODE */
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStoreTextInfo()
- *
- * Stores the current text settings into the OpenDoors global text information
- * structure.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODStoreTextInfo(void)
-{
-   ODScrnGetTextInfo(&ODTextInfo);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODRestoreTextInfo()
- *
- * Restores display settings previously stored by ODStoreTextInfo()
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODRestoreTextInfo(void)
-{
-   ODScrnSetBoundary(ODTextInfo.winleft, ODTextInfo.wintop,
-      ODTextInfo.winright, ODTextInfo.winbottom);
-   ODScrnSetAttribute(ODTextInfo.attribute);
-   ODScrnSetCursorPos(ODTextInfo.curx, ODTextInfo.cury);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStringToName()
- *
- * Reformats a string so that it has the correct capitalization for a name,
- * and removes any trailing line break character.
- *
- * Parameters: pszToConvert - Pointer to the string to reformat.
- *
- *     Return: void
- */
-void ODStringToName(char *pszToConvert)
-{
-   /* Begin by changing the entire string to lower case. */
-   strlwr(pszToConvert);
-
-   /* Trim any newline character that may be at the end of the string. */
-   if(pszToConvert[strlen(pszToConvert) - 1] == '\n')
-   {
-      pszToConvert[strlen(pszToConvert) - 1] = '\0';
-   }
-
-   /* Change the first character to lower case. */
-   *pszToConvert = toupper(*pszToConvert);
-
-   /* Loop through the rest of the string, capitalizing any other words */
-   /* in the string.                                                    */
-   while(*pszToConvert)
-   {
-      switch(*pszToConvert++)
-      {
-         case ' ':
-         case '\t':
-         case ',':
-         case '.':
-         case '-':
-            *pszToConvert = toupper(*pszToConvert);
-            break;
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_color()
- *
- * Sets the current display color for both local and remote output.
- *
- * Parameters: nForeground - New foreground (text) color.
- *
- *             nBackground - New background color.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_set_color(INT nForeground, INT nBackground)
-{
-   /* Use od_set_attrib() to perform the actual color setting.          */
-   /* Here, we rely on od_set_attrib() to look after initialization,    */
-   /* API_ENTRY() and API_EXIT() calls, etc. This allows od_set_color() */
-   /* (which was previously just a macro) to be implemented with as     */
-   /* little overhead as possible.                                      */
-   od_set_attrib(nForeground | (nBackground << 4));
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_attrib()
- *
- * Sets the current display color for both local and remote output.
- *
- * Parameters: nColor - New Display color to set, or -1 for no change.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_set_attrib(INT nColor)
-{
-   char szControlSequence[40];
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_set_attrib()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* If color value is -1, then make no change. */
-   if(nColor == -1)
-   {
-      OD_API_EXIT();
-      return;
-   }
-
-   /* If we are operating in AVATAR mode. */
-   if(od_control.user_avatar)
-   {
-      if(od_control.od_cur_attrib != nColor || od_control.od_full_color)
-      {
-         /* Change local text color. */
-         ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib = nColor));
-
-         /* Generate AVATAR control sequence. */
-         szControlSequence[0] = 22;
-         szControlSequence[1] = 1;
-         szControlSequence[2] = nColor;
-
-         /* Send AVATAR control sequence. */
-         od_disp(szControlSequence, 3, FALSE);
-      }
-   }
-
-   /* If we are operating in ANSI mode. */
-   else if(od_control.user_ansi)
-   {
-      bAnyColorChangeYet = FALSE;
-
-      if(od_control.od_cur_attrib == -1 || od_control.od_full_color)
-      {
-ansi_reset:
-         /* Reset ANSI terminal status. */
-         ODAddANSIParameter(szControlSequence, 0);
-
-         /* If blink attribute is set. */
-         if(nColor & 0x80)
-         {
-            /* Add it to the ANSI color sequence. */
-            ODAddANSIParameter(szControlSequence, 5);
-         }
-
-         /* If high intensity attribute is set. */
-         if(nColor & 0x08)
-         {
-            /* Add it to the ANSI color sequence. */
-            ODAddANSIParameter(szControlSequence, 1);
-         }
-      }
-
-      /* If current color is known. */
-      else                             
-      {
-         /* If have to reset flashing or bright. */
-         if(((od_control.od_cur_attrib&0x80) &&
-            !(nColor & 0x80)) || ((od_control.od_cur_attrib & 0x08)
-            && !(nColor & 0x08)))
-         {
-            /* Must reset entire colour settings. */
-            od_control.od_cur_attrib = -1;
-            goto ansi_reset;
-         }
-                                       
-         /* If flashing has to be turned on. */
-         if((nColor & 0x80) != (od_control.od_cur_attrib & 0x80))
-         {
-            /* Add it to the ANSI color sequence. */
-            ODAddANSIParameter(szControlSequence, 5);
-         }
-
-         /* If bright has to be turned on. */
-         if((nColor & 0x08) != (od_control.od_cur_attrib & 0x08)
-            || od_control.od_cur_attrib == -1)
-         {
-            /* Add it to the ANSI color sequence. */
-            ODAddANSIParameter(szControlSequence, 1);
-         }
-      }
-
-
-      /* If foreground color has changed. */
-      if((nColor & 0x07) != (od_control.od_cur_attrib & 0x07)
-         || od_control.od_cur_attrib == -1 || od_control.od_full_color)
-      {
-         /* Add translated color to sequence. */
-         ODAddANSIParameter(szControlSequence,
-            abtPCToANSIColorTable[nColor&0x07]);
-      }
-
-      /* If background color has changed. */
-      if((nColor & 0x70) != (od_control.od_cur_attrib & 0x70)
-         || od_control.od_cur_attrib == -1 || od_control.od_full_color)
-      {
-         /* Add translated color to sequence. */
-         ODAddANSIParameter(szControlSequence,
-            abtPCToANSIColorTable[(nColor & 0x70) >> 4] + 10);
-      }
-
-      /* If any change in color. */
-      if(bAnyColorChangeYet)
-      {
-         /* Append change-attribute command. */
-         strcat(szControlSequence, "m");
-
-         /* Send ANSI sequence to the modem. */
-         od_disp(szControlSequence, strlen(szControlSequence), FALSE);
-      }
-
-      /* Change local text color. */
-      ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib = nColor));
-   }
-   else
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODAddANSIParameter()                                *** PRIVATE FUNCTION ***
- *
- * Adds a parameter to an ANSI color sequence.
- *
- * Parameters: szControlSequence - The contents of the control sequence string
- *                                 generated so far.
- *
- *             nParameterValue   - Value of the parameter to add.
- *
- *     Return: void
- */
-static void ODAddANSIParameter(char *szControlSequence, int nParameterValue)
-{
-   char szTemp[5];
-
-   if(bAnyColorChangeYet)
-   {
-      sprintf(szTemp, ";%d", nParameterValue);
-      strcat(szControlSequence, szTemp);
-   }
-   else
-   {
-      bAnyColorChangeYet = TRUE;
-      sprintf(szControlSequence, "x[%d", nParameterValue);
-      szControlSequence[0] = 27;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_putch()
- *
- * Displays a character on the local and remote screens.
- *
- * Parameters: chToDisplay - The character to display.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_putch(char chToDisplay)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_putch()");
-
-   /* Initialize OpenDoors if it hasn't been done already. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Display the character on the local screen. */
-   ODScrnDisplayChar(chToDisplay);
-
-   /* If not operating in local mode, then send the character to the */
-   /* serial port.                                                   */
-   if(od_control.baud)
-   {
-      ODComSendByte(hSerialPort, chToDisplay);
-   }
-
-   /* If it is time to call the kernel, then do so. */
-   if(ODTimerElapsed(&RunKernelTimer))
-   {
-      CALL_KERNEL_IF_NEEDED();
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_dtr()
- *
- * Changes the state of the DTR line to the modem, if not running in local
- * mode.
- *
- * Parameters: bHigh - TRUE to raise DTR, FALSE to lower it.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_set_dtr(BOOL bHigh)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_set_dtr()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* If we are running in local mode, then return with an error. */
-   if(!od_control.baud)
-   {
-      od_control.od_error = ERR_NOREMOTE;
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Otherwise, change the state of the DTR line. */
-   ODComSetDTR(hSerialPort, bHigh);
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_get_answer()
- *
- * Waits for the user to press one of the keys listed in pszOptions. Case is
- * not sensitive, although the pressed key is returned in the same case as it
- * is specified in pszOptions.
- *
- * Parameters: pszOptions - String listing characters to accept.
- *
- *     Return: void
- */
-ODAPIDEF char ODCALL od_get_answer(char *pszOptions)
-{
-   char *pchPossibleOption;
-   char chPressed;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_get_answer()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   for(;;)
-   {
-      /* Wait for the next key press by the user. */
-      chPressed = od_get_key(TRUE);
-      chPressed = tolower(chPressed);
-
-      /* Loop through list of possible options. */
-      pchPossibleOption = (char *)pszOptions;
-      while(*pchPossibleOption)
-      {
-         /* If the key pressed matches this possible option. */
-         if(tolower(*pchPossibleOption) == chPressed)
-         {
-            /* Then return the character in the case originally specified */
-            /* by the caller.                                             */
-            OD_API_EXIT();
-            return(*pchPossibleOption);
-         }
-
-         /* Move on to the next possible option. */
-         ++pchPossibleOption;
-      }
-
-      /* If the key pressed did not match a possible option, then we */
-      /* just loop again, getting the next key.                      */
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_color_config()
- *
- * Determines the color attribute that is described by the provided string.
- * This string is in the same format that is used for specifying colors in the
- * OpenDoors configuration file.
- *
- * Parameters: pszColorDesc - Color description string.
- *
- *     Return: The PC-style color attribute corresponding to the color
- *             description string.
- */
-ODAPIDEF BYTE ODCALL od_color_config(char *pszColorDesc)
-{
-   BYTE btColor = 0x07;
-   char szToken[40];
-   char *pszStart=(char *)pszColorDesc;
-   char *pszEnd;
-   BYTE btLength;
-   BYTE btIdentifier;
-   BOOL bForeground = TRUE;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_color_config()");
-
-   /* Initialize OpenDoros if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   while(*pszStart && *pszStart!=chColorCheck)
-   {
-      if(*pszStart == ' ' || *pszStart== '\t')
-      {
-         ++pszStart;
-      }
-      else
-      {
-         btLength = 0;
-         pszEnd = (char *)pszStart;
-         while(*pszEnd && *pszEnd != chColorCheck && *pszEnd != ' '
-            && *pszEnd != '\t')
-         {
-            ++btLength;
-            ++pszEnd;
-         }
-
-         if(btLength > 39) btLength = 39;
-         strncpy(szToken, pszStart, btLength);
-         szToken[btLength] = '\0';
-         strupr(szToken);
-
-         for(btIdentifier = 0; btIdentifier < 12; ++btIdentifier)
-            if(strcmp(od_config_colours[btIdentifier], szToken) == 0)
-            {
-               if(btIdentifier <= 9)
-               {
-                  if(btIdentifier >= 8) btIdentifier -= 2;
-
-                  if(bForeground)
-                  {
-                     bForeground=FALSE;
-                     btColor &=~ 0x07;
-                     btColor |= btIdentifier;
-                  }
-                  else
-                  {
-                     btColor &=~ 0x70;
-                     btColor |= (btIdentifier << 4);
-                  }
-               }
-
-               else if(btIdentifier == 10)
-               {
-                  btColor |= 0x08;
-               }
-
-               else if(btIdentifier == 11)
-               {
-                  btColor |= 0x80;
-               }
-
-               break;
-            }
-
-         pszStart = (char *)pszEnd;
-      }
-   }
-
-   pchColorEndPos = (char *)pszStart;
-
-   OD_API_EXIT();
-
-   return(btColor);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODPagePrompt()
- *
- * Called to display the page prompt at the end of a screen of text. This page
- * prompt allows the user to stop further display, to display the next page,
- * or to display in continuous (non-stop) mode with page pausing disabled.
- *
- * Parameters: pbPausing   - Pointer to current page pausing enabled flag.
- *
- *     Return: FALSE if display should be continued, or TRUE to abort display.
- */
-BOOL ODPagePrompt(BOOL *pbPausing)
-{
-   INT nPromptLength = strlen(od_control.od_continue);
-   tODScrnTextInfo TextInfo;
-   BOOL bToReturn = FALSE;
-   char chKeyPressed;
-   BYTE btCount;
-
-   /* Return right away if page pausing is disabled. */
-   if(!*pbPausing) return(FALSE);
-
-   /* Get current text color. */
-   ODScrnGetTextInfo(&TextInfo);
-
-   /* Set to prompt color. */
-   od_set_attrib(od_control.od_continue_col);
-
-   /* Display page prompt string. */
-   od_disp_str(od_control.od_continue);
-
-   /* Restore original text color. */
-   od_set_attrib(TextInfo.attribute);
-
-   /* Loop until the user makes a valid choice. */
-   for(;;)
-   {
-      /* Obtain the next key from the user. */
-      chKeyPressed = od_get_key(TRUE);
-
-      /* If user chooses to continue. */
-      if(chKeyPressed == tolower(od_control.od_continue_yes) ||
-         chKeyPressed == toupper(od_control.od_continue_yes) ||
-         chKeyPressed == 13 ||
-         chKeyPressed == ' ')
-      {
-         /* Remove the prompt and return. */
-         goto finished_pausing;
-      }
-
-      /* If user requested nonstop display. */
-      else if(chKeyPressed == tolower(od_control.od_continue_nonstop) ||
-              chKeyPressed == toupper(od_control.od_continue_nonstop))
-      {
-         /* Disable page pausing. */
-         *pbPausing = FALSE;
-
-         /* Remove the prompt and return. */
-         goto finished_pausing;
-      }
-
-      /* If user chooses to stop display. */
-      else if(chKeyPressed == tolower(od_control.od_continue_no) ||
-              chKeyPressed == toupper(od_control.od_continue_no) ||
-              chKeyPressed == 's' || chKeyPressed == 'S' || chKeyPressed == 3
-              || chKeyPressed == 11 || chKeyPressed == 0x18)
-      {
-         /* If we are operating in remote mode. */
-         if(od_control.baud)
-         {
-            /* Clear the output buffer. */
-            ODComClearOutbound(hSerialPort);
-         }
-
-         /* Tell the caller to stop displaying more text. */
-         bToReturn = TRUE;
-
-         /* Remove the prompt and return. */
-         goto finished_pausing;
-      }
-   }
-
-finished_pausing:
-   /* Remove the pause prompt. */
-   for(btCount = 0; btCount < nPromptLength; ++btCount)
-   {
-      od_disp_str(szBackspaceWithDelete);
-   }
-
-   return(bToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_control_get()
- *
- * Returns a pointer to the od_control structure containing information
- * and settings associated with the current session.
- *
- * Parameters: None.
- *
- *     Return: A pointer to the od_control structure associated with this
- *             session.
- */
-ODAPIDEF tODControl * ODCALL od_control_get(void)
-{
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_disp_str()");
-
-   return(&od_control);
-}
diff --git a/src/odoors/ODCore.h b/src/odoors/ODCore.h
deleted file mode 100644
index 4b67bbda0800467a0637d8376dff90ec567db982..0000000000000000000000000000000000000000
--- a/src/odoors/ODCore.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODCore.h
- *
- * Description: Global functions and variables provide by the odcore.c
- *              module. These core facilities are used throughout OpenDoors,
- *              and are required regardless of what OpenDoors features that
- *              a given program uses.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 16, 1995  6.00  BP   Created.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Dec 24, 1995  6.00  BP   Added abtGreyBlock.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 01, 1996  6.00  BP   Changed TEXT_SIZE to 49.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Sep 01, 1996  6.10  BP   Update output area on od_set_per...().
- */
-
-#ifndef _INC_ODCORE
-#define _INC_ODCORE
-
-
-/* Include other header files that have definitions neede by this one. */
-#include "ODInQue.h"
-#include "ODCom.h"
-#include "ODPlat.h"
-#include "ODScrn.h"
-
-
-/* OpenDoors global initialized flag. */
-extern BOOL bODInitialized;
-
-/* Global serial port object handle. */
-extern tPortHandle hSerialPort;
-
-/* Global input queue object handle. */
-extern tODInQueueHandle hODInputQueue;
-
-/* Reentrancy control. */
-extern BOOL bIsCallbackActive;
-extern BOOL bShellChatActive;
-
-/* Global working space. */
-#define OD_GLOBAL_WORK_STRING_SIZE  257
-extern char szODWorkString[OD_GLOBAL_WORK_STRING_SIZE];
-
-/* Global instance of the text information structure for general use. */
-extern tODScrnTextInfo ODTextInfo;
-
-/* Logfile function hooks. */
-extern BOOL (*pfLogWrite)(INT);
-extern void (*pfLogClose)(INT);
-
-/* od_colour_config() support for od_printf(). */
-extern char chColorCheck;
-extern char *pchColorEndPos;
-
-/* Status line information. */
-extern BYTE btCurrentStatusLine;
-extern OD_PERSONALITY_CALLBACK *pfCurrentPersonality;
-extern char szDesiredPersonality[33];
-typedef BOOL ODCALL SET_PERSONALITY_FUNC(char *pszName);
-extern SET_PERSONALITY_FUNC *pfSetPersonality;
-
-/* Commonly used character sequences. */
-extern char abtBlackBlock[2];
-extern char abtGreyBlock[2];
-extern char szBackspaceWithDelete[4];
-
-/* Current output area on screen. */
-extern BYTE btOutputTop;
-extern BYTE btOutputBottom;
-
-
-/* Core functions used throughout OpenDoors. */
-void ODWaitDrain(tODMilliSec MaxWait);
-void ODStoreTextInfo(void);
-void ODRestoreTextInfo(void);
-void ODStringToName(char *pszToConvert);
-BOOL ODPagePrompt(BOOL *pbPausing);
-
-
-/* Number of built-in configuration file options. */
-#define TEXT_SIZE 49
-
-/* Number of user-defined info file options. */
-#define LINES_SIZE 25
-
-
-#endif /* _INC_ODCORE */
diff --git a/src/odoors/ODDrBox.c b/src/odoors/ODDrBox.c
deleted file mode 100644
index da7a0ad8414ba83dba8d37f819a3738d7fc62bad..0000000000000000000000000000000000000000
--- a/src/odoors/ODDrBox.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODDrBox.c
- *
- * Description: Implements the od_draw_box() function.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODKrnl.h"
-
-
-/* ----------------------------------------------------------------------------
- * od_draw_box()
- *
- * Draws a box on the local and remote screens, using the box characters
- * specified in od_control.od_box_chars. Unlike the window functions, this
- * function does not store the original contents of the screen where the box
- * is drawn.
- *
- * Parameters: btLeft   - Column number of the left side of the box.
- *
- *             btTop    - Row number of the top side of the box.
- *
- *             btRight  - Column number of hte right side of the box.
- *
- *             btBottom - Row number of the bottom side of the box.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_draw_box(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom)
-{
-   /* Number of current line being drawn. */
-   BYTE btLine;
-
-   /* X size of window. */
-   BYTE btBetweenSize = (btRight - btLeft) - 1;
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_draw_box()");
-
-   /* Ensure that OpenDoors has been initialized */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Setup od_box_chars appropriately */
-   if(od_control.od_box_chars[BOX_BOTTOM] == 0)
-   {
-      od_control.od_box_chars[BOX_BOTTOM] = od_control.od_box_chars[BOX_TOP];
-   }
-   if(od_control.od_box_chars[BOX_RIGHT] == 0)
-   {
-      od_control.od_box_chars[BOX_RIGHT] = od_control.od_box_chars[BOX_LEFT];
-   }
-
-   /* Check that required display capabilities are supported. */
-   if(!(od_control.user_ansi || od_control.user_avatar))
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Check that parameters are within valid range. */
-   if(btLeft<1 || btTop<1 || btRight>80 || btBottom>25)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Move to top corner, if needed. */
-   od_set_cursor(btTop, btLeft);
-
-   /* Display left corner character. */
-   od_putch(od_control.od_box_chars[BOX_UPPERLEFT]);
-
-   /* Display top line. */
-   od_repeat(od_control.od_box_chars[BOX_TOP], btBetweenSize);
-
-   /* Display right corner character. */
-   od_putch(od_control.od_box_chars[BOX_UPPERRIGHT]);
-
-   /* If AVATAR display mode is available. */
-   if(od_control.user_avatar)                    
-   {
-      /* Display first left vertical line. */
-      od_set_cursor(btTop + 1, btLeft);
-      od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-      /* Fill in the center of the window. */
-      od_emulate(22);
-      od_emulate(12);
-      od_emulate((BYTE)od_control.od_cur_attrib);
-      od_emulate((BYTE)((btBottom - btTop) - 1));
-      od_emulate(btBetweenSize);
-
-      /* Display first right vertical line. */
-      od_set_cursor(btTop + 1, btRight);
-      od_putch(od_control.od_box_chars[BOX_RIGHT]);
-
-      /* Display remaining vertical lines. */
-      for(btLine = btTop + 2; btLine < btBottom; ++btLine)
-      {
-         /* Move to the start of the line. */
-         od_set_cursor(btLine, btLeft);
-
-         /* Display left line character. */
-         od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-         /* Move to line start. */
-         od_set_cursor(btLine, btRight);
-
-         /* Display right line character. */
-         od_putch(od_control.od_box_chars[BOX_RIGHT]);
-      }
-   }
-
-   /* If AVATAR mode is not available. */
-   else
-   {
-      /* Loop through middle lines of window. */
-      for(btLine = btTop + 1; btLine < btBottom; ++btLine)
-      {
-         /* Move to the start of the line. */
-         od_set_cursor(btLine,btLeft);
-
-         /* Display left line character. */
-         od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-         /* Display the blank area. */
-         od_repeat(' ', btBetweenSize);
-
-         /* Display the right line character. */
-         od_putch(od_control.od_box_chars[BOX_RIGHT]);
-      }
-   }
-
-   /* Move to bottom corner. */
-   od_set_cursor(btBottom, btLeft);
-
-   /* Display left corner character. */
-   od_putch(od_control.od_box_chars[BOX_LOWERLEFT]);
-
-   /* Display bottom line. */
-   od_repeat(od_control.od_box_chars[BOX_BOTTOM], btBetweenSize);
-
-   /* Display right corner character. */
-   od_putch(od_control.od_box_chars[BOX_LOWERRIGHT]);
-
-   /* Return with success. */
-   OD_API_EXIT();
-   return(TRUE);
-}
diff --git a/src/odoors/ODEdStr.c b/src/odoors/ODEdStr.c
deleted file mode 100644
index 184f473589b3ea29914869bd16d3f3ef9bfcaf2c..0000000000000000000000000000000000000000
--- a/src/odoors/ODEdStr.c
+++ /dev/null
@@ -1,1238 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODEdStr.c
- *
- * Description: Implementation of od_edit_str(). This is the advanced line
- *              editing function which requires ANSI or AVATAR graphics.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Use ODTimerSleep() instead of loop.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 23, 1995  6.00  BP   Added EDIT_FLAG_SHOW_SIZE.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 04, 1996  6.00  BP   Use od_get_input().
- *              Jan 12, 1996  6.00  BP   Claim exclusive use of arrow keys.
- *              Jan 31, 1996  6.00  BP   Added timeout for od_get_input().
- *              Feb 10, 1996  6.00  BP   Fixed ...SHOW_SIZE /w ...PERMALITERAL.
- *              Feb 13, 1996  6.00  BP   Added od_get_input() flags parameter.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Apr 08, 1996  6.10  BP   Make 'C' use word capitalization.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <ctype.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODKrnl.h"
-#include "ODStat.h"
-
-
-/* Current od_edit_str() state and settings. */
-static INT anCurrentFormatOffset[80];
-static BOOL abCurrentFormatLiteral[80];
-static char szCurrentOriginalString[81];
-static char *pszCurrentInput;
-static char *pszCurrentFormat;
-static unsigned char nCurrentStringLength;
-static char chCurrentBlank;
-
-
-/* Private helper functions used by od_edit_str(). */
-static BOOL ODEditIsCharValidForPos(char chEntered, INT nPosition);
-static char ODEditAsCharForPos(char chEntered, INT nPosition);
-static void ODEditDisplayPermaliteral(WORD nFlags);
-
-
-/* ----------------------------------------------------------------------------
- * od_edit_str()
- *
- * Provides more advanced editing capabilities than od_get_str(), requiring
- * ANSI, AVATAR or RIP modes.
- *
- * Parameters: pszInput          - Pointer to string where inputted text is
- *                                 stored.
- *
- *             pszFormat         - Pointer to format string, which specifies
- *                                 the format of inputted text.
- *
- *             nRow              - The row number where the input field should
- *                                 begin.
- *
- *             nColumn           - The column number where the input field
- *                                 should begin.
- *
- *             btNormalColour    - Color of normal text.
- *
- *             btHighlightColour - Color of highlighted text.
- *
- *             chBlank           - Character to display blanks with.
- *
- *             nFlags            - Specifies one or more flags, combined with
- *                                 the bitwise-or operator.
- *
- *     Return: One of a number of possible EDIT_RETURN_ values, which indicate
- *             why the function returned.
- */
-ODAPIDEF WORD ODCALL od_edit_str(char *pszInput, char *pszFormat, INT nRow,
-   INT nColumn, BYTE btNormalColour, BYTE btHighlightColour,
-   char chBlank, WORD nFlags)
-{
-   char chTemp;
-   unsigned int nCount;
-   unsigned char chCurrentValue;
-   char *pchCurrent;
-   unsigned int nCursorPos;
-   INT nKeysPressed = 0;
-   WORD wToReturn;
-   BOOL bInsertMode = TRUE;
-   char chAddAtEnd = '\0';
-   BOOL bNormal = TRUE;
-   tODInputEvent InputEvent;
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_edit_str()");
-
-   /* Verify that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Store pointers to current input string and current format string. */
-   pszCurrentInput=(char *)pszInput;
-   pszCurrentFormat=(char *)pszFormat;
-
-   /* Check that the parameters passed in are valid. */
-   if(pszCurrentInput == NULL || pszCurrentFormat == NULL || nRow < 1
-      || nColumn < 1)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(EDIT_RETURN_ERROR);
-   }
-
-   /* Initially, the maximum length of input string is 0. */
-   nCurrentStringLength = 0;
-
-   /* The type that is being examined. */
-   chCurrentValue = 0;
-
-   /* Counter of position in format string. */
-   nCount = 0;
-
-   /* Loop until we reach the end fo the format string. */
-   for(pchCurrent = pszCurrentFormat; *pchCurrent;)
-   {
-      /* Get next character from format string. */
-      chTemp = *pchCurrent++;
-
-      /* If current character is not a literal value. */
-      if(chCurrentValue == '\0')
-      {
-         /* If format string has " or ' characters, then this is the */
-         /* beginning of a literal string.                           */
-         if(chTemp == 39 || chTemp == 34)
-         {
-            chCurrentValue = chTemp;
-         }
-
-         /* If this is not a literal character, and not a space character... */
-         else if(chTemp != 32)
-         {
-            /* Check that we haven't exceeded the maximum allowable string */
-            /* length.                                                     */
-            if(nCurrentStringLength >= 80)
-            {
-               od_control.od_error = ERR_PARAMETER;
-               OD_API_EXIT();
-               return(EDIT_RETURN_ERROR);
-            }
-
-            /* Record format character's position. */
-            anCurrentFormatOffset[nCurrentStringLength] = nCount;
-
-            /* Record that this character is not a literal. */
-            abCurrentFormatLiteral[nCurrentStringLength] = FALSE;
-
-            /* Increment length of input string. */
-            ++nCurrentStringLength;
-         }
-      }
-
-      /* If this is a literal character. */
-      else
-      {
-         /* Check for end of literal string. */
-         if(chTemp == chCurrentValue)
-         {
-            /* If found, stop literal string processing */
-            chCurrentValue = '\0';
-         }
-         else
-         {
-            /* Check that we haven't exceeded the maximum allowable string */
-            /* length.                                                     */
-            if(nCurrentStringLength >= 80)
-            {
-               od_control.od_error = ERR_PARAMETER;
-               OD_API_EXIT();
-               return(EDIT_RETURN_ERROR);
-            }
-
-            /* Record character's position. */
-            anCurrentFormatOffset[nCurrentStringLength] = nCount;
-
-            /* Record that character IS a literal value. */
-            abCurrentFormatLiteral[nCurrentStringLength] = TRUE;
-
-            /* Increment length of input string. */
-            ++nCurrentStringLength;
-         }
-      }
-
-      /* Increment format string position. */
-      ++nCount;
-   }
-
-   /* Check that there is at least one character permitted in the input */
-   /* string. If not, return with a parameter error.                    */
-   if(nCurrentStringLength==0)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(EDIT_RETURN_ERROR);
-   }
-
-   /* If editing an existing string. */
-   if(nFlags & EDIT_FLAG_EDIT_STRING)
-   {
-      /* Check for valid existing input string. */
-      if(strlen(pszCurrentInput) > nCurrentStringLength)
-      {
-         pszCurrentInput[nCurrentStringLength] = '\0';
-      }
-
-      /* Start with cursor at the end of the string. */
-      nCursorPos = strlen(pszCurrentInput);
-   }
-
-   /* If we are not editing an existing string. */
-   else
-   {
-      /* Blank-out current string contents. */
-      pszCurrentInput[0] = '\0';
-
-      /* Set cursor to beginning of string. */
-      nCursorPos = 0;
-   }
-
-   /* Store original string, in case user cancels. */
-   strcpy(szCurrentOriginalString,pszCurrentInput);
-
-   /* Set appropriate text color. */
-   od_set_attrib(btHighlightColour);
-
-   /* Determine appropriate blank character */
-   chCurrentBlank = (nFlags & EDIT_FLAG_PASSWORD_MODE) ? ' ' : chBlank;
-
-   /* Turn off insert mode if the strict input or permaliteral flags were */
-   /* specified.                                                          */
-   if((nFlags & EDIT_FLAG_STRICT_INPUT) || (nFlags & EDIT_FLAG_PERMALITERAL))
-   {
-      bInsertMode = FALSE;
-   }
-
-   /* If the no-initial-redraw flag is not set, then do initial redraw. */
-   if(!(nFlags & EDIT_FLAG_NO_REDRAW))
-   {
-      /* Set to redraw position. */
-      od_set_cursor(nRow, nColumn);
-
-      if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-      {
-         /* If we are in password mode, then just draw password blanks. */
-         od_repeat(chBlank, (BYTE)strlen(pszCurrentInput));
-      }
-      else
-      {
-         /* Otherwise, display the actual string. */
-         od_disp_str(pszCurrentInput);
-      }
-
-      if(nFlags & EDIT_FLAG_PERMALITERAL)
-      {
-         /* If we are in permaliteral mode, then fill the remaining edit */
-         /* field with the literal characters.                           */
-         ODEditDisplayPermaliteral(nFlags);
-      }
-      else
-      {
-         /* Otherwise, fill the remaining edit field with the blank */
-         /* character.                                              */
-         BYTE btRemaining
-            = (BYTE)(nCurrentStringLength - strlen(pszCurrentInput));
-         if(!(nFlags & EDIT_FLAG_SHOW_SIZE)) ++btRemaining;
-         od_repeat(chCurrentBlank, btRemaining);
-      }
-   }
-
-   /* Claim exclusive use of arrow keys. */
-   ODStatStartArrowUse();
-
-   /* Set the cursor to appropriate position. */
-   od_set_cursor(nRow, nColumn + nCursorPos);
-
-   /* Normally, we start the input loop at the keep_going tag. */
-   if(bNormal) goto keep_going;
-
-   for(;;)
-   {
-      /* If auto-accept mode has been specified ... */
-      if(nFlags & EDIT_FLAG_AUTO_ENTER)
-      {
-         /* ... then check whether we have reached the end of the string. */
-         if(strlen(pszCurrentInput) == nCurrentStringLength)
-         {
-            /* Indicate that input has been accepted, rather than cancelled. */
-            wToReturn = EDIT_RETURN_ACCEPT;
-
-            /* Return the current string to the caller, if it is valid. */
-            goto try_to_accept;
-         }
-      }
-
-keep_going:
-      /* Check whether we have reached a literal character in permaliteral */
-      /* mode. If so, we will move past the permanent literal characters   */
-      /* automatically.                                                    */
-      if((nFlags & EDIT_FLAG_PERMALITERAL)
-         && (nCursorPos < nCurrentStringLength))
-      {
-         if(abCurrentFormatLiteral[nCursorPos])
-         {
-            if(nCursorPos < strlen(pszCurrentInput))
-            {
-               goto pressed_right_arrow;
-            }
-            chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]];
-            ++nKeysPressed;
-            goto try_this_character;
-         }
-      }
-
-get_another_key:
-      /* Block, waiting for the next key pressed by the user. */
-
-      od_get_input(&InputEvent, OD_NO_TIMEOUT, GETIN_NORMAL);
-      
-      /* Increment total number of keystrokes. */
-      ++nKeysPressed;
-
-      if(InputEvent.EventType == EVENT_EXTENDED_KEY)
-      {
-         switch(InputEvent.chKeyPress)
-         {
-            case OD_KEY_UP:
-            case OD_KEY_SHIFTTAB:
-               if(nFlags & EDIT_FLAG_FIELD_MODE)
-               {
-                  wToReturn = EDIT_RETURN_PREVIOUS;
-                  goto try_to_accept;
-               }
-               break;
-
-            case OD_KEY_DOWN:
-pressed_down_arrow:
-               if(nFlags & EDIT_FLAG_FIELD_MODE)
-               {
-                  wToReturn = EDIT_RETURN_NEXT;
-                  goto try_to_accept;
-               }
-               break;
-
-            case OD_KEY_RIGHT:
-pressed_right_arrow:
-               /* If we are not at the end of the string. */
-               if(nCursorPos < strlen(pszCurrentInput))
-               {
-                  /* Move input position right. */
-                  nCursorPos++;
-
-                  /* Move the cursor on screen. */
-                  od_set_cursor(nRow, nColumn + nCursorPos);
-               }
-               if(chAddAtEnd)
-               {
-                  chAddAtEnd = 0;
-                  goto add_another_key;
-               }
-               break;
-
-            case OD_KEY_LEFT:
-pressed_left_arrow:
-               /* If we are not at the beginning of the string. */
-               if(nCursorPos > 0)
-               {
-                  /* Move input position left. */
-                  nCursorPos--;
-
-                  /* Move cursor on screen. */
-                  od_set_cursor(nRow, nColumn + nCursorPos);
-               }
-
-               /* If we are moving past a permanent literal character, */
-               /* then continue moving further left, if possible.      */
-               if((nFlags & EDIT_FLAG_PERMALITERAL)
-                  && abCurrentFormatLiteral[nCursorPos] && nCursorPos > 0)
-               {
-                  goto pressed_left_arrow;
-               }
-               break;
-
-         case OD_KEY_HOME:
-            /* If we are not at the beginning of the string. */
-            if(nCursorPos != 0)
-            {
-               /* Move input position to the beginning of the string. */
-               nCursorPos = 0;
-
-               /* Move the cursor on the screen. */
-               od_set_cursor(nRow, nColumn);
-            }
-            break;
-
-         case OD_KEY_END:
-            /* If we are not at the end of the string .*/
-            if(nCursorPos != strlen(pszCurrentInput))
-            {
-               /* Set the input position to the end of the string. */
-               nCursorPos=strlen(pszCurrentInput);
-
-               /* Move cursor on screen. */
-               od_set_cursor(nRow,nColumn+nCursorPos);
-            }
-            break;
-
-         case OD_KEY_DELETE:
-pressed_delete:
-            /* Check whether delete key is permitted at this time. */
-            if(!(nFlags & EDIT_FLAG_STRICT_INPUT)
-               && nCursorPos < strlen(pszCurrentInput)
-               && !(nFlags & EDIT_FLAG_PERMALITERAL))
-            {
-               /* Move remaining line, if any, to the left */
-               chCurrentValue = strlen(pszCurrentInput) - 1;
-               for(nCount = nCursorPos; nCount < chCurrentValue; ++nCount)
-               {
-                  od_putch(
-                     pszCurrentInput[nCount] = pszCurrentInput[nCount + 1]);
-               }
-
-               /* Erase the last character. */
-               pszCurrentInput[chCurrentValue] = '\0';  
-
-               /* Blank out last character. */
-               od_putch(chCurrentBlank);
-
-               /* Move the cursor on the screen. */
-               od_set_cursor(nRow, nColumn + nCursorPos);
-
-               /* Update changes to string. */
-               goto check_cursor_char;
-            }
-            break;
-
-         case OD_KEY_INSERT:
-            if(!(nFlags & EDIT_FLAG_STRICT_INPUT)
-               && !(nFlags & EDIT_FLAG_PERMALITERAL))
-            {
-               /* Toggle insert setting. */
-               bInsertMode = !bInsertMode;
-            }
-            break;
-
-         }
-      }
-      else if(InputEvent.EventType == EVENT_CHARACTER)
-      {
-         chTemp = InputEvent.chKeyPress;
-try_this_character:
-
-         if(chTemp == 27)
-         {
-            /* If cancel key is allowed ... */
-            if(nFlags & EDIT_FLAG_ALLOW_CANCEL)
-            {
-               /* Reset the input string to the original contents. */
-               strcpy(pszCurrentInput, szCurrentOriginalString);
-
-               /* Indicate that return reason was due to user cancelling. */
-               wToReturn = EDIT_RETURN_CANCEL;
-
-               /* Return after redrawing the original string in the input */
-               /* field.                                                  */
-               goto exit_and_redraw;
-            }
-         }
-
-
-         /* If user pressed [Enter] or [Ctrl]-[Z]. */
-         else if(chTemp == 13 || chTemp == 26)
-         {
-            /* User has accepted input. */
-            wToReturn = EDIT_RETURN_ACCEPT;
-
-            /* Return if input string is valid. */
-            goto try_to_accept;
-         }
-
-         /* If the backspace key has been pressed. */
-         else if(chTemp == 8)
-         {
-   backspace_again:
-            /* If we are not already at the beginning of the string. */
-            if(nCursorPos > 0)
-            {
-               if(nFlags & EDIT_FLAG_PERMALITERAL)
-               {
-                  for(nCount = 0;nCount < nCursorPos; ++nCount)
-                  {
-                     if(!abCurrentFormatLiteral[nCount]) goto continue_deletion;
-                  }
-                  goto get_another_key;
-               }
-
-   continue_deletion:
-               /* If we are at the end of the string. */
-               if(nCursorPos == strlen(pszCurrentInput))
-               {
-                  /* Erase last char in string. */
-                  pszCurrentInput[--nCursorPos] = '\0';
-
-                  if((nFlags & EDIT_FLAG_PERMALITERAL)
-                     && abCurrentFormatLiteral[nCursorPos])
-                  {
-                     goto backspace_again;
-                  }
-                  else
-                  {
-                     /* Move to new cursor pos. */
-                     od_set_cursor(nRow,nColumn+nCursorPos);
-
-                     /* Blank old character. */
-                     od_putch(chCurrentBlank);
-
-                     /* Move again to cursor pos. */
-                     od_set_cursor(nRow,nColumn+nCursorPos);
-                  }
-               }
-
-               /* If we are in the middle of the string and we are not in */
-               /* string input mode.                                      */
-               else if(!(nFlags & EDIT_FLAG_STRICT_INPUT)
-                  && !(nFlags & EDIT_FLAG_PERMALITERAL))
-               {
-                  /* Move cursor left. */
-                  --nCursorPos;
-
-                  /* Move cursor on screen. */
-                  od_set_cursor(nRow, nColumn + nCursorPos);
-
-                  /* Goto standard delete handler. */
-                  goto pressed_delete;
-               }
-            }
-         }
-
-         /* If this is a next field request. */
-         else if(chTemp == 9)
-         {
-            /* Goto down arrow handler. */
-            goto pressed_down_arrow;
-         }
-
-         /* If Control-Y. */
-         else if(chTemp == 25)
-         {
-            /* Erase entire contents of line. */
-            goto kill_whole_line;
-         }
-
-         else
-         {
-            /* If this is the first key pressed, and we are in autodelete mode. */
-            if(nKeysPressed == 1 && (nFlags & EDIT_FLAG_AUTO_DELETE))
-            {
-   kill_whole_line:
-               /* If string is not empty. */
-               if(strlen(pszCurrentInput) != 0)
-               {
-                  /* Move to beginning of string. */
-                  od_set_cursor(nRow,nColumn);
-
-                  /* Blank out the entire string contents. */
-                  od_repeat(chCurrentBlank, (BYTE)strlen(pszCurrentInput));
-               }
-
-               /* Move to new cursor position. */
-               od_set_cursor(nRow,nColumn);
-
-               /* Update insert position. */
-               nCursorPos = 0;
-
-               /* Blank out the current string contents. */
-               pszCurrentInput[0] = '\0';
-            }
-
-   add_another_key:
-            if(!ODEditIsCharValidForPos(chTemp,nCursorPos))
-            {
-               /* If character is not a valid input char. */
-               if(abCurrentFormatLiteral[nCursorPos])
-               {
-                  if(nCursorPos < strlen(pszCurrentInput))
-                  {
-                     if(pszCurrentInput[nCursorPos] == 
-                        pszCurrentFormat[anCurrentFormatOffset[nCursorPos]])
-                     {
-                        chAddAtEnd = chTemp;
-                        goto pressed_right_arrow;
-                     }
-                  }
-                  chAddAtEnd = chTemp;
-                  chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]];
-               }
-               else
-               {
-                  continue;
-               }
-            }
-
-            /* Convert character to correct value, if applicable. */
-            chTemp = ODEditAsCharForPos(chTemp, nCursorPos);
-
-            /* If we are at end of string. */
-            if(nCursorPos >= strlen(pszCurrentInput))
-            {
-               /* Reset original cursor position */
-               nCursorPos = strlen(pszCurrentInput);
-
-               /* If there is room to add a char. */
-               if(nCursorPos < nCurrentStringLength)
-               {
-                  /* If password mode */
-                  if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-                  {
-                     /* Display the password character. */
-                     od_putch(chBlank);
-                  }
-                  /* If not in password mode. */
-                  else
-                  {
-                     /* Display the character. */
-                     od_putch(chTemp);
-                  }
-
-                  /* Store the character. */
-                  pszCurrentInput[nCursorPos] = chTemp;
-
-                  /* Add a new string terminator. */
-                  pszCurrentInput[++nCursorPos] = '\0';
-               }
-            }
-
-            /* If in insert mode, but not at end of string. */
-            else if(bInsertMode)
-            {
-               /* If room in string. */
-               if(strlen(pszCurrentInput) < nCurrentStringLength)
-               {
-                  /* If in password mode. */
-                  if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-                  {
-                     /* Move to end. */
-                     od_set_cursor(nRow,nColumn+strlen(pszCurrentInput));
-
-                     /* Add another password character. */
-                     od_putch(chBlank);
-                  }
-
-                  /* If not in password mode. */
-                  else
-                  {
-                     /* Display the new character. */
-                     od_putch(chTemp);
-
-                     /* Loop through rest of string. */
-                     for(nCount = nCursorPos; nCount < strlen(pszCurrentInput);
-                        ++nCount)
-                     {
-                        /* Display the next remaining character. */
-                        od_putch(pszCurrentInput[nCount]);
-                     }
-                  }
-
-                  pszCurrentInput[(strlen(pszCurrentInput) + 1)] = '\0';
-
-                  /* Sift remaining characters forward. */
-                  for(nCount = strlen(pszCurrentInput); nCount > nCursorPos;
-                     --nCount)
-                  {                     
-                     pszCurrentInput[nCount] = pszCurrentInput[nCount-1];
-                  }
-
-                  /* Add new char in space. */
-                  pszCurrentInput[nCursorPos++] = chTemp;
-
-                  /* Move to new cursor position. */
-                  od_set_cursor(nRow, nColumn + nCursorPos);
-               }
-               else
-               {
-                  goto get_another_key;
-               }
-            }
-
-            /* If we are in overwrite mode, but not at end of string. */
-            else
-            {
-               /* If password mode. */
-               if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-               {
-                  /* Display the password character. */
-                  od_putch(chBlank);
-               }
-               /* If not in password mode. */
-               else
-               {
-                  /* Display the character. */
-                  od_putch(chTemp);
-               }
-
-               /* Add character to string. */
-               pszCurrentInput[nCursorPos++] = chTemp;
-            }
-
-            /* If not at end of possible string. */
-            if(nCursorPos < nCurrentStringLength)
-            {
-               /* If the next character is literal constant. */
-               if(abCurrentFormatLiteral[nCursorPos])
-               {
-                  chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]];
-                  goto add_another_key;
-               }
-            }
-
-            if(chAddAtEnd)
-            {
-               chTemp = chAddAtEnd;
-               chAddAtEnd = 0;
-               goto add_another_key;
-            }
-
-
-   check_cursor_char:
-            /* If there is a character under cursor. */
-            if(nCursorPos < strlen(pszCurrentInput))
-            {
-               /* If character corresponds to the format string. */
-               if(ODEditIsCharValidForPos(pszCurrentInput[nCursorPos],
-                  nCursorPos))
-               {
-                  /* Determine correct character for this position. */
-                  chTemp = ODEditAsCharForPos(pszCurrentInput[nCursorPos],
-                     nCursorPos);
-
-                  /* If actual character is not correct. */
-                  if(chTemp != pszCurrentInput[nCursorPos])
-                  {                        
-                     /* Change character to correct value. */
-                     pszCurrentInput[nCursorPos] = chTemp;
-
-                     /* If password mode. */
-                     if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-                     {
-                        /* Display the password character. */
-                        od_putch(chBlank);
-                     }
-
-                     /* If not in password mode. */
-                     else
-                     {
-                        /* Display the character. */
-                        od_putch(chTemp);
-                     }
-
-                     /* Reset cursor position. */
-                     od_set_cursor(nRow, nColumn + nCursorPos);
-                  }
-               }
-            }
-         }
-      }
-   }
-
-   /* Accept string if it is valid. */
-try_to_accept:
-   /* If string must be filled. */
-   if(nFlags & EDIT_FLAG_FILL_STRING)
-   {
-      /* If string is not filled, don't return. */
-      if(strlen(pszCurrentInput) != nCurrentStringLength) goto keep_going;
-   }
-
-   /* Loop through string .... */
-   for(nCount = 0; nCount < strlen(pszCurrentInput); ++nCount)
-   {
-      /* ... testing each character for validity. */
-      if(!ODEditIsCharValidForPos(pszCurrentInput[nCount], nCount))
-         goto keep_going;
-   }
-
-   /* Initially, assume that the string has not been changed. */
-   chCurrentValue = FALSE;
-
-   /* Loop through the string. */
-   for(nCount = 0; nCount < strlen(pszCurrentInput); ++nCount)
-   {
-      /* Find correct value for each character. */
-      chTemp = ODEditAsCharForPos(pszCurrentInput[nCount], nCount);
-
-      /* If character is not correct. */
-      if(chTemp != pszCurrentInput[nCount])           
-      {
-         /* Change char to correct value */
-         pszCurrentInput[nCount] = chTemp;
-
-         /* Remember that string has been changed. */
-         chCurrentValue = TRUE;
-      }
-   }
-
-   /* If permaliteral mode. */
-   if(nFlags & EDIT_FLAG_LEAVE_BLANK)
-   {
-      /* Count # of literal characters. */
-      nCount = 0;
-      while(nCount<strlen(pszCurrentInput))
-      {
-         if(abCurrentFormatLiteral[nCount])
-         {
-            ++nCount;
-         }
-         else
-         {
-            break;
-         }
-      }
-
-      /* If only literals in string. */
-      if(strlen(pszCurrentInput) == nCount && nCount > 0)
-      {
-         /* Then they shouldn't be here. */
-         pszCurrentInput[0] = '\0';
-         goto exit_and_redraw;
-      }
-   }
-
-   /* Always redraw if string was changed. */
-   if(chCurrentValue) goto exit_and_redraw;
-
-   /* If no-redraw flag not set. */
-   if(!(nFlags & EDIT_FLAG_NO_REDRAW))
-   {
-exit_and_redraw:
-      /* Set appropriate text colour. */
-      od_set_attrib(btNormalColour);
-
-      /* Set to redraw position. */
-      od_set_cursor(nRow,nColumn);
-
-      /* If password mode. */
-      if(nFlags & EDIT_FLAG_PASSWORD_MODE)
-      {
-         /* Display blanked-out string. */
-         od_repeat(chBlank, (BYTE)strlen(pszCurrentInput));
-      }
-      else
-      {
-         /* Display actual string. */
-         od_disp_str(pszCurrentInput);
-      }
-
-      /* If we should keep the background. */
-      if(nFlags & EDIT_FLAG_KEEP_BLANK)
-      {
-         /* Then redraw background. */
-         if(nFlags & EDIT_FLAG_PERMALITERAL)
-         {
-            ODEditDisplayPermaliteral(nFlags);
-         }
-         else
-         {
-            od_repeat(chCurrentBlank,
-               (BYTE)(nCurrentStringLength - strlen(pszCurrentInput) + 1));
-         }
-      }
-      /* If we should erase the background ... */
-      else
-      {
-         /* ... then do it. */
-         od_repeat(' ',
-            (BYTE)(nCurrentStringLength - strlen(pszCurrentInput) + 1));
-      }
-   }
-
-   /* Release exclusive use of arrow keys. */
-   ODStatEndArrowUse();
-
-   /* Return with appropriate return value. */
-   OD_API_EXIT();
-   return(wToReturn);
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * ODEditIsCharValidForPos()                           *** PRIVATE FUNCTION ***
- *
- * Determines whether or not the entered character can be accepted as a valid
- * character (after any possible conversion by ODEditAsCharForPos() is applied)
- * for the specified position in the string.
- *
- * Parameters: chEntered   - The character entered by the user.
- *
- *             nPosition   - The position in the string where this character
- *                           would be inserted.
- *
- *     Return: TRUE if this character should be accepted, FALSE if not.
- */
-static BOOL ODEditIsCharValidForPos(char chEntered, INT nPosition)
-{
-   /* If this character is a literal. */
-   if(abCurrentFormatLiteral[nPosition])
-   {                                     
-      /* Check required literal character. */
-      if(chEntered != pszCurrentFormat[anCurrentFormatOffset[nPosition]])
-      {                                          
-         /* If this is not the correct literal character, then do not */
-         /* permit it to be entered in this position. */
-         return(FALSE);
-      }
-      return(TRUE);
-   }
-
-   /* If this position has a corresponding format control character, */
-   /* then check that control character. The execution path will     */
-   /* continue out of this switch statement (rather than returning   */
-   /* to the calling function) if and only if the entered character  */
-   /* is valid for the format character specified.                   */
-   switch(pszCurrentFormat[anCurrentFormatOffset[nPosition]])
-   {
-      /* Only numerical characters are to be permitted. */
-      case '#':
-         if(chEntered < '0' || chEntered > '9') return(FALSE);
-         break;
-
-      /* Only numerical and space characters are to be permitted. */
-      case '%':
-         if((chEntered < '0' || chEntered > '9') && chEntered != ' ')
-         {
-            return(FALSE);
-         }
-         break;
-
-      /* Only floating point number characters are to be permitted. */
-      case '9':
-         if(chEntered >= '0' && chEntered <= '9') break;
-         if(chEntered == '.' || chEntered == '+' || chEntered == '-') break;
-         return(FALSE);
-
-      /* Only "printable" characters are to be permitted. */
-      case '*':
-         if(chEntered < 32) return(FALSE);
-         break;
-
-      /* City name characters are to be permitted. */
-      case 'C':
-      case 'c':
-         if(chEntered >= 'A' && chEntered <= 'Z') break;
-         if(chEntered >= 'a' && chEntered <= 'z') break;
-         if(chEntered == ' ' || chEntered == ',' || chEntered == '.') break;
-         if(chEntered == '*' || chEntered == '?') break;
-         return(FALSE);
-
-      /* If only alphabetic characters are to be permitted. */
-      case 'A':
-      case 'a':
-      case 'L':
-      case 'l':
-      case 'M':
-      case 'm':
-      case 'U':
-      case 'u':
-         if(chEntered>='A' && chEntered<='Z') break;
-         if(chEntered>='a' && chEntered<='z') break;
-         if(chEntered==' ') break;
-         return(FALSE);
-
-      /* If only date characters are to be permitted. */
-      case 'D':
-      case 'd':
-         if(chEntered>='0' && chEntered<='9') break;
-         if(chEntered=='-' || chEntered=='/') break;
-         return(FALSE);
-
-      /* If only MS-DOS filename characters are to be permitted. */
-      case 'F':
-      case 'f':
-         if(chEntered >= 'A' && chEntered <= 'Z') break;
-         if(chEntered >= '0' && chEntered <= '9') break;
-         if(chEntered >= 'a' && chEntered <= 'z') break;
-         switch(chEntered)
-         {
-            /* Filename separators. */
-            case ':':
-            case '.':
-            case '\\':
-
-            /* Wildcard characters. */
-            case '?':
-            case '*':
-
-            /* Other valid symbols in filenames */
-            case '#':
-            case '$':
-            case '&':
-            case '\'':
-            case '(':
-            case '>':
-            case '-':
-            case '@':
-            case '_':
-            case '!':
-            case '{':
-            case '}':
-            case '~':
-               return(TRUE);
-         }
-
-         return(FALSE);
-
-      /* If only hexidecimal characters are to be permitted. */
-      case 'H':
-      case 'h':
-         if(chEntered>='0' && chEntered<='9') break;
-         if(chEntered>='A' && chEntered<='F') break;
-         if(chEntered>='a' && chEntered<='f') break;
-         return(FALSE);
-
-      /* If only telephone number characters are to be permitted. */
-      case 'T':                                          
-      case 't':
-         if(chEntered >= '0' && chEntered <= '9') break;
-         if(chEntered == '-' || chEntered == '(' || chEntered == ')'
-            || chEntered == ' ' || chEntered == '+')
-         {
-            break;
-         }
-         return(FALSE);
-
-      /* If filenames with wildcards are to be permitted. */
-      case 'W':
-      case 'w':
-         if(chEntered >= 'A' && chEntered <= 'Z') break;
-         if(chEntered >= 'a' && chEntered <= 'z') break;
-         if(chEntered == ':' || chEntered == '.' || chEntered == '\\'
-            || chEntered == '*' || chEntered == '?')
-         {
-            break;
-         }
-         return(FALSE);
-
-      /* If alpha-numeric characters are to be permitted. */
-      case 'X':
-      case 'x':
-         if(chEntered >= 'A' && chEntered <= 'Z') break;
-         if(chEntered >= 'a' && chEntered <= 'z') break;
-         if(chEntered >= '0' && chEntered <= '9') break;
-         if(chEntered == ' ') break;
-         return(FALSE);
-
-      /* If this is a Yes/No field. */
-      case 'Y':
-      case 'y':
-         if(chEntered == 'y' || chEntered == 'n' || chEntered == 'Y'
-            || chEntered == 'N')
-         {
-            break;
-         }
-         return(FALSE);
-   }
-
-   /* If execution gets to this point, then the character has been approved. */
-   return(TRUE);
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * ODEditAsCharForPos()                                *** PRIVATE FUNCTION ***
- *
- * Converts the character entered by the user to a valid character for this
- * position in the string. For example, for fields that are set to all
- * upper case, this function converts the entered characte to its upper case
- * equivalent.
- *
- * Parameters: chEntered   - Character that was entered by the user.
- *
- *             nPosition   - Position in the string where the character is to
- *                           be entered.
- *
- *     Return: The actual character to add to the input string at this
- *             position.
- */
-static char ODEditAsCharForPos(char chEntered, INT nPosition)
-{
-   /* If this character is a literal. */
-   if(abCurrentFormatLiteral[nPosition])
-   {                                      
-      /* Return the only valid char for this position. */
-      return(pszCurrentFormat[anCurrentFormatOffset[nPosition]]);
-   }
-
-   /* If this position has a corresponding format control character, */
-   /* then check that control character. */
-   switch(pszCurrentFormat[anCurrentFormatOffset[nPosition]])
-   {
-      /* If Yes/No characters are required. */
-      case 'Y':
-      case 'y':
-         return(toupper(chEntered));
-
-      /* If filename characters are required. */
-      case 'F':                                       
-      case 'f':
-         return(toupper(chEntered));
-
-      /* If lower case characters are required. */
-      case 'L':
-      case 'l':
-         return(tolower(chEntered));
-
-      /* If upper case characters are required. */
-      case 'U':
-      case 'u':
-         return(toupper(chEntered));
-
-      /* If automatic capitalization is required. */
-      case 'M':
-      case 'm':
-      case 'C':
-      case 'c':
-         /* First character is always upper case. */
-         if(nPosition == 0) return(toupper(chEntered));
-
-         /* Check for other base cases. */
-         if(abCurrentFormatLiteral[nPosition-1]) return(toupper(chEntered));
-         if(toupper(pszCurrentFormat[anCurrentFormatOffset[nPosition]]) != 'M'
-            && toupper(pszCurrentFormat[anCurrentFormatOffset[nPosition]])
-            != 'C')
-         {
-            return(toupper(chEntered));
-         }
-
-         /* If previous character is a word delimiter, then this character */
-         /* should be uppper case.                                         */
-         if(pszCurrentInput[nPosition-1] == ' '
-            || pszCurrentInput[nPosition-1] == '.'
-            || pszCurrentInput[nPosition-1] == ','
-            || pszCurrentInput[nPosition-1] == '-')
-         {
-            return(toupper(chEntered));                                             /* Otherwise, this should be lower */
-         }
-
-         /* Otherwise, this character should be lower-case. */
-         return(tolower(chEntered));
-   }
-
-   return(chEntered);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditDisplayPermaliteral()                         *** PRIVATE FUNCTION ***
- *
- * Displays permaliterals (characters specified in the format string that
- * should be returned in the input string, but which the user may never
- * change).
- *
- * Parameters: nFlags - Flags parameter that was passed into od_edit_str().
- *
- *     Return: void
- */
-static void ODEditDisplayPermaliteral(WORD nFlags)
-{
-   INT nCount;
-   BYTE btRepeat = 0;
-
-   for(nCount = strlen(pszCurrentInput); nCount <= nCurrentStringLength;
-      ++nCount)
-   {
-      if(nCount != nCurrentStringLength)
-      {
-         if(abCurrentFormatLiteral[nCount])
-         {
-            if(btRepeat > 0)
-            {
-               od_repeat(chCurrentBlank, btRepeat);
-               btRepeat = 0;
-            }
-            od_putch(pszCurrentFormat[anCurrentFormatOffset[nCount]]);
-         }
-         else
-         {
-            ++btRepeat;
-         }
-      }
-      else
-      {
-         if(!(nFlags & EDIT_FLAG_SHOW_SIZE))
-         {
-            ++btRepeat;
-         }
-      }
-   }
-
-   if(btRepeat > 0) od_repeat(chCurrentBlank, btRepeat);
-}
diff --git a/src/odoors/ODEdit.c b/src/odoors/ODEdit.c
deleted file mode 100644
index c6ed51158666d425698ae59a5a1a022e79191e74..0000000000000000000000000000000000000000
--- a/src/odoors/ODEdit.c
+++ /dev/null
@@ -1,2644 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODEdit.c
- *
- * Description: Implementation of the OpenDoors multi-line editor, which
- *              allows the user to edit strings which may span many lines.
- *              Provides standard text editor features, such as word wrap.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Dec 07, 1995  6.00  BP   Created.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 04, 1996  6.00  BP   Use od_get_input().
- *              Jan 12, 1996  6.00  BP   Claim exclusive use of arrow keys.
- *              Jan 31, 1996  6.00  BP   Added timeout for od_get_input().
- *              Feb 08, 1996  6.00  BP   Finished implementation details.
- *              Feb 13, 1996  6.00  BP   Added od_get_input() flags parameter.
- *              Feb 16, 1996  6.00  BP   New trans. size estimation heuristics.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 24, 1996  6.00  BP   Fixed garbage on [Enter] after w-wrap.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 13, 1996  6.10  BP   Restore cursor position after menu.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Jun 08, 1996  6.10  BP   Added cast in call to alloc function.
- *              Oct 19, 2001  6.20  RS   Eliminated MSVC 6.0 warning.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODTypes.h"
-#include "ODGen.h"
-#include "ODCore.h"
-#include "ODKrnl.h"
-#include "ODStat.h"
-#include "ODCom.h"
-#include "ODScrn.h"
-
-
-/* ========================================================================= */
-/* Misc. definitions.                                                        */
-/* ========================================================================= */
-
-/* Macros used by this module. */
-#define IS_EOL_CHAR(ch)       ((ch) == '\n' || (ch) == '\r' || (ch) == '\0')
-
-/* Configurable constants. */
-#define LINE_ARRAY_GROW_SIZE     20
-#define BUFFER_GROW_SIZE         4096
-#define ANSI_SCROLL_DISTANCE     7
-#define PRE_DRAIN_TIME           10000
-#define MAX_TAB_STOP_SIZE        8
-#define DEFAULT_TAB_STOP_SIZE    8
-#define DEFAULT_LINE_BREAK       "\n"
-
-/* Other manifest constants. */
-#define REDRAW_NO_BOUNDARY       0xffff
-
-/* Default editor options. */
-static tODEditOptions ODEditOptionsDefault =
-{
-   1, 1, 80, 23,
-   FORMAT_PARAGRAPH_BREAKS,
-   NULL,
-   NULL,
-   EFLAG_NORMAL,
-};
-
-
-
-/* ========================================================================= */
-/* Multiline editor instance structure.                                      */
-/* ========================================================================= */
-
-typedef struct
-{
-   char *pszEditBuffer;
-   UINT unBufferSize;
-   tODEditOptions *pUserOptions;
-   UINT unCurrentLine;
-   UINT unCurrentColumn;
-   UINT unLineScrolledToTop;
-   UINT unAreaWidth;
-   UINT unAreaHeight;
-   char **papchStartOfLine;
-   UINT unLineArraySize;
-   UINT unLinesInBuffer;
-   BOOL bInsertMode;
-   UINT unTabStopSize;
-   UINT unScrollDistance;
-   char *pszLineBreak;
-   char *pszParagraphBreak;
-   BOOL bWordWrapLongLines;
-   void *pRememberBuffer;
-} tEditInstance;
-
-
-
-/* ========================================================================= */
-/* Editor function prototypes.                                               */
-/* ========================================================================= */
-
-/* High level implementation. */
-static BOOL ODEditSetupInstance(tEditInstance *pEditInstance,
-   char *pszBufferToEdit, UINT unBufferSize, tODEditOptions *pUserOptions);
-static void ODEditRedrawArea(tEditInstance *pEditInstance);
-static void ODEditDrawAreaLine(tEditInstance *pEditInstance,
-   UINT unAreaLineToDraw);
-static INT ODEditMainLoop(tEditInstance *pEditInstance);
-static void ODEditGotoPreviousLine(tEditInstance *pEditInstance);
-static void ODEditGotoNextLine(tEditInstance *pEditInstance);
-static BOOL ODEditScrollArea(tEditInstance *pEditInstance, INT nDistance);
-static BOOL ODEditRecommendFullRedraw(tEditInstance *pEditInstance,
-   UINT unEstPartialRedrawBytes, BOOL bDefault);
-static UINT ODEditEstDrawBytes(tEditInstance *pEditInstance,
-   UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
-   UINT unFinishRedrawColumn);
-static UINT ODEditGetCurrentLineInArea(tEditInstance *pEditInstance);
-static void ODEditUpdateCursorPos(tEditInstance *pEditInstance);
-static void ODEditUpdateCursorIfMoved(tEditInstance *pEditInstance);
-static tODResult ODEditEnterText(tEditInstance *pEditInstance,
-   char *pszEntered, BOOL bInsertMode);
-static void ODEditSetBreakSequence(tEditInstance *pEditInstance,
-   char chFirstEOLChar, char chSecondEOLChar);
-static BOOL ODEditCursorLeft(tEditInstance *pEditInstance);
-static void ODEditDeleteCurrentChar(tEditInstance *pEditInstance);
-static void ODEditDeleteCurrentLine(tEditInstance *pEditInstance);
-static BOOL ODEditPastEndOfCurLine(tEditInstance *pEditInstance);
-static size_t ODEditRememberBufferSize(tEditInstance *pEditInstance);
-static void ODEditRememberArea(tEditInstance *pEditInstance,
-   void *pRememberedArea);
-static void ODEditRedrawChanged(tEditInstance *pEditInstance,
-   void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary);
-static BOOL ODEditDetermineChanged(tEditInstance *pEditInstance,
-   void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary, 
-   UINT *punStartRedrawLine, UINT *punStartRedrawColumn,
-   UINT *punFinishRedrawLine, UINT *punFinishRedrawColumn);
-static void ODEditRedrawSubArea(tEditInstance *pEditInstance,
-   UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
-   UINT unFinishRedrawColumn);
-static void ODEditGetActualCurPos(tEditInstance *pEditInstance,
-   UINT *punRow, UINT *punColumn);
-static BOOL ODEditIsEOLForMode(tEditInstance *pEditInstance, char chToTest);
-
-/* Low level buffer manipulation functions. */
-static BOOL ODEditBufferFormatAndIndex(tEditInstance *pEditInstance);
-static UINT ODEditBufferGetLineLength(tEditInstance *pEditInstance,
-   UINT unBufferLine);
-static UINT ODEditBufferGetTotalLines(tEditInstance *pEditInstance);
-static char *ODEditBufferGetCharacter(tEditInstance *pEditInstance,
-   UINT unBufferLine, UINT unBufferColumn);
-static tODResult ODEditBufferMakeSpace(tEditInstance *pEditInstance,
-   UINT unLine, UINT unColumn, UINT unNumChars);
-static tODResult ODEditTryToGrow(tEditInstance *pEditInstance,
-   UINT unSizeNeeded);
-
-
-
-/* ========================================================================= */
-/* High level editor implementation.                                         */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * od_multiline_edit()
- *
- * Multiline editor function, allows the user to enter or change text that
- * spans multiple lines.
- *
- * Parameters: pszBufferToEdit  - Pointer to '\0'-terminated buffer of text
- *                                to edit.
- *
- *             unBufferSize     - Size of the buffer, in characters.
- *
- *             pEditOptions     - Pointer to a tODEditOptions structure, or
- *                                NULL to use default settings.
- *
- *     Return: An od_multiline_edit()-specific result code.
- */
-ODAPIDEF INT ODCALL od_multiline_edit(char *pszBufferToEdit, UINT unBufferSize,
-   tODEditOptions *pEditOptions)
-{
-   tEditInstance EditInstance;
-   INT nToReturn;
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_node_open()");
-
-   /* Initialize OpenDoors if not already done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Validate parameters. */
-   if(pszBufferToEdit == NULL || unBufferSize == 0)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(OD_MULTIEDIT_ERROR);
-   }
-
-   /* Check the user's terminal supports the required capabilities. */
-   if(!(od_control.user_ansi || od_control.user_avatar))
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(OD_MULTIEDIT_ERROR);
-   }
-
-   /* Initialize editor instance information structure. */
-   if(!ODEditSetupInstance(&EditInstance, pszBufferToEdit, unBufferSize,
-      pEditOptions))
-   {
-      OD_API_EXIT();
-      return(OD_MULTIEDIT_ERROR);
-   }
-
-   /* Attempt to build the buffer line index and ensure that the buffer */
-   /* conforms to the format specified by the client application.       */
-   if(!ODEditBufferFormatAndIndex(&EditInstance))
-   {
-      od_control.od_error = ERR_MEMORY;
-      OD_API_EXIT();
-      return(OD_MULTIEDIT_ERROR);
-   }
-
-   /* Claim exclusive use of arrow keys. */
-   ODStatStartArrowUse();
-
-   /* Ensure that all information in the outbound communications buffer  */
-   /* has been sent before starting. This way, we can safely purge the   */
-   /* outbound buffer at any time without loosing anything that was sent */
-   /* before od_multiline_edit() was called.                             */
-   ODWaitDrain(PRE_DRAIN_TIME);
-
-   /* Draw the initial edit area. */
-   ODEditRedrawArea(&EditInstance);
-
-   /* Run the main editor loop. */
-   nToReturn = ODEditMainLoop(&EditInstance);
-
-   /* Release exclusive use of arrow keys. */
-   ODStatEndArrowUse();
-
-   /* Set final information which will be available in the user options */
-   /* structure for the client application to access.                   */
-   EditInstance.pUserOptions->pszFinalBuffer = EditInstance.pszEditBuffer;
-   EditInstance.pUserOptions->unFinalBufferSize = unBufferSize;
-
-   OD_API_EXIT();
-   return(nToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditSetupInstance()                               *** PRIVATE FUNCTION ***
- *
- * Initializes editor instance information structure.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *             pszBufferToEdit - Buffer pointer provided by client.
- *
- *             unBufferSize    - Initial buffer size, as specified by the
- *                               client.
- *
- *             pUserOptions    - Editor options specified by the client.
- *
- *     Return: TRUE on success, FALSE on failure. In the case of failure,
- *             od_control.od_error is set appropriately.
- */
-static BOOL ODEditSetupInstance(tEditInstance *pEditInstance,
-   char *pszBufferToEdit, UINT unBufferSize, tODEditOptions *pUserOptions)
-{
-   ASSERT(pEditInstance != NULL);
-   ASSERT(pszBufferToEdit != NULL);
-
-   /* Setup editor instance structure. */
-   pEditInstance->pszEditBuffer = pszBufferToEdit;
-   pEditInstance->unBufferSize = unBufferSize;
-   if(pUserOptions == NULL)
-   {
-      /* Edit options is just the defaults. */
-      pEditInstance->pUserOptions = &ODEditOptionsDefault;
-   }
-   else
-   {
-      /* Edit options are supplied by the user. */
-      pEditInstance->pUserOptions = pUserOptions;
-
-      /* Initialize any edit options that the user did not setup. */
-      /* Check that edit area has been initialized. */
-      if(pUserOptions->nAreaLeft == 0)
-      {
-         pUserOptions->nAreaLeft = ODEditOptionsDefault.nAreaLeft;
-      }
-      if(pUserOptions->nAreaRight == 0)
-      {
-         pUserOptions->nAreaRight = ODEditOptionsDefault.nAreaRight;
-      }
-        if(pUserOptions->nAreaTop == 0)
-      {
-         pUserOptions->nAreaTop = ODEditOptionsDefault.nAreaTop;
-      }
-      if(pUserOptions->nAreaBottom == 0)
-      {
-         pUserOptions->nAreaBottom = ODEditOptionsDefault.nAreaBottom;
-      }
-   }
-   pEditInstance->unCurrentLine = 0;
-   pEditInstance->unCurrentColumn = 0;
-   pEditInstance->unLineScrolledToTop = 0;
-   pEditInstance->papchStartOfLine = NULL;
-   pEditInstance->unLineArraySize = 0;
-   pEditInstance->unLinesInBuffer = 0;
-   pEditInstance->unAreaWidth = (UINT)pEditInstance->pUserOptions->
-      nAreaRight - (UINT)pEditInstance->pUserOptions->nAreaLeft + 1;
-   pEditInstance->unAreaHeight = (UINT)pEditInstance->pUserOptions->
-      nAreaBottom - (UINT)pEditInstance->pUserOptions->nAreaTop + 1;
-   pEditInstance->bInsertMode = TRUE;
-   pEditInstance->unTabStopSize = DEFAULT_TAB_STOP_SIZE;
-
-   /* Setup line break and paragraph break sequences, if they can be  */
-   /* determined at this point. If they can't be determined, set them */
-   /* to NULL.                                                        */
-   switch(pEditInstance->pUserOptions->TextFormat)
-   {
-      case FORMAT_FTSC_MESSAGE:
-         /* FTSC compliant messages use \r as a paragraph break, and do */
-         /* not have any line break characters.                         */
-         pEditInstance->pszLineBreak = "";
-         pEditInstance->pszParagraphBreak = "\r";
-         break;
-
-      case FORMAT_PARAGRAPH_BREAKS:
-         /* Paragraph break mode only inserts CR/LF sequences at the end  */
-         /* of a paragrah, and word-wraps the text that forms a paragrah. */
-         pEditInstance->pszLineBreak = "";
-         pEditInstance->pszParagraphBreak = NULL;
-         break;
-
-      case FORMAT_LINE_BREAKS:
-      case FORMAT_NO_WORDWRAP:
-         /* Line break mode and no word wrap mode both terminate every    */
-         /* line of the file with a CR/LF sequence, and have no paragrah  */
-         /* terminator. In line break mode, word wrap is enabled, whereas */
-         /* it is not in FORMAT_NO_WORDWRAP mode.                         */
-         pEditInstance->pszLineBreak = NULL;
-         pEditInstance->pszParagraphBreak = "";
-         break;
-
-      default:
-         /* An invalid text format was specified. */
-         od_control.od_error = ERR_PARAMETER;
-         return(FALSE);
-   }
-
-   /* Determine whether long lines sould be word wrapped or character */
-   /* wrapped.                                                        */
-   pEditInstance->bWordWrapLongLines = (pEditInstance->pUserOptions->TextFormat
-      != FORMAT_NO_WORDWRAP);
-
-   /* Attempt to allocate abuffer for remembered data. */
-   pEditInstance->pRememberBuffer =
-      malloc(ODEditRememberBufferSize(pEditInstance));
-   
-   if(pEditInstance->pRememberBuffer == NULL)
-   {
-      od_control.od_error = ERR_MEMORY;
-      return(FALSE);
-   }
-
-   /* If AVATAR mode or local mode is active, then scroll up or down one */
-   /* line at a time.                                                    */
-   if(od_control.user_avatar || od_control.baud == 0)
-   {
-      pEditInstance->unScrollDistance = 1;
-   }
-   /* In ANSI mode with a remote connection, scroll multiple lines at a */
-   /* time. This is the minimum of the default scroll distance, and the */
-   /* current height of the edit area - 1.                              */
-   else
-   {
-      pEditInstance->unScrollDistance = MIN(ANSI_SCROLL_DISTANCE,
-         pEditInstance->pUserOptions->nAreaBottom
-         - pEditInstance->pUserOptions->nAreaTop);
-   }
-
-   /* Return with success. */
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRedrawArea()                                  *** PRIVATE FUNCTION ***
- *
- * Redraws the area of the screen used by the editor.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditRedrawArea(tEditInstance *pEditInstance)
-{
-   UINT unAreaLine;
-
-   ASSERT(pEditInstance != NULL);
-
-   ODScrnEnableCaret(FALSE);
-
-   /* First, remove anything that is still in the outbound communications */
-   /* buffer, since whatever it was, it will no longer be visible after   */
-   /* the screen redraw anyhow.                                           */
-   if(od_control.baud != 0) ODComClearOutbound(hSerialPort);
-
-   /* Loop, drawing every line in the edit area. */
-   for(unAreaLine = 0; unAreaLine < pEditInstance->unAreaHeight; ++unAreaLine)
-   {
-      ODEditDrawAreaLine(pEditInstance, unAreaLine);
-   }
-
-   ODScrnEnableCaret(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditDrawAreaLine()                                *** PRIVATE FUNCTION ***
- *
- * Redraws the specified line in the area of the screen used by the editor.
- *
- * Parameters: pEditInstance    - Editor instance information structure.
- *
- *             unAreaLineToDraw - 0-based line number in the edit area to be
- *                                redrawn.
- *
- *     Return: void
- */
-static void ODEditDrawAreaLine(tEditInstance *pEditInstance,
-   UINT unAreaLineToDraw)
-{
-   UINT unBufferLine;
-   UINT unLineLength;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(unAreaLineToDraw >= 0);
-   ASSERT(unAreaLineToDraw < pEditInstance->unAreaHeight);
-
-   /* Determine the buffer line that is displayed on this screen line. */   
-   unBufferLine = unAreaLineToDraw + pEditInstance->unLineScrolledToTop;
-
-   /* Position the cursor to the beginning of this line. */
-   od_set_cursor((UINT)pEditInstance->pUserOptions->nAreaTop
-      + unAreaLineToDraw, (UINT)pEditInstance->pUserOptions->nAreaLeft);
-
-   /* If this line is not beyond the end of the buffer. */
-   if(unBufferLine < pEditInstance->unLinesInBuffer)
-   {
-      /* Determine the length of this buffer line. */
-      unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
-
-      od_disp(ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0),
-         unLineLength, TRUE);
-   }
-
-   /* If right edge of edit area aligns with the right edge of the screen. */
-   if(pEditInstance->pUserOptions->nAreaRight == OD_SCREEN_WIDTH)
-   {
-      /* Clear the remainder of this line on the screen. */
-      od_clr_line();
-   }
-   else
-   {
-      /* Place spaces after the end of the current line, up to right edge of */
-      /* the edit area.                                                      */
-      od_repeat(' ', (BYTE)(pEditInstance->unAreaWidth - unLineLength));
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditMainLoop()                                    *** PRIVATE FUNCTION ***
- *
- * Implements the main editor loop, which repeatedly waits for input from the
- * user, until the user chooses to exit.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: Value to be returned by od_multiline_edit.
- */
-static INT ODEditMainLoop(tEditInstance *pEditInstance)
-{
-   tODInputEvent InputEvent;
-
-   ASSERT(pEditInstance != NULL);
-
-   /* Set initial cursor position. */
-   ODEditUpdateCursorPos(pEditInstance);
-
-   /* Loop, obtaining keystrokes until the user chooses to exit. */
-   for(;;)
-   {
-      od_get_input(&InputEvent, OD_NO_TIMEOUT, GETIN_NORMAL);
-      if(InputEvent.EventType == EVENT_EXTENDED_KEY)
-      {
-         switch(InputEvent.chKeyPress)
-         {
-            case OD_KEY_UP:
-               /* If we aren't at the start of the file, then move to the */
-               /* previous line.                                          */
-               if(pEditInstance->unCurrentLine > 0)
-               {
-                  ODEditGotoPreviousLine(pEditInstance);
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               break;
-
-            case OD_KEY_DOWN:
-               /* If we aren't at the end of the file, then move to the */
-               /* next line.                                            */
-               if(pEditInstance->unCurrentLine
-                  < ODEditBufferGetTotalLines(pEditInstance) - 1)
-               {
-                  ODEditGotoNextLine(pEditInstance);
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               break;
-
-            case OD_KEY_LEFT:
-               /* Attempt to move the cursor left. */
-               if(ODEditCursorLeft(pEditInstance))
-               {
-                  /* If it was possible to move the cursor, then update the */
-                  /* cursor position on the screen.                         */
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               break;
-
-            case OD_KEY_RIGHT:
-               /* In word wrap mode, we allow the cursor to move up to the */
-               /* end of this line, and then wrap around to the next line. */
-               if(pEditInstance->bWordWrapLongLines)
-               {
-                  if(pEditInstance->unCurrentColumn < ODEditBufferGetLineLength
-                     (pEditInstance, pEditInstance->unCurrentLine))
-                  {
-                     ++pEditInstance->unCurrentColumn;
-                     ODEditUpdateCursorPos(pEditInstance);
-                  }
-                  else if(pEditInstance->unCurrentLine
-                     < ODEditBufferGetTotalLines(pEditInstance) - 1)
-                  {
-                     ODEditGotoNextLine(pEditInstance);
-                     pEditInstance->unCurrentColumn = 0;
-                     ODEditUpdateCursorPos(pEditInstance);
-                  }
-               }
-
-               /* In character wrap mode, we allow the cursor to move up to */
-               /* the right edge of the edit area.                          */
-               else
-               {
-                  if(pEditInstance->unCurrentColumn
-                     < pEditInstance->unAreaWidth - 1)
-                  {
-                     ++pEditInstance->unCurrentColumn;
-                     ODEditUpdateCursorPos(pEditInstance);
-                  }
-               }
-               break;
-
-            case OD_KEY_HOME:
-               pEditInstance->unCurrentColumn = 0;
-               ODEditUpdateCursorPos(pEditInstance);
-               break;
-
-            case OD_KEY_END:
-               pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
-                  pEditInstance, pEditInstance->unCurrentLine);
-               ODEditUpdateCursorPos(pEditInstance);
-               break;
-
-            case OD_KEY_PGUP:
-               if(pEditInstance->unLineScrolledToTop > 0)
-               {
-                  UINT unDistance = MIN(pEditInstance->unAreaHeight - 1,
-                     pEditInstance->unLineScrolledToTop);
-                  ODEditScrollArea(pEditInstance, -((INT)unDistance));
-                  pEditInstance->unCurrentLine -= unDistance;
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               else if(pEditInstance->unCurrentLine != 0)
-               {
-                  pEditInstance->unCurrentLine = 0;
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               break;
-
-            case OD_KEY_PGDN:
-               if(pEditInstance->unLineScrolledToTop <
-                  pEditInstance->unLinesInBuffer - 1)
-               {
-                  UINT unDistance = MIN(pEditInstance->unAreaHeight - 1,
-                     pEditInstance->unLinesInBuffer
-                     - pEditInstance->unLineScrolledToTop - 1);
-                  ODEditScrollArea(pEditInstance, (INT)unDistance);
-                  pEditInstance->unCurrentLine = MIN(
-                     pEditInstance->unCurrentLine + unDistance,
-                     pEditInstance->unLinesInBuffer - 1);
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-            break;
-
-            case OD_KEY_INSERT:
-               /* If the insert key is pressed, then toggle insert mode. */
-               pEditInstance->bInsertMode = !pEditInstance->bInsertMode;
-               break;
-
-            case OD_KEY_DELETE:
-               /* Delete the character at the current position. */
-               
-               /* If we are currently past the end of this line. */
-               if(ODEditPastEndOfCurLine(pEditInstance))
-               {
-                  /* Add spaces to this line to fill it up to the current */
-                  /* cursor position.                                     */
-                  switch(ODEditBufferMakeSpace(pEditInstance,
-                     pEditInstance->unCurrentLine,
-                     pEditInstance->unCurrentColumn, 0))
-                  {
-                     case kODRCUnrecoverableFailure:
-                        /* If we encountered an unrecoverable failure, then */
-                        /* exit from the editor with a memory allocation    */
-                        /* error.                                           */
-                        od_control.od_error = ERR_MEMORY;
-                        return(OD_MULTIEDIT_ERROR);
-
-                     case kODRCSuccess:
-                        /* On success, delete the current character. */
-                        ODEditDeleteCurrentChar(pEditInstance);
-                        break;
-
-                     default:
-                        /* On any other failure, just beep and continue. */
-                        od_putch('\a');
-                  }
-               }
-               else
-               {
-                  /* If we aren't pas the end of the line, then just do a */
-                  /* simple delete character operation.                   */
-                  ODEditDeleteCurrentChar(pEditInstance);
-               }
-               break;
-         }
-      }
-      else if(InputEvent.EventType == EVENT_CHARACTER)
-      {
-         if(InputEvent.chKeyPress == 25)
-         {
-            /* Control-Y (delete line) has been pressed. */
-            ODEditDeleteCurrentLine(pEditInstance);
-         }
-         else if(InputEvent.chKeyPress == 26
-            || InputEvent.chKeyPress == 27)
-         {
-            /* Escape or control-Z has been pressed. */
-
-            /* If a menu callback function has been provided by */
-            /* the client, then call it.                        */
-            if(pEditInstance->pUserOptions->pfMenuCallback != NULL)
-            {
-               /* Call the menu callback function. */
-               switch((*pEditInstance->pUserOptions->pfMenuCallback)(NULL))
-               {
-                  case EDIT_MENU_EXIT_EDITOR:
-                     return(OD_MULTIEDIT_SUCCESS);
-
-                  case EDIT_MENU_DO_NOTHING:
-                     /* Continue in the editor without doing anything. */
-                     break;
-
-                  default:
-                     ASSERT(FALSE);
-               }
-
-               /* If we are continuing, then restore initial cursor pos. */
-               ODEditUpdateCursorPos(pEditInstance);
-            }
-            else
-            {
-               /* If a menu key callback function has not been provided, */
-               /* then we exit the editor unconditionally.               */
-               return(OD_MULTIEDIT_SUCCESS);
-            }
-         }
-         else if(InputEvent.chKeyPress == '\b')
-         {
-            /* Backspace key has been pressed. */
-
-            /* If the cursor is past the end of the line, then we just move */
-            /* the cursor left, without deleting any characters. */
-            BOOL bDelete = !ODEditPastEndOfCurLine(pEditInstance);
-
-            /* Backup the cursor one space. */
-            if(ODEditCursorLeft(pEditInstance))
-            {
-               /* If there was space to move the cursor back to, then       */
-               /* proceed and remove the character at the current position. */
-               if(bDelete)
-               {
-                  ODEditDeleteCurrentChar(pEditInstance);
-               }
-               else
-               {
-                  /* In this case, we must still show the new cursor */
-                  /* position.                                       */
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-            }
-         }
-         else if(InputEvent.chKeyPress == '\t')
-         {
-            char szTextToAdd[MAX_TAB_STOP_SIZE + 1];
-            UINT unTargetColumn;
-            UINT unTargetDistance;
-
-            /* A tab key has been entered. */
-
-            /* Determine the column that this will move the cursor to. */
-            ASSERT(pEditInstance->unTabStopSize <= MAX_TAB_STOP_SIZE);
-            unTargetColumn = ((pEditInstance->unCurrentColumn / pEditInstance->
-               unTabStopSize) + 1) * pEditInstance->unTabStopSize;
-
-            /* In insert mode, then insert spaces into the buffer. */
-            if(pEditInstance->bInsertMode)
-            {
-               /* Determine the number of columns that we need to advance in */
-               /* order to reach this target column.                         */
-               unTargetDistance = unTargetColumn -
-                  pEditInstance->unCurrentColumn;
-               ASSERT(unTargetDistance <= MAX_TAB_STOP_SIZE);
-
-               /* Translate this to a string with the appropriate number of */
-               /* spaces.                                                   */
-               memset(szTextToAdd, ' ', unTargetDistance);
-               szTextToAdd[unTargetDistance] = '\0';
-
-               /* Add this to the buffer. */
-               if(ODEditEnterText(pEditInstance, szTextToAdd, TRUE) ==
-                  kODRCUnrecoverableFailure)
-               {
-                  od_control.od_error = ERR_MEMORY;
-                  return(OD_MULTIEDIT_ERROR);
-               }
-            }
-
-            /* In overwrite mode, then just advance the cursor position. */
-            else
-            {
-               /* Determine the column where the cursor should be wrapped. */
-               UINT unWrapColumn = pEditInstance->bWordWrapLongLines ?
-                  ODEditBufferGetLineLength(pEditInstance,
-                  pEditInstance->unCurrentLine)
-                  : pEditInstance->unAreaWidth;
-
-               if(unTargetColumn < unWrapColumn)
-               {
-                  pEditInstance->unCurrentColumn = unTargetColumn;
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-               else if(pEditInstance->unCurrentLine
-                  < ODEditBufferGetTotalLines(pEditInstance) - 1)
-               {
-                  ODEditGotoNextLine(pEditInstance);
-                  pEditInstance->unCurrentColumn = 0;
-                  ODEditUpdateCursorPos(pEditInstance);
-               }
-            }
-         }
-         else if(InputEvent.chKeyPress == '\r')
-         {
-            char *pszTextToAdd;
-
-            /* The enter key has been pressed. In insert mode, or at the end */
-            /* of the buffer in overwrite mode, this adds a new line.        */
-            if(pEditInstance->bInsertMode || pEditInstance->unCurrentLine
-                  >= ODEditBufferGetTotalLines(pEditInstance) - 1)
-            {
-               if(!pEditInstance->bInsertMode)
-               {
-                  /* If we are not in insert mode, begin by positioning the */
-                  /* cursor at the end of this line.                        */
-                  pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
-                     pEditInstance, pEditInstance->unCurrentLine);
-               }
-
-               /* Determine the line/paragraph break sequence to use. */
-               if(pEditInstance->pszLineBreak != NULL
-                  && strlen(pEditInstance->pszLineBreak) > 0)
-               {
-                  pszTextToAdd = pEditInstance->pszLineBreak;
-               }
-               else if(pEditInstance->pszParagraphBreak != NULL
-                  && strlen(pEditInstance->pszParagraphBreak) > 0)
-               {
-                  pszTextToAdd = pEditInstance->pszParagraphBreak;
-               }
-               else
-               {
-                  pszTextToAdd = DEFAULT_LINE_BREAK;
-               }
-
-               /* Insert the sequence into the buffer. */
-               if(ODEditEnterText(pEditInstance, pszTextToAdd, TRUE) ==
-                  kODRCUnrecoverableFailure)
-               {
-                  od_control.od_error = ERR_MEMORY;
-                  return(OD_MULTIEDIT_ERROR);
-               }
-            }
-            else
-            {
-               /* Pressing the enter key in overwrite mode just moves the   */
-               /* cursor to the beginning of the next line. In other words, */
-               /* it is equivalent to pressing Down arrow followed by home. */
-               ODEditGotoNextLine(pEditInstance);
-               pEditInstance->unCurrentColumn = 0;
-               ODEditUpdateCursorPos(pEditInstance);
-            }
-         }
-         else if(InputEvent.chKeyPress >= 32)
-         {
-            char szTextToAdd[2];
-            szTextToAdd[0] = InputEvent.chKeyPress;
-            szTextToAdd[1] = '\0';
-
-            /* A valid buffer character has been entered. */
-            if(ODEditEnterText(pEditInstance, szTextToAdd,
-               (BOOL)(pEditInstance->bInsertMode
-               || ODEditPastEndOfCurLine(pEditInstance)))
-               == kODRCUnrecoverableFailure)
-            {
-               od_control.od_error = ERR_MEMORY;
-               return(OD_MULTIEDIT_ERROR);
-            }
-         }
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditGotoPreviousLine()                            *** PRIVATE FUNCTION ***
- *
- * Moves the current cursor position to the previous line, scrolling the screen
- * if necessary to keep the cursor visible.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditGotoPreviousLine(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   /* If we are already at the first line, then return without doing */
-   /* anything.                                                      */
-   if(pEditInstance->unCurrentLine == 0) return;
-
-   /* If cursor is at top of edit area, then scroll area */
-   /* first.                                             */
-   if(ODEditGetCurrentLineInArea(pEditInstance) == 0)
-   {
-      ODEditScrollArea(pEditInstance,
-         -(INT)(MIN(pEditInstance->unScrollDistance,
-         pEditInstance->unCurrentLine)));
-   }
-
-   /* Move cursor to previous line. */
-   --pEditInstance->unCurrentLine;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditGotoNextLine()                                *** PRIVATE FUNCTION ***
- *
- * Advances the current cursor position to the next line, scrolling the screen
- * if necessary to keep the cursor visible.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditGotoNextLine(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   /* If we are already at the end of the file, then return without */
-   /* doing anything.                                               */
-   if(pEditInstance->unCurrentLine
-      >= ODEditBufferGetTotalLines(pEditInstance) - 1)
-   {
-      return;
-   }
-
-   /* If cursor is at the bottom of the edit area, then scroll area first. */
-   if(ODEditGetCurrentLineInArea(pEditInstance)
-      == pEditInstance->unAreaHeight - 1)
-   {
-      ODEditScrollArea(pEditInstance,
-         (INT)MIN(pEditInstance->unScrollDistance,
-         ODEditBufferGetTotalLines(pEditInstance)
-         - pEditInstance->unCurrentLine));
-   }
-
-   /* Move cursor to next line. */
-   ++pEditInstance->unCurrentLine;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditScrollArea()                                  *** PRIVATE FUNCTION ***
- *
- * Scrolls the edit area up or down the specified distance, redrawing newly
- * "exposed" lines.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *             nDistance     - Number of lines to scroll, where a positive
- *                             value moves the text upwards, and a negative
- *                             value moves the text down.
- *
- *     Return: FALSE if a full redraw has been performed, TRUE if an efficient
- *             scroll command has been used.
- */
-static BOOL ODEditScrollArea(tEditInstance *pEditInstance, INT nDistance)
-{
-   BOOL bUseScrollCommand = FALSE;
-   UINT unAreaLine;
-   UINT unBufferLine;
-   UINT unFirstAreaLineToDraw;
-   UINT unLastAreaLineToDraw;
-   UINT unPositiveDistance;
-
-   ASSERT(pEditInstance);
-
-   /* If scroll distance is zero, then we don't need to do anything at all. */
-   if(nDistance == 0)
-   {
-      return(TRUE);
-   }
-   /* Otherwise, obtain the absolute value of the distance as an unsigned */
-   /* integer.                                                            */
-   else if(nDistance < 0)
-   {
-      unPositiveDistance = (UINT)-nDistance;
-   }
-   else
-   {
-      unPositiveDistance = (UINT)nDistance;
-   }
-
-   /* In AVATAR mode, if more than one of the currently visible lines will */
-   /* still be visible after scrolling, then we will consider using the    */
-   /* scroll operation.                                                    */
-   if(od_control.user_avatar
-      && ((INT)pEditInstance->unAreaHeight) - ((INT)unPositiveDistance) > 1)
-   {
-      /* Even under this situation, we only want to use the scroll operation */
-      /* if the amount of data still in the outbound buffer + our estimate   */
-      /* of the amount of data that will be sent to perform the scroll       */
-      /* operation is less than our estimate of the amount of data that      */
-      /* would be sent by a complete screen redraw.                          */
-      UINT unEstimatedScrollData = ((pEditInstance->unAreaWidth + 4) *
-         unPositiveDistance) + 7;
-
-      if(!ODEditRecommendFullRedraw(pEditInstance, unEstimatedScrollData,
-         TRUE))
-      {
-         bUseScrollCommand = TRUE;
-      }
-   }
-
-   /* In local mode, we can also use the scroll command for efficiency. */
-   if(od_control.baud == 0)
-   {
-      bUseScrollCommand = TRUE;
-   }
-
-   /* Area scroll is achieved by one of two means. We either use the scroll */
-   /* command, and then draw just the newly visible lines, or we redraw the */
-   /* entire edit area, after removing any data from the outbound           */
-   /* communications buffer.                                                */
-
-   if(bUseScrollCommand)
-   {
-      /* Use the od_scroll() function to scroll the screen contents. */
-      od_scroll(pEditInstance->pUserOptions->nAreaLeft,
-         pEditInstance->pUserOptions->nAreaTop,
-         pEditInstance->pUserOptions->nAreaRight,
-         pEditInstance->pUserOptions->nAreaBottom,
-         nDistance, SCROLL_NO_CLEAR);
-
-      /* Fill the newly visible lines. First, the portion of the area that   */
-      /* requires redrawing is determined, and then a loop redraws the lines */
-      /* that must be drawn.                                                 */
-
-      /* If we are moving text upwards, exposing new lines at the bottom of */
-      /* the area:                                                          */
-      if(nDistance > 0)
-      {
-         ASSERT(pEditInstance->unLineScrolledToTop + unPositiveDistance
-            < pEditInstance->unLinesInBuffer);
-         pEditInstance->unLineScrolledToTop += unPositiveDistance;
-         unFirstAreaLineToDraw = pEditInstance->unAreaHeight
-            - (UINT)unPositiveDistance;
-         unLastAreaLineToDraw = pEditInstance->unAreaHeight - 1;
-      }
-      /* Otherwise, we have moved text downwards, exposing new lines at the */
-      /* top of the edit area.                                              */
-      else
-      {
-         ASSERT(pEditInstance->unLineScrolledToTop >= unPositiveDistance);
-         pEditInstance->unLineScrolledToTop -= unPositiveDistance;
-         unFirstAreaLineToDraw = 0;
-         unLastAreaLineToDraw = unPositiveDistance - 1;
-      }
-
-      ODScrnEnableCaret(FALSE);
-
-      /* Now, redraw the new lines. */
-      unBufferLine = unFirstAreaLineToDraw
-         + pEditInstance->unLineScrolledToTop;
-      for(unAreaLine = unFirstAreaLineToDraw; unAreaLine <=
-         unLastAreaLineToDraw; ++unAreaLine, ++unBufferLine)
-      {
-         /* Draw the entire line. */
-         ODEditDrawAreaLine(pEditInstance, unAreaLine);
-      }
-
-      ODScrnEnableCaret(TRUE);
-   }
-
-   /* Just redraw the entire edit area. */
-   else
-   {
-      /* Adjust the line number that is scrolled to the top of the screen. */
-      if(nDistance > 0)
-      {
-         pEditInstance->unLineScrolledToTop += unPositiveDistance;
-      }
-      else
-      {
-         pEditInstance->unLineScrolledToTop -= unPositiveDistance;
-      }
-
-      /* Perform redraw, first purging outbound buffer. */
-      ODEditRedrawArea(pEditInstance);
-   }
-
-   return(bUseScrollCommand);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRecommendFullRedraw()                         *** PRIVATE FUNCTION ***
- *
- * Determines whether it would be more efficient to add the specified number
- * of bytes to the outbound buffer as part of an incremental redraw, or if
- * it would be more efficient to just purge the outbound buffer and do a
- * complete redraw of the edit area.
- *
- * Parameters: pEditInstance           - Editor instance information structure.
- *
- *             unEstPartialRedrawBytes - Estimate of the number of bytes that
- *                                       would be transmitted if an incremental
- *                                       redraw is performed.
- *
- *             bDefault                - The default action (TRUE for full
- *                                       redraw, FALSE for incremental) if the
- *                                       number of bytes in the outbound buffer
- *                                       cannot be determined.
- *
- *     Return: TRUE if a full redraw is recommended, FALSE if an the
- *             incremental redraw is recommended.
- */
-static BOOL ODEditRecommendFullRedraw(tEditInstance *pEditInstance,
-   UINT unEstPartialRedrawBytes, BOOL bDefault)
-{
-   int nOutboundBufferBytes;
-   UINT unEstFullRedrawBytes;
-
-   /* In local mode, just return the default action. */
-   if(od_control.baud == 0)
-   {
-      return(bDefault);
-   }
-
-   /* Attempt to obtain the number of bytes in the communications outbound */
-   /* buffer. Unfortunately, this information may not be available. For    */
-   /* example, FOSSIL drivers will only report whether or not there is     */
-   /* still data in the outbound buffer, but not a count of the number of  */
-   /* bytes in the buffer. Under such a situation, ODComOutbound() returns */
-   /* SIZE_NON_ZERO if there is data in the buffer, and 0 if there is no   */
-   /* data in the buffer. This is not a problem under OpenDoor's internal  */
-   /* serial I/O code, nor is it a problem under Win32's communications    */
-   /* facilities.                                                          */
-   ODComOutbound(hSerialPort, &nOutboundBufferBytes);
-
-   if(nOutboundBufferBytes == SIZE_NON_ZERO)
-   {
-      /* We know that there is data in the outbound buffer, but we don't */
-      /* know how much, and so we cannot make a recommendation. Instead, */
-      /* the default course of action will be taken.                     */
-      return(bDefault);
-   }
-
-   /* Estimate the # of bytes required for a full redraw of the edit area. */
-   unEstFullRedrawBytes = ODEditEstDrawBytes(pEditInstance, 0,
-      0, pEditInstance->unAreaHeight - 1, pEditInstance->unAreaWidth);
-
-   /* Recommend a full redraw if the number of bytes for an incremental */
-   /* redraw plus the number of bytes already in the outbound buffer    */
-   /* exceed the number of bytes required for a full redraw.            */
-   if(unEstPartialRedrawBytes + (UINT)nOutboundBufferBytes
-      > unEstFullRedrawBytes)
-   {
-      return(TRUE);
-   }
-   else
-   {
-      return(FALSE);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditEstDrawBytes()                                *** PRIVATE FUNCTION ***
- *
- * Estimates the number of bytes which will be transmitted in order to redraw
- * the specified portion of the edit area.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *             unStartRedrawLine    - Line of first character to draw.
- *
- *             unStartRedrawColumn  - Column of first character to draw.
- *
- *             unFinishRedrawLine   - Line of last character to draw.
- *
- *             unFinishRedrawColumn - Column after last character to draw.
- *
- *     Return: A rough estimate of the number of bytes required for the redraw.
- */
-static UINT ODEditEstDrawBytes(tEditInstance *pEditInstance,
-   UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
-   UINT unFinishRedrawColumn)
-{
-   UINT unAreaLine;
-   UINT unBufferLine;
-   UINT unLineLength;
-   UINT unByteTally = 0;
-
-   /* If we are only drawing text on a single line, then estimate is just  */
-   /* the distance between the start and finish redraw column. This number */
-   /* is precise only if the cursor is already at the location where       */
-   /* output is to begin, and the final cursor position is the location    */
-   /* where output finishes. This is in fact the situation when the user   */
-   /* is entering new text in the middle of the line - the most common     */
-   /* situation that will be encountered.                                  */
-   if(unStartRedrawLine == unFinishRedrawLine)
-   {
-      return(unFinishRedrawColumn - unStartRedrawColumn);
-   }
-
-   /* If we are drawing text on multiple lines, then inspect the contents */
-   /* of those lines to estimate the number of bytes to be transmitted.   */
-   for(unAreaLine = unStartRedrawLine,
-      unBufferLine = pEditInstance->unLineScrolledToTop + unStartRedrawLine;
-      unAreaLine <= unFinishRedrawLine;
-      ++unAreaLine, ++unBufferLine)
-   {
-      /* Determine the length of this line. */
-      if(unBufferLine < pEditInstance->unLinesInBuffer)
-      {
-         unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
-         if(unAreaLine == unStartRedrawLine)
-         {
-            unLineLength -= unStartRedrawColumn;
-         }
-      }
-      else
-      {
-         unLineLength = 0;
-      }
-
-      /* Add the number of characters on this line, along with the number of */
-      /* bytes required to reposition the cursor and to clear the unused     */
-      /* portion of this line to the tally. This assumes that the edit area  */
-      /* spans the entire screen.                                            */
-      unByteTally += unLineLength + 7;
-   }
-
-   return(unByteTally);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditGetCurrentLineInArea()                        *** PRIVATE FUNCTION ***
- *
- * Determines which line of the edit area the cursor is currently located in.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: 0-based index of the distance from the top of the edit area
- *             (as specified in the user options structure) where the
- *             cursor is currently located.
- */
-static UINT ODEditGetCurrentLineInArea(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   return(pEditInstance->unCurrentLine - pEditInstance->unLineScrolledToTop);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditUpdateCursorPos()                             *** PRIVATE FUNCTION ***
- *
- * Unconditionally updates the position of the cursor on the screen to 
- * reflect its actual position. Compare with ODEditUpdateCursorIfMoved().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditUpdateCursorPos(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   /* Reposition the cursor on the screen. */
-   od_set_cursor(ODEditGetCurrentLineInArea(pEditInstance)
-      + pEditInstance->pUserOptions->nAreaTop,
-      pEditInstance->unCurrentColumn + pEditInstance->pUserOptions->nAreaLeft);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditUpdateCursorIfMoved()                         *** PRIVATE FUNCTION ***
- *
- * Updates the position of the cursor on the screen to reflec its actual
- * position only if we belive it isn't already there. Compare with
- * ODEditUpdateCursorPos().
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditUpdateCursorIfMoved(tEditInstance *pEditInstance)
-{
-   UINT unActualRow;
-   UINT unActualColumn;
-   ODEditGetActualCurPos(pEditInstance, &unActualRow, &unActualColumn);
-
-   if(!(unActualRow == ODEditGetCurrentLineInArea(pEditInstance)
-         + pEditInstance->pUserOptions->nAreaTop
-      && unActualColumn == pEditInstance->unCurrentColumn
-         + pEditInstance->pUserOptions->nAreaLeft))
-   {
-      ODEditUpdateCursorPos(pEditInstance);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditEnterText()                                   *** PRIVATE FUNCTION ***
- *
- * Inserts new text at the current cursor position, updating the cursor
- * position accordingly.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *             pszEntered    - The character(s) to be inserted.
- *
- *     Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- *             obtain enough buffer space before making any changes, or
- *             kODRCUnrecoverableFailure if the buffer has been changed, but
- *             there was insufficient memory to re-index the buffer.
- */
-static tODResult ODEditEnterText(tEditInstance *pEditInstance,
-   char *pszEntered, BOOL bInsertMode)
-{
-   UINT unNumCharsToAdd;
-   char *pch;
-   tODResult Result;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(pszEntered != NULL);
-
-   /* Remember initial edit area contents, to permit selective redraw. */
-   ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
-
-   /* Determine the number of characters that are to be added to the buffer. */
-   unNumCharsToAdd = strlen(pszEntered);
-
-   /* Make room in the buffer for the new characters, if needed. */
-   if(bInsertMode)
-   {
-      Result = ODEditBufferMakeSpace(pEditInstance,
-         pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn,
-         unNumCharsToAdd);
-
-      if(Result != kODRCSuccess)
-      {
-         /* Beep on failure. */
-         od_putch('\a');
-         return(Result);
-      }
-   }
-
-   /* Copy the new characters to the buffer. */
-   pch = ODEditBufferGetCharacter(pEditInstance,
-      pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn);
-   memcpy(pch, pszEntered, unNumCharsToAdd);
-
-   /* Move the cursor position to the end of the newly added text. The  */
-   /* cursor position may be temporarily assigned to a position that is */
-   /* past the end of the edit area or past the end of the buffer.      */
-   for(pch = pszEntered; *pch != '\0'; ++pch)
-   {
-      if(IS_EOL_CHAR(*pch))
-      {
-         /* A carriage return character advances the cursor to the */
-         /* leftmost column on the next line.                      */
-         pEditInstance->unCurrentColumn = 0;
-         pEditInstance->unCurrentLine++;
-
-         /* If the next character is a different EOL character, and is */
-         /* not the end of the string, then skip that character.       */
-         if(IS_EOL_CHAR(pch[1]) && pch[1] != '\0' && pch[1] != *pch)
-         {
-            ++pch;
-         }
-      }
-      else
-      {
-         /* All other characters move the cursor ahead one column. */
-         pEditInstance->unCurrentColumn++;
-      }
-   }
-
-   /* Reindex and reformat the buffer based on its new contents. */
-   if(!ODEditBufferFormatAndIndex(pEditInstance))
-   {
-      return(kODRCUnrecoverableFailure);
-   }
-
-   /* Check whether the cursor is now positioned past the end of the edit */
-   /* area, requiring the edit area to be scrolled up.                    */
-   if(ODEditGetCurrentLineInArea(pEditInstance)
-      >= pEditInstance->unAreaHeight)
-   {
-      /* We need to scroll the area accordingly. */
-
-      /* Distance to scroll is maximum of the current single-step scroll */
-      /* distance, and the distance that the cursor is positioned below  */
-      /* the bottom of the current edit area.                            */
-      UINT unScrollDistance = MAX(pEditInstance->unScrollDistance,
-         ODEditGetCurrentLineInArea(pEditInstance) -
-         pEditInstance->unAreaHeight + 1);
-
-      /* Perform actual scroll operation. */
-      if(ODEditScrollArea(pEditInstance, (INT)unScrollDistance))
-      {
-         /* Entire area wasn't redrawn by operation, so some redrawing */
-         /* may still be required, within the area of text that was    */
-         /* visible before the scroll operation.                       */
-         ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
-            0, pEditInstance->unAreaHeight - unScrollDistance);
-      }
-   }
-
-   /* Perform necessary redrawing and reposition the cursor if needed. */
-   ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
-      REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditSetBreakSequence()                            *** PRIVATE FUNCTION ***
- *
- * If the default line or paragraph break sequence has not yet been set, then
- * this function sets it based on the break sequence that was encountered in
- * the buffer supplied by the client application.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *             chFirstEOLChar  - First character in the encountered sequence.
- *
- *             chSecondEOLChar - Second character in the encountered sequence.
- *
- *     Return: void
- */
-static void ODEditSetBreakSequence(tEditInstance *pEditInstance,
-   char chFirstEOLChar, char chSecondEOLChar)
-{
-   char *pszSequence;
-
-   ASSERT(pEditInstance != NULL);
-
-   if(pEditInstance->pszParagraphBreak != NULL
-      && pEditInstance->pszLineBreak != NULL)
-   {
-      /* In this situation, both the default line break sequence and default */
-      /* paragraph break sequence have been set, so there is nothing for us  */
-      /* to do.                                                              */
-      return;
-   }
-
-   /* Obtain a pointer to the encountered sequence. We want to use a static */
-   /* string constant for this, so that the string will continue to exist,  */
-   /* in unchanged form.                                                    */
-   if(chFirstEOLChar == '\r' && chSecondEOLChar == '\0')
-   {
-      pszSequence = "\r";
-   }
-   else if(chFirstEOLChar == '\n' && chSecondEOLChar == '\0')
-   {
-      pszSequence = "\n";
-   }
-   else if(chFirstEOLChar == '\n' && chSecondEOLChar == '\r')
-   {
-      pszSequence = "\n\r";
-   }
-   else if(chFirstEOLChar == '\r' && chSecondEOLChar == '\n')
-   {
-      pszSequence = "\r\n";
-   }
-   else
-   {
-      /* This should never happen: an invalid end of line sequence was */
-      /* passed in.                                                    */
-      ASSERT(FALSE);
-   }
-
-   /* Set the as yet undetermined line/paragraph terminators. */
-   if(pEditInstance->pszParagraphBreak == NULL)
-   {
-      pEditInstance->pszParagraphBreak = pszSequence;
-   }
-
-   if(pEditInstance->pszLineBreak == NULL)
-   {
-      pEditInstance->pszLineBreak = pszSequence;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditCursorLeft()                                  *** PRIVATE FUNCTION ***
- *
- * Attempts to move the cursor left. Called when the user presses the left
- * arrow key, and is also called as part of the process of handling the
- * backspace key.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *     Return: TRUE on success, or FALSE if the cursor cannot be moved left any
- *             further.
- */
-static BOOL ODEditCursorLeft(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   /* In word wrap mode, pressing the left key when the cursor */
-   /* is past the end of the line jumps the cursor to the end  */
-   /* of the line.                                             */
-   if(pEditInstance->bWordWrapLongLines &&
-      pEditInstance->unCurrentColumn > ODEditBufferGetLineLength
-      (pEditInstance, pEditInstance->unCurrentLine))
-   {
-      pEditInstance->unCurrentColumn = ODEditBufferGetLineLength
-         (pEditInstance, pEditInstance->unCurrentLine);
-      return(TRUE);
-   }
-
-   /* If we are not already at the leftmost column. */
-   else if(pEditInstance->unCurrentColumn > 0)
-   {
-      /* Move left one column. */
-      --pEditInstance->unCurrentColumn;
-      return(TRUE);
-   }
-   else if(pEditInstance->bWordWrapLongLines)
-   {
-      /* In word wrap mode, this will move us up to the end of */
-      /* the previous line.                                    */
-      if(pEditInstance->unCurrentLine > 0)
-      {
-         ODEditGotoPreviousLine(pEditInstance);
-         pEditInstance->unCurrentColumn = ODEditBufferGetLineLength(
-            pEditInstance, pEditInstance->unCurrentLine);
-         return(TRUE);
-      }
-   }
-
-   /* It wasn't possible to move the cursor. */
-   return(FALSE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditDeleteCurrentChar()                           *** PRIVATE FUNCTION ***
- *
- * Deletes the character at the current cursor position, performing necessary
- * redraw. Pressing the delete key causes just this function to be called.
- * Pressing the backspace key causes ODEditCursorLeft() to be called to first
- * move the cursor left before calling ODEditDeleteCurrentChar().
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditDeleteCurrentChar(tEditInstance *pEditInstance)
-{
-   char *pch;
-
-   ASSERT(pEditInstance != NULL);
-
-   /* Remember initial edit area contents, to permit selective redraw. */
-   ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
-
-   /* Backup the entire buffer contents by one character. */
-   pch = ODEditBufferGetCharacter(pEditInstance,
-      pEditInstance->unCurrentLine, pEditInstance->unCurrentColumn);
-   memmove(pch, pch + 1, strlen(pch + 1) + 1);
-
-   /* Reindex and reformat the buffer based on its new contents. */
-   ODEditBufferFormatAndIndex(pEditInstance);
-
-   /* Perform necessary redrawing and reposition the cursor if needed. */
-   ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
-      REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditDeleteCurrentLine()                           *** PRIVATE FUNCTION ***
- *
- * Removes the entire current line from the buffer.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: void
- */
-static void ODEditDeleteCurrentLine(tEditInstance *pEditInstance)
-{
-   char *pszStartOfThisLine;
-   char *pszStartOfNextLine;
-
-   ASSERT(pEditInstance != NULL);
-
-   /* Remember initial edit area contents, to permit selective redraw. */
-   ODEditRememberArea(pEditInstance, pEditInstance->pRememberBuffer);
-
-   /* Determine start of this line. */
-   pszStartOfThisLine = ODEditBufferGetCharacter(pEditInstance,
-      pEditInstance->unCurrentLine, 0);
-
-   if(pEditInstance->unLinesInBuffer == pEditInstance->unCurrentLine + 1)
-   {
-      /* If this is the last line of the buffer, then we just remove    */
-      /* everything from this line, without actually removing the line. */
-      *pszStartOfThisLine = '\0';
-   }
-   else
-   {
-      /* If this is not the last line of the buffer, then remove this */
-      /* entire line, so that the next line will become the current   */
-      /* line.                                                        */
-      pszStartOfNextLine = ODEditBufferGetCharacter(pEditInstance,
-         pEditInstance->unCurrentLine + 1, 0);
-      memmove(pszStartOfThisLine, pszStartOfNextLine,
-         strlen(pszStartOfNextLine) + 1);
-   }
-
-   /* Reset the cursor position to the beginning of the current line. */
-   pEditInstance->unCurrentColumn = 0;
-
-   /* Reindex and reformat the buffer based on its new contents. */
-   ODEditBufferFormatAndIndex(pEditInstance);
-
-   /* Perform necessary redrawing and reposition the cursor if needed. */
-   ODEditRedrawChanged(pEditInstance, pEditInstance->pRememberBuffer,
-      REDRAW_NO_BOUNDARY, REDRAW_NO_BOUNDARY);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditPastEndOfCurLine()                            *** PRIVATE FUNCTION ***
- *
- * Determines whether the cursor is currently past the end of the current line.
- * The end of the line is considered to be the first column after the last
- * character on the line. So, on a blank line, a cursor is considered to be
- * past the end if it is in or past the second column (column 0).
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *     Return: TRUE if the cursor is past the end of the current line,
- *             FALSE if it is not.
- */
-static BOOL ODEditPastEndOfCurLine(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   return(pEditInstance->unCurrentColumn >
-      ODEditBufferGetLineLength(pEditInstance, pEditInstance->unCurrentLine));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRememberBufferSize()                          *** PRIVATE FUNCTION ***
- *
- * Determines the buffer size required by ODEditRememberArea().
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *     Return: the required buffer size, in size_t units (bytes).
- */
-static size_t ODEditRememberBufferSize(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-
-   return((pEditInstance->unAreaWidth + 1)
-         * pEditInstance->unAreaHeight);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRememberArea()                                *** PRIVATE FUNCTION ***
- *
- * Stores a copy of the text currently displayed in the edit area in the
- * provided buffer, so that it can later be reused to redraw only the portion
- * of the edit area which has been changed by an operation.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *             pRememberedArea - Pointer to a buffer, which is at least
- *                               the number of bytes specified by
- *                               ODEditRememberBufferSize() in size.
- *
- *     Return: void
- */
-static void ODEditRememberArea(tEditInstance *pEditInstance,
-   void *pRememberedArea)
-{
-   UINT unDataLineOffset = 0;
-   UINT unDataLineSize;
-   UINT unAreaLine;
-   UINT unBufferLine;
-   UINT unLineLength;
-   char *pchStartOfLine;
-   char *pchDataLocation;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(pRememberedArea != NULL);
-
-   /* Determine the length of a single line in the remember buffer. */
-   unDataLineSize = pEditInstance->unAreaWidth + 1;
-
-   pchDataLocation = (char *)pRememberedArea + unDataLineOffset;
-   for(unBufferLine = pEditInstance->unLineScrolledToTop, unAreaLine = 0;
-      unAreaLine < pEditInstance->unAreaHeight;
-      ++unAreaLine, ++unBufferLine)
-   {
-      /* If this line is not beyond the end of the buffer. */
-      if(unBufferLine < pEditInstance->unLinesInBuffer)
-      {
-         /* Determine the length of this buffer line. */
-         unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
-
-         /* Determine the start location of this buffer line. */
-         pchStartOfLine = ODEditBufferGetCharacter(pEditInstance, unBufferLine,
-            0);
-      }
-      else
-      {
-         /* If this line is beyond the end of the buffer, then it is empty. */
-         unLineLength = 0;
-         pchStartOfLine = "";
-      }
-
-      /* Copy the contents of this line to the data buffer. */
-      memcpy(pchDataLocation, pchStartOfLine, unLineLength);
-      pchDataLocation[unLineLength] = '\0';
-
-      /* Update the location where data is being stored in the buffer. */
-      pchDataLocation += unDataLineSize;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRedrawChanged()                               *** PRIVATE FUNCTION ***
- *
- * Redraws the portion of the edit area which has been changed by an operation,
- * based on the original edit area contents as stored in a buffer by the
- * ODEditRememberArea() function.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *             pRememberedArea - Pointer to a buffer that was filled by a
- *                               previous call to ODEditRememberArea().
- *
- *             unUpperBoundary - The first line in the edit area to consider
- *                               redrawing, or REDRAW_NO_BOUNDARY to specify
- *                               the top of the edit area.
- *
- *             unLowerBoundary - The last line in the edit area to consider
- *                               redrawing, or REDRAW_NO_BOUNDARY to specify
- *                               the bottom of the edit area.
- *
- *     Return: void
- */
-static void ODEditRedrawChanged(tEditInstance *pEditInstance,
-   void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary)
-{
-   UINT unStartRedrawLine;
-   UINT unStartRedrawColumn;
-   UINT unFinishRedrawLine;
-   UINT unFinishRedrawColumn;
-   UINT unEstPartialRedrawBytes;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(pRememberedArea != NULL);
-
-   /* Determine what portion of the edit area, within the specified upper */
-   /* and lower boundaries, has been changed.                             */
-   if(!ODEditDetermineChanged(pEditInstance, pRememberedArea, unUpperBoundary,
-      unLowerBoundary, &unStartRedrawLine, &unStartRedrawColumn,
-      &unFinishRedrawLine, &unFinishRedrawColumn))
-   {
-      /* Nothing has changed in the edit area. */
-      ODEditUpdateCursorIfMoved(pEditInstance);
-      return;
-   }
-
-   /* Now that we have determined the portion of the edit area that would */
-   /* be redraw by a partial (incremental) redraw, we compare the amount  */
-   /* of data involved + the amount of data still in the outbound buffer  */
-   /* with the amount of data involved in a full redraw. If the amount of */
-   /* data in the outbound buffer cannot be determined, we default to     */
-   /* using an incremental redraw.                                        */
-   unEstPartialRedrawBytes = ODEditEstDrawBytes(pEditInstance,
-      unStartRedrawLine, unStartRedrawColumn, unFinishRedrawLine,
-      unFinishRedrawColumn);
-   if(ODEditRecommendFullRedraw(pEditInstance, unEstPartialRedrawBytes,
-      FALSE))
-   {
-      /* Purge the outbound buffer and do a full redraw. */
-      ODEditRedrawArea(pEditInstance);
-
-      /* Move the cursor back to its appropriate position. */
-      ODEditUpdateCursorPos(pEditInstance);
-   }
-   else
-   {
-      /* Perform a partial (incremental) redraw. */
-
-      /* Now, redraw the portion of the edit area that has been determined to */
-      /* require redrawing.                                                   */
-      ODEditRedrawSubArea(pEditInstance, unStartRedrawLine, unStartRedrawColumn,
-         unFinishRedrawLine, unFinishRedrawColumn);
-
-      /* Now, move the cursor back to its appropriate position, if it isn't */
-      /* already there.                                                     */
-      ODEditUpdateCursorIfMoved(pEditInstance);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditDetermineChanged()                            *** PRIVATE FUNCTION ***
- *
- * Determines what portion of the edit area, within the specifiede upper and
- * lower boundary, has been changed. Area is specified as row and column
- * position of the first changed characer between boundaries, and the row
- * and column position past the last changed character between the boundaries.
- *
- * Parameters: pEditInstance         - Editor instance information structure.
- *
- *             pRememberedArea       - Pointer to a buffer that was filled by a
- *                                     previous call to ODEditRememberArea().
- *
- *             unUpperBoundary       - The first line in the edit area to
- *                                     consider redrawing, or
- *                                     REDRAW_NO_BOUNDARY to specify the top of 
- *                                     the edit area.
- *
- *             unLowerBoundary       - The last line in the edit area to
- *                                     consider redrawing, or
- *                                     REDRAW_NO_BOUNDARY to specify the bottom
- *                                     of the edit area.
- *
- *             punStartRedrawLine    - Output: Line of first changed character.
- *
- *             punStartRedrawColumn  - Output: Column of first changed char.
- *
- *             punFinishRedrawLine   - Output: Line of last changed character.
- *
- *             punFinishRedrawColumn - Output: Column after last changed char.
- *
- *     Return: TRUE if some text in the edit area has been changed, FALSE
- *             if there is no change.
- */
-static BOOL ODEditDetermineChanged(tEditInstance *pEditInstance,
-   void *pRememberedArea, UINT unUpperBoundary, UINT unLowerBoundary, 
-   UINT *punStartRedrawLine, UINT *punStartRedrawColumn,
-   UINT *punFinishRedrawLine, UINT *punFinishRedrawColumn)
-{
-   BOOL bFoundStart = FALSE;
-   BOOL bFoundFinish = FALSE;
-   UINT unDataLineOffset = 0;
-   UINT unDataLineSize;
-   UINT unAreaLine;
-   UINT unLineLength;
-   UINT unColumn;
-   UINT unBufferLine;
-   char *pchCurrent;
-   char *pchRemembered;
-
-   /* Determine the length of a single line in the remember buffer. */
-   unDataLineSize = pEditInstance->unAreaWidth + 1;
-
-   /* If caller specified no upper boundary, then reset upper boundary */
-   /* to 0.                                                            */
-   if(unUpperBoundary == REDRAW_NO_BOUNDARY) unUpperBoundary = 0;
-
-   /* Likewise, iff caller specified no lower boundary, then reset the */
-   /* lower boundary to the bottom of the edit area.                   */
-   if(unLowerBoundary == REDRAW_NO_BOUNDARY)
-   {
-      unLowerBoundary = pEditInstance->unAreaHeight;
-   }
-
-   /* Loop through the area within boundaries, determining which */
-   /* portion of the edit area has changed.                      */
-   for(unBufferLine = pEditInstance->unLineScrolledToTop + unUpperBoundary,
-      unAreaLine = unUpperBoundary; unAreaLine < unLowerBoundary;
-      ++unAreaLine, ++unBufferLine)
-   {
-      /* Determine location of corresponding line in remembered data. */
-      pchRemembered = (char *)pRememberedArea + unDataLineOffset
-         + unDataLineSize * unAreaLine;
-
-      /* If this line is not beyond the end of the buffer. */
-      if(unBufferLine < pEditInstance->unLinesInBuffer)
-      {
-         /* Determine the start location of this buffer line. */
-         pchCurrent = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
-
-         /* Determine the length of this buffer line. */
-         unLineLength = ODEditBufferGetLineLength(pEditInstance, unBufferLine);
-      }
-      else
-      {
-         pchCurrent = "";
-         unLineLength = 0;
-      }
-
-      /* Start at the first column on this line. */
-      unColumn = 0;
-
-      /* Look for any characters that differ. */
-      for(;; ++unColumn, ++pchCurrent, ++pchRemembered)
-      {
-         /* Determine if we are at the end of the remembered line. */
-         BOOL bEndOfRemembered = (*pchRemembered == '\0');
-
-         /* Determine if we are at the end of the current buffer line. */
-         BOOL bEndOfCurrent = (unColumn == unLineLength);
-
-         /* If we are at the end of either of the buffers (but not both), */
-         /* or if these two characters differ, then we have found the     */
-         /* start of the area that must be redrawn.                       */
-         if(!(bEndOfRemembered && bEndOfCurrent))
-         {
-            if(bEndOfRemembered || bEndOfCurrent
-               || *pchCurrent != *pchRemembered)
-            {
-               if(bFoundStart)
-               {
-                  bFoundFinish = FALSE;
-               }
-               else
-               {
-                  /* We have found a character that differs. */
-                  bFoundStart = TRUE;
-                  *punStartRedrawLine = unAreaLine;
-                  *punStartRedrawColumn = unColumn;
-               }
-            }
-         }
-
-         /* If we have found the first changed text in the buffer, then we */
-         /* are now looking for the last changed text in the buffer.       */
-         if(bFoundStart && !bFoundFinish)
-         {
-            if(*pchCurrent == *pchRemembered)
-            {
-               bFoundFinish = TRUE;
-               *punFinishRedrawLine = unAreaLine;
-               *punFinishRedrawColumn = unColumn;
-            }
-            else if(bEndOfRemembered)
-            {
-               bFoundFinish = TRUE;
-               *punFinishRedrawLine = unAreaLine;
-               *punFinishRedrawColumn = unLineLength;
-            }
-            else if(bEndOfCurrent)
-            {
-               bFoundFinish = TRUE;
-               *punFinishRedrawLine = unAreaLine;
-               *punFinishRedrawColumn = unColumn + strlen(pchRemembered);
-            }
-         }
-
-         /* If we are at the end of either buffers. */
-         if(bEndOfRemembered || bEndOfCurrent)
-         {
-            /* Now, proceed to processing the next line in the edit area. */
-            break;
-         }
-      }
-   }
-
-   /* If we haven't found any text in the edit area that has changed. */
-   if(!bFoundStart)
-   {
-      /* Then return indicating no change. */
-      return(FALSE);
-   }
-
-   /* If we haven't found an end to the portion of the area that has */
-   /* changed, then we must redraw up to the end of the edit area.   */
-   if(!bFoundFinish)
-   {
-      *punFinishRedrawLine = unLowerBoundary;
-      *punFinishRedrawColumn = unColumn;
-   }
-
-   /* Return indicating that ther has been some change. */
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditRedrawSubArea()                               *** PRIVATE FUNCTION ***
- *
- * Redraws the portion of the edit area within the specified range. Redrawing
- * is performed from the location of the start redraw row and column, up to
- * but not includin gthe finish redraw row and column.
- *
- * Parameters: pEditInstance        - Editor instance information structure.
- *
- *             unStartRedrawLine    - Line of first character to draw.
- *
- *             unStartRedrawColumn  - Column of first character to draw.
- *
- *             unFinishRedrawLine   - Line of last character to draw.
- *
- *             unFinishRedrawColumn - Column after last character to draw.
- *
- *     Return: void
- */
-static void ODEditRedrawSubArea(tEditInstance *pEditInstance,
-   UINT unStartRedrawLine, UINT unStartRedrawColumn, UINT unFinishRedrawLine,
-   UINT unFinishRedrawColumn)
-{
-   UINT unAreaLine;
-   UINT unLineLength;
-   UINT unBufferLine;
-   char *pchCurrent;
-   UINT unStartColumn;
-   UINT unFinishColumn;
-   UINT unScrnStartColumn;
-   UINT unTextLength;
-
-   /* Now, perform actual redraw in area that requires redrawing. */
-   for(unBufferLine = pEditInstance->unLineScrolledToTop + unStartRedrawLine,
-      unAreaLine = unStartRedrawLine; unAreaLine <= unFinishRedrawLine;
-      ++unBufferLine, ++unAreaLine)
-   {
-      BOOL bFirstLine = (unAreaLine == unStartRedrawLine);
-      BOOL bLastLine = (unAreaLine == unFinishRedrawLine);
-      UINT unScrnRow = (UINT)pEditInstance->pUserOptions->nAreaTop
-         + unAreaLine;
-
-      /* If this line is not beyond the end of the buffer. */
-      if(unBufferLine < pEditInstance->unLinesInBuffer)
-      {
-         pchCurrent = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
-         unTextLength = unLineLength =
-            ODEditBufferGetLineLength(pEditInstance, unBufferLine);
-      }
-      else
-      {
-         pchCurrent = "";
-         unTextLength = unLineLength = 0;
-      }
-
-      /* Move to the position on the first line to begin redraw. */
-      if(bFirstLine)
-      {
-         UINT unActualRow;
-         UINT unActualColumn;
-         ODEditGetActualCurPos(pEditInstance, &unActualRow, &unActualColumn);
-
-         unStartColumn = unStartRedrawColumn;
-         unScrnStartColumn = (UINT)pEditInstance->pUserOptions->nAreaLeft
-            + unStartColumn;
-
-         if(unScrnRow != unActualRow || unScrnStartColumn != unActualColumn)
-         {
-            od_set_cursor(unScrnRow, unScrnStartColumn);
-         }
-
-         pchCurrent += unStartRedrawColumn;
-         unTextLength -= unStartRedrawColumn;
-      }
-      else
-      {
-         unStartColumn = 0;
-         unScrnStartColumn = (UINT)pEditInstance->pUserOptions->nAreaLeft;
-         od_set_cursor(unScrnRow, unScrnStartColumn);
-      }
-
-      /* If this is the last line to redraw, then adjust accordingly. */
-      if(bLastLine)
-      {
-         if(unFinishRedrawColumn < unLineLength)
-         {
-            unTextLength -= unLineLength - unFinishRedrawColumn;
-         }
-         unFinishColumn = unFinishRedrawColumn;
-      }
-      else
-      {
-         unFinishColumn = pEditInstance->unAreaWidth;
-      }
-
-      /* Output changed text. */
-      if(unStartColumn < unLineLength)
-      {
-         od_disp(pchCurrent, unTextLength, TRUE);
-         unStartColumn += unTextLength;
-      }
-
-      /* If we need to clear the rest of the line. */
-      if(unFinishColumn == pEditInstance->unAreaWidth)
-      {
-         /* If right edge of edit area aligns with the right edge of the */
-         /* screen.                                                      */
-         if(pEditInstance->pUserOptions->nAreaRight == OD_SCREEN_WIDTH)
-         {
-            /* Clear the remainder of this line on the screen. */
-            od_clr_line();
-         }
-         else
-         {
-            /* Place spaces after the end of the current line, up to right */
-            /* edge of the edit area.                                      */
-            od_repeat(' ', (BYTE)(pEditInstance->unAreaWidth - unLineLength));
-         }
-      }
-      else if(unStartColumn < unFinishColumn)
-      {
-         od_repeat(' ', (BYTE)(unFinishColumn - unStartColumn));
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditGetActualCurPos()                             *** PRIVATE FUNCTION ***
- *
- * Estimates the actual position of the cursor on the screen.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *             punRow          - Pointer to location where cursor row number
- *                               should be stored.
- *
- *             punColumn       - Pointer to location where cursor column number
- *                               should be stored.
- *
- *     Return: void
- */
-static void ODEditGetActualCurPos(tEditInstance *pEditInstance,
-   UINT *punRow, UINT *punColumn)
-{
-   tODScrnTextInfo TextInfo;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(punRow != NULL);
-   ASSERT(punColumn != NULL);
-
-   UNUSED(pEditInstance);
-
-   /* Obtain current cursor position information from the ODScrn module. */
-   ODScrnGetTextInfo(&TextInfo);
-   *punRow = (UINT)TextInfo.cury;
-   *punColumn = (UINT)TextInfo.curx;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditIsEOLForMode()                                *** PRIVATE FUNCTION ***
- *
- * Determines whether the specified character should be treated as an EOL
- * character for the current mode.
- *
- * Parameters: pEditInstance   - Editor instance information structure.
- *
- *     Return: TRUE if this is an EOL character, FALSE otherwise.
- */
-static BOOL ODEditIsEOLForMode(tEditInstance *pEditInstance, char chToTest)
-{
-   switch(pEditInstance->pUserOptions->TextFormat)
-   {
-      case FORMAT_FTSC_MESSAGE:
-         return(chToTest == '\r' || chToTest == '\0');
-
-      default:
-         return(IS_EOL_CHAR(chToTest));
-   }
-}
-
-
-
-/* ========================================================================= */
-/* Low level buffer manipulation functions.                                  */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODEditBufferFormatAndIndex()                        *** PRIVATE FUNCTION ***
- *
- * Regenerates the count of lines in the buffer, and the array of pointers to
- * the start of each line.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: TRUE on success, or FALSE if there is not enough memory
- *             available to complete this operation.
- */
-static BOOL ODEditBufferFormatAndIndex(tEditInstance *pEditInstance)
-{
-   char *pch;
-   char *pchLastSpace;
-   UINT unProcessingColumn;
-   UINT unProcessingLine;
-   BOOL bAtEndOfBuffer = FALSE;
-   BOOL bLineEndedByBreak;
-   BOOL bFTSCMode =
-      (pEditInstance->pUserOptions->TextFormat == FORMAT_FTSC_MESSAGE);
-
-   ASSERT(pEditInstance != NULL);
-
-   /* Reset current line count. */
-   unProcessingLine = 0;
-
-   /* Begin at the beginning of the buffer to edit. */
-   pch = pEditInstance->pszEditBuffer;
-   ASSERT(pch != NULL);
-
-   /* Loop for each line in the buffer. */
-   while(!bAtEndOfBuffer)   
-   {
-      /* In FTSC mode, skip a line if it begins with a ^A ("kludge lines"). */
-      if(bFTSCMode)
-      {
-         /* Loop while the current line begins with a ^A. */
-         while(*pch == 0x01)
-         {
-            /* Loop until the end of the line is found. */
-            while(!ODEditIsEOLForMode(pEditInstance, *pch)) ++pch;
-
-            if(*pch == '\0')
-            {
-               /* If the line was ended by a null character, then note that */
-               /* the end of the buffer has been reached.                   */
-               bAtEndOfBuffer = TRUE;
-            }
-            else
-            {
-               /* If the line was not ended by a null character, then skip */
-               /* the end of line character.                               */
-               ++pch;
-            }
-         }
-
-         continue;
-      }
-
-      /* Add the address of the start of this line to the line array. */
-      
-      /* If the line array is full, then attempt to grow it. */
-      ASSERT(unProcessingLine <= pEditInstance->unLineArraySize);
-      if(unProcessingLine == pEditInstance->unLineArraySize)
-      {
-         /* Determine the size to grow the array to. */
-         UINT unNewArraySize = pEditInstance->unLineArraySize
-            + LINE_ARRAY_GROW_SIZE;
-
-         /* Attempt to reallocate this memory block. */
-         char **papchNewLineArray = (char **)realloc(
-            pEditInstance->papchStartOfLine, unNewArraySize * sizeof(char *));
-
-         /* If reallocation failed, then return with failure. */
-         if(papchNewLineArray == NULL)
-         {
-            return(FALSE);
-         }
-
-         /* Otherwise, update the editor instance information with the new */
-         /* array address and array size information.                      */
-         pEditInstance->papchStartOfLine = papchNewLineArray;
-         pEditInstance->unLineArraySize = unNewArraySize;
-      }
-
-      /* Add the address of the start of this line to the array. */
-      pEditInstance->papchStartOfLine[unProcessingLine] = pch;
-
-      /* Reset word wrap information. */
-      pchLastSpace = NULL;
-
-      /* Now, find the end of this line. */
-      bLineEndedByBreak = TRUE;
-      unProcessingColumn = 0;
-      while(!ODEditIsEOLForMode(pEditInstance, *pch))
-      {
-         /* If this character is a space, then record the location of the */
-         /* last space characters.                                        */
-         if(*pch == ' ') pchLastSpace = pch;
-
-         /* Check for characters which must be filtered from the buffer */
-         /* in FTSC message mode.                                       */
-         if(bFTSCMode)
-         {
-            if(*pch == 0x0a || ((unsigned char)*pch) == 0x8d)
-            {
-               /* If this character must be removed, then move rest of */
-               /* buffer up by one character, and proceed to next loop */
-               /* iteration.                                           */
-               memmove(pch, pch + 1, strlen(pch + 1) + 1);
-               continue;
-            }
-         }
-
-         /* Increment count of characters on this line. */
-         ++unProcessingColumn;
-
-         /* Check whether we have reached the maximum number of characters */
-         /* that will fit on this line.                                    */
-         if(unProcessingColumn >= pEditInstance->unAreaWidth - 1)
-         {
-            if(pEditInstance->bWordWrapLongLines)
-            {
-               /* If we are to word wrap long lines, then back up to the */
-               /* beginning of the last word, if we have encountered any */
-               /* space characters.                                      */
-               if(pchLastSpace != NULL && pchLastSpace < pch)
-               {
-                  /* Update current column number accordingly. */
-                  unProcessingColumn -= (UINT)(pch - pchLastSpace);
-
-                  /* Back up to position to perform word wrap at. */
-                  pch = pchLastSpace;
-               }
-            }
-
-            /* If we are wrapping text where the cursor is located, then we */
-            /* will have to reposition the cursor accordingly.              */
-            if(unProcessingLine == pEditInstance->unCurrentLine
-               && unProcessingColumn < pEditInstance->unCurrentColumn)
-            {
-               /* Move the cursor to the next line. */
-               pEditInstance->unCurrentLine++;
-
-               /* Adjust the cursor column number to the position where the */
-               /* corresponding wrapped text will appear.                   */
-               pEditInstance->unCurrentColumn -= unProcessingColumn;
-            }
-
-            /* Note that line was not ended by en explicit line break. */
-            bLineEndedByBreak = FALSE;
-
-            break;
-         }
-
-         /* Move to the next character in the buffer. */
-         ++pch;
-      }
-
-      /* If we the line was terminated by a '\0', then note that the end of */
-      /* the buffer has been reached.                                       */
-      if(*pch == '\0')
-      {
-         bAtEndOfBuffer = TRUE;
-      }
-
-      /* If the line was not terminated by a '\0', then find the first */
-      /* character of the next line.                                   */
-      else
-      {
-         char chFirstEOLChar = *pch;
-         char chSecondEOLChar = '\0';
-
-         /* Move to the next character in the buffer. */
-         ++pch;
-         
-         /* If this character is a different EOL sequence character from the */
-         /* already encountered EOL character, then skip past it too.        */
-         if(ODEditIsEOLForMode(pEditInstance, chFirstEOLChar) && *pch != '\0'
-            && ODEditIsEOLForMode(pEditInstance, *pch)
-            && *pch != chFirstEOLChar)
-         {
-            chSecondEOLChar = *pch;
-            ++pch;
-         }
-         
-         /* If we don't already know what form of line/paragraph break to */
-         /* use (just a CR, just a LF, a CR/LF sequence or a LF/CR        */
-         /* sequence), then use this line termination as an example of    */
-         /* what should be used.                                          */
-         if(bLineEndedByBreak)
-         {
-            ODEditSetBreakSequence(pEditInstance, chFirstEOLChar,
-               chSecondEOLChar);
-         }
-      }
-
-      /* Increment the count of the current line number. */
-      unProcessingLine++;
-   }
-
-   /* Update count of number of lines in the buffer, based on the number */
-   /* that we have found.                                                */
-   pEditInstance->unLinesInBuffer = unProcessingLine;
-
-   /* Return with success. */
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditBufferGetLineLength()                         *** PRIVATE FUNCTION ***
- *
- * Determines the length of the specified line in the buffer, not including
- * any line terminator characters.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *             unBufferLine  - 0-based index of the line in question.
- *
- *     Return: The number of characters on this line.
- */
-static UINT ODEditBufferGetLineLength(tEditInstance *pEditInstance,
-   UINT unBufferLine)
-{
-   char *pch;
-   char *pchStartOfLine;
-   UINT unCharsBeforeEOL;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(unBufferLine < pEditInstance->unLinesInBuffer);
-   ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
-
-   /* Get the address of the start of this line in the buffer. */
-   pchStartOfLine
-      = ODEditBufferGetCharacter(pEditInstance, unBufferLine, 0);
-
-   /* Count the number of characters before the next end of line character. */
-   for(pch = pchStartOfLine, unCharsBeforeEOL = 0;
-      !ODEditIsEOLForMode(pEditInstance, *pch);
-      ++unCharsBeforeEOL, ++pch);
-
-   /* If this is the last line in the buffer, then the number of characers */
-   /* before the next end of line character is the length of this line.    */
-   if(unBufferLine >= pEditInstance->unLinesInBuffer - 1)
-   {
-      return(unCharsBeforeEOL);
-   }
-
-   /* If this is not the last line in the buffer, then the length of this  */
-   /* line is the minimum of the number of characters before the next end  */
-   /* of line character and the number of characters before the next line, */
-   /* according to the line index information. This is because all lines   */
-   /* do not necessarily end with an end-of-line character.                */
-   else
-   {
-       return(MIN(unCharsBeforeEOL, (UINT)(ODEditBufferGetCharacter(
-          pEditInstance, unBufferLine + 1, 0) - pchStartOfLine)));
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditBufferGetTotalLines()                         *** PRIVATE FUNCTION ***
- *
- * Determines the number of lines in the current edit buffer.
- *
- * Parameters: pEditInstance - Editor instance information structure.
- *
- *     Return: The total number of lines in the buffer.
- */
-static UINT ODEditBufferGetTotalLines(tEditInstance *pEditInstance)
-{
-   ASSERT(pEditInstance != NULL);
-   ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
-
-   /* Return the total number of lines in the buffer. */
-   return(pEditInstance->unLinesInBuffer);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditBufferGetCharacter()                          *** PRIVATE FUNCTION ***
- *
- * Obtains the character at the specified position in the buffer.
- *
- * Parameters: pEditInstance  - Editor instance information structure.
- *
- *             unBufferLine   - 0-based index of the line in question.
- *
- *             unBufferColumn - The position in the line of the required
- *                              character.
- *
- *     Return: A pointer to the character at the specified position in the
- *             specified line. The caller can assume that any remaining
- *             character(s) in the line follow this character, but should
- *             not assume that the pointer can be used to access following
- *             lines in the buffer.
- */
-static char *ODEditBufferGetCharacter(tEditInstance *pEditInstance,
-   UINT unBufferLine, UINT unBufferColumn)
-{
-   ASSERT(pEditInstance != NULL);
-   ASSERT(unBufferLine < pEditInstance->unLinesInBuffer);
-   ASSERT(pEditInstance->unLinesInBuffer <= pEditInstance->unLineArraySize);
-   ASSERT(unBufferColumn <= ODEditBufferGetLineLength(pEditInstance, unBufferLine));
-
-   /* The position of this character is the position of this line, plus */
-   /* the number of characters into the line.                           */
-   return(pEditInstance->papchStartOfLine[unBufferLine] + unBufferColumn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditBufferMakeSpace()                             *** PRIVATE FUNCTION ***
- *
- * Moves the remaining buffer contents by the specified distance to make room
- * for new text. The new space is filled by space (' ') characters. Does not
- * necessarily reindex the buffer before returning, and so this should be done
- * by the caller after the new buffer space has been filled.
- *
- * Parameters: pEditInstance       - Editor instance information structure.
- *
- *             unLine              - Line number to make more room on.
- *
- *             unColumn            - Column number to insert the space.
- *
- *             unNumChars          - Number of characters to make room for.
- *
- *     Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- *             obtain enough buffer space before making any changes, or
- *             kODRCUnrecoverableFailure if the buffer has been changed, but
- *             there was insufficient memory to re-index the buffer.
- */
-static tODResult ODEditBufferMakeSpace(tEditInstance *pEditInstance,
-   UINT unLine, UINT unColumn, UINT unNumChars)
-{
-   UINT unLineLength;
-   UINT unBufferUsed;
-   UINT unBufferUnused;
-   UINT unRemainingBufferBytes;
-   UINT unCount;
-   char *pchBufferPos;
-   tODResult Result;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(unLine < pEditInstance->unLinesInBuffer);
-
-   /* Determine the current length of the specified line. */
-   unLineLength = ODEditBufferGetLineLength(pEditInstance, unLine);
-
-   /* If a column past the current end of this line was specified, then    */
-   /* adjust column and number of characters in order to extend the line   */
-   /* up to the specified column as well as adding space beginning at that */
-   /* column.                                                              */
-   if(unColumn > unLineLength)
-   {
-      UINT unExtendLineBy = unColumn - unLineLength;
-      unColumn -= unExtendLineBy;
-      unNumChars += unExtendLineBy;
-   }
-
-   /* Now, determine whether the buffer is large enough for the additional */
-   /* space that will be added.                                            */
-   unBufferUsed = strlen(pEditInstance->pszEditBuffer) + 1;
-   unBufferUnused = pEditInstance->unBufferSize - unBufferUsed;
-   if(unBufferUnused < unNumChars)
-   {
-      /* There is not currently sufficient room in the buffer for the new */
-      /* characters, then attempt to grow the buffer to make more room.   */
-      Result = ODEditTryToGrow(pEditInstance, unBufferUsed + unNumChars);
-      if(Result != kODRCSuccess)
-      {
-         /* On failure, return the result code that indicates the nature */
-         /* of the failure.                                              */
-         return(Result);
-      }
-   }
-
-   /* Now, shift the buffer contents from this location forward by */
-   /* unNumChars characters.                                       */
-   pchBufferPos = ODEditBufferGetCharacter(pEditInstance, unLine, unColumn);
-   unRemainingBufferBytes = strlen(pchBufferPos) + 1;
-   memmove(pchBufferPos + unNumChars, pchBufferPos, unRemainingBufferBytes);
-
-   /* Next, we fill the new buffer area with space characters. */
-   for(unCount = 0; unCount < unNumChars; ++unCount)
-   {
-      *pchBufferPos++ = ' ';
-   }
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEditTryToGrow()                                   *** PRIVATE FUNCTION ***
- *
- * Attempts to reallocate the buffer to a larger size. This function is called
- * if it is found that the current buffer isn't large enough to complete some
- * operation. If the client application has setup the editor to permit buffer
- * reallocation, then this function will call the realloc callback function
- * supplied by the client application. If buffer growing is not possible, then
- * this function automatically fails.
- *
- * Parameters: pEditInstance       - Editor instance information structure.
- *
- *             unSizeNeeded        - The minimum buffer size that is needed.
- *
- *     Return: kODRCSuccess on success, kODRCSafeFailure if we were unable to
- *             obtain enough buffer space before making any changes, or
- *             kODRCUnrecoverableFailure if the buffer has been changed, but
- *             there was insufficient memory to re-index the buffer.
- */
-static tODResult ODEditTryToGrow(tEditInstance *pEditInstance,
-   UINT unSizeNeeded)
-{
-   BOOL bFullReIndexRequired = FALSE;
-
-   ASSERT(pEditInstance != NULL);
-   ASSERT(unSizeNeeded > pEditInstance->unBufferSize);
-
-   if(pEditInstance->pUserOptions->pfBufferRealloc != NULL)
-   {
-      /* If the buffer is growable, then attempt to grow it using the */
-      /* realloc function provided by the client application.         */
-      UINT unNewBufferSize = MAX(pEditInstance->unBufferSize
-         + BUFFER_GROW_SIZE, unSizeNeeded);
-      char *pszNewBuffer = (char *)((*pEditInstance->pUserOptions->
-         pfBufferRealloc)(pEditInstance->pszEditBuffer, unNewBufferSize));
-
-      /* If we were unable to grow the buffer, then fail now. At this */
-      /* point, nothing has changed, and so the buffer information    */
-      /* is still intact and valid.                                   */
-      if(pszNewBuffer == NULL)
-      {
-         return(kODRCSafeFailure);
-      }
-
-      /* Otherwise, determine whether the entire buffer will now have to */
-      /* be reindexed. This is necessary if the reallocated buffer is at */
-      /* a new location than the original was.                           */
-      if(pszNewBuffer != pEditInstance->pszEditBuffer)
-      {
-         bFullReIndexRequired = TRUE;
-      }
-
-      /* Now, store the new buffer pointer and buffer size information. */
-      pEditInstance->pszEditBuffer = pszNewBuffer;
-      pEditInstance->unBufferSize = unNewBufferSize;
-   }
-   else
-   {
-      /* If the buffer is not growable, then fail right away. */
-      return(kODRCSafeFailure);
-   }
-
-   /* If a full reindex is required due to buffer reallocation, then do so. */
-   if(bFullReIndexRequired)
-   {
-      if(!ODEditBufferFormatAndIndex(pEditInstance))
-      {
-         /* If this fails, then return with failure. */
-         return(kODRCUnrecoverableFailure);
-      }
-      bFullReIndexRequired = FALSE;
-   }
-
-   /* If we get to this point, we suceeded in growing the buffer to the */
-   /* required size, so return with success.                            */
-   return(kODRCSuccess);
-}
diff --git a/src/odoors/ODEmu.c b/src/odoors/ODEmu.c
deleted file mode 100644
index 5d6ddc048eebc9feeb12ee9b66eff9d03f5c5f24..0000000000000000000000000000000000000000
--- a/src/odoors/ODEmu.c
+++ /dev/null
@@ -1,2210 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODEmu.c
- *
- * Description: Code for the TTY/ANSI/AVATAR terminal emulation routines,
- *              including .ASC/.ANS/.AVT/.RIP file display functions.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Jun 07, 1995  6.00  BP   Added od_emu_simulate_modem.
- *              Jul 18, 1995  6.00  BP   Fixed warning in call to _ulongdiv().
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 15, 1995  6.00  BP   Terminal emulation speed optimization.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 24, 1995  6.00  BP   Use od_connect_speed for modem sim.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 21, 1996  6.00  BP   Use ODScrnShowMessage().
- *              Jan 09, 1996  6.00  BP   ODComOutbound() returns actual size.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Prevent TC generated N_LXMUL@ call.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Oct 18, 2001  6.11  MD   Added od_send_file_section()
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODCom.h"
-#include "ODTypes.h"
-#include "ODScrn.h"
-#include "ODKrnl.h"
-#include "ODUtil.h"
-
-
-/* Manifest constants. */
-#define MODEM_SIMULATOR_TICK 54L
-
-#define LEVEL_NONE      0
-#define LEVEL_ASCII     1
-#define LEVEL_ANSI      2
-#define LEVEL_AVATAR    3
-#define LEVEL_RIP       4
-
-
-/* Local helper function prototypes. */
-static void ODEmulateFromBuffer(char *pszBuffer, BOOL bRemoteEcho);
-static FILE *ODEmulateFindCompatFile(char *pszBaseName, INT *pnLevel);
-static void ODEmulateFillArea(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom, char chToFillWith);
-
-
-/* Current terminal emulator state variables. */
-static BYTE btANSISeqLevel = 0;
-static INT anANSIParams[10];
-static char szCurrentParam[4] = "";
-static BYTE btCurrentParamLength;
-static BYTE btSavedColumn=1;
-static BYTE btSavedRow = 1;
-static char szToRepeat[129];
-static BYTE btRepeatCount;
-static BYTE btAvatarSeqLevel = 0;
-static char chPrevParam;
-static BYTE btNumParams;
-static BYTE btDefaultAttrib = 7;
-static BOOL bAvatarInsertMode = FALSE;
-static INT8 btScrollLines;
-static BYTE btScrollLeft, btScrollTop, btScrollRight, btScrollBottom;
-
-/* Variables for tracking hotkeys while displaying a menu file. */
-static char *pszCurrentHotkeys=NULL;
-static char chHotkeyPressed;
-
-/* Lookup table to map colors from ANSI values to PC color values. */
-static BYTE abtANSIToPCColorTable[8] = {0, 4, 2, 6, 1, 5, 3, 7};
-
-
-/* ----------------------------------------------------------------------------
- * od_hotkey_menu()
- *
- * Displays a .ASC/.ANS/.AVT/.RIP file, just as od_send_file() does. However,
- * unlike od_send_file(), od_hotkey_menu() also allows checks for keypresses
- * by the user. If any of the hotkeys listed in pszHotKeys are pressed while
- * the file is being displayed, or after the file has finished being displayed,
- * od_hotkey_menu() will return this value to the caller. This allows menu
- * screens to be easily displayed from on-disk files, while permitting the user
- * to choose a menu item at any time.
- *
- * Parameters: pszFileName  - Pointer to the filename to display.
- *
- *             pszHotKeys   - Pointer to a string listing the valid keys.
- *                            Keys are not case sensitive.
- *
- *             bWait        - If TRUE, od_hotkey_menu() will not return until
- *                            the user presses one of the valid keys. If FALSE,
- *                            then od_hotkey_menu() will return as soon as it
- *                            has finished displaying the file, even if the
- *                            user has not pressed any key;.
- *
- *     Return: The key pressed by the user, or '\0' if no key was pressed.
- */
-ODAPIDEF char ODCALL od_hotkey_menu(char *pszFileName, char *pszHotKeys,
-   BOOL bWait)
-{
-   char chPressed;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_hotkey_menu()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   if(!pszHotKeys)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return('\0');
-   }
-
-   /* Store pointer to string of hotkeys in global hotkey array for access */
-   /* from od_send_file(). */
-   pszCurrentHotkeys = (char *)pszHotKeys;
-
-   /* Clear the hotkey status variable. */
-   chHotkeyPressed = '\0';
-
-   /* Display the menu file using od_send_file() primitive. */
-   if(!od_send_file(pszFileName))
-   {
-      OD_API_EXIT();
-      return('\0');
-   }
-
-   /* Clear the global hotkey array. */
-   pszCurrentHotkeys = NULL;
-
-   /* If the file display was interrupted by the pressing of one of the */
-   /* hotkeys, return the pressed hotkey immediately.                   */
-   if(chHotkeyPressed != '\0')
-   {
-      OD_API_EXIT();
-      return(chHotkeyPressed);
-   }
-
-   /* If no hotkey has been pressed key, and the wait flag has been set, */
-   /* wait for the user to press a valid hotkey.                         */
-   if(bWait)
-   {
-      /* Wait for a valid hotkey using the od_get_answer() primitive. */
-      chPressed = od_get_answer(pszHotKeys);
-
-      /* If a remote user is connected on this node. */
-      if(od_control.baud)
-      {
-         /* Clear the outbound buffer. */
-         ODComClearOutbound(hSerialPort);
-      }
-
-      /* Return the hotkey pressed by the user. */
-      OD_API_EXIT();
-      return(chPressed);
-   }
-
-   /* No hotkey has been pressed, so return 0.                          */
-   /* (Since 0 is used to terminate the string of valid hotkeys, it can */
-   /* never be a valid hotkey itself, and is therefore a safe value to  */
-   /* indicate the "no key press" state.)                               */
-   OD_API_EXIT();
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_send_file()
- *
- * Displays a .ASC/.ANS/.AVT/.RIP file to the local and remote screens. If
- * OpenDoors is unable to display the required file format locally, an
- * equivalent file that is locally displayable is selected. If no such
- * equivalent file can be found, then a message box is displayed, indicating
- * that the file is being transmitted to the remote system.
- *
- * Parameters: pszFileName - The name of the file to send. This parameter may
- *                           explicitly specify the full filename and
- *                           extension, or the extension may be omitted. In the
- *                           case that the extension is omitted, this function
- *                           automatically selects the appropriate file type
- *                           for the current display mode (RIP, ANSI, etc.).
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_send_file(char *pszFileName)
-{
-   FILE *pfRemoteFile;
-   FILE *pfLocalFile = NULL;
-   BOOL bAnythingLocal = TRUE;
-   void *pWindow;
-   INT nFileLevel;
-   BYTE btCount;
-   BOOL bPausing;
-   char chKey;
-   char *pchParsing;
-   char szMessage[74];
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_send_file()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   if(!pszFileName)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Initialize local variables. */
-   btCount = 2;
-
-   /* Turn on page pausing, if available. */
-   bPausing = od_control.od_page_pausing;
-
-   /* If operating in auto-filename mode (no extension specified). */
-   if(strchr(pszFileName, '.') == NULL)
-   {                                
-      /* Begin by searching for a .RIP file. */
-      nFileLevel = LEVEL_RIP;
-
-      /* If no .ASC/.ANS/.AVT/.RIP file. */      
-      if((pfRemoteFile = ODEmulateFindCompatFile(pszFileName, &nFileLevel))
-         == NULL)
-      {
-         /* Then return with an error. */
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      /* If the file found was a .RIP. */
-      if(nFileLevel == LEVEL_RIP)
-      {
-         /* Search for file to display locally. */
-         nFileLevel = LEVEL_AVATAR;
-
-         /* No page pausing with .RIP display. */
-         bPausing = FALSE;
-
-         if((pfLocalFile = ODEmulateFindCompatFile(pszFileName, &nFileLevel))
-            == NULL)
-         {
-            /* If there is no further .ASC/.ANS/.AVT/.RIP files, then no */
-            /* local display.                                            */
-            bAnythingLocal = FALSE;
-         }
-      }
-      else if(nFileLevel == LEVEL_NONE)
-      {
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      /* Get filename of remote file. */
-      strcpy(szODWorkString, pszFileName);
-      strcat(szODWorkString, ".RIP");
-      strupr(szODWorkString);
-   }
-   else
-   {
-      /* If the full filename was specified, then attempt to open that file. */
-      if((pfRemoteFile = fopen(pszFileName,"rb")) == NULL)
-      {
-         /* If unable to open file, then return. */
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      strcpy(szODWorkString, pszFileName);
-      strupr(szODWorkString);
-
-      if(strstr(szODWorkString, ".RIP"))
-      {
-         /* No page pausing during .RIP display. */
-         bPausing = FALSE;
-
-         /* Disable local display. */
-         bAnythingLocal = FALSE;
-      }
-   }
-
-   /* Set default colour to grey on black. */
-   btDefaultAttrib = 0x07;
-
-   /* Reset all terminal emulation. */
-   btAvatarSeqLevel = 0;
-   btANSISeqLevel = 0;
-
-   /* Turn off AVATAR insert mode. */
-   bAvatarInsertMode = FALSE;
-
-   /* Reset [S]top/[P]ause control key status. */
-   chLastControlKey = 0;
-
-   if(!bAnythingLocal)
-   {
-      strcpy(szODWorkString, od_control.od_sending_rip);
-      strcat(szODWorkString, pszFileName);
-      ODStringCopy(szMessage, szODWorkString, sizeof(szMessage));
-
-      pWindow = ODScrnShowMessage(szMessage, 0);
-   }
-
-   /* Loop to display each line in the file(s) with page pausing, etc. */
-   for(;;)
-   {
-      /* Call the OpenDoors kernel routine. */
-      CALL_KERNEL_IF_NEEDED();
-
-      /* If hotkeys are active. */
-      if(pszCurrentHotkeys != NULL)
-      {
-         /* If a key is waiting in buffer. */
-         while((chKey = (char)tolower(od_get_key(FALSE))) != 0)
-         {
-            /* Check for key in hotkey string. */
-            pchParsing = (char *)pszCurrentHotkeys;
-            while(*pchParsing)
-            {
-               /* If key is found. */
-               if(tolower(*pchParsing) == chKey)
-               {
-                  /* Return, indicating that hotkey was pressed. */
-                  chHotkeyPressed = *pchParsing;
-                  goto abort_send;
-               }
-               ++pchParsing;
-            }
-         }
-      }
-
-      /* If a control key has been pressed. */
-      if(chLastControlKey)
-      {
-         switch(chLastControlKey)
-         {
-            /* If it was a stop control key. */
-            case 's':
-               if(od_control.od_list_stop)
-               {
-                  /* If enabled, clear keyboard buffer. */
-abort_send:
-                  /* If operating in remote mode. */
-                  if(od_control.baud)
-                  {
-                     /* Clear the outbound FOSSIL buffer. */
-                     ODComClearOutbound(hSerialPort);
-                  }
-
-                  /* Return from function. */
-                  goto end_transmission;
-               }
-               break;
-
-            /* If control key was "pause". */
-            case 'p':
-               /* If pause is enabled. */
-               if(od_control.od_list_pause)
-               {
-                  /* Clear keyboard buffer. */
-                  od_clear_keybuffer();
-
-                  /* Wait for any keypress. */
-                  od_get_key(TRUE);
-               }
-         }
-
-         /* Clear control key status. */
-         chLastControlKey = 0;
-      }
-
-      /* Get next line, if any. */
-      if(fgets(szODWorkString, 256, pfRemoteFile) == NULL)
-      {
-         /* If different local file. */
-         if(pfLocalFile)
-         {
-            /* Display rest of it. */
-            while(fgets(szODWorkString, 256, pfLocalFile))
-            {
-                /* Pass each line to terminal emulator. */
-               ODEmulateFromBuffer(szODWorkString, FALSE);
-            }
-         }
-
-         /* Return from od_send_file(). */
-         goto end_transmission;
-      }
-
-      /* Set parsepos = last char in globworkstr. */
-      pchParsing = (char *)&szODWorkString;
-      while(*++pchParsing) ;
-      --pchParsing;
-
-      /* Check for end of page state. */
-      if((*pchParsing == '\r' || *pchParsing == '\n') &&
-         ++btCount >= od_control.user_screen_length && bPausing)
-      {
-         /* Display page pause prompt. */
-         if(ODPagePrompt(&bPausing))
-         {
-            /* If user chose to abort, then return from od_send_file(). */
-            goto end_transmission;
-         }
-
-         /* Reset line count. */
-         btCount = 2;
-      }
-
-
-      /* If the file is also to be displayed locally. */
-      if(bAnythingLocal)
-      {
-         /* If the local file is different from the remote file, then obtain */
-         /* the next line from the local file.                               */
-         if(pfLocalFile)
-         {
-            od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-
-            if(fgets(szODWorkString, 256, pfLocalFile) == NULL)
-            {
-               while(fgets(szODWorkString, 256, pfRemoteFile))
-               {
-                  od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-               }
-
-               /* Return from od_send_file(). */
-               goto end_transmission;
-            }
-
-            ODEmulateFromBuffer(szODWorkString, FALSE);
-         }
-         else
-         {
-            /* Pass the string through the local terminal emulation */
-            /* system, and send a copy to the remote system.        */
-            if(od_control.od_no_ra_codes)
-            {
-               ODEmulateFromBuffer(szODWorkString, FALSE);
-               od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-            }
-            else
-            {
-               ODEmulateFromBuffer(szODWorkString,TRUE);
-            }
-         }
-      }
-      else
-      {
-         /* If the file is not being displayed locally, then just send the */
-         /* entire line to the remote system (if any).                     */
-         od_disp(szODWorkString,strlen(szODWorkString),FALSE);
-      }
-   }
-
-end_transmission:
-
-   /* Close remote file. */
-   fclose(pfRemoteFile);
-
-   /* If there is a different local file, then close it too. */
-   if(pfLocalFile)
-   {
-      fclose(pfLocalFile);
-   }
-
-   /* If we are not displaying anything on the local system. */
-   if(!bAnythingLocal)
-   {
-      /* Wait while file is being sent. */
-      if(od_control.baud != 0)
-      {
-         int nOutboundSize;
-         do
-         {
-            CALL_KERNEL_IF_NEEDED();
-            ODComOutbound(hSerialPort, &nOutboundSize);
-         } while(nOutboundSize != 0);
-      }
-
-      /* Get rid of the window. */
-      ODScrnRemoveMessage(pWindow);
-   }
-
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * od_send_file_section()
- *
- * Displays a .ASC/.ANS/.AVT/.RIP multi-section file to the local and remote
- * screens.  If OpenDoors is unable to display the required file format locally,
- * an equivalent file that is locally displayable is selected. If no such
- * equivalent file can be found, then a message box is displayed, incdicating
- * that the file is being transmitted to the remote system.
- *
- * Note: This function works virtually identical to od_send_file() except it
- *       checks for the section headers (if found).
- *
- * Parameters: pszFileName - The name of the file to send. This parameter may
- *                           explicitly specify the full filename and
- *                           extension, or the extension may be omitted. In the
- *                           case that the extension is omitted, this function
- *                           automatically selects the appropriate file type
- *                           for the current display mode (RIP, ANSI, etc.).
- *             pszSectionname - Name of the section in which to send. This 
- *                              parameter must include only the section name 
- *                              and not the @# delimiter.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_send_file_section(char *pszFileName, char *pszSectionName)
-{
-   FILE *pfRemoteFile;
-   FILE *pfLocalFile = NULL;
-   BOOL bAnythingLocal = TRUE;
-   void *pWindow;
-   INT nFileLevel;
-   BYTE btCount;
-   BOOL bPausing;
-   char chKey;
-   char *pchParsing;
-   char szMessage[74];
-   char szFullSectionName[256];
-   BOOL bSectionFound = FALSE;
-   UINT uSectionNameLength;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_send_file_section()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   if(!pszFileName || !pszSectionName)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Initialize local variables. */
-   btCount = 2;
-
-   /* Turn on page pausing, if available. */
-   bPausing = od_control.od_page_pausing;
-
-   /* If operating in auto-filename mode (no extension specified). */
-   if(strchr(pszFileName, '.') == NULL)
-   {                                
-      /* Begin by searching for a .RIP file. */
-      nFileLevel = LEVEL_RIP;
-
-      /* If no .ASC/.ANS/.AVT/.RIP file. */      
-      if((pfRemoteFile = ODEmulateFindCompatFile(pszFileName, &nFileLevel))
-         == NULL)
-      {
-         /* Then return with an error. */
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      /* If the file found was a .RIP. */
-      if(nFileLevel == LEVEL_RIP)
-      {
-         /* Search for file to display locally. */
-         nFileLevel = LEVEL_AVATAR;
-
-         /* No page pausing with .RIP display. */
-         bPausing = FALSE;
-
-         if((pfLocalFile = ODEmulateFindCompatFile(pszFileName, &nFileLevel))
-            == NULL)
-         {
-            /* If there is no further .ASC/.ANS/.AVT/.RIP files, then no */
-            /* local display.                                            */
-            bAnythingLocal = FALSE;
-         }
-      }
-      else if(nFileLevel == LEVEL_NONE)
-      {
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      /* Get filename of remote file. */
-      strcpy(szODWorkString, pszFileName);
-      strcat(szODWorkString, ".RIP");
-      strupr(szODWorkString);
-   }
-   else
-   {
-      /* If the full filename was specified, then attempt to open that file. */
-      if((pfRemoteFile = fopen(pszFileName,"rb")) == NULL)
-      {
-         /* If unable to open file, then return. */
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-
-      strcpy(szODWorkString, pszFileName);
-      strupr(szODWorkString);
-
-      if(strstr(szODWorkString, ".RIP"))
-      {
-         /* No page pausing during .RIP display. */
-         bPausing = FALSE;
-
-         /* Disable local display. */
-         bAnythingLocal = FALSE;
-      }
-   }
-
-   /* Set default colour to grey on black. */
-   btDefaultAttrib = 0x07;
-
-   /* Reset all terminal emulation. */
-   btAvatarSeqLevel = 0;
-   btANSISeqLevel = 0;
-
-   /* Turn off AVATAR insert mode. */
-   bAvatarInsertMode = FALSE;
-
-   /* Reset [S]top/[P]ause control key status. */
-   chLastControlKey = 0;
-
-   if(!bAnythingLocal)
-   {
-      strcpy(szODWorkString, od_control.od_sending_rip);
-      strcat(szODWorkString, pszFileName);
-      ODStringCopy(szMessage, szODWorkString, sizeof(szMessage));
-
-      pWindow = ODScrnShowMessage(szMessage, 0);
-   }
-
-   /* Create section name information */
-   strcpy(szFullSectionName, "@#");
-   strncat(szFullSectionName, pszSectionName, 254);
-
-   /* Get the length of the section name in it's full form */
-   uSectionNameLength = strlen(szFullSectionName); 
-
-   /* Loop to display each line in the file(s) with page pausing, etc. */
-   for(;;)
-   {
-      /* Call the OpenDoors kernel routine. */
-      CALL_KERNEL_IF_NEEDED();
-
-      /* If hotkeys are active. */
-      if(pszCurrentHotkeys != NULL)
-      {
-         /* If a key is waiting in buffer. */
-         while((chKey = (char)tolower(od_get_key(FALSE))) != 0)
-         {
-            /* Check for key in hotkey string. */
-            pchParsing = (char *)pszCurrentHotkeys;
-            while(*pchParsing)
-            {
-               /* If key is found. */
-               if(tolower(*pchParsing) == chKey)
-               {
-                  /* Return, indicating that hotkey was pressed. */
-                  chHotkeyPressed = *pchParsing;
-                  goto abort_send;
-               }
-               ++pchParsing;
-            }
-         }
-      }
-
-      /* If a control key has been pressed. */
-      if(chLastControlKey)
-      {
-         switch(chLastControlKey)
-         {
-            /* If it was a stop control key. */
-            case 's':
-               if(od_control.od_list_stop)
-               {
-                  /* If enabled, clear keyboard buffer. */
-abort_send:
-                  /* If operating in remote mode. */
-                  if(od_control.baud)
-                  {
-                     /* Clear the outbound FOSSIL buffer. */
-                     ODComClearOutbound(hSerialPort);
-                  }
-
-                  /* Return from function. */
-                  goto end_transmission;
-               }
-               break;
-
-            /* If control key was "pause". */
-            case 'p':
-               /* If pause is enabled. */
-               if(od_control.od_list_pause)
-               {
-                  /* Clear keyboard buffer. */
-                  od_clear_keybuffer();
-
-                  /* Wait for any keypress. */
-                  od_get_key(TRUE);
-               }
-         }
-
-         /* Clear control key status. */
-         chLastControlKey = 0;
-      }
-
-      /* Get next line, if any. */
-      if(fgets(szODWorkString, 256, pfRemoteFile) == NULL)
-      {
-         /* If different local file. */
-         if(pfLocalFile)
-         {
-            /* Display rest of it. */
-            while(fgets(szODWorkString, 256, pfLocalFile))
-            {
-               if (!bSectionFound && strncmp(szFullSectionName, szODWorkString, uSectionNameLength) == 0) 
-               {
-                  /* Section Found, allow all lines up to EOF or new section to be displayed */
-                  bSectionFound = TRUE;
-                  /* Read next line, ignore the section line */
-                  continue;
-               } 
-               else if (!bSectionFound) 
-               {
-                  /* Section not found yet, continue loop */
-                  continue;
-               } 
-               else if (bSectionFound && strncmp(szODWorkString, "@#", 2) == 0) 
-               {
-                  /* New Section Intercepted */
-                  goto end_transmission;
-               }
-                /* Pass each line to terminal emulator. */
-               ODEmulateFromBuffer(szODWorkString, FALSE);
-            }
-         }
-
-         /* Return from od_send_file(). */
-         goto end_transmission;
-      }
-
-      /* Check for section header @# + pszSectionName */
-      if (!bSectionFound && strncmp(szFullSectionName, szODWorkString, uSectionNameLength) == 0) 
-      {
-         /* Flag the section as found */
-         bSectionFound = TRUE;
-         /* Read next line, ignore section line */
-         continue;
-      } 
-      else if (!bSectionFound) 
-      {
-         /* Section hasn't been found yet */
-         continue;
-      } 
-      else if (bSectionFound && strncmp(szODWorkString, "@#", 2) == 0) 
-      {
-         /* New section found, terminate send */
-         goto end_transmission;
-      }
-
-      /* Set parsepos = last char in globworkstr. */
-      pchParsing = (char *)&szODWorkString;
-      while(*++pchParsing) ;
-      --pchParsing;
-
-      /* Check for end of page state. */
-      if((*pchParsing == '\r' || *pchParsing == '\n') &&
-         ++btCount >= od_control.user_screen_length && bPausing)
-      {
-         /* Display page pause prompt. */
-         if(ODPagePrompt(&bPausing))
-         {
-            /* If user chose to abort, then return from od_send_file(). */
-            goto end_transmission;
-         }
-
-         /* Reset line count. */
-         btCount = 2;
-      }
-
-
-      /* If the file is also to be displayed locally. */
-      if(bAnythingLocal)
-      {
-         /* If the local file is different from the remote file, then obtain */
-         /* the next line from the local file.                               */
-         if(pfLocalFile)
-         {
-            od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-
-            if(fgets(szODWorkString, 256, pfLocalFile) == NULL)
-            {
-               while(fgets(szODWorkString, 256, pfRemoteFile))
-               {
-                  od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-               }
-
-               /* Return from od_send_file(). */
-               goto end_transmission;
-            }
-
-            ODEmulateFromBuffer(szODWorkString, FALSE);
-         }
-         else
-         {
-            /* Pass the string through the local terminal emulation */
-            /* system, and send a copy to the remote system.        */
-            if(od_control.od_no_ra_codes)
-            {
-               ODEmulateFromBuffer(szODWorkString, FALSE);
-               od_disp(szODWorkString, strlen(szODWorkString), FALSE);
-            }
-            else
-            {
-               ODEmulateFromBuffer(szODWorkString,TRUE);
-            }
-         }
-      }
-      else
-      {
-         /* If the file is not being displayed locally, then just send the */
-         /* entire line to the remote system (if any).                     */
-         od_disp(szODWorkString,strlen(szODWorkString),FALSE);
-      }
-   }
-
-end_transmission:
-
-   /* Close remote file. */
-   fclose(pfRemoteFile);
-
-   /* If there is a different local file, then close it too. */
-   if(pfLocalFile)
-   {
-      fclose(pfLocalFile);
-   }
-
-   /* If we are not displaying anything on the local system. */
-   if(!bAnythingLocal)
-   {
-      /* Wait while file is being sent. */
-      if(od_control.baud != 0)
-      {
-         int nOutboundSize;
-         do
-         {
-            CALL_KERNEL_IF_NEEDED();
-            ODComOutbound(hSerialPort, &nOutboundSize);
-         } while(nOutboundSize != 0);
-      }
-
-      /* Get rid of the window. */
-      ODScrnRemoveMessage(pWindow);
-   }
-   
-   /* If the section was not found, return FALSE for error */
-   if (!bSectionFound)
-   {
-      OD_API_EXIT();
-      return (FALSE);   
-   }
-
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * ODEmulateFindCompatFile()                           *** PRIVATE FUNCTION ***
- *
- * Searches for an .ASC/.ANS/.AVT/.RIP file that is compatible with the
- * specified display capabilities level.
- *
- * Parameters: pszBaseName - Base filename to use.
- *
- *             pnLevel     - Highest file level to search for. This value is
- *                           updated to indicate the type of file found.
- *
- *     Return: A pointer to a now-open file of the required type, or NULL if
- *             no match was found.
- */
-static FILE *ODEmulateFindCompatFile(char *pszBaseName, INT *pnLevel)
-{
-   FILE *pfCompatibleFile;
-
-   ASSERT(pszBaseName != NULL);
-   ASSERT(pnLevel != NULL);
-   ASSERT(*pnLevel >= 0 && *pnLevel <= 4);
-
-   /* Loop though .RIP/.AVT/.ANS/.ASC extensions. */
-   for(;*pnLevel > LEVEL_NONE; --*pnLevel)
-   {
-      /* Get base-filename passed in. */
-      strcpy(szODWorkString, pszBaseName);
-
-      /* Try current extension. */
-      switch(*pnLevel)
-      {
-         case LEVEL_RIP:
-            if(!od_control.user_rip) continue;
-            strcat(szODWorkString, ".RIP");
-            break;
-
-         case LEVEL_AVATAR:
-            if(!od_control.user_avatar) continue;
-            strcat(szODWorkString, ".AVT");
-            break;
-
-         case LEVEL_ANSI:
-            if(!od_control.user_ansi) continue;
-            strcat(szODWorkString, ".ANS");
-            break;
-
-         case LEVEL_ASCII:
-            strcat(szODWorkString, ".ASC");
-            break;
-      }
-
-      /* If we are able to open this file, then return a pointer to */
-      /* the file.                                                  */
-      if((pfCompatibleFile = fopen(szODWorkString,"rb")) != NULL)
-         return(pfCompatibleFile);
-   }
-
-   /* Return NULL if no file was found. */
-   return(NULL);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_disp_emu()
- *
- * Sends an entire string to both local and remote systems. The characters
- * displayed locally are fed through the local terminal emulation sub-system,
- * allowing aribtrary ANSI/AVATAR control sequences to be displayed both
- * locally and remotely.
- *
- * Parameters: pszToDisplay - Pointer to string to display.
- *
- *             bRemoteEcho  - TRUE if characters should also be transmitted
- *                            to the remote system.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_disp_emu(char *pszToDisplay, BOOL bRemoteEcho)
-{
-   BOOL bTranslateRemote;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_disp_emu()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Send pszToDisplay to remote system. */
-   if(bRemoteEcho)
-   {
-      if(od_control.od_no_ra_codes)
-      {
-         od_disp(pszToDisplay, strlen(pszToDisplay), FALSE);
-         bTranslateRemote = FALSE;
-      }
-      else
-      {
-         bTranslateRemote = TRUE;
-      }
-   }
-   else
-   {
-      bTranslateRemote = FALSE;
-   }
-
-   /* Pass string to be emulated to local terminal emulation function. */
-   ODEmulateFromBuffer(pszToDisplay, bTranslateRemote);
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_emulate()
- *
- * Sends a single character to both local and remote systems. The characters
- * displayed locally are fed through the local terminal emulation sub-system,
- * allowing aribtrary ANSII/AVATAR control sequences to be displayed both
- * locally and remotely.
- *
- * Parameters: chToEmulate - Character to feed through the terminal emulator.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_emulate(char chToEmulate)
-{
-   static char szBuffer[2];
-
-   *szBuffer = chToEmulate;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_emulate()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Pass character to be emulated to local terminal emulation function. */
-   ODEmulateFromBuffer(szBuffer, TRUE);
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEmulateFromBuffer()                               *** PRIVATE FUNCTION ***
- *
- * Displays a string on the local screen, interpreting any terminal emulation
- * control sequences. The string may also be sent to the remote system at the
- * same time.
- *
- * Parameters: pszBuffer   - Pointer to the string to transmit.
- *
- *             bRemoteEcho - TRUE if string should also be sent to the remote
- *                           system, FALSE if it should not be.
- *
- *     Return: void
- */
-static void ODEmulateFromBuffer(char *pszBuffer, BOOL bRemoteEcho)
-{
-   char chCurrent;
-   static tODScrnTextInfo TextInfo;
-   INT nTemp;
-   BOOL bEchoThisChar;
-   INT nCharsPerTick;
-   INT nCharsThisTick;
-   tODTimer ModemSimTimer;
-
-   ASSERT(pszBuffer != NULL);
-
-   /* If we should simulate modem transmission speed. */
-   if(od_control.od_emu_simulate_modem)
-   {
-      DWORD lCharsPerSecond;
-
-      /* Determine character per second rate to simulate. */
-      if(od_control.baud == 0)
-      {
-         lCharsPerSecond = 960L;
-      }
-      else
-      {
-         ODDWordDivide(&lCharsPerSecond, (DWORD *)NULL,
-            od_control.od_connect_speed, 10L);
-      }
-
-      /* Determine number of characters to send per timer tick. */
-      lCharsPerSecond = ODDWordMultiply(lCharsPerSecond, MODEM_SIMULATOR_TICK);
-      ODDWordDivide(&lCharsPerSecond, (DWORD *)NULL, lCharsPerSecond, 1000L);
-      nCharsPerTick = (INT)lCharsPerSecond;
-
-      /* Start tick timer. */
-      ODTimerStart(&ModemSimTimer, MODEM_SIMULATOR_TICK);
-
-      /* Reset number of characters that we have sent during this tick. */
-      nCharsThisTick = 0;
-   }
-
-   while(*pszBuffer)
-   {
-      /* Read the next character from the buffer into local variable for */
-      /* access speed efficiency.                                        */
-      chCurrent = *pszBuffer;
-
-      /* If we should simulate modem transmission speed. */
-      if(od_control.od_emu_simulate_modem)
-      {
-         /* If we have now sent all of the characters that should be sent */
-         /* during this tick.                                             */
-         if(nCharsThisTick++ >= nCharsPerTick)
-         {
-            /* Wait for timer to elapse. */
-            ODTimerWaitForElapse(&ModemSimTimer);
-
-            /* Restart tick timer. */
-            ODTimerStart(&ModemSimTimer, MODEM_SIMULATOR_TICK);
-
-            /* Reset characters sent in this tick. */
-            nCharsThisTick = 0;
-         }
-      }
-
-      bEchoThisChar = bRemoteEcho;
-
-      /* Switch according to ANSI emulator state. */
-      switch(btANSISeqLevel)
-      {
-         /* If we are not in the middle of an ANSI command string. */
-         case 0:
-            /* Switch according to current character. */
-            switch(chCurrent)
-            {
-               /* If this is the escape character. */
-               case 27:
-                  /* If we are not in the middle of an AVATAR sequence. */
-                  if(btAvatarSeqLevel == 0)
-                  {
-                     /* Then treat this as the start an ANSI sequence. */
-                     btANSISeqLevel = 1;
-                     break;
-                  }
-
-                  /* Deliberate fallthrough to default case. */
-
-               /* If not start of an ANSI sequence. */
-               default:
-                  /* Check our position in AVATAR sequence. */
-                  switch(btAvatarSeqLevel)
-                  {
-                     /* If not in middle of an AVATAR command. */
-                     case 0:
-                        /* Check the character we've been sent. */
-                        switch(chCurrent)
-                        {
-                           /* Check for QBBS/RA pause for keypress code. */
-                           case 0x01:
-                              if(od_control.od_no_ra_codes)
-                              {
-                                 goto output_next_char;
-                              }
-
-                              /* Wait for user to press [ENTER] key. */
-                              od_get_answer("\n\r");
-                              bEchoThisChar = FALSE;
-                              break;
-
-                           /* QBBS/RA ^F user parameters. */
-                           case 0x06:
-                              if(od_control.od_no_ra_codes)
-                              {
-                                 goto output_next_char;
-                              }
-                              btAvatarSeqLevel = 21;
-                              bEchoThisChar = FALSE;
-                              break;
-
-                           /* QBBS/RA ^K user parameters. */
-                           case 0x0b:
-                              if(od_control.od_no_ra_codes)
-                              {
-                                 goto output_next_char;
-                              }
-                              btAvatarSeqLevel = 22;
-                              bEchoThisChar = FALSE;
-                              break;
-
-                           case 0x0c:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnSetAttribute((BYTE)(
-                                 od_control.od_cur_attrib = btDefaultAttrib));
-                              ODScrnClear();
-                              break;
-
-                           case 0x19:
-                              bAvatarInsertMode = FALSE;
-                              btAvatarSeqLevel = 1;
-                              break;
-
-                           case 0x16:   /* ^V */
-                              btAvatarSeqLevel = 3;
-                              break;
-
-                           default:
-   output_next_char:
-                              /* Output next character. */
-                              if(bAvatarInsertMode)
-                              {
-                                 ODScrnGetTextInfo(&TextInfo);
-                                 if(TextInfo.curx < 80)
-                                 {
-                                    ODScrnCopyText(TextInfo.curx,
-                                       TextInfo.cury, 79, TextInfo.cury,
-                                       (BYTE)(TextInfo.curx + 1),
-                                       TextInfo.cury);
-                                 }
-                                 ODScrnDisplayChar(chCurrent);
-                              }
-
-                              else
-                              {
-                                 ODScrnDisplayChar(chCurrent);
-                              }
-                        }
-                        break;
-
-                     case 1:
-                        bAvatarInsertMode = FALSE;
-                        chPrevParam = chCurrent;
-                        btAvatarSeqLevel = 2;
-                        break;
-
-                     case 2:
-                        for(nTemp = 0; nTemp < (INT)chCurrent;
-                           ++nTemp)
-                        {
-                           ODScrnDisplayChar(chPrevParam);
-                        }
-                        btAvatarSeqLevel = 0;
-                        break;
-
-                     case 3:
-                        switch(chCurrent)
-                        {
-                           case 0x01:
-                              bAvatarInsertMode = FALSE;
-                              btAvatarSeqLevel = 4;
-                              break;
-
-                           case 0x02:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnGetTextInfo(&TextInfo);
-                              ODScrnSetAttribute((BYTE)
-                                 (od_control.od_cur_attrib =
-                                 TextInfo.attribute | 0x80));
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x03:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnGetTextInfo(&TextInfo);
-                              if(TextInfo.cury > 1)
-                              {
-                                 ODScrnSetCursorPos(TextInfo.curx,
-                                    (BYTE)(TextInfo.cury - 1));
-                              }
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x04:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnGetTextInfo(&TextInfo);
-                              if(TextInfo.cury < 25)
-                              {
-                                 ODScrnSetCursorPos(TextInfo.curx,
-                                    (BYTE)(TextInfo.cury + 1));
-                              }
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x05:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnGetTextInfo(&TextInfo);
-                              if(TextInfo.curx > 1)
-                              {
-                                 ODScrnSetCursorPos((BYTE)(TextInfo.curx - 1),
-                                    TextInfo.cury);
-                              }
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x06:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnGetTextInfo(&TextInfo);
-                              if(TextInfo.curx < 80)
-                              {
-                                 ODScrnSetCursorPos((BYTE)(TextInfo.curx + 1),
-                                    TextInfo.cury);
-                              }
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x07:
-                              bAvatarInsertMode = FALSE;
-                              ODScrnClearToEndOfLine();
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x08:
-                              bAvatarInsertMode = FALSE;
-                              btAvatarSeqLevel = 5;
-                              break;
-
-                           case 0x09:   /* ^I */
-                              bAvatarInsertMode = TRUE;
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x0a:   /* ^J */
-                              btScrollLines = -1;
-                              btAvatarSeqLevel = 7;
-                              break;
-
-                           case 0x0b:   /* ^K */
-                              btScrollLines = 1;
-                              btAvatarSeqLevel = 7;
-                              break;
-
-                           case 0x0c:   /* ^L */
-                              btAvatarSeqLevel = 14;
-                              break;
-
-                           case 0x0d:   /* ^M */
-                              btAvatarSeqLevel = 15;
-                              break;
-
-                           case 0x0e:   /* ^N */
-                              ODScrnGetTextInfo(&TextInfo);
-                              if(TextInfo.curx < 80)
-                              {
-                                 ODScrnCopyText((BYTE)(TextInfo.curx + 1),
-                                    TextInfo.cury, 80, TextInfo.cury,
-                                    TextInfo.curx, TextInfo.cury);
-                              }
-
-                              ODScrnEnableScrolling(FALSE);
-                              ODScrnSetCursorPos(80, TextInfo.cury);
-                              ODScrnDisplayChar(' ');
-                              ODScrnEnableScrolling(TRUE);
-                              ODScrnSetCursorPos(TextInfo.curx, TextInfo.cury);
-
-                              btAvatarSeqLevel = 0;
-                              break;
-
-                           case 0x19:   /* ^Y */
-                              btAvatarSeqLevel = 19;
-                              break;
-
-                           default:
-                              btAvatarSeqLevel = 0;
-                        }
-                        break;
-
-                     case 4:
-                        ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                           = chCurrent));
-                        btAvatarSeqLevel = 0;
-                        break;
-
-                     case 5:
-                        chPrevParam = chCurrent;
-                        btAvatarSeqLevel = 6;
-                        break;
-
-                     case 6:
-                        ODScrnSetCursorPos(chCurrent, chPrevParam);
-                        btAvatarSeqLevel = 0;
-                        break;
-
-                     case 7:
-                        if(btScrollLines < 1)
-                        {
-                           btScrollLines = chCurrent;
-                        }
-                        else
-                        {
-                           btScrollLines = -chCurrent;
-                        }
-                        btAvatarSeqLevel = 8;
-                        break;
-
-                     case 8:
-                        btScrollTop = chCurrent;
-                        btAvatarSeqLevel = 9;
-                        break;
-
-                     case 9:
-                        btScrollLeft = chCurrent;
-                        btAvatarSeqLevel = 10;
-                        break;
-
-                     case 10:
-                        btScrollBottom = chCurrent;
-                        btAvatarSeqLevel = 11;
-                        break;
-
-                     case 11:
-                        btScrollRight = chCurrent;
-                        btAvatarSeqLevel = 12;
-                        break;
-
-                     case 12:
-                        if(btScrollLines == 0
-                           || abs(btScrollLines) > 
-                           (btScrollBottom - btScrollTop))
-                        {
-                           ODEmulateFillArea(btScrollLeft, btScrollTop,
-                              btScrollRight, btScrollBottom, ' ');
-                        }
-
-                        else if(btScrollLines < 0)
-                        {
-                           ODScrnCopyText(btScrollLeft, btScrollTop,
-                              btScrollRight,
-                              (BYTE)(btScrollBottom + btScrollLines),
-                              btScrollLeft,
-                              (BYTE)(btScrollTop - btScrollLines));
-                           ODEmulateFillArea(btScrollLeft, btScrollTop,
-                              btScrollRight,
-                              (BYTE)(btScrollTop - (btScrollLines - 1)), ' ');
-                        }
-
-                        else
-                        {
-                           ODScrnCopyText(btScrollLeft,
-                              (BYTE)(btScrollTop + btScrollLines),
-                              btScrollRight, btScrollBottom,
-                              btScrollLeft, btScrollTop);
-                           ODEmulateFillArea(btScrollLeft,
-                              (BYTE)(btScrollBottom - (btScrollLines - 1)),
-                              btScrollRight, btScrollBottom, ' ');
-                        }
-                        btAvatarSeqLevel = 0;
-                        break;
-
-                     case 14:
-                        btScrollLines = (chCurrent & 0x7f);
-                        btScrollRight = ' ';
-                        btAvatarSeqLevel = 17;
-                        break;
-
-                     case 15:
-                        btScrollLines = (chCurrent & 0x7f);
-                        btAvatarSeqLevel = 16;
-                        break;
-
-                     case 16:
-                        btScrollRight = chCurrent;
-                        btAvatarSeqLevel = 17;
-                        break;
-
-                     case 17:
-                        btScrollTop = chCurrent;
-                        btAvatarSeqLevel = 18;
-                        break;
-
-                     case 18:
-                        ODScrnGetTextInfo(&TextInfo);
-                        ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                           = btScrollLines));
-                        ODEmulateFillArea(TextInfo.curx, TextInfo.cury,
-                           (BYTE)(TextInfo.curx + chCurrent),
-                           (BYTE)(TextInfo.cury + btScrollTop), btScrollRight);
-                        btAvatarSeqLevel = 0;
-                        break;
-
-                     case 19:
-                        btScrollLines = (chCurrent & 0x7f);
-                        szToRepeat[btRepeatCount = 0] = '\0';
-                        btAvatarSeqLevel = 20;
-                        break;
-
-                     case 20:
-                        if(btRepeatCount < btScrollLines)
-                        {
-                           szToRepeat[btRepeatCount] = chCurrent;
-                           szToRepeat[++btRepeatCount] = '\0';
-                        }
-                        else
-                        {
-                           for(btRepeatCount = 0; btRepeatCount <
-                              (BYTE)chCurrent;++btRepeatCount)
-                           {
-                              ODScrnDisplayString(szToRepeat);
-                           }
-                           btAvatarSeqLevel = 0;
-                        }
-                        break;
-
-                     /* RA/QBBS ^F control codes. */
-                     case 21:
-                        bEchoThisChar = FALSE;
-                        switch(chCurrent)
-                        {
-                           case 'A':
-                              od_disp_str(od_control.user_name);
-                              break;
-                           case 'B':
-                              od_disp_str(od_control.user_location);
-                              break;
-                           case 'C':
-                              od_disp_str(od_control.user_password);
-                              break;
-                           case 'D':
-                              od_disp_str(od_control.user_dataphone);
-                              break;
-                           case 'E':
-                              od_disp_str(od_control.user_homephone);
-                              break;
-                           case 'F':
-                              od_disp_str(od_control.user_lastdate);
-                              break;
-                           case 'G':
-                              od_disp_str(od_control.user_lasttime);
-                              break;
-                           case 'H':
-                              btScrollLines = 0;
-                              goto show_flags;
-                           case 'I':
-                              btScrollLines = 1;
-                              goto show_flags;
-                           case 'J':
-                              btScrollLines = 2;
-                              goto show_flags;
-                           case 'K':
-                              btScrollLines = 3;
-   show_flags:                for(btRepeatCount = 0; btRepeatCount < 8;
-                                 ++btRepeatCount)
-                              {
-                                 if((od_control.user_flags[btScrollLines] >>
-                                    btRepeatCount) & 0x01)
-                                 {
-                                    szToRepeat[btRepeatCount] = 'X';
-                                 }
-                                 else
-                                 {
-                                    szToRepeat[btRepeatCount] = '-';
-                                 }
-                              }
-                              szToRepeat[btRepeatCount] = '\0';
-                              od_disp_str(szToRepeat);
-                              break;
-                           case 'L':
-                              od_printf("%lu", od_control.user_net_credit);
-                              break;
-                           case 'M':
-                              od_printf("%u", od_control.user_messages);
-                              break;
-                           case 'N':
-                              od_printf("%u", od_control.user_lastread);
-                              break;
-                           case 'O':
-                              od_printf("%u", od_control.user_security);
-                              break;
-                           case 'P':
-                              od_printf("%u", od_control.user_numcalls);
-                              break;
-                           case 'Q':
-                              od_printf("%ul", od_control.user_uploads);
-                              break;
-                           case 'R':
-                              od_printf("%ul", od_control.user_upk);
-                              break;
-                           case 'S':
-                              od_printf("%ul", od_control.user_downloads);
-                              break;
-                           case 'T':
-                              od_printf("%ul", od_control.user_downk);
-                              break;
-                           case 'U':
-                              od_printf("%d", od_control.user_time_used);
-                              break;
-                           case 'V':
-                              od_printf("%d", od_control.user_screen_length);
-                              break;
-                           case 'W':
-                              btRepeatCount = 0;
-                              while(od_control.user_name[btRepeatCount])
-                              {
-                                 if((szToRepeat[btRepeatCount]
-                                    = od_control.user_name[btRepeatCount])
-                                    == ' ')
-                                 {
-                                    szToRepeat[btRepeatCount] = '\0';
-                                    break;
-                                 }
-                                 ++btRepeatCount;
-                              }
-                              od_disp_str(szToRepeat);
-                              break;
-                           case 'X':
-                              if(od_control.user_ansi)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case 'Y':
-                              if(od_control.user_attribute & 0x04)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case 'Z':
-                              if(od_control.user_attribute & 0x02)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case '0':
-                              if(od_control.user_attribute & 0x40)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case '1':
-                              if(od_control.user_attribute & 0x80)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case '2':
-                              if(od_control.user_attrib2 & 0x01)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case '3':
-                              od_disp_str(od_control.user_handle);
-                              break;
-                           case '4':
-                              od_disp_str(od_control.user_firstcall);
-                              break;
-                           case '5':
-                              od_disp_str(od_control.user_birthday);
-                              break;
-                           case '6':
-                              od_disp_str(od_control.user_subdate);
-                              break;
-                           case '7':
-                              /* days until subscrption expiry */
-                              break;
-                           case '8':
-                              if(od_control.user_attrib2 & 0x02)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                              break;
-                           case '9':
-                              od_printf("%lu:%lu",
-                                 od_control.user_uploads,
-                                 od_control.user_downloads);
-                              break;
-                           case ':':
-                              od_printf("%lu:%lu",
-                                 od_control.user_upk,
-                                 od_control.user_downk);
-                              break;
-                           case ';':
-                              if(od_control.user_attrib2 & 0x04)
-                              {
-                                 od_disp_str("ON");
-                              }
-                              else
-                              {
-                                 od_disp_str("OFF");
-                              }
-                        }
-                        btAvatarSeqLevel=0;
-                        break;
-
-                     /* QBBS/RA ^K control codes. */
-                     case 22:
-                        bEchoThisChar = FALSE;
-                        switch(chCurrent)
-                        {
-                           case 'A':
-                              od_printf("%lu", od_control.system_calls);
-                              break;
-                           case 'B':
-                              od_disp_str(od_control.system_last_caller);
-                              break;
-                           case 'C':
-                              /* number of active messages */
-                              break;
-                           case 'D':
-                              /* system starting message number */
-                              break;
-                           case 'E':
-                              /* system ending message number */
-                              break;
-                           case 'F':
-                              /* number of times user has paged sysop */
-                              break;
-                           case 'G':
-                              /* day of the week (Monday, Tuesday, etc.) */
-                              break;
-                           case 'H':
-                              /* number of users in user file */
-                              break;
-                           case 'I':
-                              /* Time in 24 hour format */
-                              break;
-                           case 'J':
-                              /* today's date */
-                              break;
-                           case 'K':
-                              /* minutes connected this call */
-                              break;
-                           case 'L':
-                              /* Seconds connected (0) */
-                              break;
-                           case 'M':
-                              od_printf("%d", od_control.user_time_used);
-                              break;
-                           case 'N':
-                              od_disp_str("00");
-                              break;
-                           case 'O':
-                              /* Minutes remaining today */
-                              od_printf("%d", od_control.user_timelimit);
-                              break;
-                           case 'P':
-                              /* seconds remaining today (0) */
-                              break;
-                           case 'Q':
-                              od_printf("0", od_control.user_timelimit);
-                              break;
-                           case 'R':      /* current baud rate */
-                              od_printf("0", od_control.baud);
-                              break;
-                           case 'S':
-                              /* day of the week (MON, TUE) */
-                              break;
-                           case 'T':
-                              /* Daily download limit (in K) */
-                              break;
-                           case 'U':
-                              /* Minutes until next system event */
-                              break;
-                           case 'V':
-                              ODScrnDisplayString(od_control.event_starttime);
-                              break;
-                           case 'W':
-                              /* line number (from command line) */
-                              break;
-                           case 'X':
-                              od_exit(2, TRUE);
-                              break;
-                           case 'Y':
-                              /* Name of current msg area */
-                              break;
-                           case 'Z':
-                              /* name of current file area */
-                              break;
-                           case '0':
-                              /* # of messages in area */
-                              break;
-                           case '1':
-                              /* # of message area */
-                              break;
-                           case '2':
-                              /* # of file area */
-                              break;
-                        }
-                        btAvatarSeqLevel = 0;
-                  }
-            }
-            break;
-
-         case 1:
-            switch(chCurrent)
-            {
-               case '[':
-                  btANSISeqLevel = 2;
-                  btCurrentParamLength = 0;
-                  btNumParams = 0;
-                  break;
-
-               default:
-                  btANSISeqLevel = 0;
-                  ODScrnDisplayChar(27);
-                  ODScrnDisplayChar(chCurrent);
-            }
-            break;
-
-         default:
-            if((chCurrent >= '0' && chCurrent <= '9') || chCurrent == '?')
-            {
-               if(btCurrentParamLength < 3)
-               {
-                  szCurrentParam[btCurrentParamLength] = chCurrent;
-                  szCurrentParam[++btCurrentParamLength] = '\0';
-               }
-               else
-               {
-                  btANSISeqLevel = 0;
-               }
-            }
-
-            else if(chCurrent == ';')
-            {
-               if(btNumParams < 10)
-               {
-                  if(btCurrentParamLength != 0)
-                  {
-                     if(strcmp(szCurrentParam, "?9") == 0)
-                     {
-                        anANSIParams[btNumParams] = -2;
-                     }
-                     else
-                     {
-                        anANSIParams[btNumParams] = atoi(szCurrentParam);
-                     }
-                     szCurrentParam[0] = '\0';
-                     btCurrentParamLength = 0;
-                     ++btNumParams;
-                  }
-                  else
-                  {
-                     anANSIParams[btNumParams++] = -1;
-                  }
-               }
-               else
-               {
-                  btANSISeqLevel = 0;
-               }
-            }
-
-            else
-            {
-               btANSISeqLevel = 0;
-
-               if(btCurrentParamLength != 0 && btNumParams < 10)
-               {
-                  if(strcmp(szCurrentParam,"?9") == 0)
-                  {
-                     anANSIParams[btNumParams] = -2;
-                  }
-                  else
-                  {
-                     anANSIParams[btNumParams] = atoi(szCurrentParam);
-                  }
-                  szCurrentParam[0] = '\0';
-                  btCurrentParamLength = 0;
-                  ++btNumParams;
-               }
-
-               ODScrnGetTextInfo(&TextInfo);
-
-               switch(chCurrent)
-               {
-                  case 'A':
-                     if(btNumParams == 0) anANSIParams[0] = 1;
-                     if((nTemp = TextInfo.cury - anANSIParams[0]) < 1)
-                     {
-                        nTemp = 1;
-                     }
-                     if(nTemp > 25) nTemp=25;
-                     ODScrnSetCursorPos(TextInfo.curx, (BYTE)nTemp);
-                     break;
-
-                  case 'B':
-                     if(btNumParams == 0) anANSIParams[0] = 1;
-                     if((nTemp = TextInfo.cury + anANSIParams[0]) > 25)
-                     {
-                        nTemp = 25;
-                     }
-                     if(nTemp < 1) nTemp = 1;
-                     ODScrnSetCursorPos(TextInfo.curx, (BYTE)nTemp);
-                     break;
-
-                  case 'C':
-                     if(btNumParams == 0) anANSIParams[0] = 1;
-                     if((nTemp=TextInfo.curx + anANSIParams[0]) > 80)
-                     {
-                        nTemp = 80;
-                     }
-                     if(nTemp < 1) nTemp = 1;
-                     ODScrnSetCursorPos((BYTE)nTemp, TextInfo.cury);
-                     break;
-
-                  case 'D':
-                     if(btNumParams == 0) anANSIParams[0] = 1;
-                     if((nTemp = TextInfo.curx - anANSIParams[0]) < 1)
-                     {
-                        nTemp = 1;
-                     }
-                     if(nTemp > 80) nTemp = 80;
-                     ODScrnSetCursorPos((BYTE)nTemp, TextInfo.cury);
-                     break;
-
-                  case 'H':
-                  case 'f':
-                     if(btNumParams >= 2)
-                     {
-                        if(anANSIParams[0] == -1)
-                        {
-                           ODScrnSetCursorPos((BYTE)anANSIParams[1], 1);
-                        }
-                        else
-                        {
-                           ODScrnSetCursorPos((BYTE)anANSIParams[1],
-                              (BYTE)anANSIParams[0]);
-                        }
-                     }
-                     else if(btNumParams == 1)
-                     {
-                        if(anANSIParams[0] <= 0)
-                        {
-                           ODScrnSetCursorPos(1, TextInfo.cury);
-                        }
-                        else
-                        {
-                           ODScrnSetCursorPos(1, (BYTE)anANSIParams[0]);
-                        }
-                     }
-                     else /* if(num_params==0) */
-                     {
-                        ODScrnSetCursorPos(1, 1);
-                     }
-                     break;
-
-                  case 'J':
-                     if(btNumParams >= 1 && anANSIParams[0] == 2)
-                     {
-                        /* Clear entire screen. */
-                        ODScrnClear();
-                     }
-                     else if(btNumParams == 0 || anANSIParams[0] == 0)
-                     {
-                        /* Not supported - Clears from cursor to end of */
-                        /* screen.                                      */
-                     }
-                     else if(btNumParams>=1 && anANSIParams[0]==1)
-                     {
-                        /* Not supported - Clears from beginning of screen to */
-                        /* cursor.                                            */
-                     }
-                     break;
-
-                  case 'K':
-                     if(btNumParams == 0 || anANSIParams[0] == 0)
-                     {
-                        /* Clear to end of line. */
-                        ODScrnClearToEndOfLine();
-                     }
-                     else if(btNumParams >= 1 && anANSIParams[0] == 1)
-                     {
-                        /* Not supported - should clear to beginning of line. */
-                     }
-                     else if(btNumParams >= 1 && anANSIParams[0] == 2)
-                     {
-                        /* Not supported - should clear entire line. */
-                     }
-                     break;
-
-                  case 'm':
-                     for(nTemp = 0; nTemp < btNumParams; ++nTemp)
-                     {
-                        if(anANSIParams[nTemp] == 0)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute = 0x07));
-                        }
-                        else if(anANSIParams[nTemp] == 1)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = TextInfo.attribute | 0x08));
-                        }
-                        else if(anANSIParams[nTemp] == 2)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = TextInfo.attribute & (~0x08)));
-                        }
-                        else if(anANSIParams[nTemp] == 4)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = (TextInfo.attribute & 0xf8) | (1)));
-                        }
-                        else if(anANSIParams[nTemp] == 5)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = TextInfo.attribute | 0x80));
-                        }
-                        else if(anANSIParams[nTemp] == 7)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = (TextInfo.attribute << 4)
-                              | (TextInfo.attribute >> 4)));
-                        }
-                        else if(anANSIParams[nTemp] == 8)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = (TextInfo.attribute & 0xf0)
-                              | ((TextInfo.attribute >> 4) & 0x07)));
-                        }
-                        else if(anANSIParams[nTemp] >= 30
-                           && anANSIParams[nTemp] <= 37)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                              = TextInfo.attribute
-                              = (TextInfo.attribute & 0xf8)
-                              + abtANSIToPCColorTable[
-                              (anANSIParams[nTemp] - 30)]));
-                        }
-                        else if(anANSIParams[nTemp] >= 40
-                           && anANSIParams[nTemp]<=47)
-                        {
-                           ODScrnSetAttribute((BYTE)(od_control.od_cur_attrib
-                            = TextInfo.attribute
-                            = (TextInfo.attribute & 0x8f)
-                            + (abtANSIToPCColorTable[
-                            anANSIParams[nTemp] - 40] << 4)));
-                        }
-                     }
-                     break;
-
-                  case 's':
-                     btSavedColumn = TextInfo.curx;
-                     btSavedRow = TextInfo.cury;
-                     break;
-
-                  case 'u':
-                     ODScrnSetCursorPos(btSavedColumn, btSavedRow);
-                     break;
-
-                  case '@':
-                     /* Not supported - inserts spaces at cursor. */
-                     break;
-
-                  case 'P':
-                     /* Not supported - deletes characters at cursor. */
-                     break;
-
-                  case 'L':
-                     /* Not supported - inserts lines at cursor. */
-                     break;
-
-                  case 'M':
-                     /* Not supported - deletes lines at cursor. */
-                     break;
-
-                  case 'r':
-                     /* Not supported - sets scrolling zone - 1st param is */
-                     /* top row, 2nd param is bottom row. Cursor may go    */
-                     /* outside zone, but no scrolling occurs there.       */
-                     /* Also resets cursor to row 1, column 1.             */
-                     /* If only one param, bottom row is bottom of screen. */
-                     break;
-
-                  case 'h':
-                     if(btNumParams >= 1 && anANSIParams[0] == 4)
-                     {
-                        /* Not suppored - turn insert mode on. */
-                     }
-                     else if(btNumParams >= 1 && anANSIParams[0] == -2)
-                     {
-                        /* Home cursor. */
-                        ODScrnSetCursorPos(1, 1);
-                     }
-                     break;
-
-                  case 'l':
-                     if(btNumParams >= 1 && anANSIParams[0] == 4)
-                     {
-                        /* Not suppored - turn insert mode off. */
-                     }
-                     break;
-
-                  case 'E':
-                     /* Not supported - repeat CRLF specified # of times. */
-                     break;
-
-                  case 'F':
-                     /* Not supported - repeat reverse CRLF specified # */
-                     /* of times. Also not suppored ESC M - reverse     */
-                     /* linefeed, ESC D - LF, ESC E - CRLF              */
-                     break;
-               }
-            }
-      }
-
-      if(bEchoThisChar && od_control.baud != 0)
-      {
-         ODComSendByte(hSerialPort, chCurrent);
-      }
-
-      ++pszBuffer;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODEmulateFillArea()                                 *** PRIVATE FUNCTION ***
- *
- * Fills an area of the local screen with the specified character, in the
- * current display color.
- *
- * Parameters: btLeft       - The left column of the area to fill.
- *
- *             btTop        - The top row of the area to fill.
- *
- *             btRight      - The right column of the area to fill.
- *
- *             btBottom     - The bottom row of the area to fill.
- *
- *             chToFillWith - Character to fill in the specified area with.
- *
- *     Return: void
- */
-static void ODEmulateFillArea(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom, char chToFillWith)
-{
-   BYTE btCount;
-   BYTE btLast;
-   static char szTemp[81];
-   static tODScrnTextInfo TextInfo;
-
-   ODScrnGetTextInfo(&TextInfo);
-
-   btLast = btRight - btLeft;
-
-   for(btCount=0; btCount <= btLast; ++btCount)
-   {
-      szTemp[btCount] = chToFillWith;
-   }
-   szTemp[btCount] = 0;
-
-   ODScrnEnableScrolling(FALSE);
-
-   for(btCount = btTop; btCount <= btBottom; ++btCount)
-   {
-      ODScrnSetCursorPos(btLeft, btCount);
-      ODScrnDisplayString(szTemp);
-   }
-
-   ODScrnSetCursorPos(TextInfo.curx, TextInfo.cury);
-
-   ODScrnEnableScrolling(TRUE);
-}
diff --git a/src/odoors/ODFrame.c b/src/odoors/ODFrame.c
deleted file mode 100644
index fb82bfe59626d85094149d6dbe4a9f814905ffc0..0000000000000000000000000000000000000000
--- a/src/odoors/ODFrame.c
+++ /dev/null
@@ -1,1758 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODFrame.c
- *
- * Description: Implements the OpenDoors frame window which provides the
- *              menu, toolbar, and status bar. The frame window's client
- *              area contains the display window which shows the door's
- *              output as the remote user would see it. This file should
- *              not be built into non-Windows versions of OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Aug 20, 1995  6.00  BP   Created.
- *              Dec 20, 1995  6.00  BP   Remember toolbar & statusbar settings.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Jan 20, 1996  6.00  BP   Made ODFrameCenter...() shared.
- *              Jan 21, 1996  6.00  BP   Added ODScrnShowMessage() and related.
- *              Feb 17, 1996  6.00  BP   Add ...Accelerator() return value.
- *              Feb 17, 1996  6.00  BP   Pass WM_MENUSELECT to DefWindowProc().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 21, 1996  6.00  BP   Fixed user keyboard off command.
- *              Feb 22, 1996  6.00  BP   Allow escape to close Help About box.
- *              Feb 23, 1996  6.00  BP   Properly update when toolbar turned on
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 14, 1996  6.10  BP   Added configuration menu option.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-
-#include "windows.h"
-#include "commctrl.h"
-
-#include "OpenDoor.h"
-#include "ODRes.h"
-#include "ODFrame.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODKrnl.h"
-
-#ifdef ODPLAT_WIN32
-
-/* Frame window information structure. */
-typedef struct
-{
-   HINSTANCE hInstance;
-   BOOL bToolbarOn;
-   HWND hwndToolbar;
-   BOOL bStatusBarOn;
-   HWND hwndStatusBar;
-   HWND hwndTimeEdit;
-   HWND hwndTimeUpDown;
-   BOOL bWantsChatIndicator;
-   HACCEL hacclFrameCommands;
-   HWND hwndMessageWindow;
-   char *pszCurrentMessage;
-   int nCurrentMessageFlags;
-} tODFrameWindowInfo;
-
-/* Toolbar button information. */
-TBBUTTON atbButtons[] =
-{
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {0,   ID_DOOR_CHATMODE,          TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {1,   ID_DOOR_USERKEYBOARDOFF,   TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-   {2,   ID_DOOR_SYSOPNEXT,         TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-   {0,   0,                         TBSTATE_ENABLED,  TBSTYLE_SEP,    0, 0},
-   {3,   ID_DOOR_HANGUP,            TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-   {4,   ID_DOOR_LOCKOUT,           TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-   {5,   ID_DOOR_EXIT,              TBSTATE_ENABLED,  TBSTYLE_BUTTON, 0, 0},
-};
-
-/* Other toolbar settings. */
-#define NUM_TOOLBAR_BITMAPS   6
-#define MIN_TIME              0
-#define MAX_TIME              1440
-
-/* Pointer to default edit box window procedure. */
-WNDPROC pfnDefEditProc = NULL;
-WNDPROC pfnDefToolbarProc = NULL;
-
-/* Global frame window handle. */
-static HWND hwndCurrentFrame;
-
-/* Status bar settings. */
-#define NUM_STATUS_PARTS      2
-#define NODE_PART_WIDTH       65
-
-/* Child window IDs. */
-#define ID_TOOLBAR            1000
-#define ID_TIME_EDIT          1001
-#define ID_TIME_UPDOWN        1002
-#define ID_STATUSBAR          1003
-
-
-/* Private function prototypes. */
-static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
-   tODFrameWindowInfo *pWindowInfo);
-static void ODFrameDestroyToolbar(HWND hwndToolbar,
-   tODFrameWindowInfo *pWindowInfo);
-static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance);
-static void ODFrameSetMainStatusText(HWND hwndStatusBar);
-static void ODFrameDestroyStatusBar(HWND hwndStatusBar);
-static void ODFrameSizeStatusBar(HWND hwndStatusBar);
-LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo);
-LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-static HWND ODFrameCreateWindow(HANDLE hInstance);
-static void ODFrameDestroyWindow(HWND hwndFrame);
-static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame);
-DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam);
-BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameCreateWindow()                               *** PRIVATE FUNCTION ***
- *
- * Creates the OpenDoors frame window and its children.
- *
- * Parameters: hInstance   - Handle to application instance.
- *
- *     Return: A handle to the newly created window, or NULL on failure.
- */
-static HWND ODFrameCreateWindow(HANDLE hInstance)
-{
-   HWND hwndFrameWindow = NULL;
-   WNDCLASS wcFrameWindow;
-   tODFrameWindowInfo *pWindowInfo = NULL;
-   tODThreadHandle hScreenThread;
-   HKEY hOpenDoorsKey;
-   DWORD cbData;
-
-   /* Register the main frame window's window class. */
-   memset(&wcFrameWindow, 0, sizeof(wcFrameWindow));
-   wcFrameWindow.style = CS_HREDRAW | CS_VREDRAW;
-   wcFrameWindow.lpfnWndProc = ODFrameWindowProc;
-   wcFrameWindow.cbClsExtra = 0;
-   wcFrameWindow.cbWndExtra = 0;
-   wcFrameWindow.hInstance = hInstance;
-   if(od_control.od_app_icon != NULL)
-   {
-      wcFrameWindow.hIcon = od_control.od_app_icon;
-   }
-   else
-   {
-      wcFrameWindow.hIcon
-         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_OPENDOORS));
-   }
-   wcFrameWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
-   wcFrameWindow.hbrBackground = NULL;
-   wcFrameWindow.lpszMenuName = MAKEINTRESOURCE(IDR_FRAME_MENU);
-   wcFrameWindow.lpszClassName = "ODFrame";
-
-   RegisterClass(&wcFrameWindow);
-
-   /* Setup window information structure. */
-   pWindowInfo = malloc(sizeof(tODFrameWindowInfo));
-   if(!pWindowInfo)
-   {
-      return(NULL);
-   }
-   pWindowInfo->hInstance = hInstance;
-   pWindowInfo->hwndTimeEdit = NULL;
-   pWindowInfo->hwndTimeUpDown = NULL;
-   pWindowInfo->bWantsChatIndicator = FALSE;
-   pWindowInfo->hwndMessageWindow = NULL;
-
-   /* Determine whether or not the toolbar and status bar are on. */
-   RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
-      &hOpenDoorsKey);
-
-   cbData = sizeof(pWindowInfo->bToolbarOn);
-   if(RegQueryValueEx(hOpenDoorsKey, "ToolBarOn", NULL, NULL, 
-      (LPBYTE)&pWindowInfo->bToolbarOn,
-      &cbData) != ERROR_SUCCESS)
-   {
-      pWindowInfo->bToolbarOn = TRUE;
-      RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
-         (LPBYTE)&pWindowInfo->bToolbarOn,
-         sizeof(pWindowInfo->bToolbarOn));
-   }
-
-   cbData = sizeof(pWindowInfo->bStatusBarOn);
-   if(RegQueryValueEx(hOpenDoorsKey, "StatusBarOn", NULL, NULL, 
-      (LPBYTE)&pWindowInfo->bStatusBarOn,
-      &cbData) != ERROR_SUCCESS)
-   {
-      pWindowInfo->bStatusBarOn = TRUE;
-      RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
-         (LPBYTE)&pWindowInfo->bStatusBarOn,
-         sizeof(pWindowInfo->bStatusBarOn));
-   }
-
-   RegCloseKey(hOpenDoorsKey);
-
-   /* Create the main frame window. */
-   if((hwndFrameWindow = CreateWindowEx(
-      0L,
-      wcFrameWindow.lpszClassName,
-      od_control.od_prog_name,
-      WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX,
-      CW_USEDEFAULT,
-      0,
-      0,
-      0,
-      NULL,
-      NULL,
-      hInstance,
-      pWindowInfo)) == NULL)
-   {
-      /* On window creation failure, return NULL. */
-      return(NULL);
-   }
-
-   /* Load accelerator table for the  frame window. */
-   pWindowInfo->hacclFrameCommands
-      = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_FRAME));
-
-   /* Create the OpenDoors toolbar. On failure, we will continue anyhow. */
-   if(pWindowInfo->bToolbarOn)
-   {
-      pWindowInfo->hwndToolbar =
-         ODFrameCreateToolbar(hwndFrameWindow, hInstance, pWindowInfo);
-   }
-
-   /* Create the status bar. On failure, we will continue anyhow. */
-   if(pWindowInfo->bStatusBarOn)
-   {
-      pWindowInfo->hwndStatusBar =
-         ODFrameCreateStatusBar(hwndFrameWindow, hInstance);
-   }
-
-   /* Updates state of the window from whether or not the user has */
-   /* requested a chat with the sysop.                             */
-   ODFrameUpdateWantChat();
-
-   /* Create the local screen window, which occupies the remaining */
-   /* client area of the frame window.                             */
-   ODScrnStartWindow(hInstance, &hScreenThread, hwndFrameWindow);
-
-   return(hwndFrameWindow);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameCreateToolbar()                              *** PRIVATE FUNCTION ***
- *
- * Creates the OpenDoors toolbar.
- *
- * Parameters: hwndParent  - Handle to the parent window.
- *
- *             hInstance   - Handle to the executable file's module instance.
- *
- *             pWindowInfo - Pointer to frame window information structure.
- *
- *     Return: A handle to the toolbar on success, or NULL on failure.
- */
-static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
-   tODFrameWindowInfo *pWindowInfo)
-{
-   HWND hwndToolbar = NULL;
-   HWND hwndTimeEdit = NULL;
-   HWND hwndTimeUpDown = NULL;
-   HWND hwndToolTip;
-   BOOL bSuccess = FALSE;
-
-   ASSERT(hwndParent != NULL);
-   ASSERT(hInstance != NULL);
-   ASSERT(pWindowInfo != NULL);
-
-   /* First, attempt to create the toolbar window. */
-   hwndToolbar = CreateToolbarEx(hwndParent,
-      WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,
-      ID_TOOLBAR, NUM_TOOLBAR_BITMAPS, hInstance, IDB_TOOLBAR,
-      atbButtons, DIM(atbButtons), 0, 0, 0, 0, sizeof(TBBUTTON));
-
-   if(hwndToolbar == NULL)
-   {
-      goto CleanUp;
-   }
-
-   /* Change the window proc for the toolbar window to our own, keeping a */
-   /* pointer to the original window proc.                                */
-   pfnDefToolbarProc = (WNDPROC)GetWindowLong(hwndToolbar, GWL_WNDPROC);
-   SetWindowLong(hwndToolbar, GWL_WNDPROC, (LONG)ODFrameToolbarProc);
-
-   /* Next, create an edit control on the toolbar, to allow the user's */
-   /* time remaining online to be adjusted.                            */
-   hwndTimeEdit = CreateWindowEx(WS_EX_STATICEDGE, "EDIT", "",
-      WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT,
-      0, 0, 70, 22, hwndToolbar, (HMENU)ID_TIME_EDIT, hInstance, NULL);
-
-   if(hwndTimeEdit == NULL)
-   {
-      goto CleanUp;
-   }
-
-   /* Now that the edit window has the appropriate parent, we set its */
-   /* position accordingly. */
-   SetWindowPos(hwndTimeEdit, NULL, 2, 2, 0, 0,
-      SWP_NOZORDER | SWP_NOSIZE);
-
-   /* Set font of the edit control to be the standard non-bold font. */
-   SendMessage(hwndTimeEdit, WM_SETFONT,
-      (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0));
-
-   /* Change the window proc for the edit window to our own, keeping a */
-   /* pointer to the original window proc. */
-   pfnDefEditProc = (WNDPROC)GetWindowLong(hwndTimeEdit, GWL_WNDPROC);
-   SetWindowLong(hwndTimeEdit, GWL_WNDPROC, (LONG)ODFrameTimeEditProc);
-
-   /* Add the time edit control to the tooltip control. */
-
-   /* Obtain a handle to the toolbar's tooltip control. */
-   hwndToolTip = (HWND)SendMessage(hwndToolbar, TB_GETTOOLTIPS, 0, 0);
-   if(hwndToolTip)
-   {
-      TOOLINFO ToolInfo;
-
-      /* Fill TOOLINFO structure. */
-      ToolInfo.cbSize = sizeof(ToolInfo);
-      ToolInfo.uFlags = TTF_IDISHWND | TTF_CENTERTIP;
-      ToolInfo.lpszText = "User's Time Remaining";
-      ToolInfo.hwnd = hwndParent;
-      ToolInfo.uId = (UINT)hwndTimeEdit;
-      ToolInfo.hinst = hInstance;
-
-      /* Setup tooltips for the time edit box. */
-      SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ToolInfo);
-   }
-
-   /* Now, we create an up-down control to buddy with the edit control. */
-   hwndTimeUpDown = CreateWindowEx(0L, UPDOWN_CLASS, "",
-      WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ARROWKEYS |
-      UDS_ALIGNRIGHT, 0, 0, 8, 8,
-         hwndToolbar, (HMENU)ID_TIME_UPDOWN, hInstance, NULL);
-
-   if(hwndTimeUpDown == NULL)
-   {
-      goto CleanUp;
-   }
-
-   /* Set the up-down control's buddy control to be the edit control that */
-   /* we just created.                                                    */
-   SendMessage(hwndTimeUpDown, UDM_SETBUDDY, (LONG)hwndTimeEdit, 0L);
-
-   /* Set the valid range of values for the edit control. */
-   SendMessage(hwndTimeUpDown, UDM_SETRANGE, 0L, MAKELONG(MAX_TIME, MIN_TIME));
-
-   /* Store handles to time limit edit and up-down controls. */
-   pWindowInfo->hwndTimeEdit = hwndTimeEdit;
-   pWindowInfo->hwndTimeUpDown = hwndTimeUpDown;
-
-   /* Next, we set the default text for the edit control. */
-   ODFrameUpdateTimeLeft(pWindowInfo);
-
-   /* Return with success. */
-   bSuccess = TRUE;
-
-CleanUp:
-   if(!bSuccess)
-   {
-      /* On failure, free any allocated resources. */
-      if(hwndTimeUpDown != NULL)
-      {
-         DestroyWindow(hwndTimeUpDown);
-      }
-      if(hwndTimeEdit != NULL)
-      {
-         DestroyWindow(hwndTimeUpDown);
-      }
-      if(hwndToolbar != NULL)
-      {
-         DestroyWindow(hwndToolbar);
-         hwndToolbar = NULL;
-      }
-   }
-
-   /* Return handle to newly created toolbar, or NULL on failure. */
-   return(hwndToolbar);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameDestroyToolbar()                             *** PRIVATE FUNCTION ***
- *
- * Destroys the OpenDoors toolbar.
- *
- * Parameters: hwndToolbar - Handle to previously created toolbar.
- *
- *             pWindowInfo - Pointer to frame window information structure.
- *
- *     Return: void.
- */
-static void ODFrameDestroyToolbar(HWND hwndToolbar,
-   tODFrameWindowInfo *pWindowInfo)
-{
-   ASSERT(hwndToolbar != NULL);
-   ASSERT(pWindowInfo != NULL);
-
-   /* Destroy the time up-down control, and NULL its handle in the frame */
-   /* window information structure.                                      */
-   DestroyWindow(pWindowInfo->hwndTimeUpDown);
-   pWindowInfo->hwndTimeUpDown = NULL;
-
-   /* Destroy the time edit control, and NULL its handle in the frame window */
-   /* information structure.                                                 */
-   DestroyWindow(pWindowInfo->hwndTimeEdit);
-   pWindowInfo->hwndTimeEdit = NULL;
-
-   /* Now, destroy the toolbar itself. */
-   DestroyWindow(hwndToolbar);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameCreateStatusBar()                            *** PRIVATE FUNCTION ***
- *
- * Creates the OpenDoors status bar.
- *
- * Parameters: hwndParent  - Handle to the parent window.
- *
- *             hInstance   - Handle to the executable file's module instance.
- *
- *     Return: A handle to the status bar on success, or NULL on failure.
- */
-static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance)
-{
-   HWND hwndStatusBar = NULL;
-   char szStatusText[20];
-
-   ASSERT(hwndParent != NULL);
-
-   /* Create the status bar window. */
-   hwndStatusBar = CreateWindowEx(0L, STATUSCLASSNAME, "",
-      WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
-      hwndParent, (HMENU)ID_STATUSBAR, hInstance, NULL);
-
-   if(hwndStatusBar == NULL)
-   {
-      return(NULL);
-   }
-
-   /* Set the size of the status bar parts from the size of the frame */
-   /* window.                                                         */
-   ODFrameSizeStatusBar(hwndStatusBar);
-
-   /* Add the user's name, location and connection info string. */
-   ODFrameSetMainStatusText(hwndStatusBar);
-
-   /* Add the node number string. */
-   sprintf(szStatusText, "Node %d", od_control.od_node);
-   SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)1, (LPARAM)szStatusText);
-
-   return(hwndStatusBar);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameSetMainStatusText()                          *** PRIVATE FUNCTION ***
- *
- * Updates the text that is displayed in the main pane of the status bar.
- *
- * Parameters: hwndStatusBar - Handle to the status bar.
- *
- *     Return: void.
- */
-static void ODFrameSetMainStatusText(HWND hwndStatusBar)
-{
-   char szStatusText[160];
-
-   ASSERT(hwndStatusBar != NULL);
-
-   /* Generate base status bar text, with the user's name, location and */
-   /* connection information.                                           */
-   if(od_control.baud == 0)
-   {
-      sprintf(szStatusText, "%s of %s in local mode",
-         od_control.user_name,
-         od_control.user_location);
-   }
-   else
-   {
-      sprintf(szStatusText, "%s of %s at %ldbps",
-         od_control.user_name,
-         od_control.user_location,
-         od_control.od_connect_speed);
-   }
-
-   /* If the user has paged the sysop, then include reason for chat if */
-   /* it is available.                                                 */
-   if(od_control.user_wantchat && strlen(od_control.user_reasonforchat) > 0)
-   {
-      strcat(szStatusText, " (Reason for chat: \"");
-      strcat(szStatusText, od_control.user_reasonforchat);
-      strcat(szStatusText, "\")");
-   }
-
-   /* Update status bar text in the main status bar pane with the newly */
-   /* generated string.                                                 */
-   SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameDestroyStatusBar()                           *** PRIVATE FUNCTION ***
- *
- * Destroys the OpenDoors status bar.
- *
- * Parameters: hwndStatusBar    - Handle to previously created status bar.
- *
- *     Return: void.
- */
-static void ODFrameDestroyStatusBar(HWND hwndStatusBar)
-{
-   DestroyWindow(hwndStatusBar);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameSizeStatusBar()                              *** PRIVATE FUNCTION ***
- *
- * Creates the OpenDoors status bar.
- *
- * Parameters: hwndStatusBar  - Handle to existing status bar window.
- *
- *     Return: void.
- */
-static void ODFrameSizeStatusBar(HWND hwndStatusBar)
-{
-   int anWidths[NUM_STATUS_PARTS];
-   int nStatusWidth;
-   RECT rcStatusBar;
-
-   /* Determine the total width of the status bar. */
-   GetWindowRect(hwndStatusBar, &rcStatusBar);
-   nStatusWidth = rcStatusBar.right - rcStatusBar.left;
-
-   /* Calculate the width of the parts from the total width. */
-   anWidths[0] = nStatusWidth - NODE_PART_WIDTH;
-   anWidths[1] = -1;
-
-   /* Update the status bar part settings. */
-   SendMessage(hwndStatusBar, SB_SETPARTS, NUM_STATUS_PARTS,
-      (LPARAM)anWidths);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameGetUsedClientAtTop()
- *
- * Determines height in pixels of the space used at the top of the
- * frame window's client area, by the toolbar, etc.
- *
- * Parameters: hwndFrame - Handle to the OpenDoors frame window.
- *
- *     Return: The height of the used space, in pixels.
- */
-INT ODFrameGetUsedClientAtTop(HWND hwndFrame)
-{
-   tODFrameWindowInfo *pWindowInfo;
-   RECT rcWindow;
-
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
-
-   if(!pWindowInfo->bToolbarOn) return(0);
-
-   GetWindowRect(pWindowInfo->hwndToolbar, &rcWindow);
-
-   return(rcWindow.bottom - rcWindow.top - 2);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameGetUsedClientAtBottom()
- *
- * Determines height in pixels of the space used at the bottom of the
- * frame window's client area, by the status bar, etc.
- *
- * Parameters: hwndFrame - Handle to the OpenDoors frame window.
- *
- *     Return: The height of the used space, in pixels.
- */
-INT ODFrameGetUsedClientAtBottom(HWND hwndFrame)
-{
-   tODFrameWindowInfo *pWindowInfo;
-   RECT rcWindow;
-
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
-
-   if(!pWindowInfo->bStatusBarOn) return(0);
-
-   GetWindowRect(pWindowInfo->hwndStatusBar, &rcWindow);
-
-   return(rcWindow.bottom - rcWindow.top - 1);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameWindowProc()                                 *** PRIVATE FUNCTION ***
- *
- * The OpenDoors frame window proceedure.
- *
- * Parameters: hwnd   - Handle to the OpenDoors frame window.
- *
- *             uMsg   - Specifies the message.
- *
- *             wParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *             lParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *     Return: The return value is the result of the message processing and
- *             depends on the message.
- */
-LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   tODFrameWindowInfo *pWindowInfo;
-
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwnd, GWL_USERDATA);
-
-   switch(uMsg)
-   {
-      case WM_CREATE:
-      {
-         /* At window creation time, store a pointer to the window */
-         /* information structure in window's user data.           */
-         CREATESTRUCT *pCreateStruct = (CREATESTRUCT *)lParam;
-         pWindowInfo = (tODFrameWindowInfo *)pCreateStruct->lpCreateParams;
-         SetWindowLong(hwnd, GWL_USERDATA, (LONG)pWindowInfo);
-
-         /* Update the enabled and checked states of frame window commands. */
-         ODFrameUpdateCmdUI();
-
-         /* If the client has not provided a help callback function, then */
-         /* remove the Contents item from the help menu.                  */
-         if(od_control.od_help_callback == NULL)
-         {
-            RemoveMenu(GetMenu(hwnd), ID_HELP_CONTENTS, MF_BYCOMMAND);
-         }
-
-         if(od_control.od_config_callback == NULL)
-         {
-            RemoveMenu(GetMenu(hwnd), ID_DOOR_CONFIG, MF_BYCOMMAND);
-         }
-         break;
-      }
-
-      case WM_CLOSE:
-         /* If door exit has been chosen, confirm with local user. */
-         if(MessageBox(hwnd,
-            "You are about to terminate this session and return the user to the BBS.\nDo you wish to proceed?",
-            od_control.od_prog_name,
-            MB_ICONQUESTION | MB_YESNO) == IDYES)
-         {
-            /* Normal door exit (drop to BBS) is implemented by the */
-            /* WM_DESTROY handler.                                  */
-            ODFrameDestroyWindow(hwnd);
-         }
-         break;
-
-      case WM_DESTROY:
-         /* If toolbar is on, then it must be destroyed when the frame */
-         /* window is destroyed.                                       */
-         if(pWindowInfo->bToolbarOn)
-         {
-            ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR), pWindowInfo);
-         }
-
-         /* If status bar is on, then it must be destroyed when the frame */
-         /* window is destroyed.                                          */
-         if(pWindowInfo->bStatusBarOn)
-         {
-            ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
-         }
-
-         /* Now, force OpenDoors to shutdown. */
-         ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_DROPTOBBS);
-
-         /* When the frame window is destroyed, it is the window proc's   */
-         /* responsiblity to deallocate the window information structure. */
-         free(pWindowInfo);
-         SetWindowLong(hwnd, GWL_USERDATA, (LONG)NULL);
-
-         /* Reset current frame window handle. */
-         hwndCurrentFrame = NULL;
-         break;
-
-      case WM_SETFOCUS:
-         /* Whenver input focus is set to the frame window, pass the input */
-         /* focus on to the screen window, which fills most of our client  */
-         /* area.                                                          */
-         ODScrnSetFocusToWindow();
-         break;
-
-      case WM_TIMER:
-         /* If the window flash timer has elapsed, then flash the window. */
-         FlashWindow(hwnd, TRUE);
-         break;
-
-      case WM_COMMAND:
-         /* An OpenDoors-defined command has been selected, so switch on */
-         /* the command ID.                                              */
-         switch(LOWORD(wParam))
-         {
-            case ID_HELP_ABOUT:
-               /* Display the OpenDoors default about box. */
-               DialogBox(pWindowInfo->hInstance, MAKEINTRESOURCE(IDD_ABOUT),
-                  hwnd, ODFrameAboutDlgProc);
-               break;
-
-            case ID_HELP_CONTENTS:
-               /* Call the client's help callback function, if one was */
-               /* provided.                                            */
-               if(od_control.od_help_callback != NULL)
-               {
-                  (*od_control.od_help_callback)();
-               }
-               break;
-
-            case ID_DOOR_CONFIG:
-               if(od_control.od_config_callback != NULL)
-               {
-                  (*od_control.od_config_callback)();
-               }
-               break;
-
-            case ID_DOOR_EXIT:
-               /* On request for normal door exit (drop to BBS), just send  */
-               /* a close message to this window. This will prompt to       */
-               /* confirm exit, and then shutdown OpenDoors if appropriate. */
-               PostMessage(hwnd, WM_CLOSE, 0, 0L);
-               break;
-
-            case ID_DOOR_CHATMODE:
-               /* If chat mode is currently active, then end it. */
-               if(od_control.od_chat_active)
-               {
-                  ODKrnlEndChatMode();
-               }
-               /* If chat mode is not currently active, then start it. */
-               else
-               {
-                  ODKrnlStartChatThread(TRUE);
-               }
-               break;
-
-            case ID_DOOR_USERKEYBOARDOFF:
-               /* If user keyboard off command has been chosen, then toggle */
-               /* keyboard off mode on or off.                              */
-               od_control.od_user_keyboard_on
-                  = !od_control.od_user_keyboard_on;
-
-               /* Update the keyboard off menu item and toolbar button. */
-               CheckMenuItem(GetMenu(hwnd), ID_DOOR_USERKEYBOARDOFF,
-                  MF_BYCOMMAND | (od_control.od_user_keyboard_on
-                  ? MF_UNCHECKED : MF_CHECKED));
-               SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
-                  ID_DOOR_USERKEYBOARDOFF,
-                  MAKELONG(!od_control.od_user_keyboard_on, 0));
-               break;
-
-            case ID_DOOR_SYSOPNEXT:
-               /* If sysop next command has been chosen, then toggle the */
-               /* sysop next flag on or off.                             */
-               od_control.sysop_next = !od_control.sysop_next;
-
-               /* Update the sysop next menu item and toolbar button. */
-               CheckMenuItem(GetMenu(hwnd), ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
-                  (od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
-               SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
-                  ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
-               break;
-
-            case ID_DOOR_HANGUP:
-               /* If hangup command has been chosen, then confirm with the */
-               /* local user.                                              */
-               if(MessageBox(hwnd,
-                  "You are about to disconnect this user. Do you wish to proceed?",
-                  od_control.od_prog_name,
-                  MB_ICONQUESTION | MB_YESNO) == IDYES)
-               {
-                  ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
-               }
-               break;
-
-            case ID_DOOR_LOCKOUT:
-               /* If lockout command has been chosen, the confirm with the */
-               /* local user.                                              */
-               if(MessageBox(hwnd,
-                  "You are about to lock out this user. Do you wish to proceed?",
-                  od_control.od_prog_name,
-                  MB_ICONQUESTION | MB_YESNO) == IDYES)
-               {
-                  /* Set the user's access security level to 0. */
-                  od_control.user_security = 0;
-
-                  ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
-               }
-               break;
-
-            case ID_VIEW_TOOL_BAR:
-            {
-               HKEY hOpenDoorsKey;
-
-               /* If toolbar on/off command has been chosen ... */
-               if(pWindowInfo->bToolbarOn)
-               {
-                  /* If the toolbar is on, then turn it off. */
-                  ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR),
-                     pWindowInfo);
-                  pWindowInfo->bToolbarOn = FALSE;
-                  CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
-                     MF_BYCOMMAND | MF_UNCHECKED);
-               }
-               else
-               {
-                  /* If the toolbar is off, then turn it on. */
-                  pWindowInfo->hwndToolbar = ODFrameCreateToolbar(hwnd,
-                     pWindowInfo->hInstance, pWindowInfo);
-                  pWindowInfo->bToolbarOn = TRUE;
-                  CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
-                     MF_BYCOMMAND | MF_CHECKED);
-                  ODFrameUpdateCmdUI();
-               }
-
-               /* Adjust window sizes accordingly. */
-               ODScrnAdjustWindows();
-
-               /* Update the toolbar setting in the registry. */
-               RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
-                  &hOpenDoorsKey);
-               RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
-                  (LPBYTE)&pWindowInfo->bToolbarOn,
-                  sizeof(pWindowInfo->bToolbarOn));
-               RegCloseKey(hOpenDoorsKey);
-               break;
-            }
-
-            case ID_VIEW_STAT_BAR:
-            {
-               HKEY hOpenDoorsKey;
-
-               /* If the status bar on/off command has been chosen ... */
-               if(pWindowInfo->bStatusBarOn)
-               {
-                  /* If the status bar is on, then turn it off. */
-                  pWindowInfo->bStatusBarOn = FALSE;
-                  CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
-                     MF_BYCOMMAND | MF_UNCHECKED);
-                  ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
-               }
-               else
-               {
-                  /* If the status bar is off, then turn it on. */
-                  pWindowInfo->bStatusBarOn = TRUE;
-                  CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
-                     MF_BYCOMMAND | MF_CHECKED);
-                  pWindowInfo->hwndStatusBar =
-                     ODFrameCreateStatusBar(hwnd, pWindowInfo->hInstance);
-               }
-
-               /* Adjust window sizes accordingly. */
-               ODScrnAdjustWindows();
-
-               /* Update the status bar setting in the registry. */
-               RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
-                  &hOpenDoorsKey);
-               RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
-                  (LPBYTE)&pWindowInfo->bStatusBarOn,
-                  sizeof(pWindowInfo->bStatusBarOn));
-               RegCloseKey(hOpenDoorsKey);
-               break;
-            }
-
-            case ID_USER_ADDONEMINUTE:
-               /* If add one minute command has been chosen, then        */
-               /* increment the user's time, up to the maximum allowable */
-               /* time.                                                  */
-               if(od_control.user_timelimit < MAX_TIME)
-               {
-                  od_control.user_timelimit++;
-                  ODFrameUpdateTimeLeft(pWindowInfo);
-               }
-               break;
-
-            case ID_USER_ADDFIVEMINUTES:
-               /* If add five minutes command has been chosen, then */
-               /* adjust the user's time accordingly.               */
-               od_control.user_timelimit =
-                  MIN(od_control.user_timelimit + 5, MAX_TIME);
-               ODFrameUpdateTimeLeft(pWindowInfo);
-               break;
-
-            case ID_USER_SUBTRACTONEMINUTE:
-               /* If subtract one minute command has been chosen, then */
-               /* adjust the user's time accordingly.                  */
-               if(od_control.user_timelimit > MIN_TIME)
-               {
-                  od_control.user_timelimit--;
-                  ODFrameUpdateTimeLeft(pWindowInfo);
-               }
-               break;
-
-            case ID_USER_SUBTRACTFIVEMINUTES:
-               /* If the subtract five mintues command has been chosen, */
-               /* then adjust the user's time accordingly.              */
-               od_control.user_timelimit =
-                  MAX(od_control.user_timelimit - 5, MIN_TIME);
-               ODFrameUpdateTimeLeft(pWindowInfo);
-               break;
-
-            case ID_USER_INACTIVITYTIMER:
-               /* If the user inactivity timer command has been chosen, */
-               /* then toggle the timer on or off.                      */
-               od_control.od_disable_inactivity =
-                  !od_control.od_disable_inactivity;
-               CheckMenuItem(GetMenu(hwnd), ID_USER_INACTIVITYTIMER,
-                  MF_BYCOMMAND | (od_control.od_disable_inactivity ?
-                  MF_UNCHECKED : MF_CHECKED));
-               break;
-
-            case ID_TIME_EDIT:
-            {
-               /* If the user's time remaining has been directly edited, */
-               /* then adjust the time limit accordingly.                */
-               if(HIWORD(wParam) == EN_CHANGE)
-               {
-                  char szTimeText[40];
-                  GetWindowText((HWND)lParam, szTimeText, sizeof(szTimeText));
-                  od_control.user_timelimit = atoi(szTimeText);
-
-                  /* Do not allow the time limit to fall outside of the */
-                  /* valid range.                                       */
-                  od_control.user_timelimit =
-                     MAX(MIN_TIME, od_control.user_timelimit);
-                  od_control.user_timelimit =
-                     MIN(MAX_TIME, od_control.user_timelimit);
-
-                  /* Update the position of the up-down control. */
-                  SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
-                     (LPARAM)MAKELONG(od_control.user_timelimit, 0));
-               }
-            }
-
-            default:
-               return(TRUE);
-         }
-         return(FALSE);
-
-      case WM_NOTIFY:
-         /* A control parent notification message has been sent. */
-         switch(((LPNMHDR)lParam)->code)
-         {
-            case TTN_NEEDTEXT:
-            {
-               /* This is the message from the tool tip control, requesting */
-               /* the appropriate string to display for the current toolbar */
-               /* item.                                                     */
-               LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT)lParam;
-               switch(lpToolTipText->hdr.idFrom)
-               {
-                  case ID_DOOR_EXIT:
-                     lpToolTipText->lpszText = "Exit To BBS";
-                     break;
-                  case ID_DOOR_CHATMODE:
-                     lpToolTipText->lpszText = "Chat Mode";
-                     break;
-                  case ID_DOOR_USERKEYBOARDOFF:
-                     lpToolTipText->lpszText = "User Keyboard Off";
-                     break;
-                  case ID_DOOR_SYSOPNEXT:
-                     lpToolTipText->lpszText = "Sysop Next";
-                     break;
-                  case ID_DOOR_HANGUP:
-                     lpToolTipText->lpszText = "Hangup";
-                     break;
-                  case ID_DOOR_LOCKOUT:
-                     lpToolTipText->lpszText = "Lockout";
-                     break;
-               }
-               break;
-            }
-         }
-         break;
-
-      case WM_VSCROLL:
-         /* A scrolling action has taken place. */
-
-         /* If it is the time limit up-down control that has scrolled. */
-         if((HWND)lParam == pWindowInfo->hwndTimeUpDown)
-         {
-            int nPos = HIWORD(wParam);
-
-            /* Adjust the user's time limit. */
-            od_control.user_timelimit = MAX(MIN(nPos, MAX_TIME), MIN_TIME);
-
-            /* Update the time left displayed in the edit box. */
-            ODFrameUpdateTimeLeft(pWindowInfo);
-         }
-         break;
-
-      case WM_SIZE:
-         /* The OpenDoors frame window has been resized, so its contents */
-         /* must now be resized accordingly.                             */
-
-         /* Pass the message on to the status bar window, so that it will */
-         /* automatically adjust its own position and overall size.       */
-         SendMessage(GetDlgItem(hwnd, ID_STATUSBAR), WM_SIZE, wParam, lParam);
-
-         /* Now, adjust the size of each part of the status bar. */
-         ODFrameSizeStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
-
-         /* Pass the message on to the toolbar, so that it will resize */
-         /* iteself.                                                   */
-         SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), WM_SIZE, wParam, lParam);
-         break;
-
-      case WM_MENUSELECT:
-         /* If the user has selected an item on the menu, then we should */
-         /* update the status bar accordingly.                           */
-         if(HIWORD(wParam) == 0xFFFF)
-         {
-            /* If menu is being exited, then turn off the status bar simple */
-            /* mode.                                                        */
-            HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
-
-            SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)FALSE, 0L);
-         }
-         else
-         {
-            char szCommandString[160] = "";
-            HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
-
-            /* A new menu item is being selected. */
-
-            /* If this item is on the system menu, then provide the strings */
-            /* for any of those menu items.                                 */
-            if(HIWORD(wParam) & MF_SYSMENU)
-            {
-               switch(LOWORD(wParam))
-               {
-                  case SC_SIZE:
-                     strcpy(szCommandString,
-                        "Resizes this window.");
-                     break;
-                  case SC_MOVE:
-                     strcpy(szCommandString,
-                        "Moves this window.");
-                     break;
-                  case SC_MINIMIZE:
-                     strcpy(szCommandString,
-                        "Collapses this window to an icon.");
-                     break;
-                  case SC_MAXIMIZE:
-                     strcpy(szCommandString,
-                        "Expands this window to fill the screen.");
-                     break;
-                  case SC_CLOSE:
-                     strcpy(szCommandString,
-                        "Closes this window, and returns the user to the BBS.");
-                     break;
-                  case SC_RESTORE:
-                     strcpy(szCommandString,
-                        "Restores this window to normal size.");
-                     break;
-                  case SC_TASKLIST:
-                     strcpy(szCommandString,
-                        "");
-                     break;
-               }
-            }
-            else
-            {
-               /* If this item is on the window menu provided by OpenDoors, */
-               /* then load the status bar string for this command ID.      */
-               LoadString(pWindowInfo->hInstance, LOWORD(wParam),
-                  szCommandString, sizeof(szCommandString));
-            }
-
-            /* Switch the status bar into simple (single-paned) mode. */
-            SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)TRUE, 0L);
-
-            /* Set the text for the status bar. */
-            SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)255 | SBT_NOBORDERS,
-               (LPARAM)szCommandString);
-         }
-         return(DefWindowProc(hwnd, uMsg, wParam, lParam));
-
-      case WM_SHOW_MESSAGE:
-         if(pWindowInfo->hwndMessageWindow == NULL)
-         {
-            pWindowInfo->pszCurrentMessage = (char *)lParam;
-            pWindowInfo->nCurrentMessageFlags = (int)wParam;
-
-            /* Create the message window. */
-            DialogBoxParam(pWindowInfo->hInstance,
-               MAKEINTRESOURCE(IDD_MESSAGE), hwnd, ODFrameMessageDlgProc,
-               (LPARAM)pWindowInfo);
-         }
-         break;
-
-      case WM_REMOVE_MESSAGE:
-         if(pWindowInfo->hwndMessageWindow != NULL)
-         {
-            PostMessage(pWindowInfo->hwndMessageWindow, WM_COMMAND,
-               MAKELONG(IDOK, 0), 0L);
-            pWindowInfo->hwndMessageWindow = NULL;
-         }
-         break;
-
-      default:
-         /* Pass messages that we don't explicitly handle on to the */
-         /* default window proc.                                    */
-         return(DefWindowProc(hwnd, uMsg, wParam, lParam));
-   }
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameUpdateCmdUI()
- *
- * Updates the enabled and checked state of OpenDoors commands that may change.
- *
- * Parameters: None.
- *
- *     Return: void.
- */
-void ODFrameUpdateCmdUI(void)
-{
-   HWND hwndFrame = hwndCurrentFrame;
-   HMENU hMenu = GetMenu(hwndFrame);
-   HWND hwndToolbar = GetDlgItem(hwndFrame, ID_TOOLBAR);
-   tODFrameWindowInfo *pWindowInfo;
-
-   if(hwndFrame == NULL) return;
-
-   /* Obtain window information structure. */
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
-   if(pWindowInfo == NULL) return;
-
-   /* Check or uncheck the toolbar and status bar menu items. */
-   CheckMenuItem(hMenu, ID_VIEW_TOOL_BAR, MF_BYCOMMAND |
-      (pWindowInfo->bToolbarOn ? MF_CHECKED : MF_UNCHECKED));
-   CheckMenuItem(hMenu, ID_VIEW_STAT_BAR, MF_BYCOMMAND |
-      (pWindowInfo->bStatusBarOn ? MF_CHECKED : MF_UNCHECKED));
-
-   /* Check or uncheck the inactivity timer menu item. */
-   CheckMenuItem(hMenu, ID_USER_INACTIVITYTIMER, MF_BYCOMMAND |
-      (od_control.od_disable_inactivity ? MF_UNCHECKED : MF_CHECKED));
-
-   /* Check or uncheck the sysop next menu item and toolbar button. */
-   CheckMenuItem(hMenu, ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
-      (od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
-   SendMessage(hwndToolbar, TB_CHECKBUTTON,
-      ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
-
-   /* Check or uncheck the keyboard off menu item and toolbar button. */
-   CheckMenuItem(hMenu, ID_DOOR_USERKEYBOARDOFF, MF_BYCOMMAND |
-      (od_control.od_user_keyboard_on ? MF_UNCHECKED : MF_CHECKED));
-   SendMessage(hwndToolbar, TB_CHECKBUTTON,
-      ID_DOOR_USERKEYBOARDOFF,
-      MAKELONG(!od_control.od_user_keyboard_on, 0));
-
-   /* Update the chat mode menu item and toolbar button. */
-   CheckMenuItem(hMenu, ID_DOOR_CHATMODE, MF_BYCOMMAND |
-      (od_control.od_chat_active ? MF_CHECKED : MF_UNCHECKED));
-   SendMessage(hwndToolbar, TB_CHECKBUTTON, ID_DOOR_CHATMODE,
-      MAKELONG(od_control.od_chat_active, 0));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameUpdateTimeDisplay()
- *
- * Updates the remaining time online that is displayed anywhere by the frame
- * window. Uses ODFrameUpdateTimeLeft().
- *
- * Parameters: None.
- *
- *     Return: void.
- */
-void ODFrameUpdateTimeDisplay(void)
-{
-   tODFrameWindowInfo *pWindowInfo;
-
-   /* If there is no current frame window, then return without doing */
-   /* anything.                                                      */
-   if(hwndCurrentFrame == NULL) return;
-
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
-      GWL_USERDATA);
-   ASSERT(pWindowInfo != NULL);
-
-   ODFrameUpdateTimeLeft(pWindowInfo);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameUpdateWantChat()
- *
- * Updates the state of the flashing wants-chat indicator on the frame window.
- *
- * Parameters: None.
- *
- *     Return: void.
- */
-void ODFrameUpdateWantChat(void)
-{
-   tODFrameWindowInfo *pWindowInfo;
-
-   /* If there is no current frame window, then return without doing */
-   /* anything.                                                      */
-   if(hwndCurrentFrame == NULL) return;
-
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
-      GWL_USERDATA);
-   ASSERT(pWindowInfo != NULL);
-
-   /* If the status bar is on, then update the text displayed in the */
-   /* status bar's main pane.                                        */
-   if(pWindowInfo->bStatusBarOn)
-   {
-      ODFrameSetMainStatusText(pWindowInfo->hwndStatusBar);
-   }
-
-   /* Toggle the state of the wants-chat indicator, of needed. */
-   if(pWindowInfo->bWantsChatIndicator && !od_control.user_wantchat)
-   {
-      /* Restore original window text. */
-      SetWindowText(hwndCurrentFrame, od_control.od_prog_name);
-
-      /* Restore the window flash to its original state. */
-      FlashWindow(hwndCurrentFrame, FALSE);
-
-      /* Destroy the Windows timer. */
-      KillTimer(hwndCurrentFrame, 1);
-
-      /* Record that wants chat indicator is now off. */
-      pWindowInfo->bWantsChatIndicator = FALSE;
-   }
-   else if (!pWindowInfo->bWantsChatIndicator && od_control.user_wantchat)
-   {
-      /* Set window title to include the wants chat indicator. */
-      char szNewWindowTitle[sizeof(od_control.od_prog_name) + 20];
-      sprintf(szNewWindowTitle, "%s - User Wants Chat",
-         od_control.od_prog_name);
-      SetWindowText(hwndCurrentFrame, szNewWindowTitle);
-
-      /* Start the flashing the window. */
-      SetTimer(hwndCurrentFrame, 1,
-         GetCaretBlinkTime(), NULL);
-
-      /* Record that wants chat indicator is now on. */
-      pWindowInfo->bWantsChatIndicator = TRUE;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameDestroyWindow()                              *** PRIVATE FUNCTION ***
- *
- * Destroys the OpenDoors frame window and its children.
- *
- * Parameters: hwndFrame   - Handle to the window previously created by
- *                           ODFrameCreateWindow().
- *
- *     Return: void.
- */
-static void ODFrameDestroyWindow(HWND hwndFrame)
-{
-   tODFrameWindowInfo *pWindowInfo;
-
-   ASSERT(hwndFrame != NULL);
-
-   /* Obtain a pointer to the frame window information structure. */
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
-
-   /* At this point, deallocate the accelerator table. */
-   if(pWindowInfo->hacclFrameCommands != NULL)
-   {
-      DestroyAcceleratorTable(pWindowInfo->hacclFrameCommands);
-   }
-
-   /* Destroying the main frame window will automatically cause its */
-   /* children to be destroyed.                                     */
-   DestroyWindow(hwndFrame);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameToolbarProc()                                *** PRIVATE FUNCTION ***
- *
- * The toolbar window proceedure.
- *
- * Parameters: hwnd   - Handle to the toolbar window.
- *
- *             uMsg   - Specifies the message.
- *
- *             wParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *             lParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *     Return: The return value is the result of the message processing and
- *             depends on the message.
- */
-LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   switch(uMsg)
-   {
-      /* Forward needed message to the main frame window proceedure. */
-      case WM_VSCROLL:
-      case WM_COMMAND:
-         SendMessage(GetParent(hwnd), uMsg, wParam, lParam);
-         break;
-   }
-
-   /* Pass all messages on to the default toolbar window proceedure. */
-   return(CallWindowProc(pfnDefToolbarProc, hwnd, uMsg, wParam, lParam));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameUpdateTimeLeft()                             *** PRIVATE FUNCTION ***
- *
- * Updates the displayed time remaining from od_control.user_timelimit.
- *
- * Parameters: pWindowInfo - Pointer to frame window information structure.
- *
- *     Return: void.
- */
-static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo)
-{
-   char szTimeLeft[12];
-   RECT rcWindow;
-
-   if(pWindowInfo->hwndTimeEdit == NULL)
-   {
-      /* If the time limit edit control does not exist (i.e., if the       */
-      /* toolbar is not currently on), then there is nothing for us to do. */
-      return;
-   }
-
-   /* Generate the string to be displayed in the edit control. */
-   sprintf(szTimeLeft, "%d min.", od_control.user_timelimit);
-
-   /* Set the edit control's text to the new string. */
-   SetWindowText(pWindowInfo->hwndTimeEdit, szTimeLeft);
-
-   /* Force edit control to be redrawn. (Except for rightmost pixel */
-   /* column.)                                                      */
-   GetWindowRect(pWindowInfo->hwndTimeEdit, &rcWindow);
-   rcWindow.right--;
-   InvalidateRect(pWindowInfo->hwndTimeEdit, &rcWindow, TRUE);
-
-   /* Set the position of the up-down control to match. */
-   SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
-      (LPARAM)MAKELONG(od_control.user_timelimit, 0));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameTimeEditProc()                               *** PRIVATE FUNCTION ***
- *
- * The time edit window proceedure. Relays mouse messages from the edit box
- * to the tooltip control, and then passes all messages on to the standard
- * edit box window proceedure.
- *
- * Parameters: hwnd   - Handle to the time edit window.
- *
- *             uMsg   - Specifies the message.
- *
- *             wParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *             lParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *     Return: The return value is the result of the message processing and
- *             depends on the message.
- */
-LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   switch(uMsg)
-   {
-      case WM_MOUSEMOVE:
-      case WM_LBUTTONDOWN:
-      case WM_LBUTTONUP:
-      {
-         MSG msg;
-         HWND hwndToolTip;
-
-         /* Setup message structure. */
-         msg.lParam = lParam;
-         msg.wParam = wParam;
-         msg.message = uMsg;
-         msg.hwnd = hwnd;
-
-         /* Obtain handle to the tooltip window. */
-         hwndToolTip = (HWND)SendMessage(GetParent(hwnd), TB_GETTOOLTIPS,
-            0, 0);
-
-         /* Relay the message to the tooltip window. */
-         SendMessage(hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
-
-         break;
-      }
-   }
-
-   /* Pass all messages on to the default edit box window proceedure. */
-   return(CallWindowProc(pfnDefEditProc, hwnd, uMsg, wParam, lParam));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameAboutDlgProc()
- *
- * DialogProc for the OpenDoors default Help About dialog box.
- *
- * Parameters: hwndDlg  - Window handle to the dialog box.
- *
- *             uMsg     - Message ID.
- *
- *             wParam   - First message parameter.
- *
- *             lParam   - Second message parameter.
- *
- *     Return: TRUE if message is processed, FALSE otherwise.
- */
-BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   switch(uMsg)
-   {
-      case WM_INITDIALOG:
-         /* At dialog box creation time, update the text in the about      */
-         /* box with any information provided by the OpenDoors programmer. */
-
-         /* If a program name has been provided, then display it. */
-         if(strcmp(od_control.od_prog_name, OD_VER_SHORTNAME) != 0)
-         {
-            SetWindowText(GetDlgItem(hwndDlg, IDC_DOORNAME),
-               od_control.od_prog_name);
-         }
-
-         /* If copyright information has been provided, then display it. */
-         if(strlen(od_control.od_prog_copyright) > 0)
-         {
-            SetWindowText(GetDlgItem(hwndDlg, IDC_COPYRIGHT),
-               od_control.od_prog_copyright);
-         }
-
-         /* If program version information has been provided, then display */
-         /* it.                                                            */
-         if(strlen(od_control.od_prog_version) > 0)
-         {
-            SetWindowText(GetDlgItem(hwndDlg, IDC_VERSION),
-               od_control.od_prog_version);
-         }
-
-         /* Center the about dialog box in the area occupied by the */
-         /* main frame window.                                      */
-         ODFrameCenterWindowInParent(hwndDlg);
-
-         return(TRUE);
-
-      case WM_COMMAND:
-         /* If a command has been chosen. */
-         switch(LOWORD(wParam))
-         {
-            case IDCANCEL:
-            case IDOK:
-               /* If the OK button has been pressed, then close the dialog. */
-               EndDialog(hwndDlg, IDOK);
-               break;
-         }
-         return(TRUE);
-
-      default:
-         /* Otherwise, indicate that this message has not been processed. */
-         return(FALSE);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameCenterWindowInParent()                       *** PRIVATE FUNCTION ***
- *
- * Repositions the specified window so that it is centered in its parent.
- *
- * Parameters: hwndChild - The window to reposition.
- *
- *     Return: void.
- */
-void ODFrameCenterWindowInParent(HWND hwndChild)
-{
-   HWND hwndParent;
-   RECT rcParent;
-   RECT rcChild;
-   INT nChildWidth;
-   INT nChildHeight;
-   INT nParentWidth;
-   INT nParentHeight;
-
-   ASSERT(hwndChild != NULL);
-
-   /* Obtain a handle to the parent window. */
-   hwndParent = GetParent(hwndChild);
-   ASSERT(hwndParent != NULL);
-
-   /* Obtain the bounding boxes of both windows. */
-   GetWindowRect(hwndChild, &rcChild);
-   GetWindowRect(hwndParent, &rcParent);
-   
-   /* Determine the height and width of both windows. */
-   nChildWidth = rcChild.right - rcChild.left;
-   nChildHeight = rcChild.bottom - rcChild.top;
-   nParentWidth = rcParent.right - rcParent.left;
-   nParentHeight = rcParent.bottom - rcParent.top;
-
-   /* Move the child to the center of the parent. */
-   SetWindowPos(hwndChild, NULL,
-      rcParent.left + (nParentWidth - nChildWidth) / 2,
-      rcParent.top + (nParentHeight - nChildHeight) / 2,
-      0, 0, SWP_NOSIZE | SWP_NOZORDER);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameMessageLoop()                                *** PRIVATE FUNCTION ***
- *
- * Message loop for OpenDoors local UI thread (frame window handling).
- *
- * Parameters: hInstance   - Handle to current instance.
- *
- *             hwndFrame   - Handle to the frame window.
- *
- *     Return: void.
- */
-static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame)
-{
-   MSG msg;
-
-   ASSERT(hInstance != NULL);
-   ASSERT(hwndFrame != NULL);
-
-   /* Loop, fetching, translating and dispatching messages for any windows */
-   /* created by this thread. (GetMessage() blocks when no messages are    */
-   /* available.)                                                          */
-   while(GetMessage(&msg, NULL, 0, 0))
-   {
-      if(!ODFrameTranslateAccelerator(hwndFrame, &msg))
-      {
-         TranslateMessage(&msg);
-         DispatchMessage(&msg);
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameTranslateAccelerator()
- *
- * Translates WM_KEYDOWN or WM_SYSKEYDOWN messages to frame window commands,
- * if needed, based on the frame window's accelerator table.
- *
- * Parameters: hwndFrame  - Handle to the OpenDoors main frame window.
- *
- *             pMsg       - Pointer to the message that may require
- *                          translation.
- *
- *     Return: TRUE if message was translated, FALSE if not.
- */
-BOOL ODFrameTranslateAccelerator(HWND hwndFrame, LPMSG pMsg)
-{
-   tODFrameWindowInfo *pWindowInfo;
-
-   ASSERT(hwndFrame != NULL);
-   ASSERT(pMsg != NULL);
-
-   /* Obtain a pointer to the frame window information structure. */
-   pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
-   ASSERT(pWindowInfo != NULL);
-
-   /* Perform accelerator translation, based on the frame window's */
-   /* accelerator table, sending any resulting WM_COMMAND messages */
-   /* to the frame window.                                         */
-   return(TranslateAccelerator(hwndFrame, pWindowInfo->hacclFrameCommands,
-      pMsg) != 0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameThreadProc()                                 *** PRIVATE FUNCTION ***
- *
- * Function that execute the OpenDoors frame window thread.
- *
- * Parameters: pParam   - The thread parameter, which must be the handle to the
- *                        current application instance.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam)
-{
-   HWND hwndFrame;
-   HANDLE hInstance = (HANDLE)pParam;
-
-   /* Create the frame window. */
-   hwndFrame = ODFrameCreateWindow(hInstance);
-
-   if(hwndFrame == NULL)
-   {
-      return(FALSE);
-   }
-
-   /* Store a pointer to the frame window. */
-   hwndCurrentFrame = hwndFrame;
-
-   /* Loop, processing messages for the frame window. */
-   ODFrameMessageLoop(hInstance, hwndFrame);
-
-   /* Destroy the frame window. */
-   ODFrameDestroyWindow(hwndFrame);
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameStart()
- *
- * Function that starts up the frame window.
- *
- * Parameters: hInstance     - Handle to the current application instance.
- *
- *             phFrameThread - Pointer to the frame thread handle.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODFrameStart(HANDLE hInstance, tODThreadHandle *phFrameThread)
-{
-   return(ODThreadCreate(phFrameThread, ODFrameThreadProc,
-      (void *)hInstance));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFrameMessageDlgProc()
- *
- * Dialog proceedure for the OpenDoors message window.
- *
- * Parameters: hwndDlg  - Window handle to the dialog box.
- *
- *             uMsg     - Message ID.
- *
- *             wParam   - First message parameter.
- *
- *             lParam   - Second message parameter.
- *
- *     Return: TRUE if message is processed, FALSE otherwise.
- */
-BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   switch(uMsg)
-   {
-      case WM_INITDIALOG:
-      {
-         tODFrameWindowInfo *pWindowInfo;
-
-         pWindowInfo = (tODFrameWindowInfo *)lParam;
-
-         ASSERT(pWindowInfo != NULL);
-
-         pWindowInfo->hwndMessageWindow = hwndDlg;
-         
-         /* Set the message window title. */
-         SetWindowText(hwndDlg, od_control.od_prog_name);
-
-         /* Change the text displayed in the message window. */
-         SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE_TEXT1),
-            (char *)pWindowInfo->pszCurrentMessage);
-
-         /* Center window in parent window. */
-         ODFrameCenterWindowInParent(hwndDlg);
-
-         return(FALSE);
-      }
-
-      case WM_COMMAND:
-         /* If a command has been chosen. */
-         switch(LOWORD(wParam))
-         {
-            case IDOK:
-               /* If the OK button has been pressed, then close the dialog. */
-               EndDialog(hwndDlg, IDOK);
-               break;
-         }
-         return(TRUE);
-
-      default:
-         /* Indicate that this message has not been processed. */
-         return(FALSE);
-   }
-
-   return(TRUE);
-}
-
-
-#endif /* ODPLAT_WIN32 */
diff --git a/src/odoors/ODFrame.h b/src/odoors/ODFrame.h
deleted file mode 100644
index d10a41d1191d2643e0de9fe309521d0a4e26b846..0000000000000000000000000000000000000000
--- a/src/odoors/ODFrame.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODFrame.h
- *
- * Description: Defines the public interface to the OpenDoors frame window.
- *              This file is only applicable when building the Win32 version
- *              of OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Aug 20, 1995  6.00  BP   Created.
- *              Jan 20, 1996  6.00  BP   Made ODFrameCenter...() shared.
- *              Feb 17, 1996  6.00  BP   Add ...Accelerator() return value.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODFRAME
-#define _INC_ODFRAME
-
-#include "ODPlat.h"
-#include "ODGen.h"
-
-#ifdef ODPLAT_WIN32
-
-/* Public frame window functions. */
-tODResult ODFrameStart(HANDLE hInstance, tODThreadHandle *phFrameThread);
-INT ODFrameGetUsedClientAtTop(HWND hwndFrame);
-INT ODFrameGetUsedClientAtBottom(HWND hwndFrame);
-BOOL ODFrameTranslateAccelerator(HWND hwndFrame, LPMSG pMsg);
-void ODFrameUpdateCmdUI(void);
-void ODFrameUpdateTimeDisplay(void);
-void ODFrameUpdateWantChat(void);
-void ODFrameCenterWindowInParent(HWND hwndChild);
-
-/* User defined messages that are handled by the frame window. */
-#define WM_SHOW_MESSAGE             (WM_USER + 1)
-#define WM_REMOVE_MESSAGE           (WM_USER + 2)
-
-#endif /* ODPLAT_WIN32 */
-
-#endif /* _INC_ODFRAME */
diff --git a/src/odoors/ODGen.h b/src/odoors/ODGen.h
deleted file mode 100644
index e525674fed9017fa3fc2083b9662c209eb96b263..0000000000000000000000000000000000000000
--- a/src/odoors/ODGen.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODGen.h
- *
- * Description: Contains general definitions used throughout OpenDoors,
- *              including: - version information manifest constants
- *                         - debugging macros
- *                         - compiler-dependent definitions
- *                         - internally used macros
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   Created.
- *              Oct 20, 1994  6.00  BP   Added DIM macro.
- *              Dec 31, 1994  6.00  BP   Remove USEINLINE option.
- *              Dec 12, 1995  6.00  BP   Moved ODPLAT_??? to OpenDoor.h.
- *              Dec 19, 1995  6.00  BP   Implement ASSERT() for Win32.
- *              Jan 23, 1996  6.00  BP   Added OD_TEXTMODE.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 24, 1996  6.00  BP   Turn off OD_DIAGNOSTICS.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 03, 1996  6.10  BP   Moved ODFAR to OpenDoor.h.
- *              Oct 19, 2001  6.20  RS   Incremented version for socket support.
- */
-
-#ifndef _INC_ODGEN
-#define _INC_ODGEN
-
-
-/* PLATFORM-SPECIFIC DEFINITIONS. */
-
-/* DLL specific defintions. */
-#ifdef OD_DLL
-#ifdef ODPLAT_WIN32
-#define OD_DLL_NAME "ODOORS62"
-#endif /* ODPLAT_WIN32 */
-#endif /* OD_DLL */
-
-/* Mutlithreading specific definitions. */
-#ifdef ODPLAT_WIN32
-#define OD_MULTITHREADED
-#endif /* ODPLAT_WIN32 */
-
-/* Text mode specific definitions. */
-#ifdef ODPLAT_DOS
-#define OD_TEXTMODE
-#endif /* ODPLAT_DOS */
-
-/* DOS specific definitions. */
-#ifdef ODPLAT_DOS
-
-/* Keyword to flag ISR functions. */
-#define INTERRUPT interrupt
-
-/* Inline assembly keyword varies from compiler to compiler. */
-#ifdef _MSC_VER
-#define ASM __asm
-#else
-#define ASM asm
-#endif
-
-/* Memory model information. */
-#ifdef __TINY__
-#define SMALLDATA
-#define SMALLCODE
-#endif
-#ifdef __SMALL__
-#define SMALLDATA
-#define SMALLCODE
-#endif
-#ifdef __COMPACT__
-#define LARGEDATA
-#define SMALLCODE
-#endif
-#ifdef __MEDIUM__
-#define SMALLDATA
-#define LARGECODE
-#endif
-#ifdef __LARGE__
-#define LARGEDATA
-#define LARGECODE
-#endif
-#ifdef __HUGE__
-#define LARGEDATA
-#define LARGECODE
-#endif
-#endif /* ODPLAT_DOS */
-
-
-/* VERSION INFORMATION CONSTANTS. */
-#define OD_VER_SHORTNAME   "OpenDoors"
-#define OD_VER_STATUSLINE  "  OpenDoors 6.20 - (C) Copyright 1991-2001" \
-                           " by Brian Pirie                      "
-#define OD_VER_UNREG_STAT  "  OpenDoors 6.20  *WARNING* Unregistered Version" \
-                           " - Limit 1 month trial period! "
-
-#ifdef ODPLAT_DOS
-#define OD_VER_SIGNON      "[OpenDoors 6.20/DOS - " \
-                           "(C) Copyright 1991-2001 by Brian Pirie]\n\r"
-#define OD_VER_FULLNAME    "OpenDoors 6.20/DOS"
-#endif /* ODPLAT_DOS */
-#ifdef ODPLAT_WIN32
-#define OD_VER_SIGNON      "[OpenDoors 6.20/Win32 - " \
-                           "(C) Copyright 1991-2001 by Brian Pirie]\n\r"
-#define OD_VER_FULLNAME    "OpenDoors 6.20/Win32"
-#endif /* ODPLAT_WIN32 */
-
-
-/* COMPILER DEPENDENT DEFINITIONS. */
-
-/* Some compilers don't like const keyword on parameters. */
-#define CONST const
-
-
-/* DEBUG MACROS. */
-
-/* OD_DEBUG is defined for debug version of the library. */
-/* #define OD_DEBUG */
-
-/* OD_DIAGNOSTICS is defined to enable od_internal_debug. */
-/* #define OD_DIAGNOSTICS */
-
-/* ASSERTion macro - terminates if test condition fails. */
-#ifdef OD_DEBUG
-#define __STR(x) __VAL(x)
-#define __VAL(x) #x
-#ifdef ODPLAT_WIN32
-#define ASSERT(x) if(!(x)) { MessageBox(NULL, __FILE__ ":" \
-   __STR(__LINE__) "\n" #x,  OD_VER_FULLNAME " - Test condition failed", \
-   MB_ICONSTOP | MB_OK); exit(1); }
-#else /* !ODPLAT_WIN32 */
-#define ASSERT(x) if(!(x)) { puts(OD_VER_FULLNAME \
-   " - Test condition failed:\n" __FILE__ ":" __STR(__LINE__) "\n" #x); \
-   exit(1); }
-#endif /* !ODPLAT_WIN32 */
-#else /* !OD_DEBUG */
-#define ASSERT(x)
-#endif /* !OD_DEBUG */
-
-/* TRACE() macro - used to generate debug output. */
-#ifdef OD_TRACE
-#include <stdio.h>
-#define TRACE_API 1
-#define TRACE(x, y) printf("[%s]", y);
-#else
-#define TRACE(x, y)
-#endif
-
-
-/* SCREEN SIZE. */
-#define OD_SCREEN_WIDTH    80
-#define OD_SCREEN_HEIGHT   25
-
-
-/* INTERNALLY USED MACROS. */
-
-/* MIN() and MAX() macros. Note that expressions passed to macros may be */
-/* evaluated more than once. For this reason, it is best to only pass    */
-/* constants or variables to these macros.                               */
-#ifndef MIN
-#define MIN(x, y) ((x) > (y)) ? (y) : (x)
-#endif /* !MIN */
-#ifndef MAX
-#define MAX(x, y) ((x) > (y)) ? (x) : (y)
-#endif /* !MAX */
-
-/* DIM() macro. Returns the number of elements in an array. */
-#ifndef DIM
-#define DIM(x) (sizeof(x) / sizeof(*x))
-#endif /* !DIM */
-
-/* UNUSED() macro. Used to flag that a function parameter is intentionally */
-/* not used, thus preventing a compile-time warning.                       */
-#define UNUSED(x) ((void)(x))
-
-#endif /* !_INC_ODGEN */
diff --git a/src/odoors/ODGetIn.c b/src/odoors/ODGetIn.c
deleted file mode 100644
index 78cfd47f50380b2e9dd80c4797647b7d133935a2..0000000000000000000000000000000000000000
--- a/src/odoors/ODGetIn.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODGetIn.c
- *
- * Description: Implements the od_get_input() function, which obtains the
- *              next input event of any type, optionally performing
- *              translation.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Jan 04, 1996  6.00  BP   Created.
- *              Jan 30, 1996  6.00  BP   Tweaked TREAT_ESC_AS_ANSI_TIMEOUT.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add ODInQueueGetNextEvent() timeout.
- *              Jan 31, 1996  6.00  BP   Added timeout for od_get_input().
- *              Feb 13, 1996  6.00  BP   Added od_get_input() flags parameter.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 19, 1996  6.00  BP   Switched to table implementation.
- *              Feb 25, 1996  6.00  BP   Added new control sequences to table.
- *              Feb 27, 1996  6.00  BP   Added od_max_key_latency.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stddef.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODInQue.h"
-#include "ODCore.h"
-#include "ODKrnl.h"
-
-/* Control sequence table definitions. */
-typedef struct
-{
-   char *pszSequence;
-   char chExtendedKey;
-   BOOL bIsControlKey;
-} tODKeySequence;
-
-tODKeySequence aKeySequences[] =
-{
-   /* VT-52 control sequences. */
-   {"\033A", OD_KEY_UP, FALSE},
-   {"\033B", OD_KEY_DOWN, FALSE},
-   {"\033C", OD_KEY_RIGHT, FALSE},
-   {"\033D", OD_KEY_LEFT, FALSE},
-   {"\033H", OD_KEY_HOME, FALSE},
-   {"\033K", OD_KEY_END, FALSE},
-   {"\033P", OD_KEY_F1, FALSE},
-   {"\033Q", OD_KEY_F2, FALSE},
-   {"\033?w", OD_KEY_F3, FALSE},
-   {"\033?x", OD_KEY_F4, FALSE},
-   {"\033?t", OD_KEY_F5, FALSE},
-   {"\033?u", OD_KEY_F6, FALSE},
-   {"\033?q", OD_KEY_F7, FALSE},
-   {"\033?r", OD_KEY_F8, FALSE},
-   {"\033?p", OD_KEY_F9, FALSE},
-
-   /* Control sequences common to VT-100/VT-102/VT-220/VT-320/ANSI. */
-   {"\033[A", OD_KEY_UP, FALSE},
-   {"\033[B", OD_KEY_DOWN, FALSE},
-   {"\033[C", OD_KEY_RIGHT, FALSE},
-   {"\033[D", OD_KEY_LEFT, FALSE},
-   {"\033[M", OD_KEY_PGUP, FALSE},
-   {"\033[H\x1b[2J", OD_KEY_PGDN, FALSE},
-   {"\033[H", OD_KEY_HOME, FALSE},
-   {"\033[K", OD_KEY_END, FALSE},
-   {"\033OP", OD_KEY_F1, FALSE},
-   {"\033OQ", OD_KEY_F2, FALSE},
-   {"\033OR", OD_KEY_F3, FALSE},
-   {"\033OS", OD_KEY_F4, FALSE},
-
-   /* VT-220/VT-320 specific control sequences. */
-   {"\033[17~", OD_KEY_F6, FALSE},
-   {"\033[18~", OD_KEY_F7, FALSE},
-   {"\033[19~", OD_KEY_F8, FALSE},
-   {"\033[20~", OD_KEY_F9, FALSE},
-   {"\033[21~", OD_KEY_F10, FALSE},
-
-   /* ANSI-specific control sequences. */
-   {"\033[L", OD_KEY_HOME, FALSE},
-   {"\033Ow", OD_KEY_F3, FALSE},
-   {"\033Ox", OD_KEY_F4, FALSE},
-   {"\033Ot", OD_KEY_F5, FALSE},
-   {"\033Ou", OD_KEY_F6, FALSE},
-   {"\033Oq", OD_KEY_F7, FALSE},
-   {"\033Or", OD_KEY_F8, FALSE},
-   {"\033Op", OD_KEY_F9, FALSE},
-
-   /* PROCOMM-specific control sequences (non-keypad alternatives). */
-   {"\033OA", OD_KEY_UP, FALSE},
-   {"\033OB", OD_KEY_DOWN, FALSE},
-   {"\033OC", OD_KEY_RIGHT, FALSE},
-   {"\033OD", OD_KEY_LEFT, FALSE},
-   {"\033OH", OD_KEY_HOME, FALSE},
-   {"\033OK", OD_KEY_END, FALSE},
-
-   /* Other standard control sequences. */
-   {"\x16\t", OD_KEY_INSERT, TRUE},
-
-   /* OpenDoors-specific alternatives. */
-   {"\x7f", OD_KEY_DELETE, FALSE},
-   {"\x5", OD_KEY_UP, TRUE},
-   {"\x18", OD_KEY_DOWN, TRUE},
-   {"\x13", OD_KEY_LEFT, TRUE},
-   {"\x4", OD_KEY_RIGHT, TRUE},
-   {"\x7", OD_KEY_DELETE, TRUE},
-   {"\x16", OD_KEY_INSERT, TRUE},
-};
-
-/* Constant that indicates no match has been found. */
-#define NO_MATCH DIM(aKeySequences)
-
-/* Configurable constants. */
-
-/* The time, in milliseconds, to wait for a second character in a control */
-/* sequence, before deciding that none is going to come.                  */
-#define MAX_CHARACTER_LATENCY 250
-
-/* Size of inbound sequence buffer. */
-#define SEQUENCE_BUFFER_SIZE 10
-
-/* Current control sequence received state. */
-static char szCurrentSequence[SEQUENCE_BUFFER_SIZE] = "";
-static tODTimer SequenceFailTimer;
-static BOOL bSequenceFromRemote;
-static int nMatchedSequence = NO_MATCH;
-static BOOL bDoorwaySequence = FALSE;
-static BOOL bTimerActive = FALSE;
-
-/* Local private function prototypes. */
-static void ODGetInResetSequence(void);
-
-
-
-/* ----------------------------------------------------------------------------
- * od_get_input()
- *
- * Obtains the next input event of any type, optionally performing
- * translation on input events.
- *
- * Parameters: pInputEvent  - Pointer to a tODInputEvent structure, which
- *                            will be filled by information on the next input
- *                            event, if any is obtained.
- *
- *             TimeToWait   - Number of milliseconds to wait for input to be
- *                            available. A value of 0 causes od_get_input()
- *                            to return immediately if no input is waiting,
- *                            while a value of OD_NO_TIMEOUT causes the
- *                            function to never return unless input has been
- *                            obtained.
- *
- *             wFlags       - Flags which customize od_get_input()'s behaviour.
- *
- *     Return: TRUE if an input event was obtained, FALSE if not.
- */
-ODAPIDEF BOOL ODCALL od_get_input(tODInputEvent *pInputEvent,
-   tODMilliSec TimeToWait, WORD wFlags)
-{
-   BOOL bGotEvent;
-   tODTimer TotalWaitTimer;
-   tODInputEvent LastInputEvent;
-   tODMilliSec TimeLeft;
-   tODMilliSec MaximumWait;
-   int nSequence;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_get_input()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check for parameter validity. */
-   if(pInputEvent == NULL)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      goto FunctionExit;
-   }
-
-   /* Call the OpenDoors kernel, if applicable */
-   CALL_KERNEL_IF_NEEDED();
-
-   /* Start a timer if the caller has specified a timeout. */
-   if(TimeToWait != 0 && TimeToWait != OD_NO_TIMEOUT)
-   {
-      ODTimerStart(&TotalWaitTimer, TimeToWait);
-   }
-
-   /* Loop until we have a valid input event, or until we should exit for */
-   /* some other reason.                                                  */
-   bGotEvent = FALSE;
-   while(!bGotEvent)
-   {
-      /* If we aren't supposed to wait for input, then fail if there is */
-      /* nothing waiting in the queue.                                  */
-      if(TimeToWait == 0)
-      {
-         if(!ODInQueueWaiting(hODInputQueue)) break;
-      }
-
-      /* If a maximum wait timeout has been specified, then determine how */
-      /* much of that time is left.                                       */
-      if(TimeToWait != 0 && TimeToWait != OD_NO_TIMEOUT)
-      {
-         TimeLeft = ODTimerLeft(&TotalWaitTimer);
-      }
-      else
-      {
-         TimeLeft = OD_NO_TIMEOUT;
-      }
-
-      /* Determine the maximum time to wait for the next input event. */
-      if(bTimerActive)
-      {
-         MaximumWait = MIN(TimeLeft, ODTimerLeft(&SequenceFailTimer));
-      }
-      else
-      {
-         MaximumWait = TimeLeft;
-      }
-
-      /* Otherwise, attempt to obtain the next input event. */
-      if(MaximumWait == 0 ||
-         ODInQueueGetNextEvent(hODInputQueue, &LastInputEvent, MaximumWait)
-         != kODRCSuccess)
-      {
-         if(TimeToWait != OD_NO_TIMEOUT ||
-            (bTimerActive && ODTimerElapsed(&SequenceFailTimer)
-            && szCurrentSequence[0] == 27 && strlen(szCurrentSequence) == 1))
-         {
-            /* If no input event could be obtained within the specified */
-            /* then return with failure.                                */
-            break;
-         }
-      }
-
-      /* If no translation is required, then just return this event. */
-      if((wFlags & GETIN_RAW)
-         || LastInputEvent.EventType != EVENT_CHARACTER)
-      {
-         bGotEvent = TRUE;
-         memcpy(pInputEvent, &LastInputEvent, sizeof(tODInputEvent));
-      }
-      else
-      {
-         /* We have a character event in translation mode. */
-
-         /* First, check whether this is a doorway sequence, which is */
-         /* handled differently than all other control sequences,     */
-         if(bDoorwaySequence)
-         {
-            pInputEvent->bFromRemote = LastInputEvent.bFromRemote;
-            pInputEvent->chKeyPress = LastInputEvent.chKeyPress;
-            pInputEvent->EventType = EVENT_EXTENDED_KEY;
-            bGotEvent = TRUE;
-            break;
-         }
-         else if(LastInputEvent.chKeyPress == '\0')
-         {
-            bDoorwaySequence = TRUE;
-            continue;
-         }
-
-         /* If sequence buffer is full, then reset the buffer and coninue. */
-         /* Possible improvement: Is this what really should be done?      */
-         if(strlen(szCurrentSequence) >= SEQUENCE_BUFFER_SIZE - 1)
-         {
-            ODGetInResetSequence();
-            continue;
-         }
-
-         /* Otherwise, add this character to the sequence buffer. */
-         szCurrentSequence[strlen(szCurrentSequence)] =
-            LastInputEvent.chKeyPress;
-         bSequenceFromRemote = LastInputEvent.bFromRemote;
-
-         /* Search for a matching control sequence. */
-         for(nMatchedSequence = 0; nMatchedSequence < DIM(aKeySequences);
-            ++nMatchedSequence)
-         {
-            /* Skip sequences that use control characters if required. */
-            if((wFlags & GETIN_RAWCTRL)
-               && aKeySequences[nMatchedSequence].bIsControlKey)
-            {
-               continue;
-            }
-
-            /* Stop loop if we have a match. */
-            if(strcmp(szCurrentSequence,
-               aKeySequences[nMatchedSequence].pszSequence) == 0)
-            {
-               break;
-            }
-         }
-
-         /* If we have a full match of a control sequence. */
-         if(nMatchedSequence != NO_MATCH)
-         {
-            /* Check whether there is another, longer sequence that may */
-            /* match.                                                   */
-            if(!bTimerActive || !ODTimerElapsed(&SequenceFailTimer))
-            {
-               for(nSequence = 0; nSequence < DIM(aKeySequences);
-                  ++nSequence)
-               {
-                  /* Skip sequences that use control characters if required. */
-                  if((wFlags & GETIN_RAWCTRL)
-                     && aKeySequences[nSequence].bIsControlKey)
-                  {
-                     continue;
-                  }
-
-                  /* Stop loop if we have found another possible match. */
-                  if(strlen(szCurrentSequence) <
-                     strlen(aKeySequences[nSequence].pszSequence)
-
-                     && strncmp(szCurrentSequence,
-                     aKeySequences[nSequence].pszSequence,
-                     strlen(szCurrentSequence)) == 0
-
-                     && nSequence != nMatchedSequence)
-                  {
-                     break;
-                  }
-               }
-
-               /* If there is another possible match, we cannot determine */
-               /* whether this is the sequence we want until the maximum  */
-               /* character latency has passed.                           */
-               if(nSequence < DIM(aKeySequences)) continue;
-            }
-
-            /* Return resulting event. */
-            pInputEvent->bFromRemote = bSequenceFromRemote;
-            pInputEvent->chKeyPress =
-               aKeySequences[nMatchedSequence].chExtendedKey;
-            pInputEvent->EventType = EVENT_EXTENDED_KEY;
-            bGotEvent = TRUE;
-            break;
-         }
-
-         /* Start a timer that will elapse if no further control sequence */
-         /* characters are received within the maximum latency time.      */
-         if(od_control.od_max_key_latency != 0)
-         {
-            ODTimerStart(&SequenceFailTimer, od_control.od_max_key_latency);
-         }
-         else
-         {
-            ODTimerStart(&SequenceFailTimer, MAX_CHARACTER_LATENCY);
-         }
-         bTimerActive = TRUE;
-
-         /* We only get here if we don't fully match a control sequence.   */
-
-         /* If this was the first character of a control sequence, we only */
-         /* continue looking for the rest of the sequence if this is a     */
-         /* possible start of the sequence.                                */
-         if(strlen(szCurrentSequence) == 1)
-         {
-            for(nSequence = 0; nSequence < DIM(aKeySequences); ++nSequence)
-            {
-               /* Skip sequences that use control characters if required. */
-               if((wFlags & GETIN_RAWCTRL)
-                  && aKeySequences[nSequence].bIsControlKey)
-               {
-                  continue;
-               }
-
-               /* Stop loop if we have found a complete match. */
-               if(szCurrentSequence[0] ==
-                  aKeySequences[nSequence].pszSequence[0])
-               {
-                  break;
-               }
-            }
-
-            /* If this is not a possible control sequence start, then return */
-            /* this event in unmodified form.                                */
-            if(nSequence == NO_MATCH)
-            {
-               bGotEvent = TRUE;
-               memcpy(pInputEvent, &LastInputEvent, sizeof(tODInputEvent));
-            }
-         }
-      }
-   }
-
-FunctionExit:
-   /* If we don't have an input event to return. */
-   if(!bGotEvent)
-   {
-      /* If we have found a complete sequence already, and the seqeuence */
-      /* timer has elapsed, then return that event.                      */
-      if(bTimerActive && ODTimerElapsed(&SequenceFailTimer))
-      {
-         if(nMatchedSequence != NO_MATCH)
-         {
-            /* Return resulting event. */
-            pInputEvent->bFromRemote = bSequenceFromRemote;
-            pInputEvent->chKeyPress =
-               aKeySequences[nMatchedSequence].chExtendedKey;
-            pInputEvent->EventType = EVENT_EXTENDED_KEY;
-            bGotEvent = TRUE;
-         }
-         else
-         {
-            /* If the sequence began with an escape key, then return an escape */
-            /* key event.                                                      */
-            if(szCurrentSequence[0] == 27 && strlen(szCurrentSequence) == 1)
-            {
-               pInputEvent->bFromRemote = bSequenceFromRemote;
-               pInputEvent->chKeyPress = szCurrentSequence[0];
-               pInputEvent->EventType = EVENT_CHARACTER;
-               bGotEvent = TRUE;
-            }
-         }
-      }
-   }
-
-   /* On success, reset current sequence buffer. */
-   if(bGotEvent)
-   {
-      ODGetInResetSequence();
-   }
-
-   /* Exit function with appropriate return value. */
-   OD_API_EXIT();
-
-   return(bGotEvent);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODGetInResetSequence()                              *** PRIVATE FUNCTION ***
- *
- * Resets (empties) the current sequence buffer.
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODGetInResetSequence(void)
-{
-   memset(szCurrentSequence, '\0', SEQUENCE_BUFFER_SIZE);
-   nMatchedSequence = NO_MATCH;
-   bDoorwaySequence = FALSE;
-   bTimerActive = FALSE;
-}
diff --git a/src/odoors/ODGraph.c b/src/odoors/ODGraph.c
deleted file mode 100644
index be01354fe8ae0efe64acad5b01f0d0bcb1b36dae..0000000000000000000000000000000000000000
--- a/src/odoors/ODGraph.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODGraph.c
- *
- * Description: Implements special ANSI/AVATAR control functions.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 16, 1995  6.00  BP   Moved local vars here from odcore.c.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 13, 1996  6.10  BP   Added od_get_cursor().
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODKrnl.h"
-
-
-/* Local private variables. */
-static char szANSIClearLine[3] = {27, '[', 'K'};
-static char szAvatarClearLine[2] = {22, 7};
-
-
-/* ----------------------------------------------------------------------------
- * od_clr_line()
- *
- * Clears the contents of the current line, from the current cursor position
- * to the end of the line. This function affects both local and remote
- * screens.
- *
- * Parameters: None.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_clr_line(void)
-{
-   char *pchLine;
-   INT nCharsLeft;
-   INT nCount;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_clr_line()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Obtain the current cursor position. */
-   ODScrnGetTextInfo(&ODTextInfo);
-
-   /* Calculate the number of columns that are to be erased. */
-   nCharsLeft = 80 - ODTextInfo.curx;
-
-   /* If either ANSI or AVATAR mode is available, then we first */
-   /* clear the line on the local screen without affecting the  */
-   /* remote screen.                                            */
-   if(od_control.user_avatar || od_control.user_ansi)
-   {
-      pchLine = (char *)szODWorkString;
-      for(nCount = 0; nCount <= nCharsLeft; ++nCount) *pchLine++ = ' ';
-      *pchLine = '\0';
-      ODScrnEnableScrolling(0);
-      ODScrnDisplayString(szODWorkString);
-      ODScrnEnableScrolling(1);
-      ODScrnSetCursorPos(ODTextInfo.curx, ODTextInfo.cury);
-   }
-
-   /* If AVATAR mode is active. */
-   if(od_control.user_avatar)
-   {
-      /* Transmit the two-character AVATAR clear to end of line sequence. */
-      od_disp(szAvatarClearLine, 2, FALSE);
-   }
-
-   /* If ANSI mode is active. */
-   else if(od_control.user_ansi)
-   {
-      /* Transmit the three-character ANSI clear to end of line sequence. */
-      od_disp(szANSIClearLine, 3, FALSE);
-   }
-
-   /* If we are operating in plain-ASCII mode. */
-   else
-   {
-      /* Generate a sequence of space characters followed by backspace */
-      /* characters.                                                   */
-      pchLine = (char *)szODWorkString;
-      for(nCount = 0; nCount < nCharsLeft; ++nCount) *pchLine++ = ' ';
-      for(nCount = 0; nCount < nCharsLeft; ++nCount) *pchLine++ = 8;
-      *pchLine='\0';
-
-      /* Send this sequence to both the local and remote screens. */
-      od_disp(szODWorkString, strlen(szODWorkString), TRUE);
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_cursor()
- *
- * Moves the position of the cursor on both local and remote screens. This
- * function is available in all display modes other than plain-ASCII.
- *
- * Parameters: nRow     - 1-based index of the row to position the cursor in.
- *
- *             nColumn  - Index of the column to position the cursor in.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_set_cursor(INT nRow, INT nColumn)
-{
-   static char szControlSequence[40];
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_set_cursor()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check validity of parameters. */
-   if(nRow < 1 || nColumn < 1)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      return;
-   }
-
-   /* If AVATAR mode is on. */
-   if(od_control.user_avatar)
-   {
-      /* Position the local cursor. */
-      ODScrnSetCursorPos((BYTE)nColumn, (BYTE)nRow);
-
-      /* Generate the AVATAR control sequence to position the remote cursor. */
-      szControlSequence[0] = 22;
-      szControlSequence[1] = 8;
-      szControlSequence[2] = nRow;
-      szControlSequence[3] = nColumn;
-
-      /* Transmit the AVATAR control sequence to the remote terminal. */
-      od_disp(szControlSequence, 4, FALSE);
-   }
-
-   /* If ANSI mode is on. */
-   else if(od_control.user_ansi)
-   {
-      /* Generate the ANSI control sequence to position the remote cursor. */
-      sprintf(szControlSequence, "x[%d;%dH", nRow, nColumn);
-      szControlSequence[0] = 27;
-
-      /* Transmit the ANSI control seequence to the remote terminal. */
-      od_disp(szControlSequence, strlen(szControlSequence), FALSE);
-
-      /* Position the cursor on the local screen. */
-      ODScrnSetCursorPos((BYTE)nColumn, (BYTE)nRow);
-   }
-   else
-   {
-      /* If neither ANSI nor AVATAR modes are available, indicate this */
-      /* in the error code in od_control.                              */
-      od_control.od_error = ERR_NOGRAPHICS;
-   }
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_get_cursor()
- *
- * Returns our best estimate of the current position of the cursor on the
- * remote screen.
- *
- * Parameters: pnRow    - 1-based index of the row to position the cursor in.
- *
- *             pnColumn - Index of the column to position the cursor in.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_get_cursor(INT *pnRow, INT *pnColumn)
-{
-   tODScrnTextInfo TextInfo;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_get_cursor()");
-
-   /* Ensure that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check for parameter validity. */
-   if(pnRow == NULL && pnColumn == NULL)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Obtain current state of local screen. */
-   ODScrnGetTextInfo(&TextInfo);
-
-   /* Set the caller's parameters to the current row and column, if each */
-   /* of these parameters were supplied.                                 */
-   if(pnRow != NULL) *pnRow = (INT)TextInfo.cury;
-   if(pnColumn != NULL) *pnColumn = (INT)TextInfo.curx;
-
-   OD_API_EXIT();
-}
diff --git a/src/odoors/ODInEx.h b/src/odoors/ODInEx.h
deleted file mode 100644
index ce5f44774e1e39089137ea01371c8e726b559532..0000000000000000000000000000000000000000
--- a/src/odoors/ODInEx.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODInEx.h
- *
- * Description: OpenDoors initialization and shutdown operations
- *              (od_init() and od_exit()), including drop file I/O.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 22, 1995  6.00  BP   Created.
- *              Nov 23, 1995  6.00  BP   32-bit portability.
- *              Dec 03, 1995  6.00  BP   Win32 port.
- *              Jan 19, 1996  6.00  BP   Don't use atexit() under Win32.
- *              Jan 19, 1996  6.00  BP   Make ODInitError() a shared function.
- *              Jan 20, 1996  6.00  BP   Prompt for user name if force_local.
- *              Feb 02, 1996  6.00  BP   Added RA 2.50 EXITINFO.BBS support.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 20, 1996  6.00  BP   Added bParsedCmdLine.
- *              Feb 21, 1996  6.00  BP   Don't override command line options.
- *              Feb 21, 1996  6.00  BP   Force single-byte structure alignment.
- *              Feb 23, 1996  6.00  BP   Make DTR disable code shared.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODINEX
-#define _INC_ODINEX
-
-#include "ODPlat.h"
-
-/* Drop file structures. */
-
-/* Force byte alignment, if possible */
-#ifdef __TURBOC__
-#if(__TURBOC__ >= 0x295)
-#pragma option -a-
-#endif /* __TURBOC__ >= 0x295 */
-#endif /* __TURBOC__ */
-#ifdef _MSC_VER
-#pragma pack(1)
-#endif /* _MSC_VER */
-
-typedef struct
-{
-   WORD baud;
-   DWORD num_calls;
-   char last_caller[36];
-   char sLastHandle[36];               /* New to RA 2.50 */
-   char extra1[92];
-   char start_date[9];
-   WORD busyperhour[24];
-   WORD busyperday[7];
-   char name[36];
-   char location[26];
-   char organisation[51];
-   char address[3][51];
-   char handle[36];
-   char comment[81];
-   DWORD password_crc;
-   char dataphone[16];
-   char homephone[16];
-   char lasttime[6];
-   char lastdate[9];
-   BYTE attrib;
-   BYTE attrib2;
-   char flags[4];
-   DWORD credit;
-   DWORD pending;
-   WORD posted;
-   WORD sec;
-   DWORD lastread;
-   DWORD nocalls;
-   DWORD ups;
-   DWORD downs;
-   DWORD upk;
-   DWORD downk;
-   DWORD todayk;
-   INT16 elapsed;
-   WORD screenlen;
-   char lastpwdchange;
-   WORD group;
-   WORD combinedrecord[200];
-   char firstcall[9];
-   char birthday[9];
-   char subdate[9];
-   BYTE screenwidth;
-   BYTE language;
-   BYTE dateformat;
-   char forwardto[36];
-   WORD msgarea;
-   WORD filearea;
-   BYTE default_protocol;
-   WORD file_group;
-   BYTE last_dob_check;
-   BYTE sex;
-   DWORD xirecord;
-   WORD msg_group;
-   BYTE btAttribute3;                  /* New to RA 2.50. */
-   char sPassword[16];                 /* New to RA 2.50. */
-   BYTE extra2[31];
-   char status;
-   char starttime[6];
-   char errorlevel;
-   char days;
-   char forced;
-   char lasttimerun[9];
-   char netmailentered;
-   char echomailentered;
-   char logintime[6];
-   char logindate[9];
-   INT16 timelimit;
-   DWORD loginsec;
-   WORD userrecord;
-   WORD readthru;
-   WORD numberpages;
-   WORD downloadlimit;
-   char timeofcreation[6];
-   DWORD logonpasswordcrc;
-   BYTE wantchat;
-   INT16 deducted_time;
-   char menustack[50][9];
-   BYTE menustackpointer;
-   char extra3[200];
-   BYTE error_free;
-   BYTE sysop_next;
-   char emsi_session;
-   char emsi_crtdef[41];
-   char emsi_protocols[41];
-   char emsi_capabilities[41];
-   char emsi_requests[41];
-   char emsi_software[41];
-   BYTE hold_attr1;
-   BYTE hold_attr2;
-   BYTE hold_len;
-   char page_reason[81];
-   BYTE status_line;
-   char last_cost_menu[9];
-   WORD menu_cost_per_min;
-   BYTE has_avatar;
-   BYTE has_rip;
-   BYTE btRIPVersion;                  /* New to RA 2.50. */
-   BYTE btExtraSpace[85];
-} tRA2ExitInfoRecord;
-
-
-typedef struct
-{
-   WORD baud;
-   DWORD num_calls;
-   char last_caller[36];
-   char extraspace[128];
-   char start_date[9];
-   WORD busyperhour[24];
-   WORD busyperday[7];
-   char uname[36];
-   char uloc[26];
-   char password[16];
-   char dataphone[13];
-   char homephone[13];
-   char lasttime[6];
-   char lastdate[9];
-   BYTE attrib;
-   BYTE flags[4];
-   WORD credit;
-   WORD pending;
-   WORD posted;
-   WORD lastread;
-   WORD sec;
-   WORD nocalls;
-   WORD ups;
-   WORD downs;
-   WORD upk;
-   WORD downk;
-   WORD todayk;
-   WORD elapsed;
-   WORD screenlen;
-   BYTE lastpwdchange;
-   BYTE attrib2;
-   BYTE group;
-   WORD xirecord;
-   char extra2[3];
-   char status;
-   char starttime[6];
-   char errorlevel;
-   char days;
-   char forced;
-   char lasttimerun[9];
-   char netmailentered;
-   char echomailentered;
-   char logintime[6];
-   char logindate[9];
-   WORD timelimit;
-   DWORD loginsec;
-   DWORD net_credit;
-   WORD userrecord;
-   WORD readthru;
-   WORD numberpages;
-   WORD downloadlimint;
-   union
-   {
-      struct
-      {
-         char timeofcreation[6];
-         char logonpassword[16];
-         char wantchat;
-      } ra;
-      struct
-      {
-         char qwantchat;
-         char gosublevel;
-         char menustack[20][9];
-         char menu[9];
-         BYTE screenclear;
-         BYTE moreprompts;
-         BYTE graphicsmode;
-         BYTE externedit;
-         INT16 screenlength;
-         BYTE mnpconnect;
-         char chatreason[49];
-         BYTE externlogoff;
-         BYTE ansicapable;
-         BYTE ripactive;
-         BYTE extraspace[199];
-      } qbbs;
-   } bbs;
-} tExitInfoRecord;
-
-typedef struct
-{
-   INT16 deducted_time;
-   char menustack[50][9];
-   char menustackpointer;
-   char userhandle[36];
-   char comment[81];
-   char firstcall[9];
-   char combinedrecord[25];
-   char birthday[9];
-   char subdate[9];
-   BYTE screenwidth;
-   BYTE msgarea;
-   BYTE filearea;
-   BYTE language;
-   BYTE dateformat;
-   char forwardto[36];
-   char extra_space[43];
-   char error_free;
-   char sysop_next;
-   char emsi_session;
-   char emsi_crtdef[41];
-   char emsi_protocols[41];
-   char emsi_capabilities[41];
-   char emsi_requests[41];
-   char emsi_software[41];
-   char hold_attr1;
-   char hold_attr2;
-   char hold_len;
-   char extr_space[100];
-} tExtendedExitInfo;
-
-struct _pcbsys
-{
-   char display[2];       /* "-1" = On, " 0" = Off */
-   char printer[2];
-   char pagebell[2];
-   char calleralarm[2];
-   char sysopflag;        /* ' ', 'N'=sysop next, 'X'=exit to dos */
-   char errorcorrection[2];
-   char graphicsmode;     /* 'Y'=Yes, 'N'=No, '7'=7E1 */
-   char nodechat;         /* 'A'=available, 'U'=unavailable */
-   char dteportspeed[5];
-   char connectspeed[5];  /* "Local"=local mode */
-   WORD recordnum;
-   char firstname[15];
-   char password[15];
-   INT16 logontimeval;    /* minutes since midnight */
-   INT16 todayused;       /* -ve # of minutes */
-   char logontime[5];
-   INT16 timeallowed;
-   WORD kallowed;
-   char conference;
-   char joined[5];
-   char scanned[5];
-   INT16 conferenceaddtime;
-   INT16 creditminutes;
-   char languageext[4];
-   char fullname[25];
-   INT16 minutesremaining;
-   char node;             /* ' ' if no network */
-   char eventtime[5];
-   char eventactive[2];
-   char slideevent[2];
-   DWORD memmessage;
-   char comport;          /* 0=none, 1-8 */
-   char reserved1[2];
-   char useansi;          /* 1 = yes, 0 = no */
-   char lasteventdate[8];
-   WORD lasteventminute;
-   char dosexit;
-   char eventupcoming;
-   char stopuploads;
-   WORD conferencearea;
-};
-
-struct _userssyshdr
-{
-   WORD     Version;           /* PCBoard version number (i.e. 145) */
-   DWORD    RecNo;             /* Record number from USER's file */
-   WORD     SizeOfRec;         /* Size of "fixed" user record */
-   WORD     NumOfAreas;        /* Number of conference areas (Main=1) */
-   WORD     NumOfBitFields;    /* Number of Bit Map fields for conferences */
-   WORD     SizeOfBitFields;   /* Size of each Bit Map field */
-   char     AppName[15];       /* Name of the Third Party Application */
-   WORD     AppVersion;        /* Version number for the application */
-   WORD     AppSizeOfRec;      /* Size of a "fixed length" record (if any) */
-   WORD     AppSizeOfConfRec;  /* Size of each conference record (if any) */
-   DWORD    AppRecOffset;      /* Offset of AppRec into USERS.INF record */
-   char     Updated;           /* TRUE if USERS.SYS has been updated */
-};
-
-struct _pcbflags
-{
-   int Dirty    :1;            /* Dirty Flag (meaning file has been updated) */
-   int MsgClear :1;            /* User's choice for screen clear after messages */
-   int HasMail  :1;            /* Indicates if NEW mail has been left for user */
-   int Reserved :5;
-};
-
-struct _pcbdate
-{
-   int Day   :5;               /* 5 bit integer representing the Day */
-   int Month :4;               /* 4 bit integer representing the Month */
-   int Year  :7;               /* 7 bit integer representing the Year MINUS 80 */
-};
-
-struct _userssysrec
-{
-   char     Name[26];          /* Name (NULL terminated) */
-   char     City[25];          /* City (NULL terminated) */
-   char     Password[13];      /* Password (NULL terminated) */
-   char     BusDataPhone[14];  /* Business or Data Phone (NULL terminated) */
-   char     HomeVoicePhone[14];/* Home or Voice Phone (NULL terminated) */
-   WORD     LastDateOn;        /* Julian date for the Last Date On */
-   char     LastTimeOn[6];     /* Last Time On (NULL Terminated) */
-   char     ExpertMode;        /* 1=Expert, 0=Novice */
-   char     Protocol;          /* Protocol (A thru Z) */
-   struct _pcbflags PackedFlags;
-   struct _pcbdate DateLastDirRead;
-   INT16    SecurityLevel;     /* Security Level */
-   WORD     NumTimesOn;        /* Number of times the caller has connected */
-   char     PageLen;           /* Page Length when display data on the screen */
-   WORD     NumUploads;        /* Total number of FILES uploaded */
-   WORD NumDownloads;      /* Total number of FILES downloaded */
-   DWORD    DailyDnldBytes;    /* Number of BYTES downloaded so far today */
-   char     UserComment[31];   /* Comment field #1 (NULL terminated) */
-   char     SysopComment[31];  /* Comment field #1 (NULL terminated) */
-   INT16    ElapsedTimeOn;     /* Number of minutes online */
-   WORD     RegExpDate;        /* Julian date for Registration Expiration Date */
-   INT16    ExpSecurityLevel;  /* Expired Security Level */
-   WORD     LastConference;    /* Number of the conference the caller was in */
-   DWORD    TotDnldBytes;      /* Total number of BYTES downloaded */
-   DWORD    TotUpldBytes;      /* Total number of BYTES uploaded */
-   char     DeleteFlag;        /* 1=delete this record, 0=keep */
-   DWORD    RecNum;            /* Record Number in USERS.INF file */
-   char     Reserved[9];       /* Bytes 391-399 from the USERS file */
-   DWORD    MsgsRead;          /* Number of messages the user has read in PCB */
-   DWORD    MsgsLeft;          /* Number of messages the user has left in PCB */
-};
-
-/* Restore original structure alignment, if possible. */
-#ifdef _MSC_VER
-#pragma pack()
-#endif /* _MSC_VER */
-
-
-/* od_init() and od_exit() global helper functons. */
-#ifndef ODPLAT_WIN32
-void ODAtExitCallback(void);
-#endif /* !ODPLAT_WIN32 */
-INT ODWriteExitInfoPrimitive(FILE *pfDropFile, INT nCount);
-BOOL ODReadExitInfoPrimitive(FILE *pfDropFile, INT nCount);
-INT ODSearchForDropFile(char **papszFileNames, INT nNumFileNames,
-   char *pszFound, char *pszDirectory);
-void ODInitError(char *pszErrorText);
-#ifdef ODPLAT_WIN32
-BOOL CALLBACK ODInitLoginDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-void ODInExDisableDTR(void);
-#endif /* ODPLAT_WIN32 */
-
-
-/* Global variables. */
-extern WORD wODNodeNumber;
-extern BOOL bIsCoSysop;
-extern BOOL bIsSysop;
-extern char *apszDropFileInfo[25];
-extern BYTE btExitReason;
-extern DWORD dwForcedBPS;
-extern INT nForcedPort;
-extern DWORD dwFileBPS;
-extern char szDropFilePath[120];
-extern char szExitinfoBBSPath[120];
-extern INT16 nInitialElapsed;
-extern char *szOriginalDir;
-extern BYTE btDoorSYSLock;
-extern time_t nStartupUnixTime;
-extern INT16 nInitialRemaining;
-extern BOOL bSysopNameSet;
-extern char szForcedSysopName[40];
-extern BOOL bSystemNameSet;
-extern char szForcedSystemName[40];
-extern BOOL bUserFull;
-extern BOOL bCalledFromConfig;
-extern tRA2ExitInfoRecord *pRA2ExitInfoRecord;
-extern tExitInfoRecord *pExitInfoRecord;
-extern tExtendedExitInfo *pExtendedExitInfo;
-extern struct _pcbsys *pPCBoardSysRecord;
-extern struct _userssyshdr *pUserSysHeader;
-extern struct _userssysrec *pUserSysRecord;
-extern BOOL bPreOrExit;
-extern BOOL bRAStatus;
-extern BOOL bPromptForUserName;
-extern BOOL bParsedCmdLine;
-extern WORD wPreSetInfo;
-#ifdef ODPLAT_WIN32
-extern tODThreadHandle hFrameThread;
-#endif /* ODPLAT_WIN32 */
-
-
-/* wPreSetInfo flags. */
-#define PRESET_BPS         0x0001
-#define PRESET_PORT        0x0002
-#define PRESET_REQUIRED    (PRESET_BPS | PRESET_PORT)
-
-
-#endif /* _INC_ODINEX */
diff --git a/src/odoors/ODInEx1.c b/src/odoors/ODInEx1.c
deleted file mode 100644
index 0eccc744db590b4ed1536a402d07730cea73045c..0000000000000000000000000000000000000000
--- a/src/odoors/ODInEx1.c
+++ /dev/null
@@ -1,2416 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODInEx1.c
- *
- * Description: Performs OpenDoors initialization and shutdown operations
- *              (od_init() and od_exit()), including drop file I/O. This
- *              module is broken into two files, ODInEx1.c and ODInEx2.c.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 19, 1994  6.00  BP   Default paging hours 8:00-22:00.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Oct 29, 1994  6.00  BP   Properly read dorinfo?.def BBS name.
- *              Oct 31, 1994  6.00  BP   Only use dorinfo?.def /w exitinfo.bbs.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Remove call to _mt_init().
- *              Dec 31, 1994  6.00  BP   Add call to ODPlatInit().
- *              Jul 30, 1995  6.00  BP   Split up od_init().
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 14, 1995  6.00  BP   New default for od_colour_char is 0.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Nov 23, 1995  6.00  BP   Moved Pascal conversion to odutil.c.
- *              Dec 21, 1995  6.00  BP   Add ability to use already open port.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Dec 30, 1995  6.00  BP   Only use comm idle func under DOS.
- *              Jan 01, 1996  6.00  BP   Added od_disable_dtr.
- *              Jan 01, 1996  6.00  BP   Raise DTR after opening serial port.
- *              Jan 02, 1996  6.00  BP   Use printf() in ODInitError().
- *              Jan 03, 1996  6.00  BP   Display connect speed with %lu.
- *              Jan 19, 1996  6.00  BP   Don't use atexit() under Win32.
- *              Jan 19, 1996  6.00  BP   Make ODInitError() a shared function.
- *              Jan 20, 1996  6.00  BP   Prompt for user name if force_local.
- *              Jan 23, 1996  6.00  BP   Added od_exiting and OD_TEXTMODE.
- *              Jan 31, 1996  6.00  BP   Added DIS_NAME_PROMPT.
- *              Jan 31, 1996  6.00  BP   Support new SFDOORS.DAT format.
- *              Feb 02, 1996  6.00  BP   Added RA 2.50 EXITINFO.BBS support.
- *              Feb 06, 1996  6.00  BP   Added od_silent_mode.
- *              Feb 08, 1996  6.00  BP   Recognize SFSYSOP.DAT.
- *              Feb 09, 1996  6.00  BP   Correctly translate RA 2.x sex field.
- *              Feb 09, 1996  6.00  BP   Made default outbound buffer 3072.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 20, 1996  6.00  BP   Added bParsedCmdLine.
- *              Feb 21, 1996  6.00  BP   Don't override command line options.
- *              Feb 21, 1996  6.00  BP   Change od_always_clear default to on.
- *              Feb 23, 1996  6.00  BP   Changed default DTR disable string.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Added TRIBBS.SYS support.
- *              Mar 06, 1996  6.10  BP   Initial support for Door32 interface.
- *              Mar 13, 1996  6.10  BP   Added od_local_win_col.
- *              Mar 17, 1996  6.10  BP   Reset text color after local login.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Apr 08, 1996  6.10  BP   Store local login name in user_handle.
- *              Jan 13, 1997  6.10  BP   Fixes for Door32 support.
- *              Oct 19, 2001  6.20  RS   Added door32.sys and socket support.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODInQue.h"
-#include "ODKrnl.h"
-#include "ODInEx.h"
-#include "ODUtil.h"
-#ifdef ODPLAT_WIN32
-#include "ODFrame.h"
-#include "ODRes.h"
-#endif /* ODPLAT_WIN32 */
-
-/* Default size of local/remote combined keyboard buffer. */
-#define DEFAULT_EVENT_QUEUE_SIZE    128
-
-
-/* Local private helper functions. */
-static void ODInitReadExitInfo(void);
-static void ODInitPartTwo(void);
-static BOOL ODInitReadSFDoorsDAT(void);
-static void ODInitPartTwo(void);
-
-
-/* Private variables. */
-static BYTE btRAStatusToSet = 0;
-#ifndef ODPLAT_WIN32
-static BOOL bPreset = TRUE;
-#endif /* !ODPLAT_WIN32 */
-static char szIFTemp[256];
-
-/* Configuration file keywords. */
-static char *apszConfigText[] =
-{
-   "Node",
-   "BBSDir",
-   "DoorDir",
-   "LogFileName",
-   "DisableLogging",
-   "SundayPagingHours",
-   "MondayPagingHours",
-   "TuesdayPagingHours",
-   "WednesdayPagingHours",
-   "ThursdayPagingHours",
-   "FridayPagingHours",
-   "SaturdayPagingHours",
-   "MaximumDoorTime",
-   "SysopName",
-   "SystemName",
-   "SwappingDisable",
-   "SwappingDir",
-   "SwappingNoEMS",
-   "LockedBPS",
-   "SerialPort",
-   "CustomFileName",
-   "CustomFileLine",
-   "InactivityTimeout",
-   "PageDuration",
-   "ChatUserColour",
-   "ChatSysopColour",
-   "FileListTitleColour",
-   "FileListNameColour",
-   "FileListSizeColour",
-   "FileListDescriptionColour",
-   "FileListOfflineColour",
-   "Personality",
-   "NoFossil",
-   "PortAddress",
-   "PortIRQ",
-   "ReceiveBuffer",
-   "TransmitBuffer",
-   "PagePromptColour",
-   "LocalMode",
-   "PopupMenuTitleColour",
-   "PopupMenuBorderColour",
-   "PopupMenuTextColour",
-   "PopupMenuKeyColour",
-   "PopupMenuHighlightColour",
-   "PopupMenuHighKeyColour",
-   "NoFIFO",
-   "FIFOTriggerSize",
-   "DisableDTR",
-   "NoDTRDisable",
-};
-
-/* Custom drop file keywords. */
-static char *apszConfigLines[] =
-{
-   "Ignore",
-   "ComPort",
-   "FossilPort",
-   "ModemBPS",
-   "LocalMode",
-   "UserName",
-   "UserFirstName",
-   "UserLastName",
-   "Alias",
-   "HoursLeft",
-   "MinutesLeft",
-   "SecondsLeft",
-   "ANSI",
-   "AVATAR",
-   "PagePausing",
-   "ScreenLength",
-   "ScreenClearing",
-   "Security",
-   "City",
-   "Node",
-   "SysopName",
-   "SysopFirstName",
-   "SysopLastName",
-   "SystemName",
-   "RIP",
-};
-
-/* Logfile messages. */
-static char *apszLogMessages[] = 
-{
-   "Carrier lost, exiting door",
-   "System operator terminating call, exiting door",
-   "User's time limit expired, exiting door",
-   "User keyboard inactivity time limit exceeded, exiting door",
-   "System operator returning user to BBS, exiting door",
-   "Exiting door with errorlevel %d",
-   "Invoking operating system shell",
-   "Returning from operating system shell",
-   "User paging system operator",
-   "Entering sysop chat mode",
-   "Terminating sysop chat mode",
-   "%s entering door",
-   "Reason for chat: %s",
-   "Exiting door",
-};
-
-/* Color name strings. */
-static char *apszColorNames[] =
-{
-   "BLACK",
-   "BLUE",
-   "GREEN",
-   "CYAN",
-   "RED",
-   "MAGENTA",
-   "YELLOW",
-   "WHITE",
-   "BROWN",
-   "GREY",
-   "BRIGHT",
-   "FLASHING",
-};
-
-/* Array of door information (drop) file names to search for. */
-static char *apszDropFileNames[] = 
-{
-   "EXITINFO.BBS",
-   "DORINFO1.DEF",
-   "CHAIN.TXT",
-   "SFDOORS.DAT",
-   "DOOR.SYS",
-   "CALLINFO.BBS",
-   "SFMAIN.DAT",
-   "SFFILE.DAT",
-   "SFMESS.DAT",
-   "SFSYSOP.DAT",
-   "TRIBBS.SYS",
-   "DOOR32.SYS",
-};
-
-/* Array of door information (drop) file numbers 
- * (corresponding to apszDropFileNames) 
- */
-static enum {
-   FOUND_EXITINFO_BBS,
-   FOUND_DORINFO1_DEF,
-   FOUND_CHAIN_TXT,
-   FOUND_SFDOORS_DAT,
-   FOUND_DOOR_SYS,
-   FOUND_CALLINFO_BBS,
-   FOUND_SFMAIN_DAT,
-   FOUND_SFFILE_DAT,
-   FOUND_SFMESS_DAT,
-   FOUND_SFSYSOP_DAT,
-   FOUND_TRIBBS_SYS,
-   FOUND_DOOR32_SYS,
-};
-
-#define FOUND_NONE -1
-
-
-/* Global variables. */
-WORD wODNodeNumber = 65535U;
-BOOL bIsCoSysop;
-BOOL bIsSysop;
-char *apszDropFileInfo[25];
-BYTE btExitReason = 0;
-DWORD dwForcedBPS = 1;
-INT nForcedPort = -1;
-DWORD dwFileBPS;
-char szDropFilePath[120];
-char szExitinfoBBSPath[120];
-INT16 nInitialElapsed;
-char *szOriginalDir = NULL;
-BYTE btDoorSYSLock = 0;
-time_t nStartupUnixTime;
-INT16 nInitialRemaining;
-BOOL bSysopNameSet = FALSE;
-char szForcedSysopName[40];
-BOOL bSystemNameSet = FALSE;
-char szForcedSystemName[40];
-BOOL bUserFull = FALSE;
-BOOL bCalledFromConfig = FALSE;
-tRA2ExitInfoRecord *pRA2ExitInfoRecord = NULL;
-tExitInfoRecord *pExitInfoRecord = NULL;
-tExtendedExitInfo *pExtendedExitInfo = NULL;
-struct _pcbsys *pPCBoardSysRecord = NULL;
-struct _userssyshdr *pUserSysHeader = NULL;
-struct _userssysrec *pUserSysRecord = NULL;
-BOOL bPreOrExit = FALSE;
-BOOL bRAStatus;
-BOOL bPromptForUserName = FALSE;
-BOOL bParsedCmdLine = FALSE;
-WORD wPreSetInfo = 0;
-#ifdef ODPLAT_WIN32
-tODThreadHandle hFrameThread;
-#endif /* ODPLAT_WIN32 */
-
-
-/* ----------------------------------------------------------------------------
- * od_init()
- *
- * Starts up OpenDoors. Initializes various members of od_control, reads the
- * BBS door information (drop file), initializes the serial port and carries
- * out other operations that must be done at initialization time. May be
- * explicitly called by the user, or called as a result of the first call to
- * some other OpenDoors API function.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_init(void)
-{
-   BYTE btCount;
-   FILE *pfDropFile=NULL;
-   char *pointer;
-   INT nFound = FOUND_NONE;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_init()");
-
-   /* If a callback function is active, then don't do anything. */
-   if(bIsCallbackActive) return;
-
-   /* If we are not being called from within ODConfigInit(). */
-   if(!bCalledFromConfig)
-   {
-      /* If OpenDoors has already been initialized, then return without */
-      /* doing anything.                                                */
-      if(bODInitialized) return;
-
-      /* Otherwise, set the initialized flag so that od_init() won't be */
-      /* run again.                                                     */
-      bODInitialized = TRUE;
-
-      /* Initialize program name string. */
-      if(od_control.od_prog_name[0] == '\0')
-      {
-         strcpy(od_control.od_prog_name, OD_VER_SHORTNAME);
-      }
-
-      /* Initialize color name strings in od_control. */
-      for(btCount = 0; btCount < DIM(apszColorNames); ++btCount)
-      {
-         if(!*od_control.od_color_names[btCount])
-         {
-            strcpy(od_control.od_color_names[btCount],
-               apszColorNames[btCount]);
-         }
-      }
-
-      /* Initialize custom drop file strings in od_control. */
-      for(btCount = 0; btCount < LINES_SIZE; ++btCount)
-      {
-         if(!*od_control.od_cfg_lines[btCount])
-         {
-            strcpy(od_control.od_cfg_lines[btCount], apszConfigLines[btCount]);
-         }
-      }
-
-      /* Initialize configuration keyword strings in od_control. */
-      for(btCount = 0; btCount < TEXT_SIZE; ++btCount)
-      {
-         if(!*od_control.od_cfg_text[btCount])
-         {
-            strcpy(od_control.od_cfg_text[btCount], apszConfigText[btCount]);
-         }
-      }
-
-      /* Enable multiple personality system if it has been installed. */
-#ifdef OD_TEXTMODE
-      if(od_control.od_mps != NULL)
-      {
-         (*(OD_COMPONENT_CALLBACK *)od_control.od_mps)();
-      }
-#endif /* !OD_TEXTMODE */
-
-      /* If baud rate has been set in od_control, then remember the forced */
-      /* rate for later use.                                               */
-      if(od_control.baud != 0)
-      {
-         dwForcedBPS = od_control.baud;
-      }
-
-      /* If the serial port number has already been set in od_control, then */
-      /* remember the forced port number for later use.                     */
-      if(od_control.port != 0)
-      {
-         nForcedPort = od_control.port;
-      }
-
-      /* If the configuration file system has been installed, then allow   */
-      /* the configuration file initialization routine take over           */
-      /* initialization from here. Once it has read the configuration file */
-      /* it will call od_init() again, at which time od_init() will carry  */
-      /* on from this point in the code.                                  */
-      if(od_control.config_file != NULL)
-      {
-         (*(OD_COMPONENT_CALLBACK *)od_control.config_file)();
-         return;
-      }
-   }
-
-   /* Initialize the OpenDoors platform-specific utility functions. */
-   ODPlatInit();
-
-   /* Store the time of door startup. */
-   time(&nStartupUnixTime);
-
-   /* Allocate the set of strings that are used to store certain parts */
-   /* of drop files for rewriting at od_exit() time.                   */
-   for(btCount = 0; btCount < DIM(apszDropFileInfo); ++btCount)
-   {
-      if((apszDropFileInfo[btCount] = (char *)malloc(81)) == NULL)
-      {
-malloc_error:
-         ODInitError("Insufficient memory available to start up program.");
-         exit(od_control.od_errorlevel[1]);
-      }
-   }
-
-   /* Determine the current node number. */ 
-   if((pointer=getenv("TASK")) != NULL)
-   {
-      od_control.od_node = atoi(pointer);
-   }
-   else if(wODNodeNumber != 65535U)
-   {
-      od_control.od_node = wODNodeNumber;
-   }
-   else if(od_control.od_node == 0)
-   {
-      od_control.od_node = 1;
-   }
-
-   /* If a custom drop file format is not being used, then set certain   */
-   /* od_control members to their default values. In the case where      */
-   /* a custom drop file format is being used, these values will already */
-   /* have been set, and so we don't want to touch them.                 */
-   if(od_control.od_info_type != CUSTOM)
-   {
-      od_control.user_avatar = FALSE;
-      od_control.user_rip = FALSE;
-      od_control.user_attribute = 0x06;
-      od_control.user_screen_length = 23;
-      od_control.od_page_pausing = TRUE;
-      od_control.od_page_len = 15;
-   }
-   else
-   {
-      /* When a custom drop file is being used, there are certain      */
-      /* variables that we must initialize if they weren't already set */
-      /* when the custom drop file was read.                           */
-      if(od_control.user_timelimit == 0) od_control.user_timelimit = 60;
-      if(od_control.port == -1) od_control.baud = 0L;
-   }
-
-   /* Setup inbound local/remote buffer. */
-   if(ODInQueueAlloc(&hODInputQueue, od_control.od_in_buf_size == 0 ?
-      DEFAULT_EVENT_QUEUE_SIZE : od_control.od_in_buf_size) != kODRCSuccess)
-   {
-      goto malloc_error;
-   }
-
-   /* Enable user's keyboard by default. */
-   od_control.od_user_keyboard_on = TRUE;
-
-   /* If door information (drop) file reading has been disabled, then */
-   /* don't attempt to read any drop file.                            */
-   if(od_control.od_disable & DIS_INFOFILE)
-   {
-      od_control.od_info_type = NO_DOOR_FILE;
-   }
-
-   /* Otherwise, if the local mode override has been explicitly asked for, */
-   /* setup od_control for default local mode operation.                   */
-   else if(od_control.od_force_local)
-   {
-force_local:
-      /* No door information file is being used. */
-      od_control.od_info_type = NO_DOOR_FILE;
-
-      /* Operate in local mode. */
-      od_control.baud = 0L;
-
-      if(!bParsedCmdLine)
-      {
-         /* Enable ANSI mode. */
-         od_control.user_ansi = TRUE;
-
-         /* Default to 60 minutes of time available. */
-         od_control.user_timelimit = 60;
-      }
-
-      /* Choose the appropriate system name. */
-      if(bSystemNameSet)
-      {
-         strcpy(od_control.user_location, szForcedSystemName);
-      }
-      else if(od_control.system_name[0] != '\0')
-      {
-         strcpy(od_control.user_location, od_control.system_name);
-      }
-      else
-      {
-         strcpy(od_control.user_location, "Unknown Location");
-      }
-   }
-
-   /* If drop file reading isn't disable, if a custom format drop file */
-   /* hasn't already been read and automatic local mode hasn't been    */
-   /* specified, then attempt to find and read a standard drop file.   */
-   else if(od_control.od_info_type != CUSTOM)
-   {
-      /* Generate the name of the dorinfox.def file for this node. */
-      if(od_control.od_node > 35)
-      {
-         apszDropFileNames[1] = (char *)"DORINFO1.DEF";
-      }
-      else if(od_control.od_node > 9)
-      {
-         sprintf(szIFTemp, "DORINFO%c.DEF", od_control.od_node + 55);
-         apszDropFileNames[1] = (char *)szIFTemp;
-      }
-      else
-      {
-         sprintf(szIFTemp, "DORINFO%d.DEF", od_control.od_node);
-         apszDropFileNames[1] = (char *)szIFTemp;
-      }
-
-      nFound = FOUND_NONE;
-
-      if(!ODFileAccessMode(od_control.info_path, 4))
-      {
-         /* Check for a DORINFOx.DEF filename. */
-         if(ODStringHasTail(od_control.info_path, ".DEF") &&
-            strlen(od_control.info_path) >= strlen(apszDropFileNames[2]) &&
-            strnicmp((char *)&od_control.info_path +
-            (strlen(od_control.info_path) - 12), "DORINFO", 7) == 0)
-         {
-            nFound = FOUND_DORINFO1_DEF;
-            strcpy(szDropFilePath, od_control.info_path);
-         }
-         else
-         {
-            /* Check filenames other than DORINFOx.DEF */
-            for(btCount = 0; btCount < DIM(apszDropFileNames); ++btCount)
-            {
-               if(ODStringHasTail(od_control.info_path,
-                  apszDropFileNames[btCount]))
-               {
-                  strcpy(szDropFilePath, od_control.info_path);
-                  nFound = btCount;
-                  break;
-               }
-            }
-         }
-      }
-
-      /* Search for a door information file. */
-      if(nFound == FOUND_NONE)
-      {
-         nFound = ODSearchForDropFile((char **)&apszDropFileNames,
-            DIM(apszDropFileNames), (char *)&szDropFilePath,
-            (char *)&szExitinfoBBSPath);
-      }
-
-      if(nFound == FOUND_EXITINFO_BBS)
-      {
-         od_control.od_info_type = NO_DOOR_FILE;
-         ODInitReadExitInfo();
-         if(od_control.od_info_type == NO_DOOR_FILE)
-         {
-            goto DropFileFail;
-         }
-
-         ODMakeFilename(szODWorkString, szExitinfoBBSPath, "DORINFO1.DEF",
-            sizeof(szExitinfoBBSPath));
-         if((pfDropFile = fopen(szODWorkString, "r")) == NULL)
-         {
-            goto DropFileFail;
-         }
-
-         goto read_dorinfox;
-      }
-
-      else if(nFound==FOUND_DORINFO1_DEF)
-      {
-          /* Open DORINFO?.DEF. */
-          if((pfDropFile = fopen(szDropFilePath, "r")) == NULL) goto DropFileFail;
-
-          /* Set door type to DORINFO. */
-          od_control.od_info_type = DORINFO1;
-
-read_dorinfox:
-          /* If not able to read first line. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-
-          if(szIFTemp[strlen(szIFTemp) - 1] == '\n')
-          {
-            szIFTemp[strlen(szIFTemp) - 1] = '\0';
-          }
-          strncpy(od_control.system_name, szIFTemp, 39);
-          od_control.system_name[39] = '\0';
-
-          /* get sysop name from DORINFO1.DEF */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          strncpy(od_control.sysop_name, szIFTemp, 19);
-
-                                          /* get sysop's last name */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          if(strlen(szIFTemp))
-          {
-             strcat(od_control.sysop_name," ");
-             strncat(od_control.sysop_name,szIFTemp,19);
-          }
-                                   /* get com port that modem is connected to */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.port=szIFTemp[3]-'1';
-                                          /* determine BPS rate of connection */
-          if(fgets((char *)apszDropFileInfo[0],255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.baud= (od_control.port == -1) ? 0 : atol((char *)apszDropFileInfo[0]);
-
-          if(fgets((char *)apszDropFileInfo[1],80,pfDropFile)==NULL) goto DropFileFail;
-
-                                          /* get user's first name */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          strncpy(od_control.user_name,szIFTemp,17);
-                                          /* get user's last name */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          if(strlen(szIFTemp))
-          {
-             strcat(od_control.user_name," ");
-             strncat(od_control.user_name,szIFTemp,17);
-          }
-                                          /* get user's location */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          strncpy(od_control.user_location,szIFTemp,25);
-                                          /* get ANSI mode settings */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(szIFTemp[0]=='0') od_control.user_ansi=FALSE;
-          else od_control.user_ansi=TRUE;
-                                          /* get user security level */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_security=atoi(szIFTemp);
-                                          /* get time left in door */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_timelimit=atoi(szIFTemp);
-          fclose(pfDropFile);
-       }
-                                       /* Read CHAIN.TXT */
-       else if(nFound==FOUND_CHAIN_TXT)
-       {
-          if((pfDropFile=fopen(szDropFilePath,"r"))==NULL) goto DropFileFail;
-
-          od_control.od_info_type=CHAINTXT;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_num=atoi(szIFTemp);
-
-          if(fgets((char *)&od_control.user_handle,35,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(od_control.user_handle);
-
-          if(fgets((char *)&od_control.user_name,35,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(od_control.user_name);
-
-          if(fgets((char *)&od_control.user_callsign,12,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(od_control.user_callsign);
-
-          if(fgets((char *)apszDropFileInfo[0],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_sex=szIFTemp[0];
-
-          if(fgets((char *)apszDropFileInfo[1],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          strncpy(od_control.user_lastdate,szIFTemp,8);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_screenwidth=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_screen_length=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_security=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          bIsSysop=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          bIsCoSysop=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_ansi=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;    /* non-zero if remote */
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_timelimit=atoi(szIFTemp);
-          od_control.user_timelimit/=60;
-
-          if(fgets((char *)apszDropFileInfo[3],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets((char *)apszDropFileInfo[4],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets((char *)apszDropFileInfo[5],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(strcmp(szIFTemp,"KB")==0)
-          {
-             od_control.baud=0;
-          }
-          else
-          {
-             od_control.baud=atol(szIFTemp);
-          }
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.port=atoi(szIFTemp)-1;
-
-          if(fgets((char *)apszDropFileInfo[6],80,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets((char *)&od_control.user_password,15,pfDropFile)==NULL) goto DropFileFail;
-          ODStringToName(od_control.user_password);
-
-          if(fgets((char *)apszDropFileInfo[2],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[7],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[8],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[9],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[10],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[11],80,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets((char *)apszDropFileInfo[12],80,pfDropFile)==NULL) goto DropFileFail;
-
-          fclose(pfDropFile);
-       }
-
-       else if(nFound == FOUND_SFDOORS_DAT 
-			 || nFound == FOUND_SFMAIN_DAT 
-			 || nFound == FOUND_SFFILE_DAT 
-			 || nFound == FOUND_SFMESS_DAT
-          || nFound == FOUND_SFSYSOP_DAT)
-       {
-          od_control.od_info_type = SFDOORSDAT;
-
-          if(!ODInitReadSFDoorsDAT())
-          {
-             goto DropFileFail;
-          }
-       }
-
-       else if(nFound==FOUND_DOOR_SYS)
-       {
-          if((pfDropFile=fopen(szDropFilePath,"r"))==NULL) goto DropFileFail;
-
-          /* Read line 1. */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(szIFTemp[0]=='C' && szIFTemp[1]=='O' && szIFTemp[2]=='M' && szIFTemp[4]==':')
-          {                            /* GAP style DOOR.SYS */
-             od_control.od_info_type=DOORSYS_GAP;
-
-             od_control.port=szIFTemp[3]-'1';
-
-             /* Read line 2. */
-             if(fgets((char *)apszDropFileInfo[0], 80, pfDropFile) == NULL)
-             {
-               goto DropFileFail;
-             }
-             od_control.od_connect_speed = atol(apszDropFileInfo[0]);
-
-             /* Read line 3. */
-             if(fgets((char *)apszDropFileInfo[1],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 4. */
-             if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-             od_control.od_node = atoi(szIFTemp);
-
-             /* Read line 5. */
-             if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-             strupr(szIFTemp);
-             if(strchr(szIFTemp, 'N') != NULL)
-             {
-                btDoorSYSLock = 1;
-                od_control.baud = atol(apszDropFileInfo[0]);
-             }
-             else if(strchr(szIFTemp, 'Y') != NULL)
-             {
-                btDoorSYSLock = 2;
-                od_control.baud = 19200;
-             }
-             else
-             {
-                od_control.baud = atol(szIFTemp);
-             }
-
-             if(od_control.port == -1) od_control.baud = 0L;
-
-             /* Read line 6. */
-             if(fgets((char *)apszDropFileInfo[3],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 7. */
-             if(fgets((char *)apszDropFileInfo[4],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 8. */
-             if(fgets((char *)apszDropFileInfo[5],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 9. */
-             if(fgets((char *)apszDropFileInfo[22],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 10. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[35]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_name,szIFTemp);
-
-             /* Read line 11. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[25]='\0';
-             if(szIFTemp[strlen(szIFTemp)-1]=='\n') szIFTemp[strlen(szIFTemp)-1]='\0';
-             strcpy(od_control.user_location,szIFTemp);
-
-             /* Read line 12. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[15]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_homephone,szIFTemp);
-
-             /* Read line 13. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[15]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_dataphone,szIFTemp);
-
-             /* Read line 14. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[15]='\0';
-             if(szIFTemp[strlen(szIFTemp)-1]=='\n') szIFTemp[strlen(szIFTemp)-1]='\0';
-             strcpy(od_control.user_password,szIFTemp);
-
-             /* Read line 15. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_security=atoi(szIFTemp);
-
-             /* Read line 16. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_numcalls=atoi(szIFTemp);
-
-             /* Read line 17. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[15]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_lastdate,szIFTemp);
-
-             /* Read line 18. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 19. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_timelimit=atoi(szIFTemp);
-
-             /* Read line 20. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             strupr(szIFTemp);
-             if(!strcmp(szIFTemp,"RIP"))
-             {
-                od_control.user_rip=TRUE;
-                od_control.user_ansi=TRUE;
-             }
-             else if(szIFTemp[0]=='G')
-             {
-                od_control.user_rip=FALSE;
-                od_control.user_ansi=TRUE;
-             }
-             else
-             {
-                od_control.user_rip=FALSE;
-                od_control.user_ansi=FALSE;
-             }
-
-             /* Read line 21. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_screen_length=atoi(szIFTemp);
-
-             /* Read line 22. */
-             if(fgets((char *)apszDropFileInfo[8],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 23. */
-             if(fgets((char *)apszDropFileInfo[9],80,pfDropFile)==NULL) goto DropFileFail;
-             if(apszDropFileInfo[9][strlen(apszDropFileInfo[9])-1]!='\n')
-             {
-                int ch;
-                apszDropFileInfo[9][strlen(apszDropFileInfo[9])-1]='\n';
-                do
-                {
-                   ch = fgetc(pfDropFile);
-                } while(ch != '\n' && ch != EOF);
-             }
-
-             /* Read line 24. */
-again:
-             if(fgets((char *)apszDropFileInfo[10],80,pfDropFile)==NULL) goto DropFileFail;
-             if(strchr(apszDropFileInfo[10],',')!=NULL) goto again;
-
-             /* Read line 25. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             szIFTemp[15]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_subdate,szIFTemp);
-
-             /* Read line 26. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_num=atoi(szIFTemp);
-
-             /* Read line 27. */
-             if(fgets((char *)apszDropFileInfo[6],80,pfDropFile)==NULL) goto DropFileFail;
-
-             /* Read line 28. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_uploads=atoi(szIFTemp);
-
-             /* Read line 29. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_downloads=atoi(szIFTemp);
-
-             /* Read line 30. */
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_todayk=atoi(szIFTemp);
-
-             /* Read line 31. */
-             if(fgets((char *)apszDropFileInfo[21],80,pfDropFile)==NULL) goto DropFileFail;
-
-
-                                        /* Beginning of extending DOOR.SYS data */
-             /* Read line 32. */
-             fgets((char *)apszDropFileInfo[7],80,pfDropFile);
-             /* Read line 33. */
-             fgets((char *)apszDropFileInfo[11],80,pfDropFile);
-             /* Read line 34. */
-             fgets((char *)apszDropFileInfo[12],80,pfDropFile);
-             /* Read line 35. */
-             fgets((char *)apszDropFileInfo[13],80,pfDropFile);
-             /* Read line 36. */
-             if(fgets((char *)apszDropFileInfo[14],80,pfDropFile)!=NULL)
-             {
-                /* Read line 37. */
-                strncpy(od_control.user_birthday,apszDropFileInfo[7],8);
-                od_control.user_birthday[8]='\0';
-
-                /* Read line 38. */
-                strncpy(od_control.sysop_name,apszDropFileInfo[13],39);
-                od_control.sysop_name[39]='\0';
-                ODStringToName(od_control.sysop_name);
-
-                /* Read line 39. */
-                strncpy(od_control.user_handle,apszDropFileInfo[14],35);
-                od_control.user_handle[35]='\0';
-                ODStringToName(od_control.user_handle);
-
-                /* Read line 40. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                strncpy(od_control.event_starttime, szIFTemp, 5);
-                od_control.event_starttime[5] = '\0';
-
-                /* Read line 41. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                if(szIFTemp[0]=='y' || szIFTemp[0]=='Y')
-                   od_control.user_error_free=TRUE;
-                else
-                   od_control.user_error_free=FALSE;
-
-                /* Read line 42. */
-                if(fgets((char *)apszDropFileInfo[7],80,pfDropFile)==NULL) goto finished;
-                /* Read line 43. */
-                if(fgets((char *)apszDropFileInfo[13],80,pfDropFile)==NULL) goto finished;
-                /* Read line 44. */
-                if(fgets((char *)apszDropFileInfo[14],80,pfDropFile)==NULL) goto finished;
-                /* Read line 45. */
-                if(fgets((char *)apszDropFileInfo[15],80,pfDropFile)==NULL) goto finished;
-                /* Read line 46. */
-                if(fgets((char *)apszDropFileInfo[16],80,pfDropFile)==NULL) goto finished;
-
-                /* Read line 47. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                strncpy(od_control.user_logintime,szIFTemp,5);
-                od_control.user_logintime[5]='\0';
-
-                /* Read line 48. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                strncpy(od_control.user_lasttime,szIFTemp,5);
-                od_control.user_lasttime[5]='\0';
-
-                /* Read line 49. */
-                if(fgets((char *)apszDropFileInfo[18],80,pfDropFile)==NULL) goto finished;
-
-                /* Read line 50. */
-                if(fgets((char *)apszDropFileInfo[19],80,pfDropFile)==NULL) goto finished;
-
-                /* Read line 51. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                od_control.user_upk=atoi(szIFTemp);
-
-                /* Read line 52. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                od_control.user_downk=atoi(szIFTemp);
-
-                /* Read line 53. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                strncpy(od_control.user_comment,szIFTemp,79);
-                od_control.user_comment[79]='\0';
-                if(od_control.user_comment[strlen(od_control.user_comment)-1]=='\n')
-                   od_control.user_comment[strlen(od_control.user_comment)-1]='\0';
-
-                /* Read line 54. */
-                if(fgets((char *)apszDropFileInfo[20],80,pfDropFile)==NULL) goto finished;
-
-                /* Read line 55. */
-                if(fgets(szIFTemp,255,pfDropFile)==NULL) goto finished;
-                od_control.user_messages=atoi(szIFTemp);
-
-
-                od_control.od_info_type=DOORSYS_WILDCAT;
-             }
-          }
-
-          else                            /* DoorWay style DOOR.SYS */
-          {
-             od_control.od_info_type=DOORSYS_DRWY;
-
-             szIFTemp[35]='\0';
-             ODStringToName(szIFTemp);
-             strcpy(od_control.user_name,szIFTemp);
-
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.port=szIFTemp[0]-'1';
-
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             if(od_control.port==-1)
-             {
-                od_control.baud=0L;
-             }
-             else
-             {
-                od_control.baud=atol(szIFTemp);
-             }
-
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             od_control.user_timelimit=atoi(szIFTemp);
-
-             if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-             if(szIFTemp[0]=='G')
-             {
-                od_control.user_ansi=TRUE;
-             }
-             else
-             {
-                od_control.user_ansi=FALSE;
-             }
-          }
-finished:
-          fclose(pfDropFile);
-       }
-
-       else if(nFound==FOUND_CALLINFO_BBS)
-       {
-          if((pfDropFile=fopen(szDropFilePath,"r"))==NULL) goto DropFileFail;
-
-          od_control.od_info_type=CALLINFO;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          szIFTemp[35]='\0';
-          ODStringToName(szIFTemp);
-          strcpy(od_control.user_name,szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          szIFTemp[25]='\0';
-          ODStringToName(szIFTemp);
-          strcpy(od_control.user_location,szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_security=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_timelimit=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(szIFTemp[0]=='M')
-          {
-             od_control.user_ansi=FALSE;
-          }
-          else
-          {
-             od_control.user_ansi=TRUE;
-          }
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          szIFTemp[15]='\0';
-          ODStringToName(szIFTemp);
-          strcpy(od_control.user_password,szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          szIFTemp[15]='\0';
-          ODStringToName(szIFTemp);
-          strcpy(od_control.user_homephone,szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_screen_length=atoi(szIFTemp);
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.port=szIFTemp[3]-'1';
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.baud=atol(szIFTemp);
-
-          fclose(pfDropFile);
-       }
-       else if(nFound == FOUND_TRIBBS_SYS)
-       {
-          /* We have found reading a TRIBBS.SYS file. */
-
-          /* Attempt to open the file. */
-          if((pfDropFile = fopen(szDropFilePath, "r")) == NULL)
-          {
-             goto DropFileFail;
-          }
-
-          /* Record the drop file type being used. */
-          od_control.od_info_type = TRIBBSSYS;
-
-          /* Read line 1: User's number. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_num = atoi(szIFTemp);
-
-          /* Read line 2: User's name. */
-          if(fgets((char *)&od_control.user_name, 35, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-          ODStringToName(od_control.user_name);
-
-          /* Read line 3: User's password. */
-          if(fgets((char *)&od_control.user_password, 15, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-
-          /* Read line 4: User's security level. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_security = atoi(szIFTemp);
-
-          /* Read line 5: "Y" for expert mode, "N" for novice mode. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_expert = (szIFTemp[0] == 'Y');
-
-          /* Read line 6: "Y" for ANSI, "N" for TTY. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_ansi = (szIFTemp[0] == 'Y');
-
-          /* Read line 7: Minutes remaining for this call. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_timelimit = atoi(szIFTemp);
-
-          /* Read line 8: User's phone number. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          szIFTemp[15] = '\0';
-          ODStringToName(szIFTemp);
-          strcpy(od_control.user_homephone, szIFTemp);
-
-          /* Read line 9: User's location. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          ODStringToName(szIFTemp);
-          strncpy(od_control.user_location, szIFTemp, 25);
-
-          /* Read line 10: User's birthday. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          strncpy(od_control.user_birthday, szIFTemp, 8);
-          od_control.user_birthday[8] = '\0';
-          od_control.user_birthday[2] = '-';
-          od_control.user_birthday[5] = '-';
-
-          /* Read line 11: Node number. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.od_node = atoi(szIFTemp);
-
-          /* Read line 12: Serial port. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.port = atoi(szIFTemp) - 1;
-
-          /* Read line 13: Baud rate. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.od_connect_speed =
-             (od_control.port == -1) ? 0 : atol(szIFTemp);
-
-          /* Read line 14: Locked baud rate or 0 for unlocked port. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.baud = atol(szIFTemp);
-          if(od_control.baud == 0)
-          {
-             od_control.baud = od_control.od_connect_speed;
-          }
-
-          /* Read line 15: "Y" for RTS/CTS handshaking, "N" for none. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.od_com_flow_control = (szIFTemp[0] == 'Y')
-             ? COM_RTSCTS_FLOW : COM_NO_FLOW;
-
-          /* Read line 16: "Y" for error free connection, "N" otherwise. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_error_free = (szIFTemp[0] == 'Y');
-
-          /* Read line 17: BBS name. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          ODStringCopy(od_control.system_name, szIFTemp, 40);
-          ODStringToName(od_control.system_name);
-
-          /* Read line 18: Sysop's name. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          ODStringCopy(od_control.sysop_name, szIFTemp, 40);
-          ODStringToName(od_control.sysop_name);
-
-          /* Read line 19: User's alias. */
-          if(fgets((char *)&od_control.user_handle, 35, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-          ODStringToName(od_control.user_handle);
-
-          /* Read line 20: "Y" for RIP mode, "N" for no RIP mode. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_rip = (szIFTemp[0] == 'Y');
-
-          /* Now, close the TRIBBS.SYS file. */
-          fclose(pfDropFile);
-       }
-       else if(nFound == FOUND_DOOR32_SYS)
-       {
-          /* We have found a DOOR32.SYS file. */
-
-          /* Attempt to open the file. */
-          if((pfDropFile = fopen(szDropFilePath, "r")) == NULL)
-          {
-             goto DropFileFail;
-          }
-
-          /* Record the drop file type being used. */
-          od_control.od_info_type = DOOR32SYS;
-
-          /* Read line 1: Comm type. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          switch(atoi(szIFTemp)) {
-				case 0: /* local */
-					od_control.od_force_local = TRUE;	/* Is this the right way? */
-					break;
-				case 1: /* serial */
-					break;
-				case 2: /* telnet */
-					od_control.od_use_socket = TRUE;
-					break;
-			 }
-			 /* Read line 2: Comm or Socket handle. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.od_open_handle	= atoi(szIFTemp);
-
-			 /* Read line 3: Baud rate */
-          if(fgets((char *)apszDropFileInfo[0],255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.baud= (od_control.port == -1) ? 0 : atol((char *)apszDropFileInfo[0]);
-
-			 /* Read line 4: BBS Software name and version - unused. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-
-          /* Read line 5: User's number. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_num = atoi(szIFTemp);
-
-          /* Read line 6: User's real name. */
-          if(fgets((char *)&od_control.user_name, 35, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-          ODStringToName(od_control.user_name);
-
-          /* Read line 7: User's alias. */
-          if(fgets((char *)&od_control.user_handle, 35, pfDropFile) == NULL)
-          {
-             goto DropFileFail;
-          }
-          ODStringToName(od_control.user_handle);
-
-          /* Read line 8: User's security level */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-          od_control.user_security=atoi(szIFTemp);
-
-          /* Read line 9: Minutes remaining for this call. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.user_timelimit = atoi(szIFTemp);
-
-          /* Read line 10: User's Terminal type  */
-          if(fgets(szIFTemp,255,pfDropFile)==NULL) goto DropFileFail;
-    		 od_control.user_ansi=TRUE;
-			 switch(atoi(szIFTemp)) {
-					case 0: /* ASCII */
-						od_control.user_ansi=FALSE;
-						break;
-					case 1: /* ANSI */
-						od_control.user_ansi=TRUE;
-						break;
-					case 2: /* AVATAR */
-						od_control.user_avatar=TRUE;
-						break;
-					case 3: /* RIP */
-						od_control.user_rip=TRUE;
-						break;
-			 }
-
-          /* Read line 11: Current Node number. */
-          if(fgets(szIFTemp, 255, pfDropFile) == NULL) goto DropFileFail;
-          od_control.od_node = atoi(szIFTemp);
-
-          /* Now, close the DOOR32.SYS file. */
-          fclose(pfDropFile);
-       }
-       else
-       {
-DropFileFail:
-			 if(pfDropFile!=NULL)	/* Let's not leave the file open */
-				 fclose(pfDropFile);
-
-          od_control.od_info_type = NO_DOOR_FILE;
-
-          if(od_control.od_no_file_func != NULL)
-          {
-             (*od_control.od_no_file_func)();
-          }
-
-          /* Check whether force local has been turned on by the no */
-          /* file function.                                         */
-          if(od_control.od_force_local)
-          {
-             goto force_local;
-          }
-
-          /* Exit with failure if the no file function has not read a */
-          /* door information file itself.                            */
-          if(od_control.od_info_type == NO_DOOR_FILE
-            && (wPreSetInfo & PRESET_REQUIRED) != PRESET_REQUIRED)
-          {
-             ODInitError("Unable to read door information (drop) file.");
-             exit(od_control.od_errorlevel[1]);
-          }
-       }
-   }
-
-   ODInitPartTwo();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInitReadSFDoorsDAT()                              *** PRIVATE FUNCTION ***
- *
- * Reads an SFDOORS.DAT format drop file.
- *
- * Parameters: none
- *
- *     Return: TRUE on success or FALSE on failure.
- */
-static BOOL ODInitReadSFDoorsDAT(void)
-{
-   FILE *pfDropFile;
-
-   if((pfDropFile=fopen(szDropFilePath,"r"))==NULL) return(FALSE);
-
-   /* Line 1: User number. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_num=atoi(szIFTemp);
-
-   /* Line 2: User name. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   szIFTemp[35]='\0';
-   ODStringToName(szIFTemp);
-   strcpy(od_control.user_name,szIFTemp);
-
-   /* Line 3: User password. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   szIFTemp[15]='\0';
-   ODStringToName(szIFTemp);
-   strcpy(od_control.user_password,szIFTemp);
-
-   /* Line 4: Unused. */
-   if(fgets((char *)apszDropFileInfo[0],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 5: Modem <-> Serial port bps rate. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.baud=atol(szIFTemp);
-
-   /* Line 6: Serial port number. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.port=atoi(szIFTemp)-1;
-
-   /* Line 7: User's time remaining. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_timelimit=atoi(szIFTemp);
-
-   /* Line 8: Unused. */
-   if(fgets((char *)apszDropFileInfo[13],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 9: Unused. */
-   if(fgets((char *)apszDropFileInfo[14],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 10: User's ANSI mode setting. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   strupr(szIFTemp);
-   od_control.user_ansi=(szIFTemp[0]=='T');
-
-   /* Line 11: User's security level. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_security=atoi(szIFTemp);
-
-   /* Line 12: User's upload count. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_uploads=atoi(szIFTemp);
-
-   /* Line 13: User's download count. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_downloads=atoi(szIFTemp);
-
-   /* Line 14: Unused. */
-   if(fgets((char *)apszDropFileInfo[1],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 15: User's login time. */
-   if(fgets((char *)apszDropFileInfo[2],255,pfDropFile)==NULL) return(FALSE);
-   sprintf(od_control.user_logintime, "%02.2d:%02.2d",
-      atoi((char *)apszDropFileInfo[2]) % 60,
-      atoi((char *)apszDropFileInfo[2]) / 60);
-
-   /* Line 16: Unused. */
-   if(fgets((char *)apszDropFileInfo[3],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 17: Sysop next flag. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   strupr(szIFTemp);
-   od_control.sysop_next=(szIFTemp[0]=='T');
-
-   /* Line 18: Unused. */
-   if(fgets((char *)apszDropFileInfo[4],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 19: Unused. */
-   if(fgets((char *)apszDropFileInfo[5],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 20: Unused. */
-   if(fgets((char *)apszDropFileInfo[6],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 21: Error free connection flag. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   strupr(szIFTemp);
-   od_control.user_error_free=(szIFTemp[0]=='T');
-
-   /* Line 22: Current message area. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_msg_area=atoi(szIFTemp);
-
-   /* Line 23: Current file area. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_file_area=atoi(szIFTemp);
-
-   /* Line 24: Current node number. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.od_node=atoi(szIFTemp);
-
-   /* Line 25: Unused. */
-   if(fgets((char *)apszDropFileInfo[10],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 26: Unused. */
-   if(fgets((char *)apszDropFileInfo[11],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 27: Unused. */
-   if(fgets((char *)apszDropFileInfo[12],80,pfDropFile)==NULL) return(FALSE);
-
-   /* Line 28: Kilobytes downloaded today. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_todayk=atoi(szIFTemp);
-
-   /* Line 29: Kilobytes uploaded in total. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_upk=atoi(szIFTemp);
-
-   /* Line 30: Kilobytes downloaded in total. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   od_control.user_downk=atoi(szIFTemp);
-
-   /* Line 31: User's home phone number. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   szIFTemp[15]='\0';
-   ODStringToName(szIFTemp);
-   strcpy(od_control.user_homephone,szIFTemp);
-
-   /* Line 32: User's home location. */
-   if(fgets(szIFTemp,255,pfDropFile)==NULL) return(FALSE);
-   szIFTemp[25]='\0';
-   ODStringToName(szIFTemp);
-   strcpy(od_control.user_location,szIFTemp);
-
-   /* Line 33: Unused. */
-   if(fgets((char *)apszDropFileInfo[15],80,pfDropFile)==NULL)
-   {
-      apszDropFileInfo[15][0]='\0';
-   }
-
-   /* Line 34: RIP mode. */
-   if(fgets(szIFTemp,255,pfDropFile) != NULL)
-   {
-      strupr(szIFTemp);
-      od_control.user_rip = (szIFTemp[0] == 'T');
-   }
-
-   /* line 35: User wants chat. */
-   if(fgets(szIFTemp,255,pfDropFile) != NULL)
-   {
-      strupr(szIFTemp);
-      od_control.user_wantchat = (szIFTemp[0] == 'T');
-   }
-
-   /* Line 36: Unused. */
-   if(fgets((char *)apszDropFileInfo[17],80,pfDropFile)==NULL)
-   {
-      apszDropFileInfo[17][0]='\0';
-   }
-
-   /* Line 37: IRQ number. */
-   if(fgets(szIFTemp,255,pfDropFile) != NULL)
-   {
-      od_control.od_com_irq = atoi(szIFTemp);
-   }
-
-   /* Line 38: Serial port address. */
-   if(fgets(szIFTemp,255,pfDropFile) != NULL)
-   {
-      od_control.od_com_address = atoi(szIFTemp);
-   }
-
-   /* Line 39: Unused. */
-   if(fgets((char *)apszDropFileInfo[18],80,pfDropFile)==NULL)
-   {
-      apszDropFileInfo[18][0]='\0';
-   }
-
-   fclose(pfDropFile);
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInitReadExitInfo()                                *** PRIVATE FUNCTION ***
- *
- * Reads an EXITINFO.BBS format drop file.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODInitReadExitInfo(void)
-{
-   DWORD dwFileSize;
-   FILE *pfDropFile;
-   BYTE btCount;
-
-   od_control.od_extended_info=FALSE;
-   od_control.od_ra_info=FALSE;
-
-   /* Try to open EXITINFO.BBS. */
-   ODMakeFilename(szODWorkString, szExitinfoBBSPath, "EXITINFO.BBS",
-      sizeof(szExitinfoBBSPath));
-   if((pfDropFile = fopen(szODWorkString, "rb")) != NULL)
-   {
-      dwFileSize = ODFileSize(pfDropFile);
-
-      if(dwFileSize >= 2363)
-      {
-         if((pRA2ExitInfoRecord=malloc(sizeof(tRA2ExitInfoRecord)))!=NULL)
-         {
-            if(fread(pRA2ExitInfoRecord,1,2363,pfDropFile)==2363)
-            {
-               od_control.od_ra_info=TRUE;
-               od_control.od_extended_info=TRUE;
-               od_control.od_info_type=RA2EXITINFO;
-
-               od_control.baud=(long)pRA2ExitInfoRecord->baud;
-               od_control.system_calls=pRA2ExitInfoRecord->num_calls;
-               ODStringPascalToC(od_control.system_last_caller,pRA2ExitInfoRecord->last_caller,35);
-               ODStringPascalToC(od_control.system_last_handle,pRA2ExitInfoRecord->sLastHandle,35);
-               ODStringPascalToC(od_control.timelog_start_date,pRA2ExitInfoRecord->start_date,8);
-               memcpy(&od_control.timelog_busyperhour,&pRA2ExitInfoRecord->busyperhour,62);
-               ODStringPascalToC(od_control.user_name,pRA2ExitInfoRecord->name,35);
-               ODStringPascalToC(od_control.user_location,pRA2ExitInfoRecord->location,25);
-               ODStringPascalToC(od_control.user_org,pRA2ExitInfoRecord->organisation,50);
-               for(btCount=0;btCount<3;++btCount)
-                  ODStringPascalToC(od_control.user_address[btCount],pRA2ExitInfoRecord->address[btCount],50);
-               ODStringPascalToC(od_control.user_handle,pRA2ExitInfoRecord->handle,35);
-               ODStringPascalToC(od_control.user_comment,pRA2ExitInfoRecord->comment,80);
-               od_control.user_pwd_crc=pRA2ExitInfoRecord->password_crc;
-               ODStringPascalToC(od_control.user_dataphone,pRA2ExitInfoRecord->dataphone,15);
-               ODStringPascalToC(od_control.user_homephone,pRA2ExitInfoRecord->homephone,15);
-               ODStringPascalToC(od_control.user_lasttime,pRA2ExitInfoRecord->lasttime,5);
-               ODStringPascalToC(od_control.user_lastdate,pRA2ExitInfoRecord->lastdate,8);
-               od_control.user_attribute=pRA2ExitInfoRecord->attrib;
-               od_control.user_attrib2=pRA2ExitInfoRecord->attrib2;
-               memcpy(&od_control.user_flags,&pRA2ExitInfoRecord->flags,14);
-               od_control.user_security=pRA2ExitInfoRecord->sec;
-               od_control.user_lastread=pRA2ExitInfoRecord->lastread;
-               memcpy(&od_control.user_numcalls,&pRA2ExitInfoRecord->nocalls,29);
-               od_control.user_group=pRA2ExitInfoRecord->group;
-               memcpy(&od_control.user_combinedrecord,&pRA2ExitInfoRecord->combinedrecord,200);
-               ODStringPascalToC(od_control.user_firstcall,pRA2ExitInfoRecord->firstcall,8);
-               ODStringPascalToC(od_control.user_birthday,pRA2ExitInfoRecord->birthday,8);
-               ODStringPascalToC(od_control.user_subdate,pRA2ExitInfoRecord->subdate,8);
-               od_control.user_screenwidth=pRA2ExitInfoRecord->screenwidth;
-               od_control.user_language=pRA2ExitInfoRecord->language;
-               od_control.user_date_format=pRA2ExitInfoRecord->dateformat;
-               ODStringPascalToC(od_control.user_forward_to,pRA2ExitInfoRecord->forwardto,35);
-               memcpy(&od_control.user_msg_area,&pRA2ExitInfoRecord->msgarea,15);
-               od_control.user_sex = (pRA2ExitInfoRecord->sex == 1) ? 'M' : 'F';
-               od_control.user_attrib3=pRA2ExitInfoRecord->btAttribute3;
-               ODStringPascalToC(od_control.user_password,pRA2ExitInfoRecord->sPassword,15);
-               od_control.event_status=pRA2ExitInfoRecord->status;
-               ODStringPascalToC(od_control.event_starttime,pRA2ExitInfoRecord->starttime,5);
-               memcpy(&od_control.event_errorlevel,&pRA2ExitInfoRecord->errorlevel,3);
-               ODStringPascalToC(od_control.event_last_run,pRA2ExitInfoRecord->lasttimerun,8);
-               memcpy(&od_control.user_netmailentered,&pRA2ExitInfoRecord->netmailentered,2);
-               ODStringPascalToC(od_control.user_logintime,pRA2ExitInfoRecord->logintime,5);
-               ODStringPascalToC(od_control.user_logindate,pRA2ExitInfoRecord->logindate,8);
-               memcpy(&od_control.user_timelimit,&pRA2ExitInfoRecord->timelimit,6);
-               memcpy(&od_control.user_num,&pRA2ExitInfoRecord->userrecord,8);
-               ODStringPascalToC(od_control.user_timeofcreation,pRA2ExitInfoRecord->timeofcreation,5);
-               od_control.user_logon_pwd_crc=pRA2ExitInfoRecord->logonpasswordcrc;
-               od_control.user_wantchat=pRA2ExitInfoRecord->wantchat;
-               od_control.user_deducted_time=pRA2ExitInfoRecord->deducted_time;
-               for(btCount=0;btCount<50;++btCount)
-                  ODStringPascalToC(od_control.user_menustack[btCount],pRA2ExitInfoRecord->menustack[btCount],8);
-               od_control.user_menustackpointer=pRA2ExitInfoRecord->menustackpointer;
-               memcpy(&od_control.user_error_free,&pRA2ExitInfoRecord->error_free,3);
-               ODStringPascalToC(od_control.user_emsi_crtdef,pRA2ExitInfoRecord->emsi_crtdef,40);
-               ODStringPascalToC(od_control.user_emsi_protocols,pRA2ExitInfoRecord->emsi_protocols,40);
-               ODStringPascalToC(od_control.user_emsi_capabilities,pRA2ExitInfoRecord->emsi_capabilities,40);
-               ODStringPascalToC(od_control.user_emsi_requests,pRA2ExitInfoRecord->emsi_requests,40);
-               ODStringPascalToC(od_control.user_emsi_software,pRA2ExitInfoRecord->emsi_software,40);
-               memcpy(&od_control.user_hold_attr1,&pRA2ExitInfoRecord->hold_attr1,3);
-               ODStringPascalToC(od_control.user_reasonforchat,pRA2ExitInfoRecord->page_reason,77);
-               btRAStatusToSet = pRA2ExitInfoRecord->status_line-1;
-               ODStringPascalToC(od_control.user_last_cost_menu,pRA2ExitInfoRecord->last_cost_menu,8);
-               od_control.user_menu_cost=pRA2ExitInfoRecord->menu_cost_per_min;
-               od_control.user_rip=pRA2ExitInfoRecord->has_rip;
-               od_control.user_rip_ver=pRA2ExitInfoRecord->btRIPVersion;
-
-               od_control.user_ansi=od_control.user_attribute&8;
-               od_control.user_avatar=od_control.user_attrib2&2;
-            }
-
-            else
-            {
-               free(pRA2ExitInfoRecord);
-            }
-         }
-      }
-
-      else if(dwFileSize>=1493)
-      {
-         if(ODReadExitInfoPrimitive(pfDropFile,476))
-         {
-            if((pExtendedExitInfo=malloc(sizeof(tExtendedExitInfo)))!=NULL)
-            {
-               if(fread(pExtendedExitInfo,1,sizeof(tExtendedExitInfo), pfDropFile)==sizeof(tExtendedExitInfo))
-               {                 /* transfer info into od_control struct */
-                  ODStringPascalToC(od_control.user_timeofcreation,pExitInfoRecord->bbs.ra.timeofcreation,5);
-                  ODStringPascalToC(od_control.user_logonpassword,pExitInfoRecord->bbs.ra.logonpassword,15);
-                  od_control.user_wantchat=pExitInfoRecord->bbs.ra.wantchat;
-
-                  od_control.user_deducted_time=pExtendedExitInfo->deducted_time;
-                  for(btCount=0;btCount<50;++btCount)
-                  {
-                     ODStringPascalToC(od_control.user_menustack[btCount],pExtendedExitInfo->menustack[btCount],8);
-                  }
-                  od_control.user_menustackpointer=pExtendedExitInfo->menustackpointer;
-                  ODStringPascalToC(od_control.user_handle,pExtendedExitInfo->userhandle,35);
-                  ODStringPascalToC(od_control.user_comment,pExtendedExitInfo->comment,80);
-                  ODStringPascalToC(od_control.user_firstcall,pExtendedExitInfo->firstcall,8);
-                  memcpy(od_control.user_combinedrecord,pExtendedExitInfo->combinedrecord,25);
-                  ODStringPascalToC(od_control.user_birthday,pExtendedExitInfo->birthday,8);
-                  ODStringPascalToC(od_control.user_subdate,pExtendedExitInfo->subdate,8);
-                  od_control.user_screenwidth=pExtendedExitInfo->screenwidth;
-                  od_control.user_msg_area=pExtendedExitInfo->msgarea;
-                  od_control.user_file_area=pExtendedExitInfo->filearea;
-                  od_control.user_language=pExtendedExitInfo->language;
-                  od_control.user_date_format=pExtendedExitInfo->dateformat;
-                  ODStringPascalToC(od_control.user_forward_to,pExtendedExitInfo->forwardto,35);
-                  memcpy(&od_control.user_error_free,&pExtendedExitInfo->error_free,3);
-                  ODStringPascalToC(od_control.user_emsi_crtdef,pExtendedExitInfo->emsi_crtdef,40);
-                  ODStringPascalToC(od_control.user_emsi_protocols,pExtendedExitInfo->emsi_protocols,40);
-                  ODStringPascalToC(od_control.user_emsi_capabilities,pExtendedExitInfo->emsi_capabilities,40);
-                  ODStringPascalToC(od_control.user_emsi_requests,pExtendedExitInfo->emsi_requests,40);
-                  ODStringPascalToC(od_control.user_emsi_software,pExtendedExitInfo->emsi_software,40);
-                  memcpy(&od_control.user_hold_attr1,&pExtendedExitInfo->hold_attr1,3);
-
-                  od_control.od_ra_info=TRUE;
-                  od_control.od_extended_info=TRUE;
-                  od_control.od_info_type=RA1EXITINFO;
-               }
-            }
-         }
-      }
-
-      else if(dwFileSize>476)
-      {
-         if(dwFileSize > sizeof(tExitInfoRecord))
-         {
-            dwFileSize = sizeof(tExitInfoRecord);
-         }
-
-         if(ODReadExitInfoPrimitive(pfDropFile,(int)dwFileSize))
-         {
-            od_control.user_wantchat=pExitInfoRecord->bbs.qbbs.qwantchat;
-            for(btCount=0;btCount<pExitInfoRecord->bbs.qbbs.gosublevel;++btCount)
-            {
-               ODStringPascalToC(od_control.user_menustack[btCount],pExitInfoRecord->bbs.qbbs.menustack[btCount],8);
-            }
-            od_control.user_menustackpointer=pExitInfoRecord->bbs.qbbs.gosublevel;
-            ODStringPascalToC(od_control.user_menustack[od_control.user_menustackpointer],pExitInfoRecord->bbs.qbbs.menu,8);
-
-            od_control.od_extended_info=TRUE;
-            od_control.od_info_type=QBBS275EXITINFO;
-            nInitialElapsed=pExitInfoRecord->elapsed;
-
-            od_control.user_rip = pExitInfoRecord->bbs.qbbs.ripactive;
-         }
-      }
-
-      else if(dwFileSize>=452)
-      {
-         if(ODReadExitInfoPrimitive(pfDropFile,(int)dwFileSize))
-         {
-            ODStringPascalToC(od_control.user_timeofcreation,pExitInfoRecord->bbs.ra.timeofcreation,5);
-            ODStringPascalToC(od_control.user_logonpassword,pExitInfoRecord->bbs.ra.logonpassword,15);
-            od_control.user_wantchat=pExitInfoRecord->bbs.ra.wantchat;
-
-            od_control.od_extended_info=TRUE;
-            od_control.od_info_type=EXITINFO;
-         }
-      }
-
-      od_control.od_page_pausing=od_control.user_attribute&0x04;
-
-      fclose(pfDropFile);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInitPartTwo()                                     *** PRIVATE FUNCTION ***
- *
- * Called by od_init() to carry on with second stage of OpenDoors
- * initialization. The sole reason that this function exists is because some
- * compilers were unable to compile this file with a huge od_init() function
- * that had this code in the main od_init() body.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODInitPartTwo(void)
-{
-   BYTE btCount;
-
-   /* Initialize any colors that haven't already been set. */
-   if(!od_control.od_list_title_col) od_control.od_list_title_col = 0x0f;
-   if(!od_control.od_continue_col) od_control.od_continue_col = 0x0f;
-   if(!od_control.od_list_name_col) od_control.od_list_name_col = 0x0e;
-   if(!od_control.od_list_size_col) od_control.od_list_size_col = 0x0d;
-   if(!od_control.od_list_comment_col) od_control.od_list_comment_col = 0x03;
-   if(!od_control.od_list_offline_col) od_control.od_list_offline_col = 0x0c;
-   if(!od_control.od_local_win_col) od_control.od_local_win_col = 0x19;
-   if(!od_control.od_menu_title_col) od_control.od_menu_title_col = 0x74;
-   if(!od_control.od_menu_border_col) od_control.od_menu_border_col = 0x70;
-   if(!od_control.od_menu_text_col) od_control.od_menu_text_col = 0x70;
-   if(!od_control.od_menu_key_col) od_control.od_menu_key_col = 0x7f;
-   if(!od_control.od_menu_highkey_col) od_control.od_menu_highkey_col = 0x0f;
-   if(!od_control.od_menu_highlight_col)
-   {
-      od_control.od_menu_highlight_col = 0x07;
-   }
-
-   /* Color sequence delimiter characters. */
-   od_control.od_color_char = '\0';
-   od_control.od_color_delimiter = '`';
-
-   /* Enable sysop paging between the hours of 8:00am and 10:00pm. */
-   od_control.od_okaytopage = PAGE_USE_HOURS;
-   od_control.od_pagestartmin = 480;
-   od_control.od_pageendmin = 1320;
-
-   /* Default maximum user inactivity is 200 seconds. */
-   od_control.od_inactivity = 200;
-
-   /* Screen clearing is on by default. */
-   od_control.od_always_clear = TRUE;
-   
-   od_control.od_inactive_warning = 10;
-   od_control.od_cur_attrib = -1;
-
-   /* Enable screen clearing on door exit. */
-   od_control.od_clear_on_exit = TRUE;
-
-   /* RA/QBBS control codes are now disabled by default. */
-   od_control.od_no_ra_codes = TRUE;
-
-   if(od_control.od_chat_color1 == 0) od_control.od_chat_color1 = 0x0c;
-   if(od_control.od_chat_color2 == 0) od_control.od_chat_color2 = 0x0f;
-
-   /* Set default messages and prompts. */
-   od_control.od_before_shell = "\n\rPlease wait a moment...\n\r";
-   od_control.od_after_shell = "\n\r...Thanks for waiting\n\r\n\r";
-   od_control.od_help_text = "  Alt: [C]hat [H]angup [L]ockout [J]Dos [K]eyboard-Off [D]rop to BBS            ";
-   od_control.od_before_chat = "\n\rThe system operator has placed you in chat mode to talk with you:\n\r\n\r";
-   od_control.od_after_chat = "\n\rChat mode ended.\n\r\n\r";
-   od_control.od_inactivity_timeout = "\n\rMaximum user inactivity time has elapsed, please call again.\n\r\n\r";
-   od_control.od_inactivity_warning = "\n\rWARNING: Inactivity timeout in 10 seconds, press a key now to remain online.\n\r\n\r";
-   od_control.od_time_warning = "\n\rWARNING: You only have %d minute(s) remaining for this session.\n\r\n\r";
-   od_control.od_time_left = "%d mins   ";
-   od_control.od_sysop_next = "[SN] ";
-   od_control.od_no_keyboard = "[Keyboard]";
-   od_control.od_want_chat = "[Want-Chat]";
-   od_control.od_no_time = "\n\rSorry, you have used up of your time for this session.\n\r\n\r";
-   od_control.od_no_sysop = "\n\rSorry, the system operator is not available at this time.\n\r";
-   od_control.od_press_key = "Press [Enter] to continue";
-   od_control.od_chat_reason = "               Why would you like to chat? (Blank line to cancel)\n\r";
-   od_control.od_paging = "\n\rPaging system operator for chat";
-   od_control.od_no_response = " No response.\n\r\n\r";
-   od_control.od_status_line[0] = "                                                                     [Node:     ";
-   od_control.od_status_line[1] = "%s of %s at %lu BPS";
-   od_control.od_status_line[2] = "Security:        Time:                                               [F9]=Help ";
-   od_control.od_month[0] = "Jan";
-   od_control.od_month[1] = "Feb";
-   od_control.od_month[2] = "Mar";
-   od_control.od_month[3] = "Apr";
-   od_control.od_month[4] = "May";
-   od_control.od_month[5] = "Jun";
-   od_control.od_month[6] = "Jul";
-   od_control.od_month[7] = "Aug";
-   od_control.od_month[8] = "Sep";
-   od_control.od_month[9] = "Oct";
-   od_control.od_month[10] = "Nov";
-   od_control.od_month[11] = "Dec";
-   od_control.od_day[0] = "Sun";
-   od_control.od_day[1] = "Mon";
-   od_control.od_day[2] = "Tue";
-   od_control.od_day[3] = "Wed";
-   od_control.od_day[4] = "Thu";
-   od_control.od_day[5] = "Fri";
-   od_control.od_day[6] = "Sat";
-   od_control.od_offline = "[OFFLINE] ";
-   od_control.od_continue = "Continue? [Y/n/=]";
-   od_control.od_continue_yes = 'y';
-   od_control.od_continue_no = 'n';
-   od_control.od_continue_nonstop = '=';
-   od_control.od_help_text2 = OD_VER_STATUSLINE;
-   od_control.od_sending_rip = "Sending RIP file: ";
-   od_control.od_hanging_up = "Ending call...";
-   od_control.od_exiting = "Program is exiting...";
-   if(strlen(od_control.od_disable_dtr) == 0)
-   {
-      strcpy(od_control.od_disable_dtr, "~+++~  AT&D0|  ATO|");
-   }
-
-   nInitialRemaining = od_control.user_timelimit;
-
-   if(od_control.od_maxtime > 0 && od_control.od_maxtime <= 1440)
-   {
-      if(od_control.user_timelimit > (INT)od_control.od_maxtime)
-      {
-         od_control.od_maxtime_deduction
-            = od_control.user_timelimit-od_control.od_maxtime;
-         od_control.user_timelimit
-            = od_control.od_maxtime;
-      }
-   }
-
-   /* If sysop name is unkown, then use the word "Sysop". */
-   if(strlen(od_control.sysop_name) == 0)
-   {
-      strcpy(od_control.sysop_name, "Sysop");
-   }
-
-   /* If in foced local mode and user  name has not yet been set. */
-   if(od_control.od_force_local && od_control.user_name[0] == '\0')
-   {
-      /* If name prompting is not disabled, then turn on flag to prompt for */
-      /* user's name.                                                       */
-      if(!(od_control.od_disable & DIS_NAME_PROMPT))
-      {
-         bPromptForUserName = TRUE;
-      }
-
-      /* Use sysop's name as default user name. */
-      if(bSysopNameSet)
-      {
-         strcpy(od_control.user_name, szForcedSysopName);
-      }
-      else
-      {
-         strcpy(od_control.user_name, od_control.sysop_name);
-      }
-   }
-
-   dwFileBPS = od_control.baud;
-
-   /* Determine desired BPS rate. */
-   if(dwForcedBPS != 1)
-   {
-      if(od_control.od_disable & DIS_LOCAL_OVERRIDE || od_control.baud != 0)
-      {
-         od_control.baud = dwForcedBPS;
-      }
-   }
-
-   /* If we are not operating in local mode, then setup for serial I/O. */
-   if(od_control.baud != 0)
-   {
-      tComMethod ComMethod;
-
-      /* Attempt to allocate an OpenDoors port object. */
-      if(ODComAlloc(&hSerialPort) != kODRCSuccess)
-      {
-malloc_error:
-         ODInitError("Insufficient memory available to start up program.");
-         exit(od_control.od_errorlevel[1]);
-      }
-
-      /* Set socket I/O method, if specified by user. */
-      if(od_control.od_use_socket)
-      {
-         ODComSetPreferredMethod(hSerialPort, kComMethodSocket);
-      }
-
-#ifdef ODPLAT_WIN32
-      /* Check whether a handle has been provided by the caller. */
-      if(od_control.od_open_handle != 0)
-      {
-         if(ODComOpenFromExistingHandle(hSerialPort, od_control.od_open_handle)
-            != kODRCSuccess)
-         {
-            ODInitError("Unable to use provided serial port handle.");
-            exit(od_control.od_errorlevel[1]);
-         }
-      }
-      else
-#endif /* ODPLAT_WIN32 */
-      {
-         /* Set flow control type. */
-         switch(od_control.od_com_flow_control)
-         {
-            case COM_NO_FLOW:
-               ODComSetFlowControl(hSerialPort, FLOW_NONE);
-               break;
-            case COM_RTSCTS_FLOW:
-               ODComSetFlowControl(hSerialPort, FLOW_RTSCTS);
-               break;
-            case COM_DEFAULT_FLOW:
-               /* Don't say anything to the serial I/O module about flow */
-               /* control. */
-               break;
-            default:
-               /* We should never get here. */
-               ASSERT(FALSE);
-         }
-
-         /* Determine desired port. */
-         if(nForcedPort != -1) od_control.port=nForcedPort;
-
-         /* Set port number. */
-         ODComSetPort(hSerialPort, (BYTE)od_control.port);
-
-         /* If serial port address has been explicitly set, then set user's */
-         /* port address in serial port object.                             */
-         if(od_control.od_com_address != 0)
-         {
-            ODComSetPortAddress(hSerialPort, od_control.od_com_address);
-         }
-
-         /* If serial port IRQ line number has been explicitly set, then */
-         /* set user's setting in serial port object.                    */
-         if(od_control.od_com_irq >= 1 && od_control.od_com_irq < 15)
-         {
-            ODComSetIRQ(hSerialPort, od_control.od_com_irq);
-         }
-
-         /* Set BPS rate, if this is not disabled. */
-         if(!(od_control.od_disable&DIS_BPS_SETTING))
-         {
-            ODComSetSpeed(hSerialPort, od_control.baud);
-         }
-         else
-         {
-            ODComSetSpeed(hSerialPort, SPEED_UNSPECIFIED);
-         }
-
-         /* Set serial I/O method, if specified by user. */
-         if(od_control.od_no_fossil)
-         {
-            ODComSetPreferredMethod(hSerialPort, kComMethodUART);
-         }
-
-         /* Establish default buffer sizes */
-         if(od_control.od_com_rx_buf == 0)
-            od_control.od_com_rx_buf = 256;
-         if(od_control.od_com_tx_buf == 0)
-            od_control.od_com_tx_buf = 3072;
-
-         /* Set buffer sizes for serial port. */
-         ODComSetRXBuf(hSerialPort, od_control.od_com_rx_buf);
-         ODComSetTXBuf(hSerialPort, od_control.od_com_tx_buf);
-
-         /* Set FIFO enabled/disabled and trigger size */
-         if(od_control.od_com_no_fifo)
-         {
-            /* Disable UART FIFO buffers. */
-            ODComSetFIFO(hSerialPort, FIFO_DISABLE);
-         }
-         else
-         {
-            /* Enable FIFO, setting size of FIFO trigger. */
-            switch(od_control.od_com_fifo_trigger)
-            {
-               case 1:
-                  ODComSetFIFO(hSerialPort, FIFO_ENABLE | FIFO_TRIGGER_1);
-                  break;
-               case 4:
-                  ODComSetFIFO(hSerialPort, FIFO_ENABLE | FIFO_TRIGGER_4);
-                  break;
-               case 8:
-                  ODComSetFIFO(hSerialPort, FIFO_ENABLE | FIFO_TRIGGER_8);
-                  break;
-               case 14:
-                  ODComSetFIFO(hSerialPort, FIFO_ENABLE | FIFO_TRIGGER_14);
-                  break;
-               default:
-                  od_control.od_com_fifo_trigger = 4;
-                  ODComSetFIFO(hSerialPort, FIFO_ENABLE | FIFO_TRIGGER_4);
-            }
-         }
-
-#ifdef ODPLAT_DOS
-         /* Set od_kernel() to be idle function. */
-         ODComSetIdleFunction(hSerialPort, od_kernel);
-#endif /* ODPLAT_DOS */
-
-         /* Open serial port. */
-         switch(ODComOpen(hSerialPort))
-         {
-            case kODRCSuccess:
-               /* Serial port open succeeded, so proceed with OpenDoors */
-               /* initialization.                                       */
-               break;
-            case kODRCNoMemory:
-               goto malloc_error;
-            case kODRCNoPortAddress:
-               ODInitError("Serial port address is unknown, cannot continue.");
-               exit(od_control.od_errorlevel[1]);
-               break;
-            case kODRCNoUART:
-               ODInitError("No UART at specified port address, cannot continue.\n");
-               exit(od_control.od_errorlevel[1]);
-               break;
-            default:
-               ODInitError("Unable to access serial port, cannot continue.\n");
-               exit(od_control.od_errorlevel[1]);
-               break;
-         }
-      }
-
-      /* Raise DTR signal. */
-      ODComSetDTR(hSerialPort, TRUE);
-
-      /* Get serial I/O method actually being used. */
-      ODComGetMethod(hSerialPort, (tComMethod *)&ComMethod);
-      switch(ComMethod)
-      {
-         case kComMethodFOSSIL:
-            od_control.od_com_method = COM_FOSSIL;
-            break;
-         case kComMethodUART:
-            od_control.od_com_method = COM_INTERNAL;
-            break;
-         case kComMethodWin32:
-            od_control.od_com_method = COM_WIN32;
-            break;
-         case kComMethodDoor32:
-            od_control.od_com_method = COM_DOOR32;
-            break;
-			case kComMethodSocket:
-				od_control.od_com_method = COM_SOCKET;	/* Why are using doubling up constants here? */
-				break;
-         default:
-            ODInitError("No method of accessing serial port, cannot continue.\n");
-            exit(od_control.od_errorlevel[1]);
-            break;
-      }
-   }
-
-
-   /* If we are operating in local mode, then disable silent mode. */
-   if(od_control.baud == 0)
-   {
-      od_control.od_silent_mode = FALSE;
-   }
-
-   /* Setup local screen. */
-   ODScrnInitialize();
-#ifdef OD_TEXTMODE
-   ODScrnSetBoundary(1, 1, 80, 23);
-#else /* !OD_TEXTMODE */
-   ODScrnSetBoundary(1, 1, 80, 25);
-#endif /* !OD_TEXTMODE */
-
-#ifndef ODPLAT_WIN32
-   if(bPreset)
-   {
-      atexit(ODAtExitCallback);
-      bPreset = FALSE;
-   }
-#endif /* !ODPLAT_WIN32 */
-
-   /* Setup remote terminal for ANSI graphics if operating in RIP mode. */
-   if(od_control.user_rip)
-   {
-      od_clr_scr();
-   }
-
-#ifdef ODPLAT_WIN32
-   /* Startup the OpenDoors frame window, if we are not operating in silent */
-   /* mode.                                                                 */
-   if(!od_control.od_silent_mode)
-   {
-#ifdef OD_DLL
-      ODFrameStart(GetModuleHandle(OD_DLL_NAME), &hFrameThread);
-#else /* !OD_DLL */
-      ODFrameStart(GetModuleHandle(NULL), &hFrameThread);
-#endif /* !OD_DLL */
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Initialize the OpenDoors kernel. */
-   ODKrnlInitialize();
-
-#ifndef ODPLAT_WIN32
-   if(bPromptForUserName)
-   {
-      void *pWindow = ODScrnCreateWindow(10, 8, 70, 15,
-         od_control.od_local_win_col, od_control.od_prog_name,
-         od_control.od_local_win_col);
-
-      if(pWindow != NULL)
-      {
-         ODScrnSetCursorPos(12, 9);
-         ODScrnDisplayString("This program has been started in local mode,");
-         ODScrnSetCursorPos(12, 10);
-         ODScrnDisplayString("independently of a BBS system. When operating in this");
-         ODScrnSetCursorPos(12, 11);
-         ODScrnDisplayString("mode, you may specify what name you should be known to");
-         ODScrnSetCursorPos(12, 12);
-         ODScrnDisplayString("the program by.");
-         ODScrnSetCursorPos(12, 14);
-         ODScrnDisplayString("Your name:");
-         ODScrnLocalInput(23, 14, od_control.user_name, 35);
-         ODStringCopy(od_control.user_handle, od_control.user_name,
-            sizeof(od_control.user_name));
-         ODScrnDestroyWindow(pWindow);
-         ODScrnSetCursorPos(1, 1);
-         ODScrnSetAttribute(0x07);
-      }
-   }
-#endif /* !ODPLAT_WIN32 */
-
-#ifdef OD_TEXTMODE
-   /* Setup sysop status line/function key personality. */
-   if(pfSetPersonality == NULL)
-   {
-no_default:
-      if (od_control.od_default_personality == NULL)
-      {
-         pfCurrentPersonality = pdef_opendoors;
-      }
-      else
-      {
-         pfCurrentPersonality = od_control.od_default_personality;
-      }
-      (*pfCurrentPersonality)(20);
-      if(bRAStatus)
-      {
-         od_set_statusline(btRAStatusToSet);
-      }
-      else
-      {
-         od_set_statusline(0);
-      }
-   }
-   else
-   {
-      if(!((*pfSetPersonality)(szDesiredPersonality)))
-      {
-         goto no_default;
-      }
-   }
-#endif /* OD_TEXTMODE */
-
-   /* If connect speed has not been set yet, then set it to the */
-   /* serial port speed.                                        */
-   if(od_control.od_connect_speed == 0)
-   {
-      od_control.od_connect_speed = od_control.baud;
-   }
-
-   /* Initialize the array of characters to use for drawing boxes, */
-   /* window and menu boarders, etc.                               */
-   od_control.od_box_chars[0] = 218U;
-   od_control.od_box_chars[1] = 196U;
-   od_control.od_box_chars[2] = 191U;
-   od_control.od_box_chars[3] = 179U;
-   od_control.od_box_chars[4] = 192U;
-   od_control.od_box_chars[5] = 217U;
-
-   /* Enable pausing and stoping of listing. */
-   od_control.od_list_stop = TRUE;
-   od_control.od_list_pause = TRUE;
-
-   /* Initialize array of logfile messages. */
-   for(btCount = 0; btCount < DIM(apszLogMessages); ++btCount)
-   {
-      if(od_control.od_logfile_messages[btCount] == NULL)
-      {
-         (char *)od_control.od_logfile_messages[btCount]
-            = (char *)apszLogMessages[btCount];
-      }
-   }
-
-   /* Set log file name to default, if none has been specified already. */
-   if(strlen(od_control.od_logfile_name) == 0)
-   {
-      strcpy(od_control.od_logfile_name, "DOOR.LOG");
-   }
-
-   /* If OpenDoors log file system is installed, then start it up. */
-   if(od_control.od_logfile != NULL)
-   {
-       (*(OD_COMPONENT_CALLBACK *)od_control.od_logfile)();
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInitError()
- *
- * Called to display an error message when OpenDoors initialization fails,
- * forcing the program to exit.
- *
- * Parameters: pszErrorText - Pointer to the error message explaining the
- *                            reason for failure.
- *
- *     Return: void
- */
-void ODInitError(char *pszErrorText)
-{
-#ifdef ODPLAT_DOS
-   printf("%s: %s\n", od_control.od_prog_name, pszErrorText);
-   if(bParsedCmdLine)
-   {
-      printf("Use the -HELP command line option for help, or -LOCAL for local mode.\n");
-   }
-#endif
-#ifdef ODPLAT_WIN32
-   char *pszMessage;
-   if(!bParsedCmdLine ||
-      (pszMessage = malloc(strlen(pszErrorText) + 80)) == NULL)
-   {
-      MessageBox(NULL, pszErrorText, od_control.od_prog_name,
-         MB_ICONSTOP | MB_OK | MB_TASKMODAL);
-   }
-   else
-   {
-      sprintf(pszMessage,
-         "%s\nUse the -HELP command line option for help, or -LOCAL for local mode.",
-         pszErrorText);
-      MessageBox(NULL, pszMessage, od_control.od_prog_name,
-         MB_ICONSTOP | MB_OK | MB_TASKMODAL);
-      free(pszMessage);
-   }
-#endif
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInitLoginDlgProc()
- *
- * Dialog box proceedure for the local mode login dialog box.
- *
- * Parameters: hwndDlg  - Window handle to the dialog box.
- *
- *             uMsg     - Message ID.
- *
- *             wParam   - First message parameter.
- *
- *             lParam   - Second message parameter.
- *
- *     Return: TRUE if message is processed, FALSE otherwise.
- */
-#ifdef ODPLAT_WIN32
-BOOL CALLBACK ODInitLoginDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   switch(uMsg)
-   {
-      case WM_INITDIALOG:
-         ODFrameCenterWindowInParent(hwndDlg);
-
-         /* Set the title of the dialog box to the name of this program. */
-         SetWindowText(hwndDlg, od_control.od_prog_name);
-
-         /* The initial text in the user name dialog box should be the */
-         /* default user name.                                         */
-         SetWindowText(GetDlgItem(hwndDlg, IDC_USER_NAME),
-            od_control.user_name);
-
-         /* Limit the number of characters that may be entered as the */
-         /* user's name to the maximum size of the string.            */
-         SendMessage(GetDlgItem(hwndDlg, IDC_USER_NAME), EM_LIMITTEXT,
-            sizeof(od_control.user_name), 0L);
-
-         return(TRUE);
-
-      case WM_COMMAND:
-         /* If a command has been chosen. */
-         switch(LOWORD(wParam))
-         {
-            case IDOK:
-               /* If the OK button has been pressed, obtain the entered */
-               /* user name.                                            */
-               GetWindowText(GetDlgItem(hwndDlg, IDC_USER_NAME),
-                  od_control.user_name, sizeof(od_control.user_name));
-               ODStringCopy(od_control.user_handle, od_control.user_name,
-                  sizeof(od_control.user_name));
-
-               /* Now close the dialog. */
-               EndDialog(hwndDlg, IDOK);
-               break;
-
-            case IDCANCEL:
-               /* If the Cancel button has benn pressed, close the dialog. */
-               EndDialog(hwndDlg, IDCANCEL);
-               break;
-         }
-         return(TRUE);
-
-      default:
-         /* Otherwise, indicate that this message has not been processed. */
-         return(FALSE);
-   }
-}
-#endif /* ODPLAT_WIN32 */
diff --git a/src/odoors/ODInEx2.c b/src/odoors/ODInEx2.c
deleted file mode 100644
index c92f8cc1fbdd9f01d85e4ca68e14c2f0d8f75026..0000000000000000000000000000000000000000
--- a/src/odoors/ODInEx2.c
+++ /dev/null
@@ -1,1431 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODInEx2.c
- *
- * Description: Performs OpenDoors initialization and shutdown operations
- *              (od_init() and od_exit()), including drop file I/O. This
- *              module is broken into two files, ODInEx1.c and ODInEx2.c.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Oct 29, 1994  6.00  BP   New EXITINFO.BBS timelimit writing.
- *              Nov 01, 1994  6.00  BP   New directory access functions.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 13, 1994  6.00  BP   Remove include of dir.h.
- *              Dec 31, 1994  6.00  BP   Add DIR_ATTRIB_ARCH in file search.
- *              Dec 31, 1994  6.00  BP   Move _mt_init to new func in odplat.c
- *              Jan 01, 1995  6.00  BP   _waitdrain() -> ODWaitDrain().
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 01, 1996  6.00  BP   Added od_disable_dtr, DIS_DTR_DISABLE.
- *              Jan 04, 1996  6.00  BP   tODInQueueEvent -> tODInputEvent.
- *              Jan 19, 1996  6.00  BP   Don't use atexit() under Win32.
- *              Jan 21, 1996  6.00  BP   Try DTR disable sequence twice.
- *              Jan 21, 1996  6.00  BP   Use ODScrnShowMessage().
- *              Jan 23, 1996  6.00  BP   Added od_exiting.
- *              Jan 23, 1996  6.00  BP   Use ODProcessExit() instead of exit().
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add ODInQueueGetNextEvent() timeout.
- *              Jan 31, 1996  6.00  BP   Support new SFDOORS.DAT format.
- *              Feb 02, 1996  6.00  BP   Added RA 2.50 EXITINFO.BBS support.
- *              Feb 09, 1996  6.00  BP   Correctly translate RA 2.x sex field.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 23, 1996  6.00  BP   Make DTR disable code shared.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Added TRIBBS.SYS support.
- *              Mar 27, 1996  6.10  BP   Added WCNODEID to
- *              Jan 13, 1997  6.10  BP   Fixes for Door32 support.
- *              Oct 19, 2001  6.20  RS   Added TCP/IP socket (telnet) support.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODCom.h"
-#include "ODPlat.h"
-#include "ODTypes.h"
-#include "ODScrn.h"
-#include "ODInQue.h"
-#include "ODKrnl.h"
-#include "ODInEx.h"
-#include "ODUtil.h"
-
-
-/* Time difference leeway for door information files to be considered to */
-/* have been written during the same exit (door execution session).      */
-#define DROPFILE_TIME_LEEWAY 10
-
-/* Maximum length of modem response string. */
-#define MAX_RESPONSE_LEN 40
-
-/* Maximum time to wait for modem response string, in milliseconds. */
-#define RESPONSE_TIMEOUT 2000
-
-
-/* Environment variables that specify directories where drop files may be */
-/* found.                                                                 */
-static char *apszEnvVarNames[] =
-{
-   "RA",
-   "QUICK",
-   "PCB",
-   "BBS",
-   "WCNODEID",
-};
-#define NUM_DIR_ENV_VARS DIM(apszEnvVarNames)
-
-
-/* Local helper functions. */
-static INT ODSearchInDir(char **papszFileNames, INT nNumFileNames,
-   char *pszFound, char *pszDirectory);
-
-/* Currently, the following functions are only used in the Win32 version. */
-#ifdef ODPLAT_WIN32
-static BOOL ODSendModemCommand(char *pszCommand, int nRetries);
-static BOOL ODSendModemCommandOnce(char *pszCommand);
-static BOOL ODWaitForString(char *pszResponse, tODMilliSec ResponseTimeout);
-#endif /* ODPLAT_WIN32 */
-
-#ifdef OD_DIAGNOSTICS
-static char szDebugWorkString[500] = "";
-#endif /* OD_DIAGNOSTICS */
-
-
-
-/* ----------------------------------------------------------------------------
- * od_exit()
- *
- * Shuts down OpenDoors operations. Normally, the program is exited as soon
- * as OpenDoors is shutdown.
- *
- * Parameters: nErrorLevel - Result code to exit program with.
- *
- *             bTermCall   - TRUE to disconnect the user before exiting,
- *                           FALSE to leave the user connected.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_exit(INT nErrorLevel, BOOL bTermCall)
-{
-   BYTE btCount;
-   FILE *pfDropFile;
-   time_t nMaxTime;
-   time_t nDoorEndTime;
-   void *pWindow = NULL;
-   DWORD dwActiveMinutes;
-   static BOOL bExiting = FALSE;
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_exit()");
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Starting up od_exit()", "OpenDoors Diagnostics",
-         MB_OK);
-   }
-#endif
-
-   /* If this is a recursive od_exit() call, then ignore it. */
-   if(bExiting)
-   {
-      return;
-   }
-   bExiting = TRUE;
-
-   /* If user called od_exit() before doing anything else, then we first */
-   /* initialize OpenDoors in order to shutdown and exit.                */
-   if(!bODInitialized) od_init();
-
-   /* Update remaining time. */
-   od_control.user_timelimit += od_control.od_maxtime_deduction;
-
-   /* Calculate deducted time */
-   time(&nDoorEndTime);
-   ODDWordDivide(&dwActiveMinutes, NULL, nDoorEndTime - nStartupUnixTime, 60L);
-   od_control.user_time_used += ((nInitialRemaining
-      - od_control.user_timelimit) - (int)dwActiveMinutes);
-
-   /* Reset to original bps rate that was stored in drop file */
-   od_control.baud = dwFileBPS;
-
-   /* If function hook is defined. */
-   if(od_control.od_before_exit != NULL)
-   {
-      /* Then call it. */
-      (*od_control.od_before_exit)();
-   }
-
-   if(bTermCall && od_control.od_hanging_up != NULL)
-   {
-      pWindow = ODScrnShowMessage(od_control.od_hanging_up, 0);
-   }
-   else if(!bTermCall)
-   {
-      pWindow = ODScrnShowMessage(od_control.od_exiting, 0);
-   }
-
-   if(szOriginalDir != NULL)
-   {
-      ODDirChangeCurrent(szOriginalDir);
-      free(szOriginalDir);
-      szOriginalDir=NULL;
-   }
-
-   if(od_control.od_extended_info)     /* Update EXITINFO.BBS, if applicable */
-   {
-      ODMakeFilename(szExitinfoBBSPath, szExitinfoBBSPath, "EXITINFO.BBS",
-         sizeof(szExitinfoBBSPath));
-      if((pfDropFile = fopen(szExitinfoBBSPath, "r+b")) != NULL)
-      {
-         switch(od_control.od_info_type)
-         {
-            case RA2EXITINFO:
-               pRA2ExitInfoRecord->baud = (unsigned int)od_control.baud;
-               pRA2ExitInfoRecord->num_calls = od_control.system_calls;
-               ODStringCToPascal(pRA2ExitInfoRecord->last_caller,35,od_control.system_last_caller);
-               ODStringCToPascal(pRA2ExitInfoRecord->sLastHandle,35,od_control.system_last_handle);
-               ODStringCToPascal(pRA2ExitInfoRecord->start_date,8,od_control.timelog_start_date);
-               memcpy(&pRA2ExitInfoRecord->busyperhour,&od_control.timelog_busyperhour,62);
-               ODStringCToPascal(pRA2ExitInfoRecord->name,35,od_control.user_name);
-               ODStringCToPascal(pRA2ExitInfoRecord->location,25,od_control.user_location);
-               ODStringCToPascal(pRA2ExitInfoRecord->organisation,50,od_control.user_org);
-               for(btCount=0;btCount<3;++btCount)
-                  ODStringCToPascal(pRA2ExitInfoRecord->address[btCount],50,od_control.user_address[btCount]);
-               ODStringCToPascal(pRA2ExitInfoRecord->handle,35,od_control.user_handle);
-               ODStringCToPascal(pRA2ExitInfoRecord->comment,80,od_control.user_comment);
-               pRA2ExitInfoRecord->password_crc=od_control.user_pwd_crc;
-               ODStringCToPascal(pRA2ExitInfoRecord->dataphone,15,od_control.user_dataphone);
-               ODStringCToPascal(pRA2ExitInfoRecord->homephone,15,od_control.user_homephone);
-               ODStringCToPascal(pRA2ExitInfoRecord->lasttime,5,od_control.user_lasttime);
-               ODStringCToPascal(pRA2ExitInfoRecord->lastdate,8,od_control.user_lastdate);
-               pRA2ExitInfoRecord->attrib=od_control.user_attribute;
-               pRA2ExitInfoRecord->attrib2=od_control.user_attrib2;
-               memcpy(&pRA2ExitInfoRecord->flags,&od_control.user_flags,14);
-               pRA2ExitInfoRecord->sec=od_control.user_security;
-               pRA2ExitInfoRecord->lastread=od_control.user_lastread;
-               memcpy(&pRA2ExitInfoRecord->nocalls,&od_control.user_numcalls,29);
-               pRA2ExitInfoRecord->group=od_control.user_group;
-               memcpy(&pRA2ExitInfoRecord->combinedrecord,&od_control.user_combinedrecord,200);
-               ODStringCToPascal(pRA2ExitInfoRecord->firstcall,8,od_control.user_firstcall);
-               ODStringCToPascal(pRA2ExitInfoRecord->birthday,8,od_control.user_birthday);
-               ODStringCToPascal(pRA2ExitInfoRecord->subdate,8,od_control.user_subdate);
-               pRA2ExitInfoRecord->screenwidth=od_control.user_screenwidth;
-               pRA2ExitInfoRecord->language=od_control.user_language;
-               pRA2ExitInfoRecord->dateformat=od_control.user_date_format;
-               ODStringCToPascal(pRA2ExitInfoRecord->forwardto,35,od_control.user_forward_to);
-               memcpy(&pRA2ExitInfoRecord->msgarea,&od_control.user_msg_area,15);
-               pRA2ExitInfoRecord->sex = (od_control.user_sex == 'M') ? 1 : 2;
-               pRA2ExitInfoRecord->btAttribute3=od_control.user_attrib3;
-               ODStringCToPascal(pRA2ExitInfoRecord->sPassword,15,od_control.user_password);
-               pRA2ExitInfoRecord->status=od_control.event_status;
-               ODStringCToPascal(pRA2ExitInfoRecord->starttime,5,od_control.event_starttime);
-               memcpy(&pRA2ExitInfoRecord->errorlevel,&od_control.event_errorlevel,3);
-               ODStringCToPascal(pRA2ExitInfoRecord->lasttimerun,8,od_control.event_last_run);
-               memcpy(&pRA2ExitInfoRecord->netmailentered,&od_control.user_netmailentered,2);
-               ODStringCToPascal(pRA2ExitInfoRecord->logintime,5,od_control.user_logintime);
-               ODStringCToPascal(pRA2ExitInfoRecord->logindate,8,od_control.user_logindate);
-               memcpy(&pRA2ExitInfoRecord->timelimit,&od_control.user_timelimit,6);
-               memcpy(&pRA2ExitInfoRecord->userrecord,&od_control.user_num,8);
-               ODStringCToPascal(pRA2ExitInfoRecord->timeofcreation,5,od_control.user_timeofcreation);
-               pRA2ExitInfoRecord->logonpasswordcrc=od_control.user_logon_pwd_crc;
-               pRA2ExitInfoRecord->wantchat=od_control.user_wantchat;
-               pRA2ExitInfoRecord->deducted_time=od_control.user_deducted_time;
-               for(btCount=0;btCount<50;++btCount)
-                  ODStringCToPascal(pRA2ExitInfoRecord->menustack[btCount],8,od_control.user_menustack[btCount]);
-               pRA2ExitInfoRecord->menustackpointer=od_control.user_menustackpointer;
-               memcpy(&pRA2ExitInfoRecord->error_free,&od_control.user_error_free,3);
-               ODStringCToPascal(pRA2ExitInfoRecord->emsi_crtdef,40,od_control.user_emsi_crtdef);
-               ODStringCToPascal(pRA2ExitInfoRecord->emsi_protocols,40,od_control.user_emsi_protocols);
-               ODStringCToPascal(pRA2ExitInfoRecord->emsi_capabilities,40,od_control.user_emsi_capabilities);
-               ODStringCToPascal(pRA2ExitInfoRecord->emsi_requests,40,od_control.user_emsi_requests);
-               ODStringCToPascal(pRA2ExitInfoRecord->emsi_software,40,od_control.user_emsi_software);
-               memcpy(&pRA2ExitInfoRecord->hold_attr1,&od_control.user_hold_attr1,3);
-               ODStringCToPascal(pRA2ExitInfoRecord->page_reason,77,od_control.user_reasonforchat);
-               if(bRAStatus)
-               {
-                  pRA2ExitInfoRecord->status_line = btCurrentStatusLine + 1;
-               }
-
-               ODStringCToPascal(pRA2ExitInfoRecord->last_cost_menu,9,od_control.user_last_cost_menu);
-               pRA2ExitInfoRecord->menu_cost_per_min=od_control.user_menu_cost;
-               pRA2ExitInfoRecord->has_rip=od_control.user_rip;
-               pRA2ExitInfoRecord->btRIPVersion=od_control.user_rip_ver;
-
-               fwrite(pRA2ExitInfoRecord,1,sizeof(tRA2ExitInfoRecord),pfDropFile);
-               free(pRA2ExitInfoRecord);
-               break;
-
-            case EXITINFO:
-               ODStringCToPascal(pExitInfoRecord->bbs.ra.timeofcreation,5,od_control.user_timeofcreation);
-               ODStringCToPascal(pExitInfoRecord->bbs.ra.logonpassword,15,od_control.user_logonpassword);
-               pExitInfoRecord->bbs.ra.wantchat=od_control.user_wantchat;
-
-               ODWriteExitInfoPrimitive(pfDropFile,476);
-               break;
-
-
-            case RA1EXITINFO:
-               pExtendedExitInfo->deducted_time=od_control.user_deducted_time;
-
-               for(btCount=0;btCount<50;++btCount)
-               {
-                  ODStringCToPascal(pExtendedExitInfo->menustack[btCount],8,od_control.user_menustack[btCount]);
-               }
-
-               pExtendedExitInfo->menustackpointer=od_control.user_menustackpointer;
-               ODStringCToPascal(pExtendedExitInfo->userhandle,35,od_control.user_handle);
-               ODStringCToPascal(pExtendedExitInfo->comment,80,od_control.user_comment);
-               ODStringCToPascal(pExtendedExitInfo->firstcall,8,od_control.user_firstcall);
-               memcpy(pExtendedExitInfo->combinedrecord,od_control.user_combinedrecord,25);
-               ODStringCToPascal(pExtendedExitInfo->birthday,8,od_control.user_birthday);
-               ODStringCToPascal(pExtendedExitInfo->subdate,8,od_control.user_subdate);
-               pExtendedExitInfo->screenwidth=od_control.user_screenwidth;
-               pExtendedExitInfo->msgarea = (BYTE)od_control.user_msg_area;
-               pExtendedExitInfo->filearea = (BYTE)od_control.user_file_area;
-               pExtendedExitInfo->language=od_control.user_language;
-               pExtendedExitInfo->dateformat=od_control.user_date_format;
-               ODStringCToPascal(pExtendedExitInfo->forwardto,35,od_control.user_forward_to);
-               memcpy(&pExtendedExitInfo->error_free,&od_control.user_error_free,3);
-               ODStringCToPascal(pExtendedExitInfo->emsi_crtdef,40,od_control.user_emsi_crtdef);
-               ODStringCToPascal(pExtendedExitInfo->emsi_protocols,40,od_control.user_emsi_protocols);
-               ODStringCToPascal(pExtendedExitInfo->emsi_capabilities,40,od_control.user_emsi_capabilities);
-               ODStringCToPascal(pExtendedExitInfo->emsi_requests,40,od_control.user_emsi_requests);
-               ODStringCToPascal(pExtendedExitInfo->emsi_software,40,od_control.user_emsi_software);
-               memcpy(&pExtendedExitInfo->hold_attr1,&od_control.user_hold_attr1,3);
-
-               ODStringCToPascal(pExitInfoRecord->bbs.ra.timeofcreation,5,od_control.user_timeofcreation);
-               ODStringCToPascal(pExitInfoRecord->bbs.ra.logonpassword,15,od_control.user_logonpassword);
-               pExitInfoRecord->bbs.ra.wantchat=od_control.user_wantchat;
-
-               ODWriteExitInfoPrimitive(pfDropFile,476);
-               fwrite(pExtendedExitInfo,1,1017,pfDropFile);
-               free(pExtendedExitInfo);
-               break;
-
-
-            case QBBS275EXITINFO:
-               pExitInfoRecord->elapsed=nInitialElapsed;
-               pExitInfoRecord->bbs.qbbs.qwantchat=od_control.user_wantchat;
-               pExitInfoRecord->bbs.qbbs.gosublevel=od_control.user_menustackpointer;
-               for(btCount=0;btCount<pExitInfoRecord->bbs.qbbs.gosublevel;++btCount)
-               {
-                  ODStringCToPascal(pExitInfoRecord->bbs.qbbs.menustack[btCount],8,od_control.user_menustack[btCount]);
-               }
-               ODStringCToPascal(pExitInfoRecord->bbs.qbbs.menu,8,od_control.user_menustack[od_control.user_menustackpointer]);
-               pExitInfoRecord->bbs.qbbs.externlogoff = bTermCall ? 1 : 0;
-               pExitInfoRecord->bbs.qbbs.ripactive = od_control.user_rip ? 1 : 0;
-
-               ODWriteExitInfoPrimitive(pfDropFile,644);
-         }
-
-         fclose(pfDropFile);
-      }
-   }
-
-
-   switch(od_control.od_info_type)
-   {
-      case DOORSYS_GAP:
-      case DOORSYS_WILDCAT:
-         pfDropFile=fopen(szDropFilePath,"w");
-         if(od_control.baud==0L)
-         {
-            fprintf(pfDropFile,"COM0:\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"COM%d:\n",od_control.port+1);
-         }
-         fprintf(pfDropFile,"%s",apszDropFileInfo[0]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[1]);
-         fprintf(pfDropFile,"%u\n",od_control.od_node);
-         switch(btDoorSYSLock)
-         {
-            case 0:
-               fprintf(pfDropFile,"%lu\n",od_control.baud);
-               break;
-            case 1:
-               fprintf(pfDropFile,"N\n");
-               break;
-            case 2:
-               fprintf(pfDropFile,"Y\n");
-         }
-         fprintf(pfDropFile,"%s",apszDropFileInfo[3]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[4]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[5]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[22]);
-         strupr(od_control.user_name);
-         fprintf(pfDropFile,"%s\n",od_control.user_name);
-         fprintf(pfDropFile,"%s\n",od_control.user_location);
-         fprintf(pfDropFile,"%s\n",od_control.user_homephone);
-         fprintf(pfDropFile,"%s\n",od_control.user_dataphone);
-         fprintf(pfDropFile,"%s\n",od_control.user_password);
-         fprintf(pfDropFile,"%u\n",od_control.user_security);
-         fprintf(pfDropFile,"%d\n",od_control.user_numcalls);
-         fprintf(pfDropFile,"%s\n",od_control.user_lastdate);
-         fprintf(pfDropFile,"%u\n",(signed int)od_control.user_timelimit*60);
-         fprintf(pfDropFile,"%d\n",od_control.user_timelimit);
-         if(od_control.user_rip)
-         {
-            fprintf(pfDropFile,"RIP\n");
-         }
-         else if(od_control.user_ansi)
-         {
-            fprintf(pfDropFile,"GR\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"NG\n");
-         }
-         fprintf(pfDropFile,"%d\n",od_control.user_screen_length);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[8]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[9]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[10]);
-         fprintf(pfDropFile,"%s\n",od_control.user_subdate);
-         fprintf(pfDropFile,"%u\n",od_control.user_num);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[6]);
-         fprintf(pfDropFile,"%u\n",od_control.user_uploads);
-         fprintf(pfDropFile,"%u\n",od_control.user_downloads);
-         fprintf(pfDropFile,"%u\n",od_control.user_todayk);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[21]);
-
-
-         if(od_control.od_info_type==DOORSYS_WILDCAT)
-         {
-            fprintf(pfDropFile,"%s\n",od_control.user_birthday);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[11]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[12]);
-            fprintf(pfDropFile,"%s\n",od_control.sysop_name);
-            strupr(od_control.user_handle);
-            fprintf(pfDropFile,"%s\n",od_control.user_handle);
-            fprintf(pfDropFile,"%s\n",od_control.event_starttime);
-            if(od_control.user_error_free)
-               fprintf(pfDropFile,"Y\n");
-            else
-               fprintf(pfDropFile,"N\n");
-            fprintf(pfDropFile,"%s",apszDropFileInfo[7]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[13]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[14]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[15]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[16]);
-            fprintf(pfDropFile,"%s\n",od_control.user_logintime);
-            fprintf(pfDropFile,"%s\n",od_control.user_lasttime);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[18]);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[19]);
-            fprintf(pfDropFile,"%u\n",od_control.user_upk);
-            fprintf(pfDropFile,"%u\n",od_control.user_downk);
-            fprintf(pfDropFile,"%s\n",od_control.user_comment);
-            fprintf(pfDropFile,"%s",apszDropFileInfo[20]);
-            fprintf(pfDropFile,"%u\n",od_control.user_messages);
-         }
-
-         fclose(pfDropFile);
-         break;
-
-
-      case DOORSYS_DRWY:
-         pfDropFile=fopen(szDropFilePath,"w");
-         fprintf(pfDropFile,"%s\n",od_control.user_name);
-
-         if(od_control.baud==0L)
-         {
-            fprintf(pfDropFile,"-1\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"%d\n",od_control.port+1);
-         }
-
-         fprintf(pfDropFile,"%lu\n",od_control.baud);
-
-         fprintf(pfDropFile,"%d\n",od_control.user_timelimit);
-
-         if(od_control.user_ansi)
-         {
-            fprintf(pfDropFile,"G\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"M\n");
-         }
-
-         fclose(pfDropFile);
-         break;
-
-
-      case SFDOORSDAT:
-         pfDropFile=fopen(szDropFilePath,"w");
-
-         fprintf(pfDropFile,"%u\n",od_control.user_num);
-         fprintf(pfDropFile,"%s\n",od_control.user_name);
-         fprintf(pfDropFile,"%s\n",od_control.user_password);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[0]);
-         fprintf(pfDropFile,"%lu\n",od_control.baud);
-         fprintf(pfDropFile,"%d\n",od_control.port+1);
-         fprintf(pfDropFile,"%d\n",od_control.user_timelimit);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[13]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[14]);
-         if(od_control.user_ansi)
-         {
-            fprintf(pfDropFile,"TRUE\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"FALSE\n");
-         }
-         fprintf(pfDropFile,"%u\n",od_control.user_security);
-         fprintf(pfDropFile,"%u\n",od_control.user_uploads);
-         fprintf(pfDropFile,"%u\n",od_control.user_downloads);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[1]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[2]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[3]);
-         if(od_control.sysop_next)
-         {
-            fprintf(pfDropFile,"TRUE\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"FALSE\n");
-         }
-         fprintf(pfDropFile,"%s",apszDropFileInfo[4]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[5]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[6]);
-         if(od_control.user_error_free)
-         {
-            fprintf(pfDropFile,"TRUE\n");
-         }
-         else
-         {
-            fprintf(pfDropFile,"FALSE\n");
-         }
-
-         fprintf(pfDropFile,"%u\n",od_control.user_msg_area);
-         fprintf(pfDropFile,"%u\n",od_control.user_file_area);
-         fprintf(pfDropFile,"%u\n",od_control.od_node);
-
-         fprintf(pfDropFile,"%s",apszDropFileInfo[10]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[11]);
-         fprintf(pfDropFile,"%s",apszDropFileInfo[12]);
-         fprintf(pfDropFile,"%u\n",od_control.user_todayk);
-         fprintf(pfDropFile,"%u\n",od_control.user_upk);
-         fprintf(pfDropFile,"%u\n",od_control.user_downk);
-         fprintf(pfDropFile,"%s\n",od_control.user_homephone);
-         fprintf(pfDropFile,"%s\n",od_control.user_location);
-         if(apszDropFileInfo[15][0]!='\0')
-         {
-            fprintf(pfDropFile, "%s", apszDropFileInfo[15]);
-            fprintf(pfDropFile, od_control.user_rip ? "TRUE\n" : "FALSE\n");
-            fprintf(pfDropFile, od_control.user_wantchat ? "TRUE\n"
-               : "FALSE\n");
-            fprintf(pfDropFile, "%s", apszDropFileInfo[17]);
-            fprintf(pfDropFile, "%d\n", od_control.od_com_irq);
-            fprintf(pfDropFile, "%d\n", od_control.od_com_address);
-            fprintf(pfDropFile, "%s", apszDropFileInfo[18]);
-         }
-         fclose(pfDropFile);
-         break;
-
-
-        case CHAINTXT:
-           pfDropFile=fopen(szDropFilePath,"w");
-           fprintf(pfDropFile,"%d\n",od_control.user_num);
-           fprintf(pfDropFile,"%s\n",od_control.user_handle);
-           fprintf(pfDropFile,"%s\n",od_control.user_name);
-           fprintf(pfDropFile,"%s\n",od_control.user_callsign);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[0]);
-           fprintf(pfDropFile,"%c\n",od_control.user_sex);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[1]);
-           fprintf(pfDropFile,"%s\n",od_control.user_lastdate);
-           fprintf(pfDropFile,"%d\n",od_control.user_screenwidth);
-           fprintf(pfDropFile,"%d\n",od_control.user_screen_length);
-           fprintf(pfDropFile,"%d\n",od_control.user_security);
-           fprintf(pfDropFile,"%d\n",bIsSysop);
-           fprintf(pfDropFile,"%d\n",bIsCoSysop);
-           fprintf(pfDropFile,"%d\n",od_control.user_ansi);
-           if(od_control.baud==0L)
-           {
-              fprintf(pfDropFile,"0\n");
-           }
-           else
-           {
-              fprintf(pfDropFile,"1\n");
-           }
-           fprintf(pfDropFile,"    %d.00\n",od_control.user_timelimit*60);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[3]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[4]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[5]);
-           if(od_control.baud==0L)
-           {
-              fprintf(pfDropFile,"KB\n");
-           }
-           else
-           {
-              fprintf(pfDropFile,"%lu\n",od_control.baud);
-           }
-           fprintf(pfDropFile,"%d\n",od_control.port+1);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[6]);
-           fprintf(pfDropFile,"%s\n",od_control.user_password);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[2]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[7]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[8]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[9]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[10]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[11]);
-           fprintf(pfDropFile,"%s",apszDropFileInfo[12]);
-           fclose(pfDropFile);
-           break;
-        case TRIBBSSYS:
-           pfDropFile = fopen(szDropFilePath, "w");
-           fprintf(pfDropFile, "%u\n", od_control.user_num);
-           fprintf(pfDropFile, "%s\n", od_control.user_name);
-           fprintf(pfDropFile, "%s\n", od_control.user_password);
-           fprintf(pfDropFile, "%u\n", od_control.user_security);
-           fprintf(pfDropFile, "%c\n", od_control.user_expert ? 'Y' : 'N');
-           fprintf(pfDropFile, "%c\n", od_control.user_ansi ? 'Y' : 'N');
-           fprintf(pfDropFile, "%d\n", od_control.user_timelimit);
-           fprintf(pfDropFile, "%s\n", od_control.user_homephone);
-           fprintf(pfDropFile, "%s\n", od_control.user_location);
-          od_control.user_birthday[2] = '/';
-          od_control.user_birthday[5] = '/';
-           fprintf(pfDropFile, "%s\n", od_control.user_birthday);
-           fprintf(pfDropFile, "%d\n", od_control.od_node);
-           fprintf(pfDropFile, "%d\n", od_control.port + 1);
-           fprintf(pfDropFile, "%lu\n", od_control.od_connect_speed);
-           fprintf(pfDropFile, "%lu\n", od_control.baud);
-           fprintf(pfDropFile, "%c\n", (od_control.od_com_flow_control
-              == COM_RTSCTS_FLOW) ? 'Y' : 'N');
-           fprintf(pfDropFile, "%c\n", od_control.user_error_free ? 'Y' : 'N');
-           fprintf(pfDropFile, "%s\n", od_control.system_name);
-           fprintf(pfDropFile, "%s\n", od_control.sysop_name);
-           fprintf(pfDropFile, "%s\n", od_control.user_handle);
-           fprintf(pfDropFile, "%c\n", od_control.user_rip ? 'Y' : 'N');
-           fclose(pfDropFile);
-           break;
-   }
-
-   /* Deallocate temorary strings. */
-   for(btCount=0;btCount<25;++btCount)
-   {
-      free(apszDropFileInfo[btCount]);
-   }
-
-   /* If logfile system is active. */
-   if(pfLogClose != NULL)
-   {
-      /* Then close the logfile. */
-      (*pfLogClose)(nErrorLevel);
-   }
-
-   /* Disconnect the remote user if required. */
-   if(od_control.baud && bTermCall)
-   {
-      BOOL bCarrier;
-
-      /* Wait up to ten seconds for bufffer to drain. */
-      ODWaitDrain(10000);
-
-      /* Wait up to five seconds for no carrier */
-      ODComSetDTR(hSerialPort, FALSE);
-      nMaxTime = time(NULL) + 5L;
-
-      do
-      {
-         ODComCarrier(hSerialPort, &bCarrier);
-      } while(bCarrier && time(NULL) <= nMaxTime);
-
-      /* Raise DTR signal again. */
-      ODComSetDTR(hSerialPort, TRUE);
-   }
-
-   /* In Win32 version, disable DTR before closing serial port, if */
-   /* required.                                                    */
-#ifdef ODPLAT_WIN32
-   /* If we are operating in remote mode, and we should not hangup on the */
-   /* caller ...                                                          */
-   if(!bTermCall && od_control.baud)
-   {
-      ODInExDisableDTR();
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Remove the message that indicates we are in the process of exiting */
-   /* or hanging up.                                                     */
-   ODScrnRemoveMessage(pWindow);
-
-#ifndef ODPLAT_WIN32
-   /* Reset output area boundary to the entire screen. */
-   ODScrnSetBoundary(1,1,80,25);
-
-   /* Reset text color. */
-   ODScrnSetAttribute(0x07);
-
-   /* Clear screen if neccesary. */   
-   if(od_control.od_clear_on_exit)
-   {
-      ODScrnClear();
-   }
-   else
-   {
-      ODScrnSetCursorPos(1, 1);
-   }
-#endif /* !ODPLAT_WIN32 */
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Terminating kernel threads", "OpenDoors Diagnostics",
-         MB_OK);
-   }
-#endif
-   /* Shutdown the OpenDoors kernel. */
-   ODKrnlShutdown();
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Shutting down local screen", "OpenDoors Diagnostics",
-         MB_OK);
-   }
-#endif
-   /* Shutdown OpenDoors local screen module. */
-   ODScrnShutdown();
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Performing any final serial port deallocation",
-         "OpenDoors Diagnostics", MB_OK);
-   }
-#endif
-   /* If not operating in local mode, then deallocate serial port resources. */
-   if(od_control.baud != 0)
-   {
-      /* Close serial port. */
-      ODComClose(hSerialPort);
-
-      /* Deallocate serial port object. */
-      ODComFree(hSerialPort);
-   }
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Deallocating common queue", "OpenDoors Diagnostics",
-         MB_OK);
-   }
-#endif
-   /* Deallocate input buffer. */
-   ODInQueueFree(hODInputQueue);
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Going to inactive mode", "OpenDoors Diagnostics",
-         MB_OK);
-   }
-#endif
-   /* OpenDoors is no longer active. */
-   bODInitialized = FALSE;
-
-   /* od_exit() is no longer active. */
-   bExiting = FALSE;
-
-   /* If the client does not want a call to od_exit() to shutdown the */
-   /* application, but just to shutdown OpenDoors, then return now.   */
-   if(od_control.od_noexit) return;
-
-   /* If exit() has already been called, then do not call it again. */
-   if(bPreOrExit) return;
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-   {
-      MessageBox(NULL, "Terminating process", "OpenDoors Diagnostics", MB_OK);
-   }
-#endif
-   /* Exit with appropriate errorlevel. */
-   ODProcessExit(nErrorLevel);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSearchForDropFile()
- *
- * Searches for a door information (drop) file, given a list of possible drop
- * file names. Searches for the drop file first in the directory specified
- * by od_control.info_path. If a directory was specified in the configuration
- * file, this is where that directory name would be stored. This function will
- * then proceed to search the current directory and any directories specified
- * by recognized environment variables, until either a drop file is found, or
- * until all possibilities are exhaused.
- *
- * If a directory contains more than one supported dropfile, the choice of
- * drop files is narrowed to the most recently written file, and any files
- * written in the ten seconds before that file was written. Of these files,
- * the file with the highest priority (based on its position in the list of
- * possible drop file names) is selected. This heuristic attempts to ignore
- * any "old" drop files that may still be hanging around from another
- * program or another login session, while still choosing the file with the
- * most information.
- *
- * Parameters: papszFileNames - Array of possible drop file names.
- *
- *             nNumFilesNames - The number of names in papszFileNames.
- *
- *             pszFound       - If a drop file was found, this string
- *                              will be changed to point to the filename
- *                              of the file that was found.
- *
- *             pszDirectory   - If a drop file was found, this string
- *                              will be changed to contain the name of
- *                              the directory in which the file was found.
- *
- *     Return: Index in the array of the file that was found, or -1 if no
- *             potential drop file was found.
- */
-INT ODSearchForDropFile(char **papszFileNames, INT nNumFileNames,
-   char *pszFound, char *pszDirectory)
-{
-   BYTE btCount;
-   char *pszEnvVarSetting;
-   INT nResult;
-
-   ASSERT(papszFileNames != NULL);
-   ASSERT(nNumFileNames > 0);
-   ASSERT(pszFound != NULL);
-
-   /* First, look for the drop file(s) in the directory specified by */
-   /* od_control.info_path.                                          */
-   if(strlen(od_control.info_path) != 0)
-   {
-      if((nResult = ODSearchInDir(papszFileNames, nNumFileNames, pszFound,
-         od_control.info_path)) != -1)
-      {
-         if(pszDirectory != NULL) strcpy(pszDirectory, od_control.info_path);
-         return(nResult);
-      }
-   }
-
-   /* Next, look for the drop file(s) in the current directory. */
-   if((nResult = ODSearchInDir(papszFileNames, nNumFileNames, pszFound,
-      ".\\")) != -1)
-   {
-      if(pszDirectory != NULL) strcpy(pszDirectory, ".\\");
-      return(nResult);
-   }
-
-   /* Look through array of environment variables, checking whether any of */
-   /* them specify the name of a directory in which a drop file can be     */
-   /* found.                                                               */
-   ASSERT(DIM(apszEnvVarNames) == NUM_DIR_ENV_VARS);
-   for(btCount = 0; btCount < NUM_DIR_ENV_VARS; ++btCount)
-   {
-      if((pszEnvVarSetting = (char *)getenv(apszEnvVarNames[btCount])) != NULL)
-      {
-         if((nResult = ODSearchInDir(papszFileNames, nNumFileNames, pszFound,
-            pszEnvVarSetting)) != -1)
-         {
-            if(pszDirectory != NULL) strcpy(pszDirectory,pszEnvVarSetting);
-            return(nResult);
-         }
-      }
-   }
-
-   return(-1);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSearchInDir()                                     *** PRIVATE FUNCTION ***
- *
- * Private helper function used by ODSearchForDropFile(). Searches for a drop
- * file in a single specified directory. The heuristic for selecting a drop
- * file, if more than one exists, is described in the header for the
- * ODSearchForDropFile() function.
- *
- * Parameters: papszFileNames - Array of possible drop file names.
- *
- *             nNumFilesNames - The number of names in papszFileNames.
- *
- *             pszFound       - If a drop file was found, this string
- *                              will be changed to point to the filename
- *                              of the file that was found.
- *
- *             pszDirectory   - Name of the directory to search in.
- *
- *     Return: Index in the array of the file that was found, or -1 if no
- *             potential drop file was found.
- */
-static INT ODSearchInDir(char **papszFileNames, INT nNumFileNames,
-   char *pszFound, char *pszDirectory)
-{
-   BYTE btCount;
-   char szFullName[80];
-   INT nFound = -1;
-   tODDirHandle hDir;
-   tODDirEntry DirEntry;
-   time_t LatestTime = 0;
-
-   ASSERT(papszFileNames != NULL);
-   ASSERT(nNumFileNames > 0);
-   ASSERT(pszFound != NULL);
-   ASSERT(pszDirectory != NULL);
-
-   for(btCount=0; btCount < nNumFileNames; ++btCount)
-   {
-      /* Do not consider DORINFO1.DEF if a DORINFOx.DEF for this node has */
-      /* been found. */
-      if(btCount == 2 && nFound == 1)
-      {
-         continue;
-      }
-
-      ASSERT(papszFileNames[btCount] != NULL);
-
-      ODMakeFilename(szFullName, pszDirectory, (char *)papszFileNames[btCount],
-         sizeof(szFullName));
-
-      /* Attempt to open directory. */
-      if(ODDirOpen(szFullName, DIR_ATTRIB_NORMAL | DIR_ATTRIB_ARCH, &hDir)
-         == kODRCSuccess)
-      {
-         /* Read the first matching entry in the directory. */
-         ODDirRead(hDir, &DirEntry);
-
-         if(nFound == -1
-            || DirEntry.LastWriteTime > LatestTime + DROPFILE_TIME_LEEWAY)
-         {
-            if(!ODFileAccessMode(szFullName, 4))
-            {
-               nFound=btCount;
-               LatestTime = DirEntry.LastWriteTime;
-            }
-         }
-
-         /* Close the open directory. */
-         ODDirClose(hDir);
-      }
-   }
-
-   if(nFound != -1)
-   {
-      ODMakeFilename(pszFound, pszDirectory, (char *)papszFileNames[nFound],
-         160);
-   }
-
-   return(nFound);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODReadExitInfoPrimitive()
- *
- * Reads the core a of pre-RA2 style EXITINFO.BBS file.
- *
- * Parameters: pfDropFile - Pointer to already open EXITINFO.BBS file.
- *
- *             nCount     - Specifies the number of bytes to read.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-BOOL ODReadExitInfoPrimitive(FILE *pfDropFile, INT nCount)
-{
-   if((pExitInfoRecord=malloc(sizeof(tExitInfoRecord)))==NULL) return(FALSE);
-
-   if(fread(pExitInfoRecord,1,nCount,pfDropFile)!=(size_t)nCount)
-   {
-      return(FALSE);
-   }
-
-                                          /* now we read all the data from the */
-                                          /* EXITINFO structure to the OpenDoors */
-                                          /* control structure. This may look */
-                                          /* a bit messy, but it gets the job */
-                                          /* done, and allows the programmer */
-                                          /* to access all the strings in C */
-                                          /* format instead of Pascal */
-   od_control.baud=pExitInfoRecord->baud;
-   od_control.system_calls=pExitInfoRecord->num_calls;
-   ODStringPascalToC(od_control.system_last_caller,pExitInfoRecord->last_caller,35);
-   ODStringPascalToC(od_control.timelog_start_date,pExitInfoRecord->start_date,8);
-   memcpy(&od_control.timelog_busyperhour,&pExitInfoRecord->busyperhour,62);
-   ODStringPascalToC(od_control.user_name,pExitInfoRecord->uname,35);
-   ODStringPascalToC(od_control.user_location,pExitInfoRecord->uloc,25);
-   ODStringPascalToC(od_control.user_password,pExitInfoRecord->password,15);
-   ODStringPascalToC(od_control.user_dataphone,pExitInfoRecord->dataphone,12);
-   ODStringPascalToC(od_control.user_homephone,pExitInfoRecord->homephone,12);
-   ODStringPascalToC(od_control.user_lasttime,pExitInfoRecord->lasttime,5);
-   ODStringPascalToC(od_control.user_lastdate,pExitInfoRecord->lastdate,8);
-   memcpy(&od_control.user_attribute,&pExitInfoRecord->attrib,5);
-   od_control.user_net_credit=pExitInfoRecord->credit;
-   od_control.user_pending=pExitInfoRecord->pending;
-   od_control.user_messages=pExitInfoRecord->posted;
-   od_control.user_lastread=pExitInfoRecord->lastread;
-   od_control.user_security=pExitInfoRecord->sec;
-   od_control.user_numcalls=pExitInfoRecord->nocalls;
-   od_control.user_uploads=pExitInfoRecord->ups;
-   od_control.user_downloads=pExitInfoRecord->downs;
-   od_control.user_upk=pExitInfoRecord->upk;
-   od_control.user_downk=pExitInfoRecord->downk;
-   od_control.user_todayk=pExitInfoRecord->todayk;
-   memcpy(&od_control.user_time_used,&pExitInfoRecord->elapsed,6);
-   od_control.user_group=pExitInfoRecord->group;
-   od_control.user_xi_record=pExitInfoRecord->xirecord;
-   od_control.event_status=pExitInfoRecord->status;
-   ODStringPascalToC(od_control.event_starttime,pExitInfoRecord->starttime,5);
-   memcpy(&od_control.event_errorlevel,&pExitInfoRecord->errorlevel,3);
-   ODStringPascalToC(od_control.event_last_run,pExitInfoRecord->lasttimerun,8);
-   memcpy(&od_control.user_netmailentered,&pExitInfoRecord->netmailentered,2);
-   ODStringPascalToC(od_control.user_logintime,pExitInfoRecord->logintime,5);
-   ODStringPascalToC(od_control.user_logindate,pExitInfoRecord->logindate,8);
-
-   /* Note that the timelimit field is skipped here. This value has already */
-   /* been read from the DORINFOx.DEF file, and is not consistently written */
-   /* to the EXITINFO.BBS file by various BBS packages.                     */
-
-   memcpy(&od_control.user_loginsec,&pExitInfoRecord->loginsec,16);
-   od_control.user_ansi=od_control.user_attribute&8;
-   od_control.user_avatar=od_control.user_attrib2&2;
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODWriteExitInfoPrimitive()
- *
- * Writes the core a of pre-RA2 style EXITINFO.BBS file.
- *
- * Parameters: pfDropFile - Pointer to already open EXITINFO.BBS file.
- *
- *             nCount     - Number of bytes to be written.
- *
- *     Return: Number of bytes actually written.
- */
-INT ODWriteExitInfoPrimitive(FILE *pfDropFile, INT nCount)
-{
-   INT nToReturn;
-   DWORD dwActiveMinutes;
-   INT nUserTimeLost;
-   INT nTimeSubtractedBySysop;
-   time_t nCurrentUnixTime;
-
-   pExitInfoRecord->num_calls=od_control.system_calls;
-   ODStringCToPascal(pExitInfoRecord->last_caller,35,od_control.system_last_caller);
-   ODStringCToPascal(pExitInfoRecord->start_date,8,od_control.timelog_start_date);
-   memcpy(&pExitInfoRecord->busyperhour,&od_control.timelog_busyperhour,31);
-   ODStringCToPascal(pExitInfoRecord->uname,35,od_control.user_name);
-   ODStringCToPascal(pExitInfoRecord->uloc,25,od_control.user_location);
-   ODStringCToPascal(pExitInfoRecord->password,15,od_control.user_password);
-   ODStringCToPascal(pExitInfoRecord->dataphone,12,od_control.user_dataphone);
-   ODStringCToPascal(pExitInfoRecord->homephone,12,od_control.user_homephone);
-   ODStringCToPascal(pExitInfoRecord->lasttime,5,od_control.user_lasttime);
-   ODStringCToPascal(pExitInfoRecord->lastdate,8,od_control.user_lastdate);
-   memcpy(&pExitInfoRecord->attrib,&od_control.user_attribute,5);
-   pExitInfoRecord->credit=(WORD)od_control.user_net_credit;
-   pExitInfoRecord->pending=(WORD)od_control.user_pending;
-   pExitInfoRecord->posted=(WORD)od_control.user_messages;
-   pExitInfoRecord->lastread=(WORD)od_control.user_lastread;
-   pExitInfoRecord->sec=(WORD)od_control.user_security;
-   pExitInfoRecord->nocalls=(WORD)od_control.user_numcalls;
-   pExitInfoRecord->ups=(WORD)od_control.user_uploads;
-   pExitInfoRecord->downs=(WORD)od_control.user_downloads;
-   pExitInfoRecord->upk=(WORD)od_control.user_upk;
-   pExitInfoRecord->downk=(WORD)od_control.user_downk;
-   pExitInfoRecord->todayk=(WORD)od_control.user_todayk;
-   memcpy(&pExitInfoRecord->elapsed,&od_control.user_time_used,6);
-   pExitInfoRecord->group = (BYTE)od_control.user_group;
-   pExitInfoRecord->xirecord=(WORD)od_control.user_xi_record;
-   pExitInfoRecord->status=od_control.event_status;
-   pExitInfoRecord->status=od_control.event_status;
-   ODStringCToPascal(pExitInfoRecord->starttime,5,od_control.event_starttime);
-   memcpy(&pExitInfoRecord->errorlevel,&od_control.event_errorlevel,3);
-   ODStringCToPascal(pExitInfoRecord->lasttimerun,8,od_control.event_last_run);
-   memcpy(&pExitInfoRecord->netmailentered,&od_control.user_netmailentered,2);
-   ODStringCToPascal(pExitInfoRecord->logintime,5,od_control.user_logintime);
-   ODStringCToPascal(pExitInfoRecord->logindate,8,od_control.user_logindate);
-
-   /* Calculate new time limit based on how time was adjusted during door's */
-   /* execution.                                                            */
-   time(&nCurrentUnixTime);
-   ODDWordDivide(&dwActiveMinutes, NULL, nCurrentUnixTime-nStartupUnixTime, 60L);
-   nUserTimeLost = (nInitialRemaining - od_control.user_timelimit);
-   nTimeSubtractedBySysop = nUserTimeLost - (int)dwActiveMinutes;
-   pExitInfoRecord->timelimit -= nTimeSubtractedBySysop;
-
-   memcpy(&pExitInfoRecord->loginsec,&od_control.user_loginsec,16);
-
-   nToReturn=(fwrite(pExitInfoRecord,1,nCount,pfDropFile) == (size_t)nCount);
-   free(pExitInfoRecord);
-   return(nToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODAtExitCallback()
- *
- * OpenDoors sets up the C library to call back this function when the program
- * is about to exit. OpenDoors uses this function to attempt to trap the
- * condition where the programmer exits the program without explicitly calling
- * od_exit(). If the program is about to exit, and OpenDoors is still active,
- * then od_exit() is called.
- *
- * It is not recommended that the programmer using OpenDoors rely on this
- * mechanism, because:
- *
- *    1. It doesn't seem to be supported by all compilers.
- *
- *    2. It doesn't permit OpenDoors to determine the actual error level
- *       that the program is exiting with in order to report this information
- *       in the log file (if enabled).
- *
- * Parameters: none
- *
- *     Return: void
- */
-#ifndef ODPLAT_WIN32
-void ODAtExitCallback(void)
-{
-   if(bODInitialized)
-   {
-      bPreOrExit = TRUE;
-      if(od_control.od_errorlevel[0])
-      {
-         od_exit(od_control.od_errorlevel[7],FALSE);
-      }
-      else
-      {
-         od_exit(6,FALSE);
-      }
-   }
-}
-#endif /* !ODPLAT_WIN32 */
-
-
-/* Currently, these functions are only used in the Win32 version. */
-#ifdef ODPLAT_WIN32
-
-
-/* ----------------------------------------------------------------------------
- * ODSendModemCommand()                                *** PRIVATE FUNCTION ***
- *
- * Sends a sequence of commands to the modem, waiting for the specified
- * response between each command. The command sequence is retried the specified
- * number of times.
- *
- * Parameters: pszCommand - Command string to send to the modem, along with
- *                          response strings. Each of these are separated by
- *                          a space character. A pipe character ('|') denotes a
- *                          CR, and a tilde character ('~') denotes a one
- *                          second pause.
- *
- *             nRetries   - Number of times to retry command sequence.
- *
- *     Return: TRUE on success, or FALSE if some expected response string was
- *             not received from the modem after modem response timeout period.
- */
-static BOOL ODSendModemCommand(char *pszCommand, int nRetries)
-{
-   ASSERT(pszCommand != NULL);
-   ASSERT(nRetries >= 1);
-
-   while(nRetries--)
-   {
-      if(ODSendModemCommandOnce(pszCommand))
-      {
-         return(TRUE);
-      }
-   }
-
-   return(FALSE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSendModemCommandOnce()                            *** PRIVATE FUNCTION ***
- *
- * Sends a series of commands to the modem, waiting for the specified response
- * between each command.
- *
- * Parameters: pszCommand - Command string to send to the modem, along with
- *                          response strings. Each of these are separated by
- *                          a space character. A pipe character ('|') denotes a
- *                          CR, and a tilde character ('~') denotes a one
- *                          second pause.
- *
- *     Return: TRUE on success, or FALSE if some expected response string was
- *             not received from the modem after modem response timeout period.
- */
-static BOOL ODSendModemCommandOnce(char *pszCommand)
-{
-   char *pchCurrent;
-   char szResponse[MAX_RESPONSE_LEN + 1];
-   int nResponsePos;
-   BOOL bSendingCommand = TRUE;
-
-   ASSERT(pszCommand != NULL);
-
-   /* We must be operating in remote mode. */
-   ASSERT(od_control.baud != 0);
-
-   /* Loop through each character in the string. */
-   for(pchCurrent = pszCommand; *pchCurrent != '\0'; ++pchCurrent)
-   {
-      /* What we do with this character depends upon whether we are */
-      /* currently sending a command, or waiting for a response.    */
-      if(bSendingCommand)
-      {
-         switch(*pchCurrent)
-         {
-            case ' ':
-               /* A space character denotes that we should toggle between */
-               /* sending a command and receiving a response.             */
-               bSendingCommand = FALSE;
-
-               /* Start at the beginning of the empty response string. */
-               nResponsePos = 0;
-               szResponse[0] = '\0';
-               break;
-
-            case '|':
-               /* A pipe character denotes that a carriage return should be */
-               /* send to the modem.                                        */
-               ODComSendByte(hSerialPort, '\r');
-#ifdef OD_DIAGNOSTICS
-               strcat(szDebugWorkString, "\n");
-#endif /* OD_DIAGNOSTICS */
-               break;
-
-            case '~':
-               /* A tilde character denotes a 1 second pause. */
-               od_sleep(1000);
-               break;
-
-            default:
-               /* Otherwise, send this character as is. */
-               ODComSendByte(hSerialPort, *pchCurrent);
-#ifdef OD_DIAGNOSTICS
-               {
-                  char szAppend[2];
-                  szAppend[0] = *pchCurrent;
-                  szAppend[1] = 0;
-                  strcat(szDebugWorkString, szAppend);
-               }
-#endif /* OD_DIAGNOSTICS */
-         }
-
-         od_sleep(200);
-      }
-      else
-      {
-         /* We are currently building a string that we should wait for. */
-         switch(*pchCurrent)
-         {
-            case ' ':
-               /* A space character denotes that we should toggle between */
-               /* sending a command and receiving a response.             */
-
-               /* Wait until the response string we have built is received. */
-               if(!ODWaitForString(szResponse, RESPONSE_TIMEOUT))
-               {
-                  /* If string was not received, then return now. */
-                  return(FALSE);
-               }
-
-               /* Switch to sending command mode. */
-               bSendingCommand = TRUE;
-               break;
-
-            case '~':
-               /* Pauses are ignored in response strings. */
-               break;
-
-            default:
-               /* Otherwise, add this character to the response string. */
-               if(nResponsePos < MAX_RESPONSE_LEN)
-               {
-                  szResponse[nResponsePos] = *pchCurrent;
-                  ++nResponsePos;
-                  szResponse[nResponsePos] = '\0';
-               }
-         }
-      }
-   }
-
-   /* Return with success. */
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODWaitForString()                                   *** PRIVATE FUNCTION ***
- *
- * Waits for the specified string to be received from the modem, for up to
- * the specified length of time.
- *
- * Parameters: pszResponse     - Pointer to the string to wait for.
- *
- *             ResponseTimeout - The maximum time, in milliseconds, to wait.
- *
- *     Return: TRUE on success, or FALSE if some expected response string was
- *             not received from the modem after modem response timeout period.
- */
-static BOOL ODWaitForString(char *pszResponse, tODMilliSec ResponseTimeout)
-{
-   tODTimer Timer;
-   char szReceived[MAX_RESPONSE_LEN + 1] = "\0";
-   tODInputEvent InputEvent;
-
-   ASSERT(pszResponse != NULL);
-   ASSERT(ResponseTimeout > 0);
-
-   /* We must be operating in remote mode. */
-   ASSERT(od_control.baud != 0);
-
-   /* If response string is empty, then we don't wait for anything. */
-   if(strlen(pszResponse) == 0) return(TRUE);
-
-#ifdef OD_DIAGNOSTICS
-   strcat(szDebugWorkString, "[");
-#endif /* OD_DIAGNOSTICS */
-
-   ODTimerStart(&Timer, ResponseTimeout);
-   while(!ODTimerElapsed(&Timer))
-   {
-      if(ODInQueueGetNextEvent(hODInputQueue, &InputEvent,
-         ODTimerLeft(&Timer)) == kODRCSuccess)
-      {
-         if(InputEvent.bFromRemote && InputEvent.EventType == EVENT_CHARACTER)
-         {
-#ifdef OD_DIAGNOSTICS
-            {
-               char szAppend[2];
-               szAppend[0] = InputEvent.chKeyPress;
-               szAppend[1] = 0;
-               strcat(szDebugWorkString, szAppend);
-            }
-#endif /* OD_DIAGNOSTICS */
-
-            /* Add the received character to the received string. */
-            if(strlen(szReceived) == MAX_RESPONSE_LEN)
-            {
-               memmove(szReceived, szReceived + 1, MAX_RESPONSE_LEN);
-            }
-            szReceived[strlen(szReceived) + 1] = '\0';
-            szReceived[strlen(szReceived)] = InputEvent.chKeyPress;
-
-            /* If the sequence has been received, then return with success. */
-            if(strstr(szReceived, pszResponse) != NULL)
-            {
-#ifdef OD_DIAGNOSTICS
-               strcat(szDebugWorkString, "]");
-#endif /* OD_DIAGNOSTICS */
-               return(TRUE);
-            }
-         }
-      }
-      else
-      {
-         /* When no characters are waiting, allow other processes to run. */
-         od_sleep(0);
-      }
-   }
-
-#ifdef OD_DIAGNOSTICS
-   strcat(szDebugWorkString, "]");
-#endif OD_DIAGNOSTICS
-
-   /* Indicate that string was not received in the time alotted. */
-   return(FALSE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInExDisableDTR()
- *
- * Disables DTR response by the modem, if required.
- *
- * Parameters: None
- *
- *     Return: void
- */
-void ODInExDisableDTR(void)
-{
-   BOOL bCarrier;
-
-   /* If we are using the Door32 interface, then do not disable DTR. */
-   if(od_control.od_com_method == COM_DOOR32 || od_control.od_com_method == COM_SOCKET)
-   {
-      return;
-   }
-
-   /* Check that carrier detect signal is still present. */
-   ODComCarrier(hSerialPort, &bCarrier);
-   if(bCarrier)
-   {
-      /* Only disable DTR response if OpenDoors opened the serial port, */
-      /* and DTR disabling has not been explicitly turned off.          */
-      if(od_control.od_open_handle == 0
-         && !(od_control.od_disable & DIS_DTR_DISABLE))
-      {
-         if(!ODSendModemCommand(od_control.od_disable_dtr, 2))
-         {
-#ifdef OD_DIAGNOSTICS
-            if(od_control.od_internal_debug)
-            {
-               MessageBox(NULL, szDebugWorkString, "DTR Disable FAILED!",
-                  MB_OK);
-               szDebugWorkString[0] = '\0';
-            }
-#endif /* OD_DIAGNOSTICS */
-         }
-         else
-         {
-#ifdef OD_DIAGNOSTICS
-            if(od_control.od_internal_debug)
-            {
-               MessageBox(NULL, szDebugWorkString, "DTR Disable Succeeded!",
-                  MB_OK);
-               szDebugWorkString[0] = '\0';
-            }
-#endif /* OD_DIAGNOSTICS */
-         }
-      }
-   }
-}
-
-#endif /* ODPLAT_WIN32 */
diff --git a/src/odoors/ODInQue.c b/src/odoors/ODInQue.c
deleted file mode 100644
index f000142ad2a7a045b414d876dfbe2ecb7f073092..0000000000000000000000000000000000000000
--- a/src/odoors/ODInQue.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODInQue.h
- *
- * Description: OpenDoors input queue management. This input queue is where
- *              all input events (e.g. keystrokes) from both local and remote
- *              systems are combined into a single stream.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 16, 1995  6.00  BP   Created.
- *              Nov 17, 1995  6.00  BP   Added multithreading support.
- *              Jan 04, 1996  6.00  BP   tODInQueueEvent -> tODInputEvent.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add semaphore timeout.
- *              Jan 30, 1996  6.00  BP   Add ODInQueueGetNextEvent() timeout.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODGen.h"
-#include "ODInQue.h"
-#include "ODPlat.h"
-#include "ODKrnl.h"
-
-
-/* Input queue handle structure. */
-typedef struct
-{
-   tODInputEvent *paEvents;
-   INT nQueueEntries;
-   INT nInIndex;
-   INT nOutIndex;
-   time_t nLastActivityTime;
-#ifdef OD_MULTITHREADED
-   tODSemaphoreHandle hItemCountSemaphore;
-   tODSemaphoreHandle hAddEventSemaphore;
-#endif /* OD_MULTITHREADED */
-} tInputQueueInfo;
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueAlloc()
- *
- * Allocates a new input queue.
- *
- * Parameters: phInQueue         - Pointer to location where a handle to the
- *                                 newly allocated input queue should be
- *                                 stored.
- *
- *             nInitialQueueSize - The minimum number of events that the
- *                                 input queue should be able to hold.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODInQueueAlloc(tODInQueueHandle *phInQueue, INT nInitialQueueSize)
-{
-   tInputQueueInfo *pInputQueueInfo = NULL;
-   tODInputEvent *pInputQueue = NULL;
-   tODResult Result = kODRCNoMemory;
-
-   ASSERT(phInQueue != NULL);
-
-   if(phInQueue == NULL) return(kODRCInvalidCall);
-
-   /* Attempt to allocate a serial port information structure. */
-   pInputQueueInfo = malloc(sizeof(tInputQueueInfo));
-
-   /* If memory allocation failed, return with failure. */
-   if(pInputQueueInfo == NULL) goto CleanUp;
-
-   /* Initialize semaphore handles to NULL. */
-#ifdef OD_MULTITHREADED
-   pInputQueueInfo->hItemCountSemaphore = NULL;
-   pInputQueueInfo->hAddEventSemaphore = NULL;
-#endif /* OD_MULTITHREADED */
-   
-   /* Attempt to allocate space for the queue itself. */
-   pInputQueue = calloc(nInitialQueueSize, sizeof(tODInputEvent));
-   if(pInputQueue == NULL) goto CleanUp;
-
-   /* Create semaphores if this is a multithreaded platform. */
-#ifdef OD_MULTITHREADED
-   if(ODSemaphoreAlloc(&pInputQueueInfo->hItemCountSemaphore, 0,
-      nInitialQueueSize) != kODRCSuccess)
-   {
-      goto CleanUp;
-   }
-
-   if(ODSemaphoreAlloc(&pInputQueueInfo->hAddEventSemaphore, 1, 1)
-      != kODRCSuccess)
-   {
-      goto CleanUp;
-   }
-#endif /* OD_MULTITHREADED */
-
-   /* Initialize input queue information structure. */
-   pInputQueueInfo->paEvents = pInputQueue;
-   pInputQueueInfo->nQueueEntries = nInitialQueueSize;
-   pInputQueueInfo->nInIndex = 0;
-   pInputQueueInfo->nOutIndex = 0;
-
-   /* Convert intut queue information structure pointer to a handle. */
-   *phInQueue = ODPTR2HANDLE(pInputQueueInfo, tInputQueueInfo);
-
-   /* Reset the time of the last activity. */
-   ODInQueueResetLastActivity(*phInQueue);
-
-   Result = kODRCSuccess;
-
-CleanUp:
-   if(Result != kODRCSuccess)
-   {
-#ifdef OD_MULTITHREADED
-      if(pInputQueueInfo != NULL
-         && pInputQueueInfo->hItemCountSemaphore != NULL)
-      {
-         ODSemaphoreFree(pInputQueueInfo->hItemCountSemaphore);
-      }
-
-      if(pInputQueueInfo != NULL
-         && pInputQueueInfo->hAddEventSemaphore != NULL)
-      {
-         ODSemaphoreFree(pInputQueueInfo->hAddEventSemaphore);
-      }
-#endif /* OD_MULTITHREADED */
-
-      if(pInputQueue != NULL) free(pInputQueue);
-      if(pInputQueueInfo != NULL) free(pInputQueueInfo);
-      *phInQueue = ODPTR2HANDLE(NULL, tInputQueueInfo);
-   }
-
-   /* Return with the appropriate result code. */
-   return(Result);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueFree()
- *
- * Destroys an input queue that was previously created by ODInQueueAlloc().
- *
- * Parameters: hInQueue - Handle to the input queue to destroy.
- *
- *     Return: void
- */
-void ODInQueueFree(tODInQueueHandle hInQueue)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-
-   ASSERT(pInputQueueInfo != NULL);
-
-   /* Deallocate semaphores, if appropriate. */
-#ifdef OD_MULTITHREADED
-   ASSERT(pInputQueueInfo->hItemCountSemaphore != NULL);
-   ODSemaphoreFree(pInputQueueInfo->hItemCountSemaphore);
-#endif /* OD_MULTITHREADED */
-
-   /* Deallocate the input queue itself. */
-   ASSERT(pInputQueueInfo->paEvents != NULL);
-   free(pInputQueueInfo->paEvents);
-
-   /* Deallocate port information structure. */
-   free(pInputQueueInfo);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueWaiting()
- *
- * Determines whether or not an event is currently waiting in the input queue.
- *
- * Parameters: hInQueue - Handle to the input queue to check.
- *
- *     Return: TRUE if there is one or more waiting events, or FALSE if the
- *             queue is empty.
- */
-BOOL ODInQueueWaiting(tODInQueueHandle hInQueue)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-   BOOL bEventWaiting;
-
-   ASSERT(pInputQueueInfo != NULL);
-
-   /* There is data waiting in the queue if the in index is not equal to */
-   /* the out index.                                                     */
-   bEventWaiting = (pInputQueueInfo->nInIndex != pInputQueueInfo->nOutIndex);
-
-   return(bEventWaiting);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueAddEvent()
- *
- * Adds a new event to the input queue.
- *
- * Parameters: hInQueue  - Handle to the input queue to add an event to.
- *
- *             pEvent    - Pointer to the event structure to obtain the
- *                         event information from.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODInQueueAddEvent(tODInQueueHandle hInQueue,
-   tODInputEvent *pEvent)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-   INT nNextInPos;
-
-   ASSERT(pInputQueueInfo != NULL);
-   ASSERT(pEvent != NULL);
-   if(pInputQueueInfo == NULL || pEvent == NULL) return(kODRCInvalidCall);
-
-   /* Serialize access to add event function. */
-#ifdef OD_MULTITHREADED
-   ODSemaphoreDown(pInputQueueInfo->hAddEventSemaphore, OD_NO_TIMEOUT);
-#endif /* OD_MULTITHREADED */
-
-   /* Reset the time of the last activity. */
-   ODInQueueResetLastActivity(hInQueue);
-
-   /* Determine what the next in index would be after this addition to the */
-   /* queue.                                                               */
-   nNextInPos = (pInputQueueInfo->nInIndex + 1)
-      % pInputQueueInfo->nQueueEntries;
-
-   /* If the queue is full, then return an out of space error. */
-   if(nNextInPos == pInputQueueInfo->nOutIndex)
-   {
-      /* Allow further access to input queue. */
-#ifdef OD_MULTITHREADED
-      ODSemaphoreUp(pInputQueueInfo->hAddEventSemaphore, 1);
-#endif /* OD_MULTITHREADED */
-
-      return(kODRCNoMemory);
-   }
-
-   /* Otherwise, add the new event to the input queue. */
-   memcpy(&pInputQueueInfo->paEvents[pInputQueueInfo->nInIndex], pEvent,
-      sizeof(tODInputEvent));
-
-   /* Update queue in index. */
-   pInputQueueInfo->nInIndex = nNextInPos;
-
-   /* Increment queue items count semaphore. */
-#ifdef OD_MULTITHREADED
-   ODSemaphoreUp(pInputQueueInfo->hItemCountSemaphore, 1);
-#endif /* OD_MULTITHREADED */
-
-   /* Allow further access to add event function. */
-#ifdef OD_MULTITHREADED
-   ODSemaphoreUp(pInputQueueInfo->hAddEventSemaphore, 1);
-#endif /* OD_MULTITHREADED */
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueGetNextEvent()
- *
- * Obtains the next event from the input queue. If no events are currently
- * waiting in the input queue, this function blocks until an item is added
- * to the queue, or the maximum wait time is reached.
- *
- * Parameters: hInQueue - Handle to the input queue to obtain the next event
- *                        from.
- *
- *             pEvent   - Pointer to structure to store input event information
- *                        in.
- *
- *             Timeout  - Maximum time, in milliseconds, to wait for next input
- *                        event. A value of OD_NO_TIMEOUT causes this function
- *                        to only return when an input event is obtained.
- *
- *     Return: kODRCSuccess on succes, or kODRCTimeout if the maximum wait time
- *             is exceeded.
- */
-tODResult ODInQueueGetNextEvent(tODInQueueHandle hInQueue,
-   tODInputEvent *pEvent, tODMilliSec Timeout)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-
-   ASSERT(pInputQueueInfo != NULL);
-   ASSERT(pEvent != NULL);
-
-#ifdef OD_MULTITHREADED
-
-   /* In multithreaded implementations, we wait for there to be an item in  */
-   /* the queue by decrementing the queue size semaphore. This will cause   */
-   /* this thread to be blocked until an event is added to the queue, if it */
-   /* is currently empty.                                                   */
-
-   ODSemaphoreDown(pInputQueueInfo->hItemCountSemaphore, Timeout);
-
-#else /* !OD_MULTITHREADED */
-
-   /* In non-multithreaded implementations, we check queue in and out     */
-   /* indicies to determine whether there are any events waiting in the   */
-   /* queue. If the queue is empty we loop, calling od_kernel() to check  */
-   /* for new events and od_yeild() to give more time to other processors */
-   /* if there is nothing for us to do, until an event is added to the    */
-   /* queue.                                                              */
-   if(pInputQueueInfo->nInIndex == pInputQueueInfo->nOutIndex)
-   {
-      tODTimer Timer;
-
-      /* If a timeout has been specified, then start timer to keep track */
-      /* of how long we have been waiting.                               */
-      if(Timeout != 0 && Timeout != OD_NO_TIMEOUT)
-      {
-         ODTimerStart(&Timer, Timeout);
-      }
-
-      /* As soon as we see that there is nothing in the queue, we do an */
-      /* od_kernel() call to check for new input.                       */
-      CALL_KERNEL_IF_NEEDED();
-
-      /* As long as we don't have new input, we loop, yielding to other */
-      /* processes, and then giving od_kernel() a chance to run.        */
-      while(pInputQueueInfo->nInIndex == pInputQueueInfo->nOutIndex)
-      {
-         /* If a timeout has been specified, then ensure that the maximum */
-         /* wait time has not elapsed.                                    */
-         if(Timeout != 0 && Timeout != OD_NO_TIMEOUT
-            && ODTimerElapsed(&Timer))
-         {
-            return(kODRCTimeout);
-         }
-
-         /* Yield the processor to other tasks. */
-         od_sleep(0);
-
-         /* Call od_kernel(). */
-         CALL_KERNEL_IF_NEEDED();
-      }
-   }
-
-#endif /* !OD_MULTITHREADED */
-
-   /* Copy next input event from the queue into the caller's structure. */
-   memcpy(pEvent, &pInputQueueInfo->paEvents[pInputQueueInfo->nOutIndex],
-      sizeof(tODInputEvent));
-
-   /* Move out pointer to the next queue item, wrapping back to the start */
-   /* of the queue if needed.                                             */
-   pInputQueueInfo->nOutIndex
-      = (pInputQueueInfo->nOutIndex + 1) % pInputQueueInfo->nQueueEntries;
-
-   /* Now, return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueEmpty()
- *
- * Removes all events from the input queue.
- *
- * Parameters: hInQueue - Handle to the input queue to be emptied.
- *
- *     Return: void
- */
-void ODInQueueEmpty(tODInQueueHandle hInQueue)
-{
-   tODInputEvent InputEvent;
-
-   ASSERT(hInQueue != NULL);
-
-   /* Remove all items from the queue. */
-   while(ODInQueueWaiting(hInQueue))
-   {
-      ODInQueueGetNextEvent(hInQueue, &InputEvent, OD_NO_TIMEOUT);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueGetLastActivity()
- *
- * Returns the time of the last input activity. This is the latest of the time
- * that the queue was created, the time of the last call to
- * ODInQueueAddEvent() on this input queue, and the time of the last call to
- * ODInQueueResetLastActivity() on this input queue.
- *
- * Parameters: hInQueue - Handle to the input queue.
- *
- *     Return: void
- */
-time_t ODInQueueGetLastActivity(tODInQueueHandle hInQueue)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-
-   ASSERT(pInputQueueInfo != NULL);
-
-   /* Returns the last activity time. */
-   return(pInputQueueInfo->nLastActivityTime);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODInQueueResetLastActivity()
- *
- * Resets the time of the last input activity to the current time.
- *
- * Parameters: hInQueue - Handle to the input queue.
- *
- *     Return: void
- */
-void ODInQueueResetLastActivity(tODInQueueHandle hInQueue)
-{
-   tInputQueueInfo *pInputQueueInfo = ODHANDLE2PTR(hInQueue, tInputQueueInfo);
-
-   ASSERT(pInputQueueInfo != NULL);
-
-   /* Resets the last activity time to the current time. */
-   pInputQueueInfo->nLastActivityTime = time(NULL);
-}
diff --git a/src/odoors/ODInQue.h b/src/odoors/ODInQue.h
deleted file mode 100644
index 3be1e4ded94f8387da380f60d94ea1607aa02934..0000000000000000000000000000000000000000
--- a/src/odoors/ODInQue.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODInQue.h
- *
- * Description: OpenDoors input queue management. This input queue is where
- *              all input events (e.g. keystrokes) from both local and remote
- *              systems are combined into a single stream.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 16, 1995  6.00  BP   Created.
- *              Jan 04, 1996  6.00  BP   Moved event type defs to OpenDoor.h.
- *              Jan 04, 1996  6.00  BP   tODInQueueEvent -> tODInputEvent.
- *              Jan 30, 1996  6.00  BP   Add ODInQueueGetNextEvent() timeout.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODINQUE
-#define _INC_ODINQUE
-
-#include <time.h>
-
-#include "ODTypes.h"
-
-/* OpenDoors input queue handle. */
-typedef tODHandle tODInQueueHandle;
-
-/* Input queue functions. */
-tODResult ODInQueueAlloc(tODInQueueHandle *phInQueue,  INT nInitialQueueSize);
-void ODInQueueFree(tODInQueueHandle hInQueue);
-BOOL ODInQueueWaiting(tODInQueueHandle hInQueue);
-tODResult ODInQueueAddEvent(tODInQueueHandle hInQueue,
-   tODInputEvent *pEvent);
-tODResult ODInQueueGetNextEvent(tODInQueueHandle hInQueue,
-   tODInputEvent *pEvent, tODMilliSec Timeout);
-void ODInQueueEmpty(tODInQueueHandle hInQueue);
-time_t ODInQueueGetLastActivity(tODInQueueHandle hInQueue);
-void ODInQueueResetLastActivity(tODInQueueHandle hInQueue);
-
-#endif /* _INC_ODINQUE */
diff --git a/src/odoors/ODInfo.ico b/src/odoors/ODInfo.ico
deleted file mode 100644
index 842108fe741c285deee0f943a75a1df3e36e6e6f..0000000000000000000000000000000000000000
Binary files a/src/odoors/ODInfo.ico and /dev/null differ
diff --git a/src/odoors/ODKrnl.c b/src/odoors/ODKrnl.c
deleted file mode 100644
index 355a691e4d1756f730041f0ba67f78c94e9d4517..0000000000000000000000000000000000000000
--- a/src/odoors/ODKrnl.c
+++ /dev/null
@@ -1,1559 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODKrnl.c
- *
- * Description: Contains the OpenDoors kernel, which is responsible for many
- *              of the core functions which continue regardless of what the
- *              client program is doing. The implementation of this file is
- *              central to the OpenDoors architecture. The functionality
- *              implemented by the OpenDoors kernel includes (but is not
- *              limited to):
- *
- *                     - Obtaining and  input from the user, through the modem
- *                       and possibly the local keyboard.
- *                     - Monitoring maximum time and inactivity time limits.
- *                     - Responding to loss of carrier.
- *                     - Forcing the status line to be updated regularily,
- *                       on platforms that it exists.
- *                     - Implementing the system operator <-> remote user chat
- *                       mode.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Jan 01, 1995  6.00  BP   Split off from odcore.c
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 15, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Nov 21, 1995  6.00  BP   Ported to Win32.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 13, 1995  6.00  BP   Moved chat mode code to ODKrnl.h.
- *              Dec 24, 1995  6.00  BP   od_chat_active = TRUE on chat start.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 04, 1996  6.00  BP   tODInQueueEvent -> tODInputEvent.
- *              Jan 12, 1996  6.00  BP   Added bOnlyShiftArrow.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add semaphore timeout.
- *              Feb 06, 1996  6.00  BP   Added od_silent_mode.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 23, 1996  6.00  BP   Only create active semapore once.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Prevent TC generated N_SCOPY@ call.
- *              Mar 13, 1996  6.10  BP   bOnlyShiftArrow -> nArrowUseCount.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- *              Oct 22, 2001  6.21  RS   Lowered thread priorities to normal.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include <limits.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODCom.h"
-#include "ODKrnl.h"
-#include "ODScrn.h"
-#include "ODInQue.h"
-#include "ODInEx.h"
-#ifdef ODPLAT_WIN32
-#include "ODFrame.h"
-#endif /* ODPLAT_WIN32 */
-
-
-/* Multithreading performance tuning. */
-#define REMOTE_INPUT_THREAD_PRIORITY      OD_PRIORITY_NORMAL /* was ABOVE_NORMAL */
-#define NO_CARRIER_THREAD_PRIORITY        OD_PRIORITY_NORMAL /* was ABOVE_NORMAL */
-#define NO_CARRIER_THREAD_SLEEP_TIME      6000
-#define TIME_UPDATE_THREAD_PRIORITY       OD_PRIORITY_NORMAL
-#define TIME_UPDATE_THREAD_SLEEP_TIME     3000
-
-/* Misc performance tuning. */
-#define STATUS_UPDATE_PERIOD        3L
-#define CHAT_YIELD_PERIOD           25L
-
-/* Pending command identifiers. */
-#define KERNEL_FUNC_CHATTOGGLE      0x0001
-
-/* Private function prototypes. */
-static void ODKrnlHandleReceivedChar(char chReceived, BOOL bFromRemote);
-static void ODKrnlTimeUpdate(void);
-static void ODKrnlChatCleanup(void);
-static void ODKrnlChatMode(void);
-
-/* Functions specific to the multithreaded implementation of the kernel. */
-#ifdef OD_MULTITHREADED
-/* Thread proceedures. */
-DWORD OD_THREAD_FUNC ODKrnlRemoteInputThread(void *pParam);
-DWORD OD_THREAD_FUNC ODKrnlNoCarrierThread(void *pParam);
-DWORD OD_THREAD_FUNC ODKrnlTimeUpdateThread(void *pParam);
-DWORD OD_THREAD_FUNC ODKrnlChatThread(void *pParam);
-
-/* Helper functions. */
-static void ODKrnlWaitForExclusiveControl(void);
-static void ODKrnlGiveUpExclusiveControl(void);
-#endif /* OD_MULTITHREADED */
-
-/* Local working variables. */
-#ifdef OD_MULTITHREADED
-static tODThreadHandle hRemoteInputThread = NULL;
-static tODThreadHandle hNoCarrierThread = NULL;
-static tODThreadHandle hTimeUpdateThread = NULL;
-static tODThreadHandle hClientThread = NULL;
-static tODThreadHandle hChatThread = NULL;
-static BOOL bHaveExclusiveControl;
-static BOOL bChatActivatedInternally;
-#endif /* OD_MULTITHREADED */
-static BOOL bKernelActive = FALSE;
-static BOOL bWarnedAboutInactivity = FALSE;
-static INT16 nLastInactivitySetting = 0;
-static time_t nNextStatusUpdateTime;
-static INT nKrnlFuncPending;
-static BOOL bLastStatusSetting;
-static INT16 nChatOriginalAttrib;
-
-/* Global kernel-related variables. */
-tODTimer RunKernelTimer;
-time_t nNextTimeDeductTime;
-char chLastControlKey = '\0';
-INT nArrowUseCount = 0;
-BOOL bForceStatusUpdate = FALSE;
-BOOL bIsShell;
-#ifdef OD_MULTITHREADED
-tODSemaphoreHandle hODActiveSemaphore = NULL;
-#endif /* OD_MULTITHREADED */
-
-
-
-/* ========================================================================= */
-/* Core of the OpenDoors Kernel.                                             */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODKrnlInitialize()
- *
- * Initializes kernel activities. In multithreaded versions of OpenDoors, this
- * is the function that starts the various kernel threads.
- *
- * Parameters: kODRCSuccess on success, or an error code on failure.
- *
- *     Return: void
- */
-tODResult ODKrnlInitialize(void)
-{
-   tODResult Result = kODRCSuccess;
-
-   /* Initialize time of next status update and next time deduction. */
-   nNextStatusUpdateTime = time(NULL) + STATUS_UPDATE_PERIOD;
-   nNextTimeDeductTime = time(NULL) + 60L;
-   bLastStatusSetting = od_control.od_status_on = TRUE;
-
-   /* Initially, no kernel functions are pending. */
-   nKrnlFuncPending = 0;
-
-   /* Initially, the kernel is not active. */
-   bKernelActive = FALSE;
-
-#ifdef OD_MULTITHREADED
-   /* Initially, we do not have exclusive control of the application. */
-   bHaveExclusiveControl = FALSE;
-
-   /* Obtain a handle to the client thread. */
-   hClientThread = ODThreadGetCurrent();
-
-   /* Create OpenDoors activation semaphore. */
-   if(hODActiveSemaphore == NULL)
-   {
-      Result = ODSemaphoreAlloc(&hODActiveSemaphore, 0, INT_MAX);
-      if(Result != kODRCSuccess) return(Result);
-   }
-
-   /* Start the remote input thread if we are not operating in local mode. */
-   if(od_control.baud != 0)
-   {
-      Result = ODThreadCreate(&hRemoteInputThread, ODKrnlRemoteInputThread,
-         NULL);
-      if(Result != kODRCSuccess) return(Result);
-      ODThreadSetPriority(hRemoteInputThread, REMOTE_INPUT_THREAD_PRIORITY);
-   }
-
-   /* Start the carrier detection thread if we are not operating in local */
-   /* mode.                                                               */
-   if(od_control.baud != 0)
-   {
-      Result = ODThreadCreate(&hNoCarrierThread, ODKrnlNoCarrierThread, NULL);
-      if(Result != kODRCSuccess) return(Result);
-      ODThreadSetPriority(hNoCarrierThread, NO_CARRIER_THREAD_PRIORITY);
-   }
-
-   /* Start the time update thread. */
-   Result = ODThreadCreate(&hTimeUpdateThread, ODKrnlTimeUpdateThread, 0);
-   if(Result != kODRCSuccess) return(Result);
-   ODThreadSetPriority(hTimeUpdateThread, TIME_UPDATE_THREAD_PRIORITY);
-#endif /* OD_MULTITHREADED */
-
-   /* Return with success. */
-   return(Result);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlShutdown()
- *
- * Shuts down kernel activities.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODKrnlShutdown(void)
-{
-   if(bKernelActive) return;
-
-#ifdef OD_MULTITHREADED
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-      MessageBox(NULL, "Terminating remote input thread", "OpenDoors Diagnostics", MB_OK);
-#endif
-   /* Shutdown the remote input thread, if it exists. */
-   if(hRemoteInputThread != NULL) ODThreadTerminate(hRemoteInputThread);
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-      MessageBox(NULL, "Terminating carrier detection", "OpenDoors Diagnostics", MB_OK);
-#endif
-   /* Shutdown the carrier detection thread, if it exists. */
-   if(hNoCarrierThread != NULL) ODThreadTerminate(hNoCarrierThread);
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-      MessageBox(NULL, "Terminating time update thread", "OpenDoors Diagnostics", MB_OK);
-#endif
-   /* Shutdown the time update thread, if it exists. */
-   if(hTimeUpdateThread != NULL) ODThreadTerminate(hTimeUpdateThread);
-
-#if defined(OD_DIAGNOSTICS) && defined(ODPLAT_WIN32)
-   if(od_control.od_internal_debug)
-      MessageBox(NULL, "Releasing activation semaphore", "OpenDoors Diagnostics", MB_OK);
-#endif
-#endif /* OD_MULTITHREADED */
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_kernel()
- *
- * Carries out any kernel tasks that must be performed through regular,
- * explicit calls to this function,
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_kernel(void)
-{
-#ifndef OD_MULTITHREADED
-   WORD wKey;
-   BYTE btShiftStatus;
-   char ch;
-   char *pszShellName;
-   BOOL bCarrier;
-#endif /* OD_MULTITHREADED */
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_kernel()");
-
-   /* Initialize OpenDoors if not already done. */
-   if(!bODInitialized) od_init();
-
-   /* If this is an attempt at a re-entrant call to od_kernel() from another */
-   /* function called by a currently active od_kernel(), then return without */
-   /* doing anything.                                                        */
-   if(bKernelActive) return;
-
-   OD_API_ENTRY();
-
-   /* Note that kernel is active to prevent recursive calls to the kernel. */
-   bKernelActive = TRUE;
-
-   /* Call od_ker_exec function if required. */
-   if(od_control.od_ker_exec != NULL)
-   {
-      (*od_control.od_ker_exec)();
-   }
-
-   /* The remainder of od_kernel() only applies to non-multithreaded */
-   /* versions of OpenDoors.                                         */
-#ifndef OD_MULTITHREADED
-   /* If not operating in local mode, then perform remote-mode specific */
-   /* activies.                                                         */
-   if(od_control.baud != 0)
-   {
-      /* If carrier detection is enabled, then shutdown OpenDoors if */
-      /* the carrier detect signal is no longer high.                */
-      if(!(od_control.od_disable&DIS_CARRIERDETECT))
-      {
-         ODComCarrier(hSerialPort, &bCarrier);
-         if(!bCarrier)
-         {
-            ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_NOCARRIER);
-         }
-      }
-
-      /* Loop, obtaining any new characters from the serial port and */
-      /* adding them to the common local/remote input queue.         */
-      while(ODComGetByte(hSerialPort, &ch, FALSE) == kODRCSuccess)
-      {
-         ODKrnlHandleReceivedChar(ch, TRUE);
-      }
-   }
-
-
-check_keyboard_again:
-    if(nKrnlFuncPending && !bShellChatActive)
-    {
-       if(nKrnlFuncPending & KERNEL_FUNC_CHATTOGGLE)
-       {
-          nKrnlFuncPending &=~ KERNEL_FUNC_CHATTOGGLE;
-          goto chat_pressed;
-       }
-    }
-
-   /* Don't check local keyboard if sysop DIS_SYSOP_KEYS is set, or if we */
-   /* are operatingin silent mode.                                        */
-   if(od_control.od_disable & DIS_SYSOP_KEYS
-      || od_control.od_silent_mode)
-   {
-      goto after_key_check;
-   }
-
-   ASM    mov ah, 1
-   ASM    push si
-   ASM    push di
-   ASM    int 0x16
-   ASM    jnz key_waiting
-   ASM    pop di
-   ASM    pop si
-   ASM    jmp after_key_check
-key_waiting:
-   ASM    mov ah, 0
-   ASM    int 0x16
-   ASM    mov wKey, ax
-   ASM    mov ah, 2
-   ASM    int 0x16
-   ASM    mov btShiftStatus, al
-   ASM    pop di
-   ASM    pop si
-
-      if(nArrowUseCount > 0 && (wKey == 0x4800 || wKey == 0x5000)
-         && !(btShiftStatus & 2))
-      {
-         /* Pass key on to od_local_input, if it is defined. */
-         if(od_control.od_local_input != NULL)
-         {
-            (*od_control.od_local_input)(wKey);
-         }
-
-         /* Add this key to the local/remote input queue. */
-         ODKrnlHandleLocalKey(wKey);
-      }
-
-      /* If hangup key is pressed. */
-      else if(wKey == od_control.key_hangup)
-      {
-         ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
-      }
-
-      /* If drop to BBS key is pressed. */
-      else if(wKey == od_control.key_drop2bbs)
-      {
-         ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_DROPTOBBS);
-      }
-
-      else if(wKey == od_control.key_dosshell)
-      {
-         if(!bShellChatActive)
-         {
-            if(pfLogWrite != NULL)
-               (*pfLogWrite)(6);
-
-            /* If function hook is defined. */
-            if(od_control.od_cbefore_shell != NULL)
-            {
-               /* Then call it. */
-               bShellChatActive = TRUE;
-               (*od_control.od_cbefore_shell)();
-               bShellChatActive = FALSE;
-            }
-
-            if(od_control.od_before_shell != NULL)
-               od_disp_str(od_control.od_before_shell);
-
-            if((pszShellName = (char *)getenv("COMSPEC")) == NULL)
-            {
-               pszShellName = (char *)"COMMAND.COM";
-            }
-            bIsShell = TRUE;
-            od_spawnvpe(P_WAIT, pszShellName, NULL, NULL);
-            bIsShell = FALSE;
-
-            if(od_control.od_after_shell != NULL)
-               od_disp_str(od_control.od_after_shell);
-
-            /* If a function hook is defined. */
-            if(od_control.od_cafter_shell != NULL)
-            {
-               /* Then call it. */
-               bShellChatActive = TRUE;
-               (*od_control.od_cafter_shell)();
-               bShellChatActive = FALSE;
-            }
-
-            if(pfLogWrite != NULL)
-               (*pfLogWrite)(7);
-         }
-      }
-
-      /* If toggle chat mode key is pressed. */
-      else if(wKey == od_control.key_chat)
-      {
-chat_pressed:
-         if(!bShellChatActive || od_control.od_chat_active)
-         {
-            /* If chat mode is active. */
-            if(od_control.od_chat_active)
-            {
-               /* Signal exit of chat mode. */
-               ODKrnlEndChatMode();
-            }
-
-            /* If chat mode is off. */
-            else
-            {
-               /* Enable second call to kernel. */
-               bKernelActive = FALSE;
-
-               /* Enter chat mode. */
-               ODKrnlChatMode();
-
-               /* Disable second call to kernel. */
-               bKernelActive = TRUE;
-            }
-         }
-         else
-         {
-            if(nKrnlFuncPending & KERNEL_FUNC_CHATTOGGLE)
-            {
-               nKrnlFuncPending &= ~KERNEL_FUNC_CHATTOGGLE;
-            }
-            else
-            {
-               nKrnlFuncPending |= KERNEL_FUNC_CHATTOGGLE;
-            }
-         }
-      }
-
-      /* If sysop next key is pressed. */
-      else if(wKey == od_control.key_sysopnext)
-      {
-         /* Toggle sysop next setting. */
-         od_control.sysop_next = !od_control.sysop_next;
-
-         /* Update status line. */
-         goto statup;
-      }
-
-      /* If ESCape key is pressed and we are in chat mode. */
-      else if((wKey&0xff) == 27 && od_control.od_chat_active)
-      {
-         /* Signal exit from chat mode. */
-         od_control.od_chat_active = FALSE;
-      }
-
-      /* If lockout user key is pressed. */
-      else if(wKey == od_control.key_lockout)
-      {
-         /* Set the user's access security level to 0. */
-         od_control.user_security = 0;
-
-         /* Shutdown OpenDoors. */
-         ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
-      }
-
-
-      /* If toggle keyboard off key is pressed. */
-      else if(wKey == od_control.key_keyboardoff)
-      {
-         /* Toggle user keyboard settings. */
-         od_control.od_user_keyboard_on =! od_control.od_user_keyboard_on;
-
-         /* Update status line. */
-         goto statup;
-      }
-
-      /* If increase time key is pressed. */
-      else if(wKey == od_control.key_moretime)
-      {
-         /* If time limit is less than maximum possible time limit. */
-         if(od_control.user_timelimit < 1440)
-         {
-             /* Increase time left online. */
-            ++od_control.user_timelimit;
-         }
-
-         /* Update status line. */
-         goto statup;
-      }
-
-      /* If decrease time key is pressed. */
-      else if(wKey == od_control.key_lesstime)
-      {
-         /* Never let user's time limit be set to a negative value. */
-         if(od_control.user_timelimit > 0)
-         {
-            /* Decrease user's timelimit. */
-            --od_control.user_timelimit;
-         }
-
-         /* Update the status line. */
-         goto statup;
-      }
-
-      else
-      {
-         for(ch = 0; ch < 9; ++ch)
-         {
-            if(wKey == od_control.key_status[ch])
-            {
-               if(btCurrentStatusLine != ch && od_control.od_status_on)
-               {
-                  od_set_statusline(ch);
-               }
-               goto check_keyboard_again;
-            }
-         }
-
-         /* Look for user-defined hotkeys. */
-         for(ch=0; ch<od_control.od_num_keys; ++ch)
-         {
-            /* If it matches. */
-            if(wKey == (WORD)od_control.od_hot_key[ch])
-            {
-               /* Record keypress. */
-               od_control.od_last_hot = wKey;
-
-               /* Notify the current personality. */
-               (*pfCurrentPersonality)(21);
-
-               /* Check for a hotkey function. */
-               if(od_control.od_hot_function[ch] != NULL)
-               {
-                  /* Call it if it exists. */
-                  (*od_control.od_hot_function[ch])();
-               }
-
-               /* Stop searching. */
-               break;
-            }
-         }
-
-         /* If no hotkeys found. */
-         if(ch >= od_control.od_num_keys)
-         {
-            /* Pass key on to od_local_input, if it is defined. */
-            if(od_control.od_local_input != NULL)
-            {
-               (*od_control.od_local_input)(wKey);
-            }
-
-            /* Add this key to the local/remote input queue. */
-            ODKrnlHandleLocalKey(wKey);
-         }
-      }
-   goto check_keyboard_again;
-
-after_key_check:
-
-   /* If status line has been turned on since last call to kernel. */
-   if(bLastStatusSetting != od_control.od_status_on)
-   {
-      /* Generate the status line. */
-      od_set_statusline(0);
-   }
-
-   bLastStatusSetting = od_control.od_status_on;
-
-   if(od_control.od_update_status_now)
-   {
-      od_set_statusline(btCurrentStatusLine);
-      od_control.od_update_status_now = FALSE;
-   }
-
-   /* Update status line when needed. */
-   if(nNextStatusUpdateTime < time(NULL) || bForceStatusUpdate)
-   {
-statup:
-      nNextStatusUpdateTime = time(NULL) + STATUS_UPDATE_PERIOD;
-
-      /* Turn off status line update force flag */
-      bForceStatusUpdate = FALSE;
-
-      if(od_control.od_status_on && btCurrentStatusLine != 8)
-      {
-         /* Store console settings. */
-         ODStoreTextInfo();
-
-         /* Enable writes to whole screen. */
-         ODScrnSetBoundary(1, 1, 80, 25);
-         ODScrnEnableCaret(FALSE);
-         (*pfCurrentPersonality)((BYTE)(10 + btCurrentStatusLine));
-         ODRestoreTextInfo();
-         ODScrnEnableCaret(TRUE);
-      }
-   }
-
-   ODKrnlTimeUpdate();
-
-   ODTimerStart(&RunKernelTimer, 250);
-
-   OD_API_EXIT();
-
-   bKernelActive = FALSE;
-#endif /* !OD_MULTITHREADED */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlHandleLocalKey()
- *
- * Called when a key is pressed on the local keyboard that should be placed
- * in the common local/remote input queue. This function is not called for
- * sysop function keys.
- *
- * Parameters: wKeyCode
- *
- *     Return: void
- */
-void ODKrnlHandleLocalKey(WORD wKeyCode)
-{
-   /* If local keyboard input by sysop has not been disabled. */
-   if(!(od_control.od_disable & DIS_LOCAL_INPUT))
-   {
-      if((wKeyCode & 0xff) == 0)
-      {
-         ODKrnlHandleReceivedChar('\0', FALSE);
-         ODKrnlHandleReceivedChar((char)(wKeyCode >> 8), FALSE);
-      }
-      else
-      {
-         ODKrnlHandleReceivedChar((char)wKeyCode, FALSE);
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlHandleReceivedChar()                          *** PRIVATE FUNCTION ***
- *
- * Called when a character is received from the local or remote system.
- *
- * Parameters: chReceived  - Character that should be handled.
- *
- *             bFromRemote - TRUE if this character was received from the
- *                           remote system, FALSE if it originated from the
- *                           local console.
- *
- *     Return: void
- */
-static void ODKrnlHandleReceivedChar(char chReceived, BOOL bFromRemote)
-{
-   tODInputEvent InputEvent;
-
-   /* If we are operating in remote mode, and remote user keyboard has been */
-   /* disabled by the sysop, then return, ignoring this character.          */
-   if(bFromRemote && !od_control.od_user_keyboard_on)
-   {
-      return;
-   }
-
-   /* Add this input event to the local/remote common input queue. */
-   InputEvent.EventType = EVENT_CHARACTER;
-   InputEvent.bFromRemote = bFromRemote;
-   InputEvent.chKeyPress = chReceived;
-   ODInQueueAddEvent(hODInputQueue, &InputEvent);
-
-   /* Update last control key information. */
-   switch(chReceived)
-   {
-      case 's':
-      case 'S':
-      case 3:
-      case 11:
-      case 0x18:
-         chLastControlKey = 's';
-         break;
-      case 'p':
-      case 'P':
-         chLastControlKey = 'p';
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlTimeUpdate()                                  *** PRIVATE FUNCTION ***
- *
- * Performs regular updating of time remaining online, inactivity time, and
- * forces OpenDoors to exit if a time limit has been exceeded.
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODKrnlTimeUpdate(void)
-{
-   time_t CurrentTime;
-   static char szTemp[80];
-
-   /* Obtain the current time. */
-   CurrentTime = time(NULL);
-
-   /* If inactivity setting has changed. */
-   if(nLastInactivitySetting != od_control.od_inactivity)
-   {
-      /* If it was previously disabled. */
-      if(nLastInactivitySetting == 0)
-      {
-         /* Prevent immediate timeout. */
-         ODInQueueResetLastActivity(hODInputQueue);
-      }
-
-      /* Store current value. */
-      nLastInactivitySetting = od_control.od_inactivity;
-   }
-
-   /* Check user keyboard inactivity. */
-   if((ODInQueueGetLastActivity(hODInputQueue) + od_control.od_inactivity)
-      < CurrentTime)
-   {
-      /* If timeout, display message. */
-      if(od_control.od_inactivity != 0 && !od_control.od_disable_inactivity)
-      {
-         if(od_control.od_time_msg_func == NULL)
-         {
-            od_disp_str(od_control.od_inactivity_timeout);
-         }
-         else
-         {
-            (*od_control.od_time_msg_func)(od_control.od_inactivity_timeout);
-         }
-
-         /* End connection. */
-         ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_INACTIVITY);
-      }
-   }
-
-   /* If less than 5s left of inactivity. */
-   else if(ODInQueueGetLastActivity(hODInputQueue) + od_control.od_inactivity
-      < CurrentTime + od_control.od_inactive_warning)
-   {
-      if(!bWarnedAboutInactivity && od_control.od_inactivity != 0
-         && !od_control.od_disable_inactivity)
-      {
-         /* Warn the user. */
-         if(od_control.od_time_msg_func == NULL)
-         {
-            od_disp_str(od_control.od_inactivity_warning);
-         }
-         else
-         {
-            (*od_control.od_time_msg_func)(od_control.od_inactivity_warning);
-         }
-         /* Don't warn the user a second time. */
-         bWarnedAboutInactivity = TRUE;
-      }
-   }
-   else
-   {
-      /* Re-enable inactivity warning. */
-      bWarnedAboutInactivity = FALSE;
-   }
-
-   /* If chat mode is active. */
-   if(od_control.od_chat_active)
-   {
-      /* Prevent the user's time from being drained. */
-      nNextTimeDeductTime = time(NULL) + 60;
-   }
-
-   /* If 1 minute has passed since last time update. */
-   if(CurrentTime >= nNextTimeDeductTime)
-   {
-      /* Next time update should occur 60 seconds after this one was */
-      /* scheduled.                                                  */
-      nNextTimeDeductTime += 60;
-
-      /* Force status line to be updated immediately. */
-      bForceStatusUpdate = TRUE;
-
-      /* Decrement time left. */
-      --od_control.user_timelimit;
-
-      /* If the user's time limit is close to expiring, then notify */
-      /* the user.                                                  */
-      if(od_control.user_timelimit <= 3 &&
-         od_control.user_timelimit > 0 &&
-         !(od_control.od_disable & DIS_TIMEOUT))
-      {
-         /* If less than 3 mins left, tell user. */
-         sprintf(szTemp, od_control.od_time_warning,
-            od_control.user_timelimit);
-         if(od_control.od_time_msg_func == NULL)
-         {
-            od_disp_str(szTemp);
-         }
-         else
-         {
-            (*od_control.od_time_msg_func)(szTemp);
-         }
-      }
-
-#ifdef ODPLAT_WIN32
-      ODFrameUpdateTimeDisplay();
-#endif /* ODPLAT_WIN32 */
-   }
-
-   /* If user has no time left. */
-   if(od_control.user_timelimit <= 0
-      && !(od_control.od_disable & DIS_TIMEOUT))
-   {
-      /* Notify the user. */
-      if(od_control.od_time_msg_func == NULL)
-      {
-         od_disp_str(od_control.od_no_time);
-      }
-      else
-      {
-         (*od_control.od_time_msg_func)(od_control.od_no_time);
-      }
-
-      /* Force OpenDoors to shutdown. */
-      ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_TIMEOUT);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlForceOpenDoorsShutdown()
- *
- * Called to force the application to exit due to some event in OpenDoors,
- * such as loss of carrier, user inactivity timeout, the hangup command
- * being chosen by the system operator, etc. The only time when OpenDoors
- * is shutdown without going through this function should be as a result of
- * an explicit call to od_exit() by the client application.
- *
- * Parameters: btReasonForShutdown - An OpenDoors exit reason code.
- *
- *     Return: Never returns.
- */
-void ODKrnlForceOpenDoorsShutdown(BYTE btReasonForShutdown)
-{
-   BOOL bHangup;
-
-#ifdef OD_MULTITHREADED
-   /* First, wait until an OpenDoors API is active. This way, we won't  */
-   /* interrupt any client application operations that may leave the    */
-   /* system in an unstable state (for instance, interrupting some file */
-   /* I/O operations).                                                  */
-   ODKrnlWaitForExclusiveControl();
-#endif /* OD_MULTITHREADED */
-
-   bKernelActive = TRUE;
-
-   /* Determine whether we should hangup on the user before exiting. */
-   if(btReasonForShutdown == ERRORLEVEL_HANGUP
-      || btReasonForShutdown == ERRORLEVEL_INACTIVITY)
-   {
-      bHangup = TRUE;
-   }
-   else
-   {
-      bHangup = FALSE;
-   }
-
-   /* Record exit reason in global variable. */
-   btExitReason = btReasonForShutdown - 1;
-
-   /* Use the client-defined errorlevel, if any. */
-   if(od_control.od_errorlevel[0])
-   {
-      od_exit(od_control.od_errorlevel[btReasonForShutdown], bHangup);
-   }
-
-   /* Otherwise, use the default OpenDoors errorlevel. */
-   else
-   {
-      od_exit(btReasonForShutdown - 1, bHangup);
-   }
-}
-
-
-/* ========================================================================= */
-/* OpenDoors Kernel multithreaded implementation.                            */
-/* ========================================================================= */
-
-#ifdef OD_MULTITHREADED
-
-/* ----------------------------------------------------------------------------
- * ODKrnlRemoteInputThread()                           *** PRIVATE FUNCTION ***
- *
- * Code for the remote input thread. This thread executes an infinite loop,
- * blocking until a character is received from the remote system, and then
- * adding this character to the common local/remote input queue. This thread
- * should be given higher than normal priority.
- *
- * In non-multithreaded versions of OpenDoors, the task of checking for new
- * characters from the remote system and adding them to the common input
- * queue is performed on each call to od_kernel().
- *
- * Parameters: As dictated for any thread function.
- *
- *     Return: As dictated for any thread function.
- */
-DWORD OD_THREAD_FUNC ODKrnlRemoteInputThread(void *pParam)
-{
-   char chReceived;
-
-   /* We keep looping until someone else terminates this thread. */
-   for(;;)
-   {
-      /* Get next character from the modem, blocking if no character */
-      /* is waiting.                                                 */
-      ODComGetByte(hSerialPort, &chReceived, TRUE);
-
-      /* Handle this received character, adding it to the local/remote */
-      /* common input queue, if appropriate.                           */
-      ODKrnlHandleReceivedChar(chReceived, TRUE);
-   }
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlNoCarrierThread()                             *** PRIVATE FUNCTION ***
- *
- * Thread which performs carrier detection. Normally, this thread doesn't
- * execute at all, but instead blocks waiting for a no carrier serial port
- * event. Only when the carrier detect signal goes low does this thread
- * execute, performing its one purpose in live - to trigger an OpenDoors
- * shutdown. This thread should be given higher than normal priority.
- *
- * This thread should only be created when OpenDoors is operating in remote
- * mode.
- *
- * In non-multithreaded versions of OpenDoors, this task is performed by
- * od_kernel().
- *
- * Parameters: As dictated for any thread function.
- *
- *     Return: As dictated for any thread function.
- */
-DWORD OD_THREAD_FUNC ODKrnlNoCarrierThread(void *pParam)
-{
-   /* Block until the carrier detect signal goes low with carrier */
-   /* detection enabled.                                          */
-   for(;;)
-   {
-      /* Wait for carrier detect signal to go low. */
-      ODComWaitEvent(hSerialPort, kNoCarrier);
-
-      /* If carrier detection has not been disabled, then we have found */
-      /* a condition where OpenDoors should exit.                       */
-      if(!(od_control.od_disable&DIS_CARRIERDETECT)) break;
-
-      /* If we have no carrier but carrier detection is currently   */
-      /* disabled, then we sleep for a while before checking again. */
-      /* This isn't a very elegant implementation, and perhaps a    */
-      /* better approach will be used for future versions.          */
-      od_sleep(NO_CARRIER_THREAD_SLEEP_TIME);
-   }
-
-   /* Force OpenDoors to exit. */
-   ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_NOCARRIER);
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlTimeUpdateThread()                            *** PRIVATE FUNCTION ***
- *
- * Thread which performs time limit updating and checking. This thread executes
- * an infinite loop, sleeping for several seconds, waking up to perform time
- * limit updating, and then going back to sleep. This thead should typically
- * operate at normal priority.
- *
- * In non-multithreaded versions of OpenDoors, this task is performed by
- * od_kernel().
- *
- * Parameters: As dictated for any thread function.
- *
- *     Return: As dictated for any thread function.
- */
-DWORD OD_THREAD_FUNC ODKrnlTimeUpdateThread(void *pParam)
-{
-   /* We keep looping until someone else terminates this thread. */
-   for(;;)
-   {
-      /* Sleep until it is time to do the next update. */
-      od_sleep(TIME_UPDATE_THREAD_SLEEP_TIME);
-
-      /* Now, perform time update. */
-      ODKrnlTimeUpdate();
-   }
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlWaitForExclusiveControl()                     *** PRIVATE FUNCTION ***
- *
- * Claims exclusive control of the application by the OpenDoors kernel. This is
- * required to ensure that the client application is not busy when the
- * OpenDoors kernel interrupts other operations for one reason or another
- * (for example, to start chat mode or to force the program to exit).
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODKrnlWaitForExclusiveControl(void)
-{
-   /* If we already have exclusive control, then don't do anything. */
-   if(bHaveExclusiveControl) return;
-
-   /* Wait until an OpenDoors API is active. */
-   ODSemaphoreDown(hODActiveSemaphore, OD_NO_TIMEOUT);
-
-   /* Now, suspend the client thread. */
-   ASSERT(hClientThread != NULL);
-   ODThreadSuspend(hClientThread);
-
-   /* Record that we now have exclusive control. */
-   bHaveExclusiveControl = TRUE;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlGiveUpExclusiveControl()                      *** PRIVATE FUNCTION ***
- *
- * Relinguishes exclusive control of the application by the OpenDoors kernel.
- * A call to this function should only take place after a previous call to
- * ODKrnlWaitForExclusiveControl().
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODKrnlGiveUpExclusiveControl(void)
-{
-   /* If we don't have exclusive control, then this call doesn't do */
-   /* anything.                                                     */
-   if(!bHaveExclusiveControl) return;
-
-   /* First, restart the client thread. */
-   ASSERT(hClientThread != NULL);
-   ODThreadResume(hClientThread);
-
-   /* Now, allow currently active OpenDoors API to return control */
-   /* to the client application.                                  */
-   ODSemaphoreUp(hODActiveSemaphore, 1);
-
-   /* Note that we no longer have exclusive control. */
-   bHaveExclusiveControl = FALSE;
-}
-
-#endif /* OD_MULTITHREADED */
-
-
-
-/* ========================================================================= */
-/* OpenDoors chat mode.                                                      */
-/* ========================================================================= */
-
-BOOL bChatted;
-BOOL bSysopColor;
-
-#ifdef OD_MULTITHREADED
-
-/* ----------------------------------------------------------------------------
- * ODKrnlChatThread()                                  *** PRIVATE FUNCTION ***
- *
- * Thread which implements sysop <-> remote user chat mode.
- *
- * Parameters: As dictated for any thread function.
- *
- *     Return: As dictated for any thread function.
- */
-DWORD OD_THREAD_FUNC ODKrnlChatThread(void *pParam)
-{
-   BOOL bTriggeredInsideOpenDoors = bChatActivatedInternally;
-
-   /* The chat thread doesn't start up chat mode until the kernel has */
-   /* exclusive control of the client application.                    */
-   if(bTriggeredInsideOpenDoors)
-   {
-      ODKrnlWaitForExclusiveControl();
-   }
-
-   /* Now, execute the chat mode loop. */
-   ODKrnlChatMode();
-
-   /* If we get here, then we are responsible for relinguishing exclusive */
-   /* control of the application.                                         */
-   if(bTriggeredInsideOpenDoors)
-   {
-      ODKrnlGiveUpExclusiveControl();
-   }
-
-   /* Exit the chat thread. */
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlStartChatThread()
- *
- * Starts the chat mode thread.
- *
- * Parameters: bTriggeredInternally - TRUE if chat mode has been triggered
- *                                    inside OpenDoors, or FALSE if it has
- *                                    been triggered by a call to od_chat().
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODKrnlStartChatThread(BOOL bTriggeredInternally)
-{
-   tODResult Result;
-
-   bChatActivatedInternally = bTriggeredInternally;
-
-   Result = ODThreadCreate(&hChatThread, ODKrnlChatThread, NULL);
-   if(Result != kODRCSuccess)
-   {
-      return(Result);
-   }
-
-   /* If chat mode command has been chosen, then toggle chat */
-   /* mode on or off.                                        */
-   od_control.od_chat_active = TRUE;
-
-#ifdef ODPLAT_WIN32
-   /* Update the enabled and checked state of commands. */
-   ODFrameUpdateCmdUI();
-#endif /* ODPLAT_WIN32 */
-
-   return(kODRCSuccess);
-}
-
-
-#endif /* OD_MULTITHREADED */
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlEndChatMode()
- *
- * Forces chat mode to exit.
- *
- * Parameters: None
- *
- *     Return: void
- */
-void ODKrnlEndChatMode(void)
-{
-#ifdef OD_MULTITHREADED
-
-   /* Shutdown the chat thread. */
-   ODThreadTerminate(hChatThread);
-
-   /* Perform post-chat cleanup operations. */
-   ODKrnlChatCleanup();
-
-#else /* !OD_MULTITHREADED */
-
-   /* Turn off chat mode. */
-   od_control.od_chat_active = FALSE;
-
-#endif /* !OD_MULTITHREADED */
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_chat()
- *
- * Allows the client application to activate the line-by-line default chat
- * mode provided by OpenDoors, allowing the local sysop and remote user to
- * communicate with one another in real time.
- *
- * Parameters: none
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_chat(void)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_chat()");
-
-   /* Set the main chat active flag in od_control. */
-   od_control.od_chat_active = TRUE;
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-#ifdef OD_MULTITHREADED
-
-   /* In multithreaded versions of OpenDoors, od_chat() causes the chat */
-   /* mode thread to be started, which in turn implements chat mode.    */
-   /* od_chat() only returns when this thread exits.                    */
-   if(ODKrnlStartChatThread(FALSE) != kODRCSuccess)
-   {
-      od_control.od_error = ERR_GENERALFAILURE;
-      OD_API_EXIT();
-   }
-
-   /* Now, wait for the chat thread to exit. */
-   ODThreadWaitForExit(hChatThread);
-
-   /* Now, note that the chat thread no longer exists. */
-   hChatThread = NULL;
-
-#else /* !OD_MULTITHREADED */
-
-   /* In non-multithreaded versions, a call to od_chat() maps directly to a */
-   /* call to ODKrnlChatMode(), which implements chat mode.                 */
-   ODKrnlChatMode();
-
-#endif /* !OD_MULTITHREADED */
-
-   OD_API_EXIT();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlChatMode()                                    *** PRIVATE FUNCTION ***
- *
- * Implements the OpenDoors chat mode.
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODKrnlChatMode(void)
-{
-   BYTE chKeyPressed;
-   char szCurrentWord[79];
-   BYTE btWordLength = 0;
-   BYTE btCurrentColumn = 0;
-   char *pchCurrent;
-   BYTE btCount;
-#ifndef OD_MULTITHREADED
-   tODTimer Timer;
-#endif /* !OD_MULTITHREADED */
-
-   /* Empty current word string. */
-   szCurrentWord[0] = '\0';
-
-   /* Save current display color attribute. */
-   nChatOriginalAttrib = od_control.od_cur_attrib;
-
-   /* Record that sysop has entered chat mode. */
-   bChatted = TRUE;
-
-   /* Turn off "user wants to chat" indicator, and force the status line. */
-   /* to be updated.                                                      */
-   od_control.user_wantchat = FALSE;
-#ifdef ODPLAT_WIN32
-   ODFrameUpdateWantChat();
-#endif /* ODPLAT_WIN32 */
-
-   bForceStatusUpdate = TRUE;
-   CALL_KERNEL_IF_NEEDED();
-
-   /* Note that chat mode is now active. */
-   od_control.od_chat_active = TRUE;
-
-   /* If a pre-chat function hook has been defined, then call it. */
-   if(od_control.od_cbefore_chat!=NULL)
-   {
-      bShellChatActive = TRUE;
-      (*od_control.od_cbefore_chat)();
-      bShellChatActive = FALSE;
-
-      /* If chat has been deactivated, then return right away */
-      if(!od_control.od_chat_active) goto cleanup;
-   }
-
-   /* Display a message indicating that the sysop has entered chat mode. */
-   od_set_attrib(od_control.od_chat_color1);
-   if(od_control.od_before_chat != NULL)
-      od_disp_str(od_control.od_before_chat);
-
-   /* Currently set to sysop color. */
-   bSysopColor = TRUE;
-
-   /* If the logfile system is hooked up, then write a log entry */
-   /* indicating that the sysop has entered chat mode.           */
-   if(pfLogWrite != NULL)
-   {
-      (*pfLogWrite)(9);
-   }
-
-#ifndef OD_MULTITHREADED
-   /* Start a timer that will elapse after 25 milliseconds. */
-   ODTimerStart(&Timer, CHAT_YIELD_PERIOD);
-#endif /* !OD_MULTITHREADED */
-
-   /* Loop while sysop chat mode is stilil on. */
-   while(od_control.od_chat_active)
-   {
-      /* Obtain the next key from the user. */
-#ifdef OD_MULTITHREADED
-      chKeyPressed = od_get_key(TRUE);
-#else /* !OD_MULTITHREADED */
-      chKeyPressed = od_get_key(FALSE);
-#endif /* !OD_MULTITHREADED */
-
-      /* If color not set correctly. */
-      if((od_control.od_last_input && !bSysopColor)
-         || (!od_control.od_last_input && bSysopColor))
-      {
-         /* If sysop was last person to type. */
-         if(od_control.od_last_input)
-         {
-            /* Switch to sysop text color. */
-            od_set_attrib(od_control.od_chat_color1);
-         }
-         else
-         {
-            /* Otherwise, switch to the user text color. */
-            od_set_attrib(od_control.od_chat_color2);
-         }
-
-         /* Record current color setting. */
-         bSysopColor = od_control.od_last_input;
-      }
-
-      /* If this is a displayable character. */
-      if(chKeyPressed >= 32)
-      {
-         /* Display the character that was typed. */
-         od_putch(chKeyPressed);
-
-         /* If the user pressed spacebar, then this is the end of the */
-         /* previous word. */
-         if(chKeyPressed == 32)
-         {
-            btWordLength = 0;
-            szCurrentWord[0] = 0;
-         }
-
-         /* Add this character to the current word, if we haven't exceeded */
-         /* the maximum word length.                                       */
-         else if(btWordLength < 70)
-         {
-            szCurrentWord[btWordLength++] = chKeyPressed;
-            szCurrentWord[btWordLength] = '\0';
-         }
-
-         /* If we are not yet at the end of the line, then increment the */
-         /* current column number.                                       */
-         if(btCurrentColumn < 75)
-         {
-            ++btCurrentColumn;
-         }
-
-         /* If we are at the end of the line. */
-         else
-         {
-            /* If the current word should be wrapped to the next line. */
-            if(btWordLength < 70 && btWordLength > 0)
-            {
-               /* Generate a string to erase the word from the current line. */
-               pchCurrent = (char *)szODWorkString;
-               for(btCount = 0; btCount < btWordLength; ++btCount)
-               {
-                  *(pchCurrent++) = 8;
-               }
-
-               for(btCount = 0; btCount < btWordLength; ++btCount)
-               {
-                  *(pchCurrent++) = ' ';
-               }
-
-               *pchCurrent = '\0';
-
-               /* Display the string to erase the old word. */
-               od_disp_str(szODWorkString);
-
-               /* Move to the next line. */               
-               od_disp_str("\n\r");
-
-               /* Redisplay the word on the next line. */
-               od_disp_str(szCurrentWord);
-
-               /* Update current column number. */               
-               btCurrentColumn = btWordLength;
-            }
-
-            /* If we have reached the end of the line, but word wrap should */
-            /* not be performed.                                            */
-            else
-            {
-               /* Move to the next line. */
-               od_disp_str("\n\r");
-
-               /* Update the current column number. */
-               btCurrentColumn = 0;
-            }
-
-            /* Reset the current word information. */
-            btWordLength = 0;
-            szCurrentWord[0] = 0;
-         }
-      }
-
-      /* If the backspace key was pressed. */
-      else if(chKeyPressed == 8)
-      {
-         /* Send backspace sequence. */
-         od_disp_str(szBackspaceWithDelete);
-
-         /* If we are in the middle of a word, then we must remove the */
-         /* last character of the word.                                */         
-         if(btWordLength > 0)
-         {
-            szCurrentWord[--btWordLength] = '\0';
-         }
-
-         /* Update the current column number. */
-         if(btCurrentColumn > 0) --btCurrentColumn;
-      }
-
-      /* If the enter key was pressed. */
-      else if(chKeyPressed == 13)
-      {
-         /* Send carriage return / line feed sequence. */
-         od_disp_str("\n\r");
-
-         /* Reset the current word contents. */
-         btWordLength = 0;
-         szCurrentWord[0] = 0;
-
-         /* Update the current column number. */
-         btCurrentColumn = 0;
-      }
-
-      /* If the sysop pressed the escape key. */
-      else if(chKeyPressed == 27 && od_control.od_last_input)
-      {
-         /* Exit chat mode. */
-         goto cleanup;
-      }
-
-#ifndef OD_MULTITHREADED
-      /* Give up processor after 25 milliseconds elapsed. */
-      else if(ODTimerElapsed(&Timer))
-      {
-         od_sleep(0);
-
-         /* Restart the timer, so that it will elapse after another */
-         /* 25 milliseconds.                                        */
-         ODTimerStart(&Timer, CHAT_YIELD_PERIOD);
-      }
-#endif /* !OD_MULTITHREADED */
-   }
-
-cleanup:
-   ODKrnlChatCleanup();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODKrnlChatCleanup()                                 *** PRIVATE FUNCTION ***
- *
- * Performs post-chat operations, such as resetting the original display
- * color, etc.
- *
- * Parameters: None
- *
- *     Return: void
- */
-static void ODKrnlChatCleanup(void)
-{
-   od_set_attrib(od_control.od_chat_color1);
-
-   /* Indicate that chat mode is exiting. */
-   if(od_control.od_after_chat != NULL)
-   {
-      od_disp_str(od_control.od_after_chat);
-   }
-
-   /* If an after chat function has been provided, then call it. */
-   if(od_control.od_cafter_chat != NULL)
-   {
-      bShellChatActive = TRUE;
-      (*od_control.od_cafter_chat)();
-      bShellChatActive = FALSE;
-   }
-
-   /* If the logfile system is hooked up, then write a line to the log */
-   /* indicating that chat mode has been exited.                       */
-   if(pfLogWrite != NULL)
-   {
-      (*pfLogWrite)(10);
-   }
-
-   /* Restore original display color attribute. */
-   od_set_attrib(nChatOriginalAttrib);
-
-   /* Record that chat mode is no longer active. */
-   od_control.od_chat_active = FALSE;
-
-#ifdef ODPLAT_WIN32
-   /* Update the enabled and checked state of commands. */
-   ODFrameUpdateCmdUI();
-#endif /* ODPLAT_WIN32 */
-
-#ifdef OD_MULTITHREADED
-   if(bChatActivatedInternally)
-   {
-      ODKrnlGiveUpExclusiveControl();
-   }
-#endif
-}
diff --git a/src/odoors/ODKrnl.h b/src/odoors/ODKrnl.h
deleted file mode 100644
index d2ee917d472309d404e836fa67739347caafec02..0000000000000000000000000000000000000000
--- a/src/odoors/ODKrnl.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODKrnl.h
- *
- * Description: Contains the public definitions related to odkrnl.c
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Jan 01, 1995  6.00  BP   Split off from odcore.c and oddoor.h
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Jan 12, 1996  6.00  BP   Added bOnlyShiftArrow.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 13, 1996  6.10  BP   bOnlyShiftArrow -> nArrowUseCount.
- */
-
-#ifndef _INC_ODKRNL
-#define _INC_ODKRNL
-
-#include "ODPlat.h"
-
-/* Global kernel-related variables. */
-extern tODTimer RunKernelTimer;
-extern time_t nNextTimeDeductTime;
-extern char chLastControlKey;
-extern INT nArrowUseCount;
-extern BOOL bForceStatusUpdate;
-extern BOOL bSysopColor;
-#ifdef OD_MULTITHREADED
-extern tODSemaphoreHandle hODActiveSemaphore;
-#endif /* OD_MULTITHREADED */
-
-/* Chat mode global variables. */
-extern BOOL bIsShell;
-extern BOOL bChatted;
-
-/* Kernel function prototypes. */
-tODResult ODKrnlInitialize(void);
-void ODKrnlShutdown(void);
-void ODKrnlHandleLocalKey(WORD wKeyCode);
-void ODKrnlEndChatMode(void);
-void ODKrnlForceOpenDoorsShutdown(BYTE btReasonForShutdown);
-#ifdef OD_MULTITHREADED
-tODResult ODKrnlStartChatThread(BOOL bTriggeredInternally);
-#endif /* OD_MULTITHREADED */
-
-/* Macro used to generate the appropriate code (if any) to call */
-/* the OpenDoors kernel from within OpenDoors code.             */
-#ifdef OD_MULTITHREADED
-#define CALL_KERNEL_IF_NEEDED()
-#else /* !OD_MULTITHREADED */
-#define CALL_KERNEL_IF_NEEDED()     od_kernel()
-#endif /* !OD_MULTITHREADED */
-
-/* Macro used to increment or decrement OpenDoors active semaphore. */
-#ifdef OD_MULTITHREADED
-#define OD_API_ENTRY()              ODSemaphoreUp(hODActiveSemaphore, 1);
-#define OD_API_EXIT()               ODSemaphoreDown(hODActiveSemaphore, 1);
-#else /* !OD_MULTITHREADED */
-#define OD_API_ENTRY()
-#define OD_API_EXIT()
-#endif /* !OD_MULTITHREADED */
-
-#endif /* _INC_ODKRNL */
diff --git a/src/odoors/ODList.c b/src/odoors/ODList.c
deleted file mode 100644
index d4920ccd7c90075ce388cdc2db88e25d9bd1e0aa..0000000000000000000000000000000000000000
--- a/src/odoors/ODList.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODList.c
- *
- * Description: Implements the od_list_files() function for displaying
- *              a FILES.BBS file.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Dec 09, 1994  6.00  BP   Use new directory access functions.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Moved functions from odcore.c
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODCom.h"
-#include "ODPlat.h"
-#include "ODKrnl.h"
-#include "ODUtil.h"
-
-
-/* Filename component identifies. */
-#define WILDCARDS 0x01
-#define EXTENSION 0x02
-#define FILENAME  0x04
-#define DIRECTORY 0x08
-#define DRIVE     0x10
-
-
-/* Local private helper function prototypes. */
-static void ODListFilenameMerge(char *pszEntirePath, const char *pszDrive,
-   const char *pszDir, const char *pszName, const char *pszExtension);
-static char *ODListGetFirstWord(char *pszInStr, char *pszOutStr);
-static char *ODListGetRemainingWords(char *pszInStr);
-static INT ODListFilenameSplit(const char *pszEntirePath, char *pszDrive,
-   char *pszDir, char *pszName, char *pszExtension);
-
-
-/* ----------------------------------------------------------------------------
- * od_list_files()
- *
- * Displays a list of files available for download, using an extended version
- * of the standard FILES.BBS format index file.
- *
- * Parameters: pszFileSpec - Directory name where the FILES.BBS file can be
- *                           found, or full path and filename of a FILES.BBS
- *                           format index file.
- *
- *     Return: TRUE on success or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_list_files(char *pszFileSpec)
-{
-   BYTE btLineCount = 2;
-   BOOL bPausing;
-   static char szLine[513];
-   static char szFilename[80];
-   static char szDrive[3];
-   static char szDir[70];
-   static char szTemp1[9];
-   static char szTemp2[5];
-   static char szBaseName[9];
-   static char szExtension[5];
-   static char szDirectory[100];
-   INT nFilenameInfo;
-   FILE *pfFilesBBS;
-   static char *pszCurrent;
-   BOOL bIsDir;
-   BOOL bUseNextLine = TRUE;
-   tODDirHandle hDir;
-   tODDirEntry DirEntry;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_list_files()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Check user's page pausing setting. */
-   bPausing = od_control.od_page_pausing;
-
-   if(od_control.od_extended_info) bPausing = od_control.user_attribute & 0x04;
-
-   /* Parse directory parameter. */
-   if(pszFileSpec == NULL)
-   {
-      strcpy(szODWorkString, ".");
-      strcpy(szDirectory, ".\\");
-   }
-   else if(*pszFileSpec == '\0')
-   {
-      strcpy(szODWorkString, ".");
-      strcpy(szDirectory, ".\\");
-   }
-   else
-   {
-      strcpy(szODWorkString, pszFileSpec);
-      strcpy(szDirectory, pszFileSpec);
-      if(szODWorkString[strlen(szODWorkString) - 1] == '\\')
-      {
-         szODWorkString[strlen(szODWorkString) - 1] = '\0';
-      }
-   }
-
-   /* Get directory information on path. */
-   if(ODDirOpen(szODWorkString, DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY
-      | DIR_ATTRIB_DIREC, &hDir) != kODRCSuccess)
-   {
-      od_control.od_error = ERR_FILEOPEN;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   if(ODDirRead(hDir, &DirEntry) != kODRCSuccess)
-   {
-      ODDirClose(hDir);
-      od_control.od_error = ERR_FILEOPEN;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   ODDirClose(hDir);
-
-   /* If it is a directory. */
-   if(DirEntry.wAttributes & DIR_ATTRIB_DIREC)
-   {
-      /* Append FILES.BBS to directory name & open. */
-      bIsDir = TRUE;
-      ODMakeFilename(szODWorkString, szODWorkString, "FILES.BBS",
-         sizeof(szODWorkString));
-      if((pfFilesBBS = fopen(szODWorkString, "r")) == NULL)
-      {
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-   }
-
-   /* If it is not a directory. */
-   else
-   {
-      bIsDir = FALSE;
-      if((pfFilesBBS = fopen(szODWorkString,"r")) == NULL)
-      {
-         od_control.od_error = ERR_FILEOPEN;
-         OD_API_EXIT();
-         return(FALSE);
-      }
-   }
-
-
-   /* Ignore previously pressed control keys. */
-   chLastControlKey = 0;
-
-
-   /* Loop until the end of the FILES.BBS file has been reached. */
-   for(;;)
-   {
-      if(fgets(szLine, 512, pfFilesBBS) == NULL) break;
-
-      if(!bUseNextLine)
-      {
-         if(szLine[strlen(szLine) - 1] == '\n')
-         {
-            bUseNextLine = TRUE;
-         }
-         continue;
-      }
-
-      if(szLine[strlen(szLine) - 1] == '\n')
-      {
-         szLine[strlen(szLine) - 1] = '\0';
-      }
-      else
-      {
-         bUseNextLine = FALSE;
-      }
-
-      if(chLastControlKey != 0)
-      {
-         switch(chLastControlKey)
-         {
-            case 's':
-               if(od_control.od_list_stop)
-               {
-                  if(od_control.baud)
-                  {
-                     ODComClearOutbound(hSerialPort);
-                  }
-                  od_clear_keybuffer();
-                  fclose(pfFilesBBS);
-                  OD_API_EXIT();
-                  return(TRUE);
-               }
-               break;
-
-            case 'p':
-               if(od_control.od_list_pause)
-               {
-                  od_clear_keybuffer();
-                  od_get_key(TRUE);
-               }
-         }
-         chLastControlKey = 0;
-      }
-
-      /* Determine whether or not this is a comment line. */
-      if(szLine[0] == ' ' || strlen(szLine) == 0)
-
-      {
-         /* If so, display the line in comment color. */
-         od_set_attrib(od_control.od_list_title_col);
-         od_disp_str(szLine);
-         od_disp_str("\n\r");
-         ++btLineCount;
-      }
-
-      /* If the line is not a comment. */
-      else                             
-      {
-         /* Extract the first word of the line, */
-         ODListGetFirstWord(szLine, szFilename);
-
-         /* And extract the filename. */
-         nFilenameInfo = ODListFilenameSplit(szFilename, szDrive, szDir,
-            szBaseName, szExtension);
-         if(!((nFilenameInfo & DRIVE) || (nFilenameInfo & DIRECTORY)))
-         {
-            if(bIsDir)
-            {
-               ODMakeFilename(szDirectory, szDirectory, szFilename,
-                  sizeof(szDirectory));
-               strcpy(szFilename, szDirectory);
-            }
-            else
-            {
-               ODListFilenameSplit(szDirectory, szDrive, szDir, szTemp1,
-                  szTemp2);
-               ODListFilenameMerge(szFilename, szDrive, szDir, szBaseName,
-                  szExtension);
-            }
-         }
-
-         /* Search for the filespec in directory. */
-         if(ODDirOpen(szFilename, DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY, &hDir)
-            == kODRCSuccess)
-         {
-            /* Display information on every file that matches. */
-            while(ODDirRead(hDir, &DirEntry) == kODRCSuccess)
-            {
-               od_set_attrib(od_control.od_list_name_col);
-               od_printf("%-12.12s  ", DirEntry.szFileName);
-               od_set_attrib(od_control.od_list_size_col);
-               od_printf("%-6ld   ", DirEntry.dwFileSize);
-               od_set_attrib(od_control.od_list_comment_col);
-               pszCurrent = ODListGetRemainingWords(szLine);
-               if(strlen(pszCurrent) <= 56)
-               {
-                  od_disp_str(pszCurrent);
-                  od_disp_str("\n\r");
-               }
-               else
-               {
-                  od_printf("%-56.56s\n\r", pszCurrent);
-               }
-               ++btLineCount;
-            }
-
-            ODDirClose(hDir);
-         }
-
-         /* Otherwise, indicate that the file is "Offline". */
-         else
-         {
-            ODListFilenameMerge(szFilename, "", "", szBaseName, szExtension);
-            od_set_attrib(od_control.od_list_name_col);
-            od_printf("%-12.12s ", szFilename);
-            od_set_attrib(od_control.od_list_offline_col);
-            od_disp_str(od_control.od_offline);
-            od_set_attrib(od_control.od_list_comment_col);
-
-            od_printf("%-56.56s\n\r", ODListGetRemainingWords(szLine));
-            ++btLineCount;
-         }
-      }
-
-      /* Check for end of screen & page pausing. */
-      if(btLineCount >= od_control.user_screen_length && bPausing)
-      {
-         /* Provide page pausing at end of each screen. */
-         if(ODPagePrompt(&bPausing))
-         {
-            fclose(pfFilesBBS);
-            OD_API_EXIT();
-            return(TRUE);
-         }
-
-         /* Reset the line number counter. */
-         btLineCount = 2;
-      }
-   }
-
-   /* When finished, close the file. */
-   fclose(pfFilesBBS);
-
-   /*  Return with success. */
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODListFilenameMerge()                               *** PRIVATE FUNCTION ***
- *
- * Builds a fully-qualified path name from the provided path component
- * strings.
- *
- * Parameters: pszEntirePath - Pointer to the destination string where the
- *                             generated path should be stored.
- *
- *             pszDrive      - Pointer to the drive string.
- *
- *             pszDir        - Pointer to the directory string.
- *
- *             pszName       - Pointer to the base filename string.
- *
- *             pszExtension  - Pointer to the extension name string.
- *
- *     Return: void
- */
-static void ODListFilenameMerge(char *pszEntirePath, const char *pszDrive,
-   const char *pszDir, const char *pszName, const char *pszExtension)
-{
-   if(pszEntirePath == NULL) return;
-
-   pszEntirePath[0] = '\0';
-
-   if(pszDrive != NULL)
-   {
-      strcpy(pszEntirePath, pszDrive);
-   }
-   if(pszDir != NULL)
-   {
-      strcat(pszEntirePath, pszDir);
-   }
-   if(pszName != NULL)
-   {
-      strcat(pszEntirePath,pszName);
-   }
-   if(pszExtension != NULL)
-   {
-      strcat(pszEntirePath,pszExtension);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODListFilenameSplit()                               *** PRIVATE FUNCTION ***
- *
- * Splits the provided path string into drive, directory name, file base name
- * and file extension components.
- *
- * Parameters: pszEntirePath - A string containing the path to split.
- *
- *             pszDrive      - A string where the drive letter should be stored.
- *
- *             pszDir        - A string where the directory name should be
- *                             stored.
- *
- *             pszName       - A string where the base filename should be
- *                             stored.
- *
- *             pszExtension  - A string where the filename extension should be
- *                             stored.
- *
- *     Return: One or more flags indicating which components where found in the
- *             provided path name.
- */
-static INT ODListFilenameSplit(const char *pszEntirePath, char *pszDrive,
-   char *pszDir, char *pszName, char *pszExtension)
-{
-   char *pchCurrentPos;
-   char *pchStart;
-   BYTE btSize;
-   INT nToReturn;
-
-   ASSERT(pszEntirePath != NULL);
-   ASSERT(pszDrive != NULL);
-   ASSERT(pszDir != NULL);
-   ASSERT(pszName != NULL);
-   ASSERT(pszExtension != NULL);
-
-   pchStart = (char *)pszEntirePath;
-   nToReturn = 0;
-
-   if((pchCurrentPos = strrchr(pchStart,':')) == NULL)
-   {
-      pszDrive[0] = '\0';
-   }
-   else
-   {
-      btSize = (int)(pchCurrentPos - pchStart) + 1;
-      if(btSize > 2) btSize = 2;
-      strncpy(pszDrive, pchStart, btSize);
-      pszDrive[btSize] = '\0';
-      pchStart = pchCurrentPos + 1;
-      nToReturn |= DRIVE;
-   }
-
-   if((pchCurrentPos = strrchr(pchStart, '\\'))==NULL)
-   {
-      pszDir[0] = '\0';
-   }
-   else
-   {
-      btSize = (int)(pchCurrentPos - pchStart) + 1;
-      strncpy(pszDir,pchStart,btSize);
-      pszDir[btSize] = '\0';
-      pchStart = pchCurrentPos + 1;
-      nToReturn |= DIRECTORY;
-   }
-
-   if(strchr(pchStart,'*') != NULL || strchr(pchStart, '?') != NULL)
-   {
-      nToReturn |= WILDCARDS;
-   }
-
-   if((pchCurrentPos = strrchr(pchStart, '.')) == NULL)
-   {
-      if(pchStart =='\0')
-      {
-         pszExtension[0] = '\0';
-         pszName[0] = '\0';
-      }
-      else
-      {
-         pszExtension[0] = '\0';
-         btSize = strlen(pchStart);
-         if (btSize > 8) btSize = 0;
-         strncpy(pszName, pchStart, btSize);
-         pszName[btSize] = '\0';
-         nToReturn |= FILENAME;
-      }
-   }
-   else
-   {
-      nToReturn |= FILENAME;
-      nToReturn |= EXTENSION;
-
-      btSize = (int)(pchCurrentPos - pchStart);
-
-      if(btSize > 8) btSize = 8;
-
-      strncpy(pszName, pchStart, btSize);
-      pszName[btSize] = '\0';
-
-      btSize = strlen(pchCurrentPos);
-      if(btSize > 4) btSize = 4;
-      strncpy(pszExtension, pchCurrentPos, btSize);
-      pszExtension[btSize]='\0';
-   }
-
-   return(nToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODListGetFirstWord()                                *** PRIVATE FUNCTION ***
- *
- * Returns the first word in a string containing a series of words separated by
- * one or more spaced.
- *
- * Parameters: pszInStr  - String to look in.
- *
- *             pszOutStr - Buffer to store result in. This buffer should be at
- *                         least as long as the pszInStr string.
- *
- *     Return: Pointer to the pszOutStr that was passed in.
- */
-static char *ODListGetFirstWord(char *pszInStr, char *pszOutStr)
-{
-   char *pchOut = (char *)pszOutStr;
-
-   ASSERT(pszInStr != NULL);
-   ASSERT(pszOutStr != NULL);
-
-   while(*pszInStr && *pszInStr != ' ')
-   {
-      *pchOut++ = *pszInStr++;
-   }
-   *pchOut = '\0';
-
-   return(pszOutStr);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODListGetRemainingWords()                           *** PRIVATE FUNCTION ***
- *
- * Obtains the remaining words in a string, after the first word. This function
- * is a companion to ODListGetFirstWord(), which obtains just the first word
- * in a string of many words.
- *
- * Parameters: pszInStr  - String to look at.
- *
- *     Return: A pointer to the position in a string of the second word.
- */
-static char *ODListGetRemainingWords(char *pszInStr)
-{
-   char *pchStartOfRemaining = (char *)pszInStr;
-
-   /* Skip over the first word in the string. */
-   while(*pchStartOfRemaining && *pchStartOfRemaining != ' ')
-   {
-      ++pchStartOfRemaining;
-   }
-
-   /* Skip over any spaces after the first word. */
-   while(*pchStartOfRemaining && *pchStartOfRemaining == ' ')
-   {
-      ++pchStartOfRemaining;
-   }
-
-   /* Return pointer to the rest of the string. */
-   return((char *)pchStartOfRemaining);
- }
diff --git a/src/odoors/ODLog.c b/src/odoors/ODLog.c
deleted file mode 100644
index 92580dc5387aaf507dda44988ee4e4ebb2d640cf..0000000000000000000000000000000000000000
--- a/src/odoors/ODLog.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODLog.c
- *
- * Description: Implements the logfile subsystem.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODInEx.h"
-#include "ODKrnl.h"
-
-
-/* Private logfile file handle */
-static FILE *logfile_pointer;
-
-
-/* Private helper functions. */
-static BOOL ODLogWriteStandardMsg(INT nLogfileMessage);
-static void ODLogClose(INT nReason);
-
-
-/* ----------------------------------------------------------------------------
- * ODLogEnable()
- *
- * This function is called from od_init() when the user explicitly includes the
- * OpenDoors logfile option using the od_control.od_logfile setting.
- *
- * Parameters: None.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL ODLogEnable(void)
-{
-   /* At this time, this function simply maps to a call to od_log_open(). */
-   od_log_open();
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_log_open()
- *
- * Called to begin logfile operations. This is when the first message is
- * written to the logfile, indicating that the user is entering OpenDoors.
- *
- * Parameters: None.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_log_open()
-{
-   time_t nUnixTime;
-   struct tm *ptmTimeRecord;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_log_open()");
-
-   /* Initialize OpenDoors if not already done. */
-   if(!bODInitialized) od_init();
-
-   /* Don't open logfile if it has been disabled in config file, etc. */
-   if(od_control.od_logfile_disable) return(TRUE);
-
-   /* Open actual logfile. */
-   if((logfile_pointer=fopen(od_control.od_logfile_name, "a")) == NULL)
-   {
-      return(FALSE);
-   }
-
-   /* Get the current time. */
-   nUnixTime = time(NULL);
-   ptmTimeRecord = localtime(&nUnixTime);
-
-   /* Print logfile tear line. */
-   fprintf(logfile_pointer, "\n----------  %s %02.2d %s %02.2d, %s\n",
-      od_control.od_day[ptmTimeRecord->tm_wday],
-      ptmTimeRecord->tm_mday,
-      od_control.od_month[ptmTimeRecord->tm_mon],
-      ptmTimeRecord->tm_year,
-      od_program_name);
-
-   /* Print message of door start up. */
-   sprintf(szODWorkString, (char *)od_control.od_logfile_messages[11],
-      od_control.user_name);
-   od_log_write(szODWorkString);
-
-   /* Set internal function hooks to enable calling of logfile features */
-   /* from elsewhere in OpenDoors. */
-   pfLogWrite = ODLogWriteStandardMsg;
-   pfLogClose = ODLogClose;
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODLogWriteStandardMsg()                             *** PRIVATE FUNCTION ***
- *
- * Function called to write a standard message to the logfile.
- *
- * Parameters: nLogfileMessage   - Index of the standard message to write to
- *                                 the logfile.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-static BOOL ODLogWriteStandardMsg(INT nLogfileMessage)
-{
-   if(nLogfileMessage < 0 || nLogfileMessage > 11)
-   {
-      return(FALSE);
-   }
-
-   od_log_write((char *)od_control.od_logfile_messages[nLogfileMessage]);
-
-   if(nLogfileMessage == 8)
-   {
-      sprintf(szODWorkString, od_control.od_logfile_messages[12],
-         od_control.user_reasonforchat);
-      szODWorkString[67] = '\0';
-      od_log_write(szODWorkString);
-   }
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_log_write()
- *
- * Called to write a message to the logfile.
- *
- * Parameters: pszMessage  - Pointer to a string containing the message text.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_log_write(char *pszMessage)
-{
-   char *pszFormat;
-   time_t nUnixTime;
-   struct tm *ptmTimeRecord;
-
-   /* Verify that OpenDoors has been initialized. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Stop if logfile has been disabled in config file, etc. */
-   if(od_control.od_logfile_disable)
-   {
-      OD_API_EXIT();
-      return(TRUE);
-   }
-
-   /* If logfile has not yet been opened, then open it. */
-   if(logfile_pointer==NULL)
-   {
-      if(!od_log_open())
-      {
-         OD_API_EXIT();
-         return(FALSE);
-      }
-   }
-
-   /* Get the current system time. */
-   nUnixTime=time(NULL);
-   ptmTimeRecord=localtime(&nUnixTime);
-
-   /* Determine which logfile format string to use. */
-   if(ptmTimeRecord->tm_hour<10)
-   {
-      pszFormat=(char *)">  %1.1d:%02.2d:%02.2d  %s\n";
-   }
-   else
-   {
-      pszFormat=(char *)"> %2.2d:%02.2d:%02.2d  %s\n";
-   }
-
-   /* Write a line to the logfile. */
-   fprintf(logfile_pointer, pszFormat, ptmTimeRecord->tm_hour,
-      ptmTimeRecord->tm_min, ptmTimeRecord->tm_sec, pszMessage);
-
-   OD_API_EXIT();
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODLogClose()                                        *** PRIVATE FUNCTION ***
- *
- * Writes final entry to the logfile when OpenDoors is exiting.
- *
- * Parameters: nReason  - Specifies the reason why OpenDoors is exiting.
- *
- *     Return: void
- */
-static void ODLogClose(INT nReason)
-{
-   /* Stop if logfile has been disabled in the config file, etc. */
-   if(od_control.od_logfile_disable) return;
-
-   /* If logfile has not been opened, then abort. */
-   if(logfile_pointer==NULL) return;
-
-   if(bPreOrExit)
-   {
-      od_log_write((char *)od_control.od_logfile_messages[13]);
-   }
-   else if(btExitReason<=5 && btExitReason>=1)
-   {
-      od_log_write((char *)od_control.od_logfile_messages[btExitReason-1]);
-   }
-   else
-   {
-      sprintf(szODWorkString,(char *)od_control.od_logfile_messages[5],nReason);
-      od_log_write(szODWorkString);
-   }
-
-   /* Close the logfile. */
-   fclose(logfile_pointer);
-
-   /* Prevent further use of logfile without first re-opening it. */
-   pfLogWrite = NULL;
-   pfLogClose = NULL;
-   logfile_pointer = NULL;
-}
diff --git a/src/odoors/ODMulti.c b/src/odoors/ODMulti.c
deleted file mode 100644
index f2682470a1be5d9a300f77c751cad34929ea04d2..0000000000000000000000000000000000000000
--- a/src/odoors/ODMulti.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODMulti.c
- *
- * Description: Code for multiple personality system, which allows
- *              a status line / function key personality to be dynamically
- *              selected at run-time.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 23, 1996  6.00  BP   Disable MPS under Win32 version.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Sep 01, 1996  6.10  BP   Update output area on od_set_per...().
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <time.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODInEx.h"
-#include "ODKrnl.h"
-
-
-/* Maximum number of personalities that may be installed at once. */
-#define MAX_PERSONALITIES  12
-
-
-/* Information on installed personalities. */
-typedef struct
-{
-   char szName[33];
-   INT nStatusTopLine;
-   INT nStatusBottomLine;
-   OD_PERSONALITY_PROC *pfPersonalityFunction;
-} tPersonalityInfo;
-
-static tPersonalityInfo aPersonalityInfo[MAX_PERSONALITIES]=
-{
-   {"STANDARD", 1, 23, pdef_opendoors},
-   {"REMOTEACCESS", 1, 23, pdef_ra},
-   {"WILDCAT", 1, 23, pdef_wildcat},
-   {"PCBOARD", 1, 23, pdef_pcboard}
-};
-
-
-/* Private variables. */
-static INT nPersonalities = 5;
-static INT nCurrentPersonality = 255;
-
-
-/* ----------------------------------------------------------------------------
- * ODMPSEnable()
- *
- * This function is called from within od_init() when the user enables the
- * multiple personality system.
- *
- * Parameters: None.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL ODMPSEnable(void)
-{
-   pfSetPersonality = od_set_personality;
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_set_personality()
- *
- * Sets the current personality to the one that is specified in pszName.
- *
- * Parameters: pszName - The name of the personality to switch to.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_set_personality(char *pszName)
-{
-#ifdef OD_TEXTMODE
-   BYTE btNewPersonality;
-   char szNameToMatch[33];
-   tPersonalityInfo *pNewPersonalityInfo;
-#endif /* OD_TEXTMODE */
-
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_set_personality()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-   
-#ifdef OD_TEXTMODE
-   /* Check for valid parameters. */
-   if(strlen(pszName) == 0)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Build personality name to match. */
-   strncpy(szNameToMatch, pszName, 32);
-   szNameToMatch[32] = '\0';
-   strupr(szNameToMatch);
-
-   /* Loop through installed personalities, checking for a match. */
-   for(btNewPersonality = 0; btNewPersonality < nPersonalities;
-      ++btNewPersonality)
-   {
-      /* If the name of this personality matches the one we are looking for. */
-      if(strcmp(szNameToMatch, aPersonalityInfo[btNewPersonality].szName) == 0)
-      {
-         if(btNewPersonality != nCurrentPersonality)
-         {
-            /* Remove current status line from the screen .*/
-            od_set_statusline(8);
-
-            /* Initialize the new personality. */
-            if(nCurrentPersonality != 255)
-               (*(OD_PERSONALITY_CALLBACK *)pfCurrentPersonality)(22);
-            od_control.od_page_statusline = -1;
-            pNewPersonalityInfo = 
-               &aPersonalityInfo[nCurrentPersonality=btNewPersonality];
-            bRAStatus = TRUE;
-            (*(OD_PERSONALITY_CALLBACK *)pNewPersonalityInfo
-               ->pfPersonalityFunction)(20);
-            ODScrnSetBoundary(1, (BYTE)pNewPersonalityInfo->nStatusTopLine, 80,
-               (BYTE)pNewPersonalityInfo->nStatusBottomLine);
-            pfCurrentPersonality
-               = pNewPersonalityInfo->pfPersonalityFunction;
-            btCurrentStatusLine = 255;
-
-            /* Update output area. */
-            btOutputTop = (BYTE)pNewPersonalityInfo->nStatusTopLine;
-            btOutputBottom = (BYTE)pNewPersonalityInfo->nStatusBottomLine;
-
-            /* Draw the new statusline. */
-            od_set_statusline(0);
-         }
-
-         OD_API_EXIT();
-         return(TRUE);
-      }
-   }
-
-   OD_API_EXIT();
-   od_control.od_error = ERR_LIMIT;
-   return(FALSE);
-
-#else /* !OD_TEXTMODE */
-
-   /* The multiple personality system is not supported under this platform. */
-   od_control.od_error = ERR_UNSUPPORTED;
-
-   /* Return with failure. */
-   OD_API_EXIT();
-   return(FALSE);
-
-#endif /* !OD_TEXTMODE */
-}
-
-
-
-/* ----------------------------------------------------------------------------
- * od_add_personality()
- *
- * Installs a new personality into the set of available personalities.
- *
- * Parameters: pszName        - Pointer to string containing the name of
- *                              the new personality.
- *
- *             btOutputTop    - Index of the top line of the status bar.
- *
- *             btOutputBottom - Index of the bottom line of the status bar.
- *
- *             pfPerFunc      - Pointer to the callback function which
- *                              implements this personality.
- *
- *     Return: TRUE on success or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_add_personality(char *pszName, BYTE btOutputTop,
-   BYTE btOutputBottom, OD_PERSONALITY_PROC *pfPerFunc)
-{
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_add_personality()");
-
-#ifdef OD_TEXTMODE
-
-   /* Check that we haven't exceeded the limit on the total number of */
-   /* installed personalities.                                        */
-   if(nPersonalities == MAX_PERSONALITIES)
-   {
-      od_control.od_error = ERR_LIMIT;
-      return(FALSE);
-   }
-
-   /* Store information on this new personality. */
-   strncpy(aPersonalityInfo[nPersonalities].szName, pszName, 32);
-   aPersonalityInfo[nPersonalities].szName[32] = '\0';
-   strupr(aPersonalityInfo[nPersonalities].szName);
-   aPersonalityInfo[nPersonalities].nStatusTopLine = btOutputTop;
-   aPersonalityInfo[nPersonalities].nStatusBottomLine = btOutputBottom;
-   aPersonalityInfo[nPersonalities].pfPersonalityFunction = pfPerFunc;
-
-   /* Increment total number of personalities. */
-   ++nPersonalities;
-
-   /* Return with success. */
-   return(TRUE);
-
-#else /* !OD_TEXTMODE */
-
-   /* The multiple personality system is not supported under this platform. */
-   od_control.od_error = ERR_UNSUPPORTED;
-
-   /* Return with failure. */
-   return(FALSE);
-
-#endif /* !OD_TEXTMODE */
-}
diff --git a/src/odoors/ODOORS62.TXT b/src/odoors/ODOORS62.TXT
deleted file mode 100644
index 957d5c20ad5bc5d50898c53e5285ee95e6b2b8ac..0000000000000000000000000000000000000000
--- a/src/odoors/ODOORS62.TXT
+++ /dev/null
@@ -1,82 +0,0 @@
-**************************************************************************
-* OpenDoors v6.21 C/C++ Door Development Kit for DOS and Win32 Platforms *
-**************************************************************************
-
-October 22, 2001
-
-Door32.sys and Socket update to Brian Pirie's OpenDoors Library 
-(http://www.attcanada.net/~pirie/opendoors.html) 
-
-by Rob Swindell (http://www.synchro.net/)
-
-==============================================================================
-
-This archive includes the source code to the OpenDoors library with 
-modifications made by me (Rob Swindell, aka Digital Man) to add support for 
-the Door32.sys drop file format and Win32 TCP/IP socket (Telnet) 
-communications.
-
-I made my modifications to the 6.1.1 release by Brian Pirie (ods611.zip) and
-used Microsoft Visual C++ v6.0. I also eliminated any warnings or errors
-detected by this compiler. The linker still warns of duplicate symbol 
-definition (od_control and od_printf), but I left those duplicate defintions
-in the .def file since they may have been necessary for another platform or
-compiler that I'm not using.
-
-This version also includes the ODEmu.c:od_send_file_section() modification 
-by Michael Dillon (gsvalore@arn.net | http://members.darktech.org/gsvalore/).
-
-
-DOOR32.SYS
-----------
-The Door32.sys drop file format was created in June of 2000 to support the
-new wave of 32-bit Windows and *nix doors. The main feature of this
-drop file format is that it includes the currently open Win32 comm handle or 
-socket descriptor (whichever is appropriate for the current connection).
-
-I didn't add support for the Win32 comm handle in the door32.sys file
-(I run a telnet-only BBS and would have no way to test it). I can't
-imagine it would be very difficult to add; I'm just not sure how much demand
-there would be for such a feature today.
-
-I did however add support for the socket descriptor in the drop file (used for
-TCP/IP - Telnet connections) and this is currently the only "standard" drop 
-file format that is expected to include a socket descriptor (Synchronet's 
-XTRN.DAT drop file also includes a socket descriptor, but I don't really 
-consider that format to be a "standard").
-
-The Door32.sys drop file is currently supported by the following known BBS
-packages:
-
-    Software     Home Page                             Version
-    -----------+-------------------------------------+--------
-    Mystic BBS   www.mysticbbs.com                        1.07
-    EleBBS       www.elebbs.com                           0.08?
-    Synchronet   www.synchro.net                           3.0
-
-
-TCP SOCKET I/O
---------------
-When using a Door32.sys drop file, the communications type (Local, Serial, or 
-Telnet) is automatically determined and I added support for (and tested) the 
-Telnet/socket communication method using Synchronet BBS Software v3.10 for 
-Win32 and HyperTerminal Private Edition v6.1.
-
-It is feasible that other drop file formats may be used and the socket 
-descriptor passed on the command line, but I didn't add support for that. 
-Currently, the Door32.sys file is the only way to pass the open socket 
-descriptor to the OpenDoors library.
-
-Since the Telnet protocol specifies that an end-of-line sequence (ENTER or 
-Carriage Return) is a CRLF (ASCII 13, 10), I had to modify od_get_key() to 
-ignore any line feed (ASCII 10, Ctrl-J) characters. Without this modification, 
-hitting enter in most Telnet clients would cause a "double return" to be sent 
-to the door. There may be a more desirable solution to the problem, but this 
-one seems to work for now.
-
-v6.21 fixes a bug in the socket disconnection ("carrier-loss") detection in 
-v6.20. I also lowered the input and carrier-detect thread priorities down to 
-"normal" which makes the doors appear to run faster and also make debugging
-continuous loop problems (like the one in v6.20) much easier.
-
-/* End of ODOORS62.TXT */
\ No newline at end of file
diff --git a/src/odoors/ODPCB.c b/src/odoors/ODPCB.c
deleted file mode 100644
index d02150588b9e31ec4a7555d5ad15f25b4ea9910a..0000000000000000000000000000000000000000
--- a/src/odoors/ODPCB.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODPCB.c
- *
- * Description: Implements the PC-Board personality.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Display connect speed with %lu.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODKrnl.h"
-#include "ODUtil.h"
-#include "ODStat.h"
-
-
-/* ----------------------------------------------------------------------------
- * pdef_pcboard()
- *
- * Personality function for the PC-Board like status line / function key
- * personality.
- *
- * Parameters: btOperation - Indicates personality operation to be performed.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL pdef_pcboard(BYTE btOperation)
-{
-   static char szTemp[81];
-   BYTE btInfoType = od_control.od_info_type;
-
-
-   switch(btOperation)
-   {
-      case PEROP_DISPLAY1:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("                                                      ALT-H=Help                                                                                                ");
-         ODScrnSetCursorPos(3, 24);
-         if(od_control.baud != 0)
-         {
-            ODScrnPrintf("(%lu) ", od_control.od_connect_speed);
-         }
-         else
-         {
-            ODScrnDisplayString("(Local) ");
-         }
-         sprintf(szTemp, "%s - %s", od_control.user_name,
-            od_control.user_location);
-         szTemp[42] = '\0';
-         strupr(szTemp);
-         ODScrnDisplayString(szTemp);
-         ODScrnSetCursorPos(1,25);
-         if(od_control.user_ansi || od_control.user_avatar
-            || od_control.user_rip)
-         {
-            ODScrnDisplayChar('G');
-         }
-         else
-         {
-            ODScrnDisplayChar('A');
-         }
-         if(btInfoType == RA1EXITINFO || btInfoType == RA2EXITINFO
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnPrintf(" (%s)",od_control.user_firstcall);
-         }
-         ODScrnSetCursorPos(15, 25);
-         ODScrnPrintf("Sec(0)=%u  ",od_control.user_security);
-         if(od_control.od_extended_info || btInfoType == DOORSYS_GAP
-            || btInfoType == CHAINTXT || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnPrintf("Times On=%u  ", od_control.user_numcalls);
-         }
-         if(od_control.od_extended_info || btInfoType == SFDOORSDAT
-            || btInfoType == DOORSYS_GAP || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnPrintf("Up:Dn=%lu:%lu", od_control.user_uploads,
-               od_control.user_downloads);
-         }
-         ODScrnSetCursorPos(70, 25);
-         ODScrnPrintf("%4d", od_control.user_timelimit);
-
-         od_control.key_status[0] = 0x0000;
-         od_control.key_status[1] = 0x2300;
-         break;
-
-      case PEROP_DISPLAY2:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("  Alt-> N=Next X=DOS F1/F2=Time                                                   2=LkOut 5=SHELL 8=HngUp 10=Chat                                               ");
-
-         od_control.key_status[0] = 0x2300;
-         od_control.key_status[1] = 0x0000;
-         break;
-
-      case PEROP_UPDATE1:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(70, 25);
-         ODScrnPrintf("%4d", od_control.user_timelimit);
-         break;
-
-      case PEROP_INITIALIZE:
-         od_control.key_hangup = 0x4200;
-         od_control.key_drop2bbs = 0x2d00;
-         od_control.key_dosshell = 0x3f00;
-         od_control.key_chat = 0x4400;
-         od_control.key_sysopnext = 0x3100;
-         od_control.key_lockout = 0x3c00;
-         od_control.key_status[0] = 0x0000;
-         od_control.key_status[1] = 0x2300;
-         od_control.key_status[2] = 0x0000;
-         od_control.key_status[3] = 0x0000;
-         od_control.key_status[4] = 0x0000;
-         od_control.key_status[5] = 0x0000;
-         od_control.key_status[6] = 0x0000;
-         od_control.key_status[7] = 0x0000;
-         od_control.key_status[8] = 0x0000;
-         od_control.key_keyboardoff = 0x2500;
-         od_control.key_moretime = 0x0000;
-         od_control.key_lesstime = 0x0000;
-         ODStatAddKey(0x6900);
-         ODStatAddKey(0x6800);
-         od_control.od_page_statusline = 0;
-         break;
-
-      case PEROP_CUSTOMKEY:
-         switch(od_control.od_last_hot)
-         {
-            /* Key to add five minutes. */
-            case 0x6900:
-               if(od_control.user_timelimit <= 1435 &&
-                  od_control.user_timelimit >= 5)
-               {
-                  od_control.user_timelimit += 5;
-                  bForceStatusUpdate = TRUE;
-                  CALL_KERNEL_IF_NEEDED();
-               }
-               else if(od_control.user_timelimit < 5)
-               {
-                  od_control.user_timelimit++;
-                  bForceStatusUpdate = TRUE;
-                  CALL_KERNEL_IF_NEEDED();
-               }
-               break;
-
-            /* Subtract five minutes from the user's remaining time. */
-            case 0x6800:
-               if(od_control.user_timelimit > 5)
-               {
-                  od_control.user_timelimit -= 5;
-                  bForceStatusUpdate = TRUE;
-                  CALL_KERNEL_IF_NEEDED();
-               }
-               else if(od_control.user_timelimit > 1)
-               {
-                  --od_control.user_timelimit;
-                  bForceStatusUpdate = TRUE;
-                  CALL_KERNEL_IF_NEEDED();
-               }
-               break;
-
-            default:
-               return;
-         }
-         od_control.od_last_hot = 0;
-         break;
-   }
-}
diff --git a/src/odoors/ODPlat.c b/src/odoors/ODPlat.c
deleted file mode 100644
index 200cac19ae163557c3f9a51eb8364b2345a5b907..0000000000000000000000000000000000000000
--- a/src/odoors/ODPlat.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODPlat.c
- *
- * Description: Contains platform-specific utility functions. Non-platform
- *              specific utility functions are implemented in odutil.c
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 14, 1994  6.00  BP   Created, with od_yield().
- *              Nov 01, 1994  6.00  BP   Added new directory access functions.
- *              Dec 09, 1994  6.00  BP   Eliminate access to old dir functions.
- *              Dec 31, 1994  6.00  BP   Added timing, file delete functions.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Dec 31, 1994  6.00  BP   Added ODMultitasker and ODPlatInit()
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Added multithreading functions.
- *              Nov 21, 1995  6.00  BP   Ported to Win32.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 13, 1995  6.00  BP   Added ODThreadWaitForExit().
- *              Dec 13, 1995  6.00  BP   Added ODThreadGetCurrent().
- *              Dec 19, 1995  6.00  BP   Fixed ODThreadGetCurrent() (Win32).
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 23, 1996  6.00  BP   Added ODProcessExit().
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 30, 1996  6.00  BP   Add semaphore timeout.
- *              Jan 31, 1996  6.00  BP   Add ODTimerLeft(), rm ODTimerSleep().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Prevent TC calls N_LXMUL@ & N_LXDIV@.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "OpenDoor.h"
-#include "ODGen.h"
-#include "ODCore.h"
-#include "ODPlat.h"
-#include "ODUtil.h"
-#include "ODSwap.h"
-#include "ODKrnl.h"
-
-#ifdef ODPLAT_WIN32
-#include "windows.h"
-#endif /* ODPLAT_WIN32 */
-
-
-/* Multitasker type, only availvable under DOS. */
-#ifdef ODPLAT_DOS
-tODMultitasker ODMultitasker = kMultitaskerNone;
-static void ODPlatYield(void);
-#endif /* ODPLAT_DOS */
-
-/* ----------------------------------------------------------------------------
- * ODPlatInit()
- *
- * Performs any initialization required to use the utility functions supplied
- * by this module.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODPlatInit(void)
-{
-#ifdef ODPLAT_DOS
-   /* If this is the DOS version of OpenDoors, then ODPlatInit() must */
-   /* determine what multitasker we are running under.                */
-
-   /* Check whether running under OS/2. */
-   ASM       mov ah, 0x30
-   ASM       int 0x21
-   ASM       cmp al, 0x0a
-   ASM       jl  NoOS2
-
-   /* If we get to this point, then OS/2 has been detected. */
-   ODMultitasker = kMultitaskerOS2;
-   return;
-
-NoOS2:
-   /* Check whether we are running under DesqView. */
-   ASM    mov cx, 0x4445
-   ASM    mov dx, 0x5351
-   ASM    mov ax, 0x2b01
-   ASM    int 0x21
-   ASM    cmp al, 0xff
-   ASM    je NoDesqView
-
-   /* If we get to this point, then DesqView has been detected. */
-   ODMultitasker = kMultitaskerDV;
-
-NoDesqView:
-   /* Check whether we are running under Windows. */
-   ASM    push di
-   ASM    push si
-   ASM    mov ax, 0x1600
-   ASM    int 0x2f
-   ASM    pop si
-   ASM    pop di
-   ASM    cmp al, 0x00
-   ASM    je NoWindows
-   ASM    cmp al, 0x80
-   ASM    je NoWindows
-
-    /* If we get to this point, then Windows has been detected. */
-   ODMultitasker = kMultitaskerWin;
-
-NoWindows:
-   ODMultitasker = kMultitaskerNone;
-#endif /* ODPLAT_DOS */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODPlatYield()                                       *** PRIVATE FUNCTION ***
- *
- * Yields control to other tasks when running as a DOS application under a
- * multitasking system.
- *
- * Parameters: none
- *
- *     Return: void
- */
-#ifdef ODPLAT_DOS
-static void ODPlatYield(void)
-{
-   switch(ODMultitasker)
-   {
-      case kMultitaskerDV:
-         ASM  mov ax, 0x1000
-         ASM  int 0x15
-         break;
-
-      case kMultitaskerWin:
-         ASM  mov ax, 0x1680
-         ASM  int 0x2f
-         break;
-
-      case kMultitaskerOS2:
-      default:
-         ASM  int 0x28
-   }
-}
-#endif /* ODPLAT_DOS */
-
-
-/* ========================================================================= */
-/* Multithreading and synchronization support.                               */
-/* ========================================================================= */
-
-#ifdef OD_MULTITHREADED
-
-/* ----------------------------------------------------------------------------
- * ODThreadCreate()
- *
- * Starts a new thread of concurrent execution.
- *
- * Parameters: phThread      - Pointer to the location where the handle to the
- *                             new thread should be stored.
- *
- *             pfThreadProc  - Function to call to begin execution of the
- *                             thread.
- *
- *             pThreadParam  - Parameter to pass to the thread function when
- *                             it is called.
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODThreadCreate(tODThreadHandle *phThread,
-   ptODThreadProc *pfThreadProc, void *pThreadParam)
-{
-#ifdef ODPLAT_WIN32
-   DWORD dwThreadID;
-   HANDLE hNewThread;
-
-   ASSERT(phThread != NULL);
-   ASSERT(pfThreadProc != NULL);
-   
-   /* Attempt to create the new thread. */
-   hNewThread = CreateThread(NULL, 0, pfThreadProc, pThreadParam,
-      0, &dwThreadID);
-
-   /* Check for thread creation failure. */
-   if(hNewThread == NULL)
-   {
-      return(kODRCGeneralFailure);
-   }
-
-   /* Pass newly created thread's handle back to the caller. */
-   *phThread = hNewThread;
-
-   /* Return with success. */
-   return(kODRCSuccess);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadExit()
- *
- * Causes the calling thread to be terminated.
- *
- * Parameters: none
- *
- *     Return: Never returns!
- */
-void ODThreadExit()
-{
-#ifdef ODPLAT_WIN32
-   ExitThread(0);
-#endif /* ODPLAT_WIN32 */
-
-   /* We should never get here. */
-   ASSERT(FALSE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadTerminate()
- *
- * Terminates the specified thread. 
- *
- * Parameters: hThread - Handle to the thread to be terminated.
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODThreadTerminate(tODThreadHandle hThread)
-{
-   ASSERT(hThread != NULL);
-
-#ifdef ODPLAT_WIN32
-   return(TerminateThread(hThread, 0) ? kODRCSuccess : kODRCGeneralFailure);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadSuspend()
- *
- * Pauses execution of the specified thread, until the ODThreadResume()
- * function is called.
- *
- * Parameters: hThread - Handle to the thread to be suspended.
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODThreadSuspend(tODThreadHandle hThread)
-{
-   ASSERT(hThread != NULL);
-
-#ifdef ODPLAT_WIN32
-   return(SuspendThread(hThread) == 0xFFFFFFFF ? kODRCGeneralFailure
-      : kODRCSuccess);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadResume()
- *
- * Continues execution of a thread previously paused by a call to
- * ODThreadSuspend().
- *
- * Parameters: hThread - Handle to the thread to be resumed.
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODThreadResume(tODThreadHandle hThread)
-{
-   ASSERT(hThread != NULL);
-
-#ifdef ODPLAT_WIN32
-   return(ResumeThread(hThread) == 0xFFFFFFFF ? kODRCGeneralFailure
-      : kODRCSuccess);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadSetPriority()
- *
- * Changes the execution priority of a thread. Since the exact semantics of
- * thread priorities are different for each platform, this function should
- * be used carefully. The caller should assume that no thread will run if there
- * exists a non-blocked thread with a higher priority.
- *
- * Parameters: hThread        - Handle to the thread to change the priority of.
- *
- *             ThreadPriority - New priority to assign to the thread.
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODThreadSetPriority(tODThreadHandle hThread,
-   tODThreadPriority ThreadPriority)
-{
-#ifdef ODPLAT_WIN32
-   int nWindowsThreadPriority;
-
-   ASSERT(hThread != NULL);
-
-   /* Determine the Windows thread priority to assign to the thread. */
-   switch(ThreadPriority)   
-   {
-      case OD_PRIORITY_LOWEST:
-         nWindowsThreadPriority = THREAD_PRIORITY_LOWEST;
-         break;
-      case OD_PRIORITY_BELOW_NORMAL:
-         nWindowsThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
-         break;
-      case OD_PRIORITY_NORMAL:
-         nWindowsThreadPriority = THREAD_PRIORITY_NORMAL;
-         break;
-      case OD_PRIORITY_ABOVE_NORMAL:
-         nWindowsThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
-         break;
-      case OD_PRIORITY_HIGHEST:
-         nWindowsThreadPriority = THREAD_PRIORITY_HIGHEST;
-         break;
-      default:
-         ASSERT(FALSE);
-   }
-
-   /* Update the thread's priority. */
-   return(SetThreadPriority(hThread, nWindowsThreadPriority)
-      ? kODRCSuccess : kODRCGeneralFailure);
-
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadWaitForExit()
- *
- * Blocks until the specified thread is terminated.
- *
- * Parameters: hThread - Handle to the thread to wait for.
- *
- *     Return: void
- */
-void ODThreadWaitForExit(tODThreadHandle hThread)
-{
-#ifdef ODPLAT_WIN32
-   WaitForSingleObject(hThread, INFINITE);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODThreadGetCurrent()
- *
- * Obtains a handle to the thread that called this function.
- *
- * Parameters: None.
- *
- *     Return: Handle to the current thread.
- */
-tODThreadHandle ODThreadGetCurrent(void)
-{
-#ifdef ODPLAT_WIN32
-   HANDLE hDuplicate;
-   if(!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
-      GetCurrentProcess(), &hDuplicate, 0, FALSE, DUPLICATE_SAME_ACCESS))
-   {
-      return(NULL);
-   }
-   return(hDuplicate);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSemaphoreAlloc()
- *
- * Allocates a semaphore synchronization object.
- *
- * Parameters: phSemaphore   - Pointer to location where the handle to the
- *                             newly created semaphore should be stored.
- *
- *             nInitialCount - Initial value to assign to the semaphore.
- *
- *             nMaximumCount - Maximum value that the semaphore may have
- *                             (if supported by the current platform).
- *
- *     Return: kOCRCSuccess on success, or an error code on failure.
- */
-tODResult ODSemaphoreAlloc(tODSemaphoreHandle *phSemaphore, INT nInitialCount,
-   INT nMaximumCount)
-{
-   ASSERT(phSemaphore != NULL);
-   ASSERT(nInitialCount >= 0);
-   ASSERT(nMaximumCount >= nInitialCount);
-
-#ifdef ODPLAT_WIN32
-   *phSemaphore = CreateSemaphore(NULL, (LONG)nInitialCount,
-      (LONG)nMaximumCount, NULL);
-
-   return(*phSemaphore == NULL ? kODRCGeneralFailure : kODRCSuccess);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSemaphoreFree()
- *
- * Deallocates a semaphore that we previously created by ODSemaphoreAlloc().
- *
- * Parameters: hSemaphore - Handle to semaphore to deallocate.
- *
- *     Return: void
- */
-void ODSemaphoreFree(tODSemaphoreHandle hSemaphore)
-{
-   ASSERT(hSemaphore != NULL);
-
-#ifdef ODPLAT_WIN32
-   DeleteObject(hSemaphore);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSemaphoreUp()
- *
- * Increments the count of the specified semaphore.
- *
- * Parameters: hSemaphore   - Semaphore to increment.
- *
- *             nIncrementBy - Amount to add to the semaphore's current value.
- *
- *     Return: void
- */
-void ODSemaphoreUp(tODSemaphoreHandle hSemaphore, INT nIncrementBy)
-{
-   ASSERT(hSemaphore != NULL);
-   ASSERT(nIncrementBy > 0);
-
-#ifdef ODPLAT_WIN32
-   ReleaseSemaphore(hSemaphore, nIncrementBy, NULL);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODSemaphoreDown()
- *
- * Decrements the count of the specified semaphore. A semaphore may never have
- * a value less than 0. Hence, an attempt to decrement the value of a
- * semaphore below zero will cause the calling thread to be blocked until some
- * other thread increments the semaphore.
- *
- * Parameters: hSemaphore   - Handle to the semaphore to decrement.
- *
- *             Timeout      - Maximum time to wait for the semaphore to be
- *                            incremented, or OD_NO_TIMEOUT to prevent this
- *                            function from returning before the semaphore is
- *                            incremented.
- *
- *     Return: kODRCSuccess, or kODRCTimeout if the semaphore was not
- *             decremented before Timeout milliseconds elapsed.
- */
-tODResult ODSemaphoreDown(tODSemaphoreHandle hSemaphore, tODMilliSec Timeout)
-{
-   ASSERT(hSemaphore != NULL);
-
-#ifdef ODPLAT_WIN32
-   if(WaitForSingleObject(hSemaphore, Timeout) == WAIT_FAILED)
-   {
-      return(kODRCTimeout);
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-#endif /* OD_MULTITHREADED */
-
-
-/* ----------------------------------------------------------------------------
- * ODProcessExit()
- *
- * Ends the current process.
- *
- * Parameters: nExitCode - Exit code to return to the calling process.
- *
- *     Return: Never returns.
- */
-void ODProcessExit(INT nExitCode)
-{
-#ifdef ODPLAT_WIN32
-   ExitProcess(nExitCode);
-#else /* !ODPLAT_WIN32 */
-   exit(nExitCode);
-#endif /* !ODPLAT_WIN32 */
-}
-
-
-/* ========================================================================= */
-/* Millisecond timer functions.                                              */
-/* ========================================================================= */
-
-#ifdef ODPLAT_DOS
-/* For the DOS platform, we need to know the number of milliseconds per */
-/* clock tick.                                                          */
-#define MILLISEC_PER_TICK 55           /* (approx. == 1000 / CLOCKS_PER_SEC) */
-#endif /* ODPLAT_DOS */
-
-/* ----------------------------------------------------------------------------
- * ODTimerStart()
- *
- * Starts a timer for a specified number of milliseconds. Future calls to
- * ODTimerElapsed() can be used to determine whether or not specified time
- * has elapsed. Note that while this function accepts its parameter in
- * milliseconds, it does not gurantee millisecond resolution. In fact, under
- * DOS, this timer mechanism has just under a 55 millisecond resolution, with
- * an average error of about 27 milliseconds.
- *
- * Parameters: pTimer   - Pointer to a tODTimer structure that will be later
- *                        passed to ODTimerElapsed().
- *
- *             Duration - Number of milliseconds after which timer should
- *                        elapse.
- *
- *     Return: void
- */
-void ODTimerStart(tODTimer *pTimer, tODMilliSec Duration)
-{
-   ASSERT(pTimer != NULL);
-   ASSERT(Duration >= 0);
-
-#ifdef ODPLAT_DOS
-   /* Store timer start time right away. */
-   pTimer->Start = clock();
-
-   /* Calculate duration of timer. */
-   ODDWordDivide((DWORD *)&pTimer->Duration, NULL, Duration,
-      MILLISEC_PER_TICK);
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   /* Store timer start time now. */
-   pTimer->Start = GetCurrentTime();
-   pTimer->Duration = Duration;
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODTimerElapsed()
- *
- * Determines whether or not a timer set by ODTimerStart() has elapsed.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- *                      by ODTimerStart().
- *
- *     Return: TRUE if timer has elapsed, FALSE if it has not.
- */
-BOOL ODTimerElapsed(tODTimer *pTimer)
-{
-   ASSERT(pTimer != NULL);
-
-#ifdef ODPLAT_DOS
-   return(clock() > pTimer->Start + pTimer->Duration
-      || clock() < pTimer->Start);
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   return(GetCurrentTime() > pTimer->Start + pTimer->Duration
-      || GetCurrentTime() < pTimer->Start);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODTimerWaitForElapse()
- *
- * Sleeps until the specified timer elapses.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- *                      by ODTimerStart().
- *
- *     Return: void
- */
-void ODTimerWaitForElapse(tODTimer *pTimer)
-{
-   ASSERT(pTimer != NULL);
-
-#ifdef ODPLAT_DOS
-
-   /* Under DOS, our timer resolution is low enough (only 18.2 ticks per    */
-   /* second), that we cannot accurately calculate the time to sleep for.   */
-   /* For this reason, we simply loop until the timer has elapsed, yielding */
-   /* control to other tasks if when the timer has not elapsed.             */
-
-   /* While timer has not elapsed. */
-   while(!ODTimerElapsed(pTimer))
-   {
-      /* Let other tasks run. */
-      od_sleep(0);
-   }
-
-#else /* !ODPLAT_DOS */
-   {
-      /* Under other platforms, timer resolution is high enough that we can */
-      /* ask the OS to block this thread for the amount of time required    */
-      /* for the timer to elapse.                                           */
-
-      tODMilliSec CurrentTime;
-      tODMilliSec TimerElapseTime = pTimer->Start + pTimer->Duration;
-
-      /* Determine the current time. */
-#ifdef ODPLAT_WIN32
-      CurrentTime = GetCurrentTime();
-#endif /* ODPLAT_WIN32 */
-
-      if(TimerElapseTime <= CurrentTime)
-      {
-         /* Timer has already elapsed. */
-         return;
-      }
-
-      /* Sleep for the amount of time left until the timer should elapse. */
-      od_sleep(TimerElapseTime - CurrentTime);
-   }
-#endif /* !ODPLAT_DOS */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODTimerLeft()
- *
- * Determines the number of milliseconds left before the timer elapses.
- *
- * Parameters: pTimer - Pointer to a tODTimer structure that was populated
- *                      by ODTimerStart().
- *
- *     Return: Number of milliseconds before timer elapses, or 0 if the timer
- *             has already elapsed.
- */
-tODMilliSec ODTimerLeft(tODTimer *pTimer)
-{
-   ASSERT(pTimer != NULL);
-
-#ifdef ODPLAT_DOS
-   {
-      clock_t Now = clock();
-      clock_t Left;
-
-      /* If timer has elapsed, return 0. */
-      if(Now > pTimer->Start + pTimer->Duration
-         || Now < pTimer->Start)
-      {
-         return(0);
-      }
-
-      Left = pTimer->Start + pTimer->Duration - Now;
-
-      return(ODDWordMultiply(Left, MILLISEC_PER_TICK));
-   }
-#else /* !ODPLAT_DOS */
-   {
-      tODMilliSec Now;
-
-#ifdef ODPLAT_WIN32      
-      Now = GetCurrentTime();
-#endif /* ODPLAT_WIN32 */
-
-      /* If timer has elapsed, return 0. */
-      if(Now > pTimer->Start + pTimer->Duration
-         || Now < pTimer->Start)
-      {
-         return(0);
-      }
-
-      return(pTimer->Start + pTimer->Duration - Now);
-   }
-#endif /* !ODPLAT_DOS */
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_sleep()
- *
- * Sleeps for the specified number of milliseconds, being as friendly to other
- * running tasks as possible. Under DOS, this function uses the ODTimerStart()/
- * ODTimerElapsed() mechanism, and so its accuracy is limited by the accuracy
- * of that mechanism.
- *
- * Parameters: Milliseconds - Number of milliseconds to sleep. A value of 0
- *                            allows any other waiting processes to run for
- *                            the rest of the current timeslice.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL od_sleep(tODMilliSec Milliseconds)
-{
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_sleep()");
-
-   /* Ensure that OpenDoors is initialized before proceeding. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-#ifdef ODPLAT_DOS
-   if(Milliseconds == 0)
-   {
-      ODPlatYield();
-   }
-   else
-   {
-      tODTimer SleepTimer;
-      ODTimerStart(&SleepTimer, Milliseconds);
-      while(!ODTimerElapsed(&SleepTimer))
-      {
-         /* Let other tasks run. */
-         ODPlatYield();
-      }
-   }
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   Sleep(Milliseconds);
-#endif /* ODPLAT_WIN32 */
-
-   OD_API_EXIT();
-}
-
-
-/* ========================================================================= */
-/* Directory access.                                                         */
-/* ========================================================================= */
-
-/* Structure for directories entries returned by DOS. */
-#ifdef ODPLAT_DOS
-typedef struct
-{
-   BYTE abtReserved[21];
-   BYTE btAttrib;
-   WORD wFileTime;
-   WORD wFileDate;
-   DWORD dwFileSize;
-   char szFileName[13];
-} tDOSDirEntry;
-#endif /* ODPLAT_DOS */
-
-
-/* Dir handle structure. */
-typedef struct
-{
-   BOOL bEOF;
-#ifdef ODPLAT_DOS
-   tDOSDirEntry FindBlock;
-#endif /* ODPLAT_DOS */
-#ifdef ODPLAT_WIN32
-   HANDLE hWindowsDir;
-   WIN32_FIND_DATA WindowsDirEntry;
-   int wAttributes;
-#endif /* ODPLAT_WIN32 */
-} tODDirInfo;
-
-
-/* Directory access private function prototypes. */
-static time_t DOSToCTime(WORD wDate, WORD wTime);
-#ifdef ODPLAT_DOS
-static INT ODDirDOSFindFirst(CONST char *pszPath, tDOSDirEntry *pBlock,
-   WORD wAttributes);
-static INT ODDirDOSFindNext(tDOSDirEntry *pBlock);
-#endif /* ODPLAT_DOS */
-#ifdef ODPLAT_WIN32
-static BOOL ODDirWinMatchesAttributes(tODDirInfo *pDirInfo);
-#endif /* ODPLAT_WIN32 */
-
-
-/* ----------------------------------------------------------------------------
- * ODDirOpen()
- *
- * Opens a directory for future access using ODDirRead(). On Success,
- * ODDirOpen() provides a directory handle that represents a list of directory
- * entries that match the specified path and attributes. When finished with
- * the directory handle, the caller should release it using ODDirClose().
- *
- * Parameters: pszPath     - Directory with filename (wildcards are supported),
- *                           for which matching files should be found. If there
- *                           are no matching files, ODDirOpen() returns with
- *                           kODRCNoMatch.
- *
- *             nAttributes - One or more of the DIR_ATTRIB_... constants,
- *                           connected by the bitmap-OR (|) operator.
- *
- *             phDir       - Pointer to a tODDirHandle, into which ODDirOpen()
- *                           will place a valid directory handle if and only
- *                           if it returns kODRCSuccess.
- *
- *     Return: A tODResult indicating success or reason for failure.
- */
-tODResult ODDirOpen(CONST char *pszPath, WORD wAttributes, tODDirHandle *phDir)
-{
-   tODDirInfo *pDirInfo;
-
-   ASSERT(pszPath != NULL);
-   ASSERT(phDir != NULL);
-
-   /* Attempt to allocate a directory information structure. */
-   if((pDirInfo = malloc(sizeof(tODDirInfo))) == NULL)
-   {
-      /* If unable to allocate enough memory, return this state to the */
-      /* caller. */
-      return(kODRCNoMemory);
-   }
-
-   /* Initialize directory information structure. */
-   pDirInfo->bEOF = FALSE;
-
-#ifdef ODPLAT_DOS
-   /* Read the first matching directory entry structure. */
-   if(ODDirDOSFindFirst(pszPath, &pDirInfo->FindBlock, wAttributes))
-   {
-      /* If unable to read directory entry, release directory information   */
-      /* structure, and return indicating that there are no matching files. */
-      free(pDirInfo);
-      return(kODRCNoMatch);
-   }
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   /* Store a copy of the attributes passed to open function. */
-   pDirInfo->wAttributes = wAttributes;
-
-   /* Attempt to read first directory entry. */
-   pDirInfo->hWindowsDir = FindFirstFile(pszPath, &pDirInfo->WindowsDirEntry);
-
-   if(pDirInfo->hWindowsDir == INVALID_HANDLE_VALUE)
-   {
-      /* If unable to read directory entry, release directory information   */
-      /* structure, and return indicating that there are no matching files. */
-      free(pDirInfo);
-      return(kODRCNoMatch);
-   }
-
-   /* If first file doesn't match specified attributes, then find one that */
-   /* does.                                                                */
-   /* Find next matching entry, if any. */
-   while(!ODDirWinMatchesAttributes(pDirInfo))
-   {
-      if(!FindNextFile(pDirInfo->hWindowsDir, &pDirInfo->WindowsDirEntry))
-      {
-         /* If unable to find matching directory entry, then release       */
-         /* structure, return indicating that there are no matching files. */
-         free(pDirInfo);
-         return(kODRCNoMatch);
-      }
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Now that open operation is complete, give the caller a directory */
-   /* handle. */
-   *phDir = ODPTR2HANDLE(pDirInfo, tODDirInfo);
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDirRead()
- *
- * Reads the next directory entry from an open directory, placing the directory
- * information into the tODDirEntry structure pointed to by pDirEntry.
- *
- * Parameters: hDir      - Handle to an open directory, as provided by
- *                         ODDirOpen().
- *
- *             pDirEntry - Pointer to structure into which directory entry
- *                         information should be placed.
- *
- *     Return: A tODResult indicating success or reason for failure. After the
- *             last directory entry has been read, all subsequent calls to
- *             ODDirRead() will return kODRCEndOfFile.
- */
-tODResult ODDirRead(tODDirHandle hDir, tODDirEntry *pDirEntry)
-{
-   tODDirInfo *pDirInfo = ODHANDLE2PTR(hDir, tODDirInfo);
-#ifdef ODPLAT_WIN32
-   WORD wDOSDate;
-   WORD wDOSTime;
-#endif /* ODPLAT_WIN32 */
-   
-   ASSERT(pDirEntry != NULL);
-   ASSERT(pDirInfo != NULL);
-
-   /* Check whether the last directory entry has been returned yet. */
-   if(pDirInfo->bEOF)
-   {
-      /* Return this state information to the caller. */
-      return(kODRCEndOfFile);
-   }
-
-#ifdef ODPLAT_DOS
-   /* Provide the caller with the information from the previously read */
-   /* directory entry.                                                 */
-
-   /* Copy the filename to the caller's structure. */
-   ODStringCopy(pDirEntry->szFileName, pDirInfo->FindBlock.szFileName,
-      DIR_FILENAME_SIZE);
-
-   /* Copy the attributes to the caller's structure. */
-   pDirEntry->wAttributes = pDirInfo->FindBlock.btAttrib;
-
-   /* Copy the file size to the caller's structure. */
-   pDirEntry->dwFileSize = pDirInfo->FindBlock.dwFileSize;
-
-   /* Determine the last file write time, in C library time format. */
-   pDirEntry->LastWriteTime = DOSToCTime(pDirInfo->FindBlock.wFileDate,
-      pDirInfo->FindBlock.wFileTime);
-
-   /* Read next directory entry, if any. */
-   pDirInfo->bEOF = ODDirDOSFindNext(&pDirInfo->FindBlock);
-
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   /* Provide the caller with the information from the previously read */
-   /* directory entry.                                                 */
-
-   /* Copy filename from Win32 8.3 filename. */
-   if(strlen(pDirInfo->WindowsDirEntry.cAlternateFileName) == 0)
-   {
-      ODStringCopy(pDirEntry->szFileName,
-         pDirInfo->WindowsDirEntry.cFileName, DIR_FILENAME_SIZE);
-   }
-   else
-   {
-      ODStringCopy(pDirEntry->szFileName,
-         pDirInfo->WindowsDirEntry.cAlternateFileName, DIR_FILENAME_SIZE);
-   }
-
-   /* Copy attribute bits. */
-   pDirEntry->wAttributes = DIR_ATTRIB_NORMAL;
-   if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
-   {
-      pDirEntry->wAttributes |= DIR_ATTRIB_ARCH;
-   }
-   if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-   {
-      pDirEntry->wAttributes |= DIR_ATTRIB_DIREC;
-   }
-   if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
-   {
-      pDirEntry->wAttributes |= DIR_ATTRIB_HIDDEN;
-   }
-   if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
-   {
-      pDirEntry->wAttributes |= DIR_ATTRIB_RDONLY;
-   }
-   if(pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
-   {
-      pDirEntry->wAttributes |= DIR_ATTRIB_SYSTEM;
-   }
-
-   /* Copy the file size to the caller's structure. */
-   pDirEntry->dwFileSize = (long)pDirInfo->WindowsDirEntry.nFileSizeLow;
-
-   /* Determine the last file write time, in C library time format. */
-   FileTimeToDosDateTime(&pDirInfo->WindowsDirEntry.ftLastWriteTime, &wDOSDate,
-      &wDOSTime);
-   pDirEntry->LastWriteTime = DOSToCTime(wDOSDate, wDOSTime);
-
-   /* Find next matching entry, if any. */
-   do
-   {
-      if(!FindNextFile(pDirInfo->hWindowsDir, &pDirInfo->WindowsDirEntry))
-      {
-         pDirInfo->bEOF = TRUE;
-      }
-   } while(!ODDirWinMatchesAttributes(pDirInfo));
-#endif /* ODPLAT_WIN32 */
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDirClose()
- *
- * Closes and open directory handle.
- *
- * Parameters: hDir - Handle to an open directory handle, as provided by the
- *                    ODDirOpen() function.
- *
- *     Return: void
- */
-void ODDirClose(tODDirHandle hDir)
-{
-   tODDirInfo *pDirInfo = ODHANDLE2PTR(hDir, tODDirInfo);
-
-   ASSERT(pDirInfo != NULL);
-
-#ifdef ODPLAT_WIN32
-   /* Under Win32, close directory handle. */
-   FindClose(pDirInfo->hWindowsDir);
-#endif /* ODPLAT_WIN32 */
-
-   /* Free the directory information structure. */
-   free(pDirInfo);
-}
-
-
-/* ----------------------------------------------------------------------------
- * DOSToCTime()                                        *** PRIVATE FUNCTION ***
- *
- * Converts DOS directory entry time format to the C library time format.
- *
- * Parameters: uDate - Date portion of the time to be converted.
- *
- *             uTime - Time of day portion of the time to be converted.
- *
- *     Return: The specified time, represented as a time_t.
- */
-static time_t DOSToCTime(WORD wDate, WORD wTime)
-{
-   struct tm TimeStruct;
-
-   TimeStruct.tm_sec = (wTime & 0x001f) * 2;
-   TimeStruct.tm_min = (wTime & 0x07e0) >> 5;
-   TimeStruct.tm_hour = (wTime & 0xf800) >> 11;
-   TimeStruct.tm_mday = wDate & 0x001f;
-   TimeStruct.tm_mon = ((wDate & 0x01e0) >> 5) - 1;
-   TimeStruct.tm_year = 80 + ((wDate & 0xfe00) >> 9);
-
-   return(mktime(&TimeStruct));
-}
-
-
-/* MS-DOS specific functions for directory access. */
-#ifdef ODPLAT_DOS
-
-/* ----------------------------------------------------------------------------
- * ODDirDOSFindFirst()                                 *** PRIVATE FUNCTION ***
- *
- * MS-DOS specific "Find First" function for reading directory entries. This
- * is essentially just a C-language interface to the interrupt function call
- * that is provided by DOS.
- *
- * Parameters: pszPath     - Pointer to string containing directory and
- *                           filespec to search for.
- *
- *             pBlock      - Pointer to directory block.
- *
- *             nAttributes - Attributes to match, if any.
- *
- *     Return: 0 on success, -1 on failure.
- */
-static int ODDirDOSFindFirst(CONST char *pszPath, tDOSDirEntry *pBlock,
-   WORD wAttributes)
-{
-   int nToReturn;
-
-   ASSERT(pszPath != NULL);
-   ASSERT(pBlock != NULL);
-
-   ASM     push ds
-   ASM     mov ah, 0x2f            /* Int 0x21, ah=0x2f: Get current DOS DTA */
-   ASM     int 0x21                                       /* Get current DTA */
-   ASM     push bx                   /* Store offset of current DTA on stack */
-   ASM     push es                  /* Store segment of current DTA on stack */
-   ASM     mov ah, 0x1a                /* Int 0x21, ah=0x1a: Set new DOS DTA */
-#ifdef LARGEDATA                                    /* If using far pointers */
-   ASM     lds dx, pBlock           /* Load DS:DX with far address of pBlock */
-#else                                              /* If using near pointers */
-   ASM     mov dx, pBlock             /* Load DX with near address of pBlock */
-#endif
-   ASM     int 0x21                                           /* Set DOS DTA */
-   ASM     mov ah, 0x4e         /* Int 0x21, ah=0x4e: DOS findfirst function */
-   ASM     mov cx, wAttributes                    /* Load attributes into CX */
-#ifdef LARGEDATA                                    /* If using far pointers */
-   ASM     lds dx, pszPath         /* Load DS:DX with far address in pszPath */
-#else                                              /* If using near pointers */
-   ASM     mov dx, pszPath           /* Load DX with near address in pszPath */
-#endif
-   ASM     int 0x21                               /* Call findfirst function */
-   ASM     jc error       /* If carry flag is set, then an error has ocurred */
-   ASM     mov word ptr nToReturn, 0                /* If no error, return 0 */
-   ASM     jmp after_result
-error:
-   ASM     mov word ptr nToReturn, -1                 /* If error, return -1 */
-after_result:
-   ASM     mov ah, 0x1a                /* Int 0x21, ah=0x1a: Set new DOS DTA */
-   ASM     pop ds                   /* Pop original DTA segment off of stack */
-   ASM     pop dx                      /* Pop original DTA offest from stack */
-   ASM     int 0x21                             /* Reset DOS DTA to original */
-   ASM     pop ds                   /* Restore DS stored at function startup */
-   return(nToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDirDOSFindNext()                                  *** PRIVATE FUNCTION ***
- *
- * MS-DOS specific "Find Next" function for reading directory entries. This
- * is essentially just a C-language interface to the interrupt function call
- * that is provided by DOS.
- *
- * Parameters: pBlock - Pointer to block in which to store next directory
- *                      entry.
- *
- *     Return: 0 on success, -1 on failure.
- */
-static int ODDirDOSFindNext(tDOSDirEntry *pBlock)
-{
-   int nToReturn;
-
-   ASSERT(pBlock != NULL);
-
-   ASM     push ds                                                /* Save DS */
-   ASM     mov ah, 0x2f            /* Int 0x21, ah=0x2f: Get current DOS DTA */
-   ASM     int 0x21                                       /* Get current DTA */
-   ASM     push bx                   /* Store offset of current DTA on stack */
-   ASM     push es                  /* Store segment of current DTA on stack */
-   ASM     mov ah, 0x1a                /* Int 0x21, ah=0x1a: Set new DOS DTA */
-#ifdef LARGEDATA                                    /* If using far pointers */
-   ASM     lds dx, pBlock           /* Load DS:DX with far address of pBlock */
-#else                                              /* If using near pointers */
-   ASM     mov dx, pBlock             /* Load DX with near address of pBlock */
-#endif
-   ASM     int 0x21                                           /* Set DOS DTA */
-   ASM     mov ah, 0x4f          /* Int 0x21, ah=0x4f: DOS findnext function */
-   ASM     int 0x21                               /* Call findfirst function */
-   ASM     jc error       /* If carry flag is set, then an error has ocurred */
-   ASM     mov word ptr nToReturn, 0                /* If no error, return 0 */
-   ASM     jmp after_result
-error:
-   ASM     mov word ptr nToReturn, -1                 /* If error, return -1 */
-after_result:
-   ASM     mov ah, 0x1a                /* Int 0x21, ah=0x1a: Set new DOS DTA */
-   ASM     pop ds                   /* Pop original DTA segment off of stack */
-   ASM     pop dx                      /* Pop original DTA offest from stack */
-   ASM     int 0x21                             /* Reset DOS DTA to original */
-   ASM     pop ds                   /* Restore DS stored at function startup */
-   return(nToReturn);
-}
-
-#endif /* ODPLAT_DOS */
-
-
-/* Win32 specific private functions for directory access. */
-#ifdef ODPLAT_WIN32
-/* ----------------------------------------------------------------------------
- * ODDirWinMatchesAttributes()                         *** PRIVATE FUNCTION ***
- *
- * Determines whether or not the directory entry pDirInfo->WindowsDirEntry
- * meets the attribute requirements specified in pDirInfo->nAttributes
- *
- * Parameters: pDirInfo - Pointer to a directory information structure with
- *                        attribute and directory entry values.
- *
- *     Return: TRUE if the file matches the attributes, FALSE if it does not.
- */
-static BOOL ODDirWinMatchesAttributes(tODDirInfo *pDirInfo)
-{
-   if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-      && !(pDirInfo->wAttributes & DIR_ATTRIB_DIREC))
-   {
-      return(FALSE);
-   }
-
-   if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
-      && !(pDirInfo->wAttributes & DIR_ATTRIB_ARCH))
-   {
-      return(FALSE);
-   }
-
-   if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
-      && !(pDirInfo->wAttributes & DIR_ATTRIB_HIDDEN))
-   {
-      return(FALSE);
-   }
-
-   if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
-      && !(pDirInfo->wAttributes & DIR_ATTRIB_RDONLY))
-   {
-      return(FALSE);
-   }
-
-   if((pDirInfo->WindowsDirEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
-      && !(pDirInfo->wAttributes & DIR_ATTRIB_SYSTEM))
-   {
-      return(FALSE);
-   }
-
-   return(TRUE);
-}
-#endif /* ODPLAT_WIN32 */
-
-
-/* ----------------------------------------------------------------------------
- * ODDirChangeCurrent()
- *
- * Changes current directory to the one specified.
- *
- * Parameters: pszPath - String containing path to change to.
- *
- *     Return: void
- */
-void ODDirChangeCurrent(char *pszPath)
-{
-#ifdef ODPLAT_DOS
-   int nDrive = 0;
-
-   if(pszPath[1] == ':')
-   {
-      nDrive = (toupper(pszPath[0]) - 'A');
-   }
-
-   _setdrvcd(nDrive, (char *)pszPath);
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   SetCurrentDirectory(pszPath);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDirGetCurrent()
- *
- * Obtains the name of the  current directory, including the current drive
- * designator.
- *
- * Parameters: pszPath       - String containing path to change to.
- *
- *             nMaxPathChars - Maximum characters in the buffer pointer to by
- *                             pszPath.
- *
- *     Return: void
- */
-void ODDirGetCurrent(char *pszPath, INT nMaxPathChars)
-{
-   ASSERT(pszPath != NULL);
-   ASSERT(nMaxPathChars > 0);
-
-#ifdef ODPLAT_DOS
-   UNUSED(nMaxPathChars);
-
-   strcpy(pszPath, "X:\\");
-   pszPath[0] = 'A' + _getdrv();
-   _getcd(0, (char *)pszPath + 3);
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   GetCurrentDirectory(nMaxPathChars, pszPath);
-#endif /* ODPLAT_WIN32 */
-
-   ASSERT((INT)strlen(pszPath) + 1 <= nMaxPathChars);
-}
-
-
-/* ========================================================================= */
-/* Misc. Functions                                                           */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODFileDelete()
- *
- * Deletes the file with the specified filename.
- *
- * Parameters: pszPath - Filename, possibly with path, to delete.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODFileDelete(CONST char *pszPath)
-{
-#ifdef ODPLAT_DOS
-   {
-      tODResult Result;
-
-      ASM    push ds
-#ifdef LARGEDATA
-      ASM    lds dx, pszPath
-#else /* !LARGEDATA */
-      ASM    mov ax, ss
-      ASM    mov ds, ax
-      ASM    mov dx, pszPath
-#endif /* !LARGEDATA */
-      ASM    mov ah, 0x41
-      ASM    int 0x21
-      ASM    jc Failure
-      ASM    mov word ptr Result, kODRCSuccess
-      ASM    jmp Done
-Failure:
-      ASM    mov word ptr Result, kODRCGeneralFailure
-Done:
-      ASM    pop ds
-
-      return(Result);
-   }
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   return(DeleteFile(pszPath) ? kODRCSuccess : kODRCGeneralFailure);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFileAccessMode()
- *
- * Determines the access permissions of a file.
- *
- * Parameters: pszFilename - Name of file to test.
- *
- *             nAccessMode - Indicates which file access mode to test for.
- *                           A value of 0 indicates existance, 2 indicates
- *                           write permission, 4 indicates read permission,
- *                           and 6 indicates read/write permission.
- *
- *     Return: FALSE if file can be accessed or TRUE if file cannot be
- *             accessed.
- */
-BOOL ODFileAccessMode(char *pszFilename, int nAccessMode)
-{
-   FILE *pfFileToTest;
-   char *pszModeString;
-   tODDirHandle hDir;
-
-#ifdef ODPLAT_DOS
-   BYTE nLength;
-   /* If we are looking for the root directory. */
-   nLength = strlen(pszFilename);
-   if((nLength == 3 && pszFilename[1] == ':' && pszFilename[2] == '\\') ||
-      (nLength == 1 && pszFilename[0] == '\\'))
-   {
-      if(nAccessMode == 0)
-      {
-          int to_return = FALSE;
-
-#ifdef LARGEDATA
-         ASM push ds
-         ASM lds dx, pszFilename
-#else
-         ASM mov dx, pszFilename
-#endif
-         ASM mov ax, 0x4300
-         ASM int 0x21
-         ASM jnc done
-         ASM mov word ptr to_return, TRUE
-done:
-#ifdef LARGEDATA
-         ASM pop ds
-#endif
-          return(to_return);
-      }
-      else
-      {
-          return(TRUE);
-      }
-   }
-#endif /* ODPLAT_DOS */
-
-   /* If the file doesn't exit, we fail in any mode. */
-   if(ODDirOpen(pszFilename,
-      DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY | DIR_ATTRIB_DIREC,
-      &hDir) != kODRCSuccess)
-   {
-      return(TRUE);
-   }
-
-   /* If directory open succeeded, then close it again. */
-   ODDirClose(hDir);
-
-   /* If the file does exist, then amode 0 is satisfied. */
-   if(nAccessMode == 0) return(FALSE);
-
-   /* If testing for an access permission, determine corresponding fopen() */
-   /* mode.                                                                */
-   switch(nAccessMode)
-   {
-      case 2:
-        pszModeString = "a";
-        break;
-      case 4:
-        pszModeString = "r";
-        break;
-      default:
-         pszModeString = "r+";
-   }
-
-   /* Attempt to open the file, if unable to do so return failure. */
-   if((pfFileToTest=fopen(pszFilename,pszModeString)) == NULL) return(TRUE);
-
-   /* If file open was successful, close it again, and return success. */
-   fclose(pfFileToTest);
-   return(FALSE);
-}
diff --git a/src/odoors/ODPlat.h b/src/odoors/ODPlat.h
deleted file mode 100644
index fa213279ddd1380ec2ec07d27a21759b5f28c6a7..0000000000000000000000000000000000000000
--- a/src/odoors/ODPlat.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODPlat.h
- *
- * Description: Contains platform-related definitions and prototypes for
- *              those function's whose implementation is platform-specific
- *              (functions implemented in odplat.c). Non-platform specific
- *              utility functions are defined in odutil.h and implemented in
- *              odutil.c.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 14, 1994  6.00  BP   Created.
- *              Nov 01, 1994  6.00  BP   Added ODDir...() functions.
- *              Dec 31, 1994  6.00  BP   Added timing, file delete functions.
- *              Dec 31, 1994, 6.00  BP   Added ODMultitasker and ODPlatInit()
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 17, 1995  6.00  BP   Added multithreading functions.
- *              Dec 13, 1995  6.00  BP   Added ODThreadWaitForExit().
- *              Dec 13, 1995  6.00  BP   Added ODThreadGetCurrent().
- *              Jan 23, 1996  6.00  BP   Added ODProcessExit().
- *              Jan 30, 1996  6.00  BP   Add semaphore timeout.
- *              Jan 31, 1996  6.00  BP   Add ODTimerLeft(), rm ODTimerSleep().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODPLAT
-#define _INC_ODPLAT
-
-#include <time.h>
-
-#include "ODTypes.h"
-#include "ODGen.h"
-
-#ifdef ODPLAT_WIN32
-#include "windows.h"
-#endif /* ODPLAT_WIN32 */
-
-/* odplat.c initialization function prototype */
-void ODPlatInit(void);
-
-
-/* ========================================================================= */
-/* Millisecond timer functions.                                              */
-/* ========================================================================= */
-
-/* Timer data type. */
-typedef struct
-{
-#ifdef ODPLAT_DOS
-   clock_t Start;
-   clock_t Duration;
-#else /* !ODPLAT_DOS */
-   tODMilliSec Start;
-   tODMilliSec Duration;
-#endif /* !ODPLAT_DOS */
-} tODTimer;
-
-/* Timer function prototypes. */
-void ODTimerStart(tODTimer *pTimer, tODMilliSec Duration);
-BOOL ODTimerElapsed(tODTimer *pTimer);
-void ODTimerWaitForElapse(tODTimer *pTimer);
-tODMilliSec ODTimerLeft(tODTimer *pTimer);
-
-
-/* ========================================================================= */
-/* Multithreading and synchronization support.                               */
-/* ========================================================================= */
-
-#ifdef OD_MULTITHREADED
-
-/* Thread handle data type. */
-#ifdef ODPLAT_WIN32
-typedef HANDLE tODThreadHandle;
-#endif /* ODPLAT_WIN32 */
-
-/* Thread priority enumeration. */
-typedef enum
-{
-   OD_PRIORITY_LOWEST,
-   OD_PRIORITY_BELOW_NORMAL,
-   OD_PRIORITY_NORMAL,
-   OD_PRIORITY_ABOVE_NORMAL,
-   OD_PRIORITY_HIGHEST
-} tODThreadPriority;
-
-/* Thread start proceedure type. */
-#define OD_THREAD_FUNC WINAPI
-#ifdef ODPLAT_WIN32
-typedef DWORD (OD_THREAD_FUNC ptODThreadProc)(void *);
-#endif /* ODPLAT_WIN32 */
-
-/* Thread creation, temination and suspension. */
-tODResult ODThreadCreate(tODThreadHandle *phThread,
-   ptODThreadProc *pfThreadProc, void *pThreadParam);
-void ODThreadExit();
-tODResult ODThreadTerminate(tODThreadHandle hThread);
-tODResult ODThreadSuspend(tODThreadHandle hThread);
-tODResult ODThreadResume(tODThreadHandle hThread);
-tODResult ODThreadSetPriority(tODThreadHandle hThread,
-   tODThreadPriority ThreadPriority);
-void ODThreadWaitForExit(tODThreadHandle hThread);
-tODThreadHandle ODThreadGetCurrent(void);
-
-
-/* Semaphore handle data type. */
-#ifdef ODPLAT_WIN32
-typedef HANDLE tODSemaphoreHandle;
-#endif /* ODPLAT_WIN32 */
-
-/* Semaphore manipulation functions. */
-tODResult ODSemaphoreAlloc(tODSemaphoreHandle *phSemaphore, INT nInitialCount,
-   INT nMaximumCount);
-void ODSemaphoreFree(tODSemaphoreHandle hSemaphore);
-void ODSemaphoreUp(tODSemaphoreHandle hSemaphore, INT nIncrementBy);
-tODResult ODSemaphoreDown(tODSemaphoreHandle hSemaphore, tODMilliSec Timeout);
-
-#endif /* OD_MULTITHREADED */
-
-void ODProcessExit(INT nExitCode);
-
-
-/* ========================================================================= */
-/* DOS multitasker information.                                              */
-/* ========================================================================= */
-#ifdef ODPLAT_DOS
-typedef enum
-{
-   kMultitaskerNone,
-   kMultitaskerDV,
-   kMultitaskerWin,
-   kMultitaskerOS2
-} tODMultitasker;
-
-extern tODMultitasker ODMultitasker;
-#endif /* ODPLAT_DOS */
-
-
-/* ========================================================================= */
-/* Directory Access.                                                         */
-/* ========================================================================= */
-
-/* Open directory handle type. */
-typedef tODHandle tODDirHandle;
-
-/* Directory entry structure. */
-#define DIR_FILENAME_SIZE 13
-
-#define DIR_ATTRIB_NORMAL   0x00
-#define DIR_ATTRIB_RDONLY   0x01
-#define DIR_ATTRIB_HIDDEN   0x02
-#define DIR_ATTRIB_SYSTEM   0x04
-#define DIR_ATTRIB_LABEL    0x08
-#define DIR_ATTRIB_DIREC    0x10
-#define DIR_ATTRIB_ARCH     0x20
-
-typedef struct
-{
-   char szFileName[DIR_FILENAME_SIZE];
-   WORD wAttributes;
-   time_t LastWriteTime;
-   DWORD dwFileSize;
-} tODDirEntry;
-
-/* Directory function prototypes. */
-tODResult ODDirOpen(CONST char *pszPath, WORD wAttributes, tODDirHandle *phDir);
-tODResult ODDirRead(tODDirHandle hDir, tODDirEntry *pDirEntry);
-void ODDirClose(tODDirHandle hDir);
-void ODDirChangeCurrent(char *pszPath);
-void ODDirGetCurrent(char *pszPath, INT nMaxPathChars);
-
-
-/* ========================================================================= */
-/* Miscellaneous Functions.                                                  */
-/* ========================================================================= */
-tODResult ODFileDelete(CONST char *pszPath);
-BOOL ODFileAccessMode(char *pszFilename, int nAccessMode);
-
-#endif /* !_INC_ODPLAT */
diff --git a/src/odoors/ODPopup.c b/src/odoors/ODPopup.c
deleted file mode 100644
index e81b53db1abf42f5e8815786acaa88ffc2927e0d..0000000000000000000000000000000000000000
--- a/src/odoors/ODPopup.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODPopUp.c
- *
- * Description: Implements od_popup_menu(), for displaying a menu in
- *              a window, allowing the user to make a selection using
- *              "hot keys" or by using arrow keys.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Jan 15, 1995  6.00  BP   Free menu structure on menu destroy.
- *              Feb 02, 1995  6.00  BP   Added od_yield() call in for(;;) loop.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Change valid range of nLevel to 0-10.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 23, 1995  6.00  BP   Restore original color on exit.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 04, 1996  6.00  BP   Use od_get_input().
- *              Jan 12, 1996  6.00  BP   Claim exclusive use of arrow keys.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 31, 1996  6.00  BP   Added timeout for od_get_input().
- *              Jan 31, 1996  6.00  BP   Add ODPopupCheckForKey() wait param.
- *              Jan 31, 1996  6.00  BP   Ignore left & right if !MENU_PULLDOWN.
- *              Feb 13, 1996  6.00  BP   Added od_get_input() flags parameter.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODKrnl.h"
-#include "ODStat.h"
-
-
-/* Configurable od_popup_menu() parameters. */
-
-/* Maximum menu level. */
-#define MENU_LEVELS        11
-
-/* Maximum number of items in a menu. */
-#define MAX_MENU_ITEMS     21
-
-/* Maximum width of any menu item. */
-#define MAX_ITEM_WIDTH     76
-
-
-/* Other manifest constants. */
-#define NO_COMMAND         -10
-
-
-/* Local data types. */
-
-/* Information on an individual menu item. */
-typedef struct
-{
-   char szItemText[MAX_ITEM_WIDTH + 1];
-   BYTE btKeyIndex;
-} tMenuItem;
-
-/* Information on a popup menu level. */
-typedef struct
-{
-   tMenuItem *paMenuItems;
-   BYTE btNumMenuItems;
-   BYTE btWidth;
-   BYTE btRight;
-   BYTE btBottom;
-   BYTE btCursor;
-   BYTE btLeft;
-   BYTE btTop;
-   WORD wFlags;
-   void *pWindow;
-} tMenuLevelInfo;
-
-
-/* Private variables. */
-
-/* Array of information on each menu level. */
-tMenuLevelInfo MenuLevelInfo[MENU_LEVELS];
-
-/* Current menu settings. */
-static BYTE btCorrectItem;
-static INT nCommand;
-static WORD wCurrentFlags;
-static BYTE btCurrentNumMenuItems;
-static INT nCurrentLevel;
-
-
-/* Private helper functions used by od_popup_menu(). */
-static void ODPopupCheckForKey(BOOL bWaitForInput);
-static void ODPopupDisplayMenuItem(BYTE btLeft, BYTE btTop,
-   tMenuItem *paMenuItems, BYTE btItemIndex, BOOL bHighlighted, BYTE btWidth,
-   BOOL bPositionCursor);
-
-
-/* ----------------------------------------------------------------------------
- * od_popup_menu()
- *
- * Displays a popup menu on the local and remote screens.
- *
- * Parameters: pszTitle - Text to show as the window title of the popup menu.
- *                        If no title is desired, this parameter should be set
- *                        to either "" or NULL.
- *
- *             pszText  - String which contains the menu definition. In the
- *                        menu definition string, individual menu items are
- *                        separated by a pipe ('|') character, and hotkeys are
- *                        proceeded by a carat ('^') character.
- *
- *             nLeft    - The 1-based column number of the upper right corner
- *                        of the menu.
- *
- *             nTop     - The 1-based row number of the upper right corner of
- *                        the menu.
- *
- *             nLevel   - Menu level, which must be a value between 0 and
- *                        MENU_LEVELS.
- *
- *             uFlags   - One or more flags, combined by the bitwise or (|)
- *                        operator.
- *
- *     Return: POPUP_ERROR on error, POPUP_ESCAPE if user pressed the Escape
- *             key, POPUP_LEFT if the user choose to move to the next menu to
- *             the left, POPUP_RIGHT if the user choose to move to the next
- *             menu to the right, or a postive value if the user choose an item
- *             from the menu. In this case, the return value is the 1-based
- *             index of the selected menu item.
- */
-ODAPIDEF INT ODCALL od_popup_menu(char *pszTitle, char *pszText, INT nLeft,
-   INT nTop, INT nLevel, WORD uFlags)
-{
-   tMenuItem *paMenuItems = NULL;
-   BYTE btCount;
-   BYTE btWidth;
-   BYTE btRight;
-   BYTE btBottom;
-   BYTE btCursor;
-   BYTE btLeft;
-   BYTE btTop;
-   void *pWindow;
-   BYTE btBetweenSize;
-   BYTE btTitleSize;
-   BYTE btRemaining;
-   BYTE btLineCount;
-   INT16 nOriginalAttrib;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_popup_menu()");
-
-   /* Initialize OpenDoors, if not already done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Setup od_box_chars appropriately. */
-   if(od_control.od_box_chars[BOX_BOTTOM] == 0)
-   {
-      od_control.od_box_chars[BOX_BOTTOM] = od_control.od_box_chars[BOX_TOP];
-   }
-   if(od_control.od_box_chars[BOX_RIGHT] == 0)
-   {
-      od_control.od_box_chars[BOX_RIGHT] = od_control.od_box_chars[BOX_LEFT];
-   }
-
-   /* Store initial display color. */
-   nOriginalAttrib = od_control.od_cur_attrib;
-
-
-   /* check level bounds */
-   if(nLevel < 0 || nLevel > MENU_LEVELS)
-   {
-      od_control.od_error = ERR_LIMIT;
-      OD_API_EXIT();
-      return(POPUP_ERROR);
-   }
-   /* normalize level */
-   nCurrentLevel = nLevel;
-
-   if(MenuLevelInfo[nLevel].pWindow == NULL)
-   {
-      btLeft = nLeft;
-      btTop = nTop;
-      wCurrentFlags = uFlags;
-
-      if(pszText == NULL)
-      {
-         od_control.od_error = ERR_PARAMETER;
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      if(paMenuItems == NULL)
-      {
-         if((paMenuItems = malloc(sizeof(tMenuItem) * MAX_MENU_ITEMS)) == NULL)
-         {
-            od_control.od_error = ERR_PARAMETER;
-            OD_API_EXIT();
-            return(POPUP_ERROR);
-         }
-      }
-      MenuLevelInfo[nLevel].paMenuItems = paMenuItems;
-
-      btCurrentNumMenuItems = 0;
-      btWidth = 0;
-      btCount = 0;
-      nCommand = NO_COMMAND;
-      paMenuItems[0].btKeyIndex = 0;
-      while(*pszText && btCurrentNumMenuItems < MAX_MENU_ITEMS)
-      {
-         switch(*pszText)
-         {
-            case '|':
-                  paMenuItems[btCurrentNumMenuItems++].szItemText[btCount]
-                     = '\0';
-                  if(btCount > btWidth) btWidth = btCount;
-                  btCount = 0;
-                  paMenuItems[btCurrentNumMenuItems].btKeyIndex = 0;
-               break;
-
-            case '^':
-               if(btCount < MAX_ITEM_WIDTH)
-               {
-                  paMenuItems[btCurrentNumMenuItems].btKeyIndex = btCount;
-               }
-               break;
-
-            default:
-               if(btCount < MAX_ITEM_WIDTH)
-               {
-                  paMenuItems[btCurrentNumMenuItems].szItemText[btCount++] =
-                     *pszText;
-               }
-         }
-         ++pszText;
-      }
-
-      /* If we were in the middle of a menu item when we encountered the end */
-      /* of the string, then it should form an additional menu entry. This   */
-      /* handles the case of a menu string to no terminating | for the last  */
-      /* entry.                                                              */
-      if(btCount != 0)
-      {
-         /* null-terminate current menu entry string */
-         paMenuItems[btCurrentNumMenuItems++].szItemText[btCount] = '\0';
-
-         /* If this is the widest entry, update he menu width appropriately  */
-         if(btCount > btWidth) btWidth = btCount;
-      }
-
-      /* If the menu description string does not contain any menu items */
-      if(btCurrentNumMenuItems == 0)
-      {
-         /* Return with parameter error */
-         od_control.od_error = ERR_PARAMETER;
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      /* Adjust menu width to allow title to fit, if possible               */
-      /* If a title string was passed, and that string is wider than widest */
-      /* menu entry ...                                                     */
-      if(pszTitle != NULL && strlen(pszTitle) + 2 > btWidth)
-      {
-         /* Then width of menu window should be large enough to allow up to */
-         /* the first 76 characters of the title to fit.                    */
-         btWidth = strlen(pszTitle) + 2 > MAX_ITEM_WIDTH
-            ? MAX_ITEM_WIDTH : strlen(pszTitle) + 2;
-      }
-
-      /* Based on number and size of menu items, and width of title,         */
-      /* determine the bottom, right and inside width of the menu.           */
-      btBottom = btTop + btCurrentNumMenuItems + 1;
-      btRight = btLeft + btWidth + 3;
-      btBetweenSize = (btRight - btLeft) - 1;
-
-      /* If neither ANSI nor AVATAR mode is available, return with an error */
-      if(!(od_control.user_ansi || od_control.user_avatar))
-      {
-         od_control.od_error = ERR_NOGRAPHICS;
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      /* If menu would "fall off" edge of screen, return with an error */
-      if(btLeft < 1 || btTop < 1 || btRight > OD_SCREEN_WIDTH
-         || btBottom > OD_SCREEN_HEIGHT || btRight - btLeft < 2
-         || btBottom - btTop < 2)
-      {
-         od_control.od_error = ERR_PARAMETER;
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      /* Allocate space to store window information. If unable to allocate */
-      /* enough space, return with an error.                               */
-      if((pWindow = malloc((btRight - btLeft + 1) * 2
-         + (btBottom - btTop + 1) * 160)) == NULL)
-      {
-         od_control.od_error = ERR_MEMORY;
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      /* Store contents of screen where memu will be drawn in the temporary */
-      /* buffer.                                                            */
-      if(!od_gettext(btLeft, btTop, btRight, btBottom, pWindow))
-      {
-         free(pWindow);
-         pWindow = NULL;
-
-         /* Note that od_error code has been set in od_gettext(). */
-         OD_API_EXIT();
-         return(POPUP_ERROR);
-      }
-
-      /* Determine number of characters of title to be displayed */
-      if(pszTitle == NULL)
-      {
-         btTitleSize = 0;
-      }
-      else
-      {
-         if((btTitleSize = strlen(pszTitle)) > (btBetweenSize - 4))
-         {
-            btTitleSize = btBetweenSize - 4;
-         }
-      }
-
-      od_set_cursor(btTop,btLeft);
-      od_set_attrib(od_control.od_menu_border_col);
-      od_putch(od_control.od_box_chars[BOX_UPPERLEFT]);
-      if(btTitleSize == 0)
-      {
-         od_repeat(od_control.od_box_chars[BOX_TOP], btBetweenSize);
-      }
-      else
-      {
-         od_repeat(od_control.od_box_chars[BOX_TOP],
-            btRemaining = ((btBetweenSize - btTitleSize - 2) / 2));
-         od_set_attrib(od_control.od_menu_title_col);
-         od_putch(' ');
-         od_disp(pszTitle,btTitleSize, TRUE);
-         od_putch(' ');
-         od_set_attrib(od_control.od_menu_border_col);
-         od_repeat(od_control.od_box_chars[BOX_TOP],
-            (BYTE)(btBetweenSize - btRemaining - btTitleSize - 2));
-      }
-      od_putch(od_control.od_box_chars[BOX_UPPERRIGHT]);
-
-      btLineCount = btTop + 1;
-      btCorrectItem = 0;
-      ODPopupCheckForKey(FALSE);
-      btCursor = btCorrectItem;
-      for(btCount = 0; btCount < btCurrentNumMenuItems
-         && btLineCount < btBottom; ++btCount)
-      {
-         ODPopupCheckForKey(FALSE);
-         if(nCommand != NO_COMMAND && !(wCurrentFlags & MENU_KEEP))
-         {
-            goto exit_now;
-         }
-
-         od_set_cursor(btLineCount,btLeft);
-         od_putch(od_control.od_box_chars[BOX_LEFT]);
-         od_set_attrib(od_control.od_menu_text_col);
-
-         if(btCount == btCursor)
-         {
-            ODPopupDisplayMenuItem(btLeft, btTop, paMenuItems, btCount,
-               TRUE, btWidth, FALSE);
-         }
-         else
-         {
-            ODPopupDisplayMenuItem(btLeft, btTop, paMenuItems, btCount,
-               FALSE, btWidth, FALSE);
-         }
-
-         od_set_attrib(od_control.od_menu_border_col);
-         od_putch(od_control.od_box_chars[BOX_RIGHT]);
-         ++btLineCount;
-      }
-
-      od_set_cursor(btBottom, btLeft);
-      od_putch(od_control.od_box_chars[BOX_LOWERLEFT]);
-      od_repeat(od_control.od_box_chars[BOX_BOTTOM], btBetweenSize);
-      od_putch(od_control.od_box_chars[BOX_LOWERRIGHT]);
-      od_set_cursor(btTop + 1, btLeft + 1);
-   }
-   else
-   {
-      paMenuItems = MenuLevelInfo[nLevel].paMenuItems;
-      btCurrentNumMenuItems = MenuLevelInfo[nLevel].btNumMenuItems;
-      btWidth = MenuLevelInfo[nLevel].btWidth;
-      btRight = MenuLevelInfo[nLevel].btRight;
-      btBottom = MenuLevelInfo[nLevel].btBottom;
-      btLeft = MenuLevelInfo[nLevel].btLeft;
-      btTop = MenuLevelInfo[nLevel].btTop;
-      wCurrentFlags = MenuLevelInfo[nLevel].wFlags;
-      pWindow = MenuLevelInfo[nLevel].pWindow;
-      btCorrectItem = btCursor = MenuLevelInfo[nLevel].btCursor;
-      nCommand = NO_COMMAND;
-
-      if(uFlags & MENU_DESTROY)
-      {
-         nCommand = POPUP_ESCAPE;
-         goto destroy;
-      }
-
-      /* Otherwise, position flashing hardware cursor appropriately */
-      od_set_cursor(btTop + btCursor + 1, btLeft + 1);
-   }
-
-   /* Claim exclusive use of arrow keys. */
-   ODStatStartArrowUse();
-
-   for(;;)
-   {
-      ODPopupCheckForKey(TRUE);
-      if(btCorrectItem != btCursor)
-      {
-         ODPopupDisplayMenuItem(btLeft, btTop, paMenuItems, btCursor,
-            FALSE, btWidth, TRUE);
-         btCursor = btCorrectItem;
-         ODWaitDrain(25);
-         ODPopupCheckForKey(FALSE);
-         ODPopupDisplayMenuItem(btLeft, btTop, paMenuItems, btCursor,
-            TRUE, btWidth, TRUE);
-      }
-
-      if(nCommand != NO_COMMAND)
-      {
-         goto exit_now;
-      }
-   }
-
-exit_now:
-   if((!(wCurrentFlags & MENU_KEEP)) || nCommand <= 0)
-   {
-destroy:
-      od_puttext(btLeft, btTop, btRight, btBottom, pWindow);
-      free(pWindow);
-      MenuLevelInfo[nLevel].pWindow = NULL;
-      if(paMenuItems != NULL)
-      {
-         free(paMenuItems);
-         MenuLevelInfo[nLevel].paMenuItems = NULL;
-      }
-   }
-   else if(wCurrentFlags & MENU_KEEP)
-   {
-      MenuLevelInfo[nLevel].paMenuItems = paMenuItems;
-      MenuLevelInfo[nLevel].btNumMenuItems = btCurrentNumMenuItems;
-      MenuLevelInfo[nLevel].btWidth = btWidth;
-      MenuLevelInfo[nLevel].btRight = btRight;
-      MenuLevelInfo[nLevel].btBottom = btBottom;
-      MenuLevelInfo[nLevel].btCursor = btCursor;
-      MenuLevelInfo[nLevel].btLeft = btLeft;
-      MenuLevelInfo[nLevel].btTop = btTop;
-      MenuLevelInfo[nLevel].wFlags = wCurrentFlags;
-      MenuLevelInfo[nLevel].pWindow = pWindow;
-   }
-
-   /* Restore original display color. */
-   od_set_attrib(nOriginalAttrib);
-
-   /* Release exclusive use of arrow keys. */
-   ODStatEndArrowUse();
-
-   OD_API_EXIT();
-   return(nCommand);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODPopupCheckForKey()                                *** PRIVATE FUNCTION ***
- *
- * Checks whether or not the user has pressed any key. If one or more keys
- * have been pressed, then these keystrokes are processed. This function
- * returns when no more keys are waiting in the inbound buffer, or when a key
- * has been pressed that requires immediate action (such as the [ENTER] key).
- *
- * Parameters: bWaitForInput - Indicates whether this function should return
- *                             immediately if no input is waiting (FALSE), or
- *                             wait for the next input even before returning
- *                             (TRUE).
- *
- *     Return: void
- */
-static void ODPopupCheckForKey(BOOL bWaitForInput)
-{
-   BYTE btCount;
-   tODInputEvent InputEvent;
-   BOOL bDoneAnythingYet = FALSE;
-
-   /* Loop, processing keys. If a command has been selected, stop looping */
-   /* immediately. If there are no more keys waiting, stop looping        */
-   while(nCommand == NO_COMMAND)
-   {
-      CALL_KERNEL_IF_NEEDED();
-
-      if(!od_get_input(&InputEvent, bWaitForInput && !bDoneAnythingYet
-         ? OD_NO_TIMEOUT : 0, GETIN_NORMAL))
-      {
-         /* Return right away if no input event is waiting. */
-         return;
-      }
-
-      bDoneAnythingYet = TRUE;
-
-      if(InputEvent.EventType == EVENT_EXTENDED_KEY)
-      {
-         switch(InputEvent.chKeyPress)
-         {
-            case OD_KEY_UP:
-up_arrow:
-               if(btCorrectItem == 0)
-               {
-                  btCorrectItem = btCurrentNumMenuItems - 1;
-               }
-               else
-               {
-                  --btCorrectItem;
-               }
-               break;
-
-            case OD_KEY_DOWN:
-down_arrow:
-               if(++btCorrectItem >= btCurrentNumMenuItems)
-               {
-                  btCorrectItem = 0;
-               }
-               break;
-
-            case OD_KEY_LEFT:
-left_arrow:
-               if(wCurrentFlags & MENU_PULLDOWN)
-               {
-                  nCommand = POPUP_LEFT;
-                  return;
-               }
-               break;
-
-            case OD_KEY_RIGHT:
-right_arrow:
-               if(wCurrentFlags & MENU_PULLDOWN)
-               {
-                  nCommand = POPUP_RIGHT;
-                  return;
-               }
-               break;
-         }
-      }
-
-      else if(InputEvent.EventType == EVENT_CHARACTER)
-      {
-         if(InputEvent.chKeyPress == '\n' || InputEvent.chKeyPress == '\r')
-         {
-            nCommand = btCorrectItem + 1;
-            return;
-         }
-
-         else if(InputEvent.chKeyPress == 27)
-         {
-            if(wCurrentFlags & MENU_ALLOW_CANCEL)
-            {
-               nCommand = POPUP_ESCAPE;
-               return;
-            }
-         }
-
-         else
-         {
-            /* Check whether key is a menu "hot key" */
-            for(btCount = 0; btCount < btCurrentNumMenuItems; ++btCount)
-            {
-               if(toupper(MenuLevelInfo[nCurrentLevel].paMenuItems[btCount]
-                  .szItemText[MenuLevelInfo[nCurrentLevel].paMenuItems[btCount]
-                  .btKeyIndex]) == toupper(InputEvent.chKeyPress))
-               {
-                  btCorrectItem = btCount;
-                  nCommand = btCorrectItem + 1;
-                  return;
-               }
-            }
-
-            /* At this point, we know that key was not one of the "hot keys" */
-            /* Check for 4, 6, 8 and 2 keys as arrow keys.                   */
-            if(InputEvent.chKeyPress == '4')
-            {
-               goto left_arrow;
-            }
-            else if(InputEvent.chKeyPress == '6')
-            {
-               goto right_arrow;
-            }
-            else if(InputEvent.chKeyPress == '8')
-            {
-               goto up_arrow;
-            }
-            else if(InputEvent.chKeyPress == '2')
-            {
-               goto down_arrow;
-            }
-         }
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODPopupDisplayMenuItem()                            *** PRIVATE FUNCTION ***
- *
- * Displays an individual menu item.
- *
- * Parameters: btLeft          - Column number where the menu item will be
- *                               displayed.
- *
- *             btTop           - Row number where the menu item will be
- *                               displayed.
- *
- *             paMenuItems     - Pointer to array of available menu items.
- *
- *             btItemIndex     - Index into paMenuItems of the menu item that
- *                               is to be displayed.
- *
- *             bHighlighted    - TRUE if the items is to be displayed as
- *                               highlighted, FALSE if it is to be displayed as
- *                               non-highlighted.
- *
- *             btWidth         - Width of the menu item, in characters.
- *
- *             bPositionCursor - TRUE if the cursor needs to be positioned
- *                               prior to drawing the menu item, FALSE if the
- *                               cursor is already in the required position.
- *
- *     Return: void
- */
-static void ODPopupDisplayMenuItem(BYTE btLeft, BYTE btTop,
-   tMenuItem *paMenuItems, BYTE btItemIndex, BOOL bHighlighted, BYTE btWidth,
-   BOOL bPositionCursor)
-{
-   BYTE btCount;
-   char *pchItemText;
-   BYTE btKeyPosition;
-   BYTE btTextColor;
-   BYTE btKeyColor;
-
-   /* Check that parameters are reasonable when operating in debug mode. */
-   ASSERT(paMenuItems != NULL);
-   ASSERT(btItemIndex < MAX_MENU_ITEMS);
-   ASSERT(btWidth < OD_SCREEN_WIDTH);
-
-   ++btLeft;
-   ++btTop;
-
-   btTextColor = bHighlighted ? od_control.od_menu_highlight_col
-      : od_control.od_menu_text_col;
-   btKeyColor = bHighlighted ? od_control.od_menu_highkey_col
-      : od_control.od_menu_key_col;
-
-   pchItemText = (char *)(paMenuItems[btItemIndex].szItemText);
-   btKeyPosition = paMenuItems[btItemIndex].btKeyIndex;
-
-   if(bPositionCursor) od_set_cursor(btTop + btItemIndex, btLeft);
-
-   od_set_attrib(btTextColor);
-   od_putch(' ');
-
-   for(btCount = 0; btCount < btWidth && *pchItemText; ++btCount)
-   {
-       if(btCount == btKeyPosition)
-       {
-          od_set_attrib(btKeyColor);
-          od_putch(*pchItemText++);
-          od_set_attrib(btTextColor);
-       }
-       else
-       {
-          od_putch(*pchItemText++);
-       }
-   }
-
-   od_repeat(' ', (BYTE)((btWidth - btCount) + 1));
-
-   if(bPositionCursor) od_set_cursor(btTop + btItemIndex, btLeft);
-}
diff --git a/src/odoors/ODPrntf.c b/src/odoors/ODPrntf.c
deleted file mode 100644
index 2e38561bead0a0ff7ad59d6ec3f4e0c044ea010a..0000000000000000000000000000000000000000
--- a/src/odoors/ODPrntf.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODPrntf.c
- *
- * Description: Implements the od_printf() function.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Use ODVCALL instead of ODCALL.
- *              Jan 04, 1996  6.00  BP   Add missing OD_API_EXIT() at end.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODKrnl.h"
-
-
-/* Size of od_printf() working buffer. Adjust this upwards if you are    */
-/* encountering difficulties when calling od_printf() with long strings. */
-#define WORK_BUFFER_SIZE   512
-
-
-/* ----------------------------------------------------------------------------
- * od_printf()
- *
- * The OpenDoors equivalent of the C printf() function, this function performs
- * formatted string output to both the local and remote screens.
- *
- * Parameters: pszFormat - Format string, in the same format as the printf()
- *                         format string.
- *
- *             The semantics of any further parameters are dicated by the
- *             contents of the format string.
- *
- *     Return: void
- */
-ODAPIDEF void ODVCALL od_printf(char *pszFormat,...)
-{
-   va_list pArgumentList;
-   static char *pszWorkBuffer = NULL;
-   char *pchCurrent;
-   char *pchStart;
-   BOOL bNotFound;
-   INT nCharCount;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_printf()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   /* Allocate work buffer if none has been allocated yet. */
-   if(pszWorkBuffer == NULL &&
-      (pszWorkBuffer = malloc(WORK_BUFFER_SIZE)) == NULL)
-   {
-      /* If we are unable to allocate a buffer, return with a memory error. */
-      od_control.od_error = ERR_MEMORY;
-      OD_API_EXIT();
-      return;
-   }
-
-   /* Copy the arguments after the format string. */
-   va_start(pArgumentList, pszFormat);
-
-   /* Perform a string printf to the working buffer. */
-   vsprintf(pszWorkBuffer, pszFormat, pArgumentList);
-
-   va_end(pArgumentList);
-
-   /* If no color characters are defined, then just display the entire */
-   /* buffer in one shot.                                              */
-   if(!od_control.od_color_char && !od_control.od_color_delimiter)
-       goto quick_print;
-
-   chColorCheck = od_control.od_color_delimiter;
-
-   bNotFound = TRUE;
-   pchCurrent = (char *)pszWorkBuffer;
-   pchStart = (char *)pszWorkBuffer;
-   nCharCount = 0;
-   while(*pchCurrent)
-   {
-      if(*pchCurrent == od_control.od_color_delimiter)
-      {
-         bNotFound = FALSE;
-
-         if(nCharCount != 0)
-         {
-            od_disp(pchStart, nCharCount, TRUE);
-         }
-
-         if(!*(++pchCurrent))
-         {
-            chColorCheck = 0;
-            OD_API_EXIT();
-            return;
-         }
-         od_set_attrib(od_color_config(pchCurrent));
-         if(!*(pchCurrent = (char *)pchColorEndPos))
-         {
-            chColorCheck = 0;
-            OD_API_EXIT();
-            return;
-         }
-
-         if(!*(++pchCurrent))
-         {
-            OD_API_EXIT();
-            return;
-         }
-         pchStart = (char *)pchCurrent;
-         nCharCount = 0;
-      }
-
-      else if(*pchCurrent == od_control.od_color_char)
-      {
-         bNotFound = FALSE;
-
-         if(nCharCount != 0)
-         {
-            od_disp(pchStart, nCharCount, TRUE);
-         }
-
-         if(!*(++pchCurrent))
-         {
-            OD_API_EXIT();
-            return;
-         }
-         od_set_attrib(*pchCurrent);
-
-         if(!*(++pchCurrent))
-         {
-            OD_API_EXIT();
-            return;
-         }
-         pchStart = (char *)pchCurrent;
-         nCharCount = 0;
-      }
-      else
-      {
-         ++nCharCount;
-         ++pchCurrent;
-      }
-   }
-
-   chColorCheck = 0;
-
-   if(bNotFound)
-   {
-quick_print:
-      /* Display the entire string in one shot. */
-      od_disp_str(pszWorkBuffer);
-   }
-   else if(nCharCount != 0)
-   {
-      /* If there are remaining characters in the string, then display them. */
-      od_disp(pchStart, nCharCount, TRUE);
-   }
-
-   OD_API_EXIT();
-}
diff --git a/src/odoors/ODRA.c b/src/odoors/ODRA.c
deleted file mode 100644
index 1dd8d2e5e863489ec37a5f48a7df07c66bb5460a..0000000000000000000000000000000000000000
--- a/src/odoors/ODRA.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODRA.c
- *
- * Description: Implements the RemoteAccess personality.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 19, 1994  6.00  BP   Use new od_page constants.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Jul 18, 1995  6.00  BP   Fix ODStatGetUserAge() bug.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Dec 24, 1995  6.00  BP   Fixed black square at pos 25x80.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Display connect speed with %lu.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODStat.h"
-#include "ODInEx.h"
-
-
-/* Private variables, local to this module. */
-static BOOL bRAPersHasBeenOn = FALSE;
-
-
-/* Private function prototypes. */
-static void ODRADisplayPageInfo(void);
-static void ODRADisplayDate(char *pszDateString);
-static void ODRADisplayFlags(BYTE btFlags);
-static void ODRADisplayTime(void);
-
-
-/* ----------------------------------------------------------------------------
- * pdef_ra()
- *
- * Personality function for the RemoteAccess-like status line / function key
- * personality.
- *
- * Parameters: btOperation - Indicates personality operation to be performed.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL pdef_ra(BYTE btOperation)
-{
-   BYTE btInfoType = od_control.od_info_type;
-
-   switch(btOperation)
-   {
-      case PEROP_DISPLAY1:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("                                                                     (Node      ");
-         ODScrnSetCursorPos(1, 24);
-         ODScrnPrintf("%s of %s at %lu BPS", od_control.user_name,
-            od_control.user_location, od_control.od_connect_speed);
-
-         if(!od_control.od_user_keyboard_on)
-         {
-            ODScrnSetCursorPos(49, 24);
-            ODScrnSetAttribute(0x99);
-            ODScrnDisplayString("(Keyboard)");
-            ODScrnSetAttribute(0x70);
-            bRAPersHasBeenOn = TRUE;
-         }
-
-         ODRADisplayPageInfo();
-
-         ODScrnSetCursorPos(76, 24);
-         if(od_control.od_node < 1000)
-         {
-            ODScrnPrintf("%u)", od_control.od_node);
-         }
-         else
-         {
-            ODScrnDisplayString("?)");
-         }
-         ODScrnSetCursorPos(1, 25);
-         ODScrnDisplayString("Security:        Time:                                               (F9)=Help ");
-
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-
-         ODScrnSetCursorPos(11, 25);
-         ODScrnPrintf("%u", od_control.user_security);
-         ODScrnSetCursorPos(24, 25);
-         ODScrnPrintf("%d mins   ", od_control.user_timelimit);
-         if(od_control.user_ansi)
-         {
-            ODScrnSetCursorPos(42, 25);
-            ODScrnDisplayString("(ANSI)");
-         }
-
-         if(od_control.user_avatar)
-         {
-            ODScrnSetCursorPos(48, 25);
-            ODScrnDisplayString("(AVT)");
-         }
-
-         if(od_control.sysop_next)
-         {
-            ODScrnSetCursorPos(53, 25);
-            ODScrnDisplayString("(SN) ");
-         }
-
-         if(od_control.user_wantchat)
-         {
-            ODScrnSetCursorPos(57, 25);
-            ODScrnSetAttribute(0x99);
-            ODScrnDisplayString("(Wants Chat)");
-            ODScrnSetAttribute(0x70);
-         }
-         break;
-
-
-      case PEROP_DISPLAY2:
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("Voice#:               Last Call   :                       First Call:           ");
-         ODScrnSetCursorPos(1, 25);
-         ODScrnDisplayString("Data #:               Times Called:            Age:        Birthdate:          ");
-         if(od_control.od_extended_info || btInfoType == SFDOORSDAT
-            || btInfoType == DOORSYS_GAP || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnSetCursorPos(8, 24);
-            ODScrnPrintf("%13.13s", od_control.user_homephone);
-         }
-         if(od_control.od_extended_info || btInfoType == DOORSYS_GAP
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnSetCursorPos(8, 25);
-            ODScrnPrintf("%13.13s", od_control.user_dataphone);
-         }
-         if(od_control.od_extended_info || btInfoType == DOORSYS_GAP
-            || btInfoType == CHAINTXT || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnSetCursorPos(37, 24);
-            ODRADisplayDate(od_control.user_lastdate);
-         }
-         if(od_control.od_extended_info || btInfoType == DOORSYS_GAP
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnSetCursorPos(37, 25);
-            ODScrnPrintf("%lu", od_control.user_numcalls);
-         }
-         if(btInfoType == RA1EXITINFO || btInfoType == RA2EXITINFO
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            char szUserAge[7];
-            ODScrnSetCursorPos(53, 25);
-            ODStatGetUserAge(szUserAge);
-            ODScrnDisplayString(szUserAge);
-            ODScrnSetCursorPos(71, 24);
-            ODRADisplayDate(od_control.user_firstcall);
-            ODScrnSetCursorPos(71, 25);
-            ODRADisplayDate(od_control.user_birthday);
-         }
-         break;
-
-
-      case PEROP_DISPLAY3:
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1, 24);
-         if(od_control.od_extended_info || btInfoType == SFDOORSDAT
-            || btInfoType == DOORSYS_GAP || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnDisplayString("Uploads:                Downloads:               Tagged: 0k (0)                 ");
-            if(btInfoType == DOORSYS_GAP)
-            {
-               ODScrnSetCursorPos(10, 24);
-               ODScrnPrintf("%lu", od_control.user_uploads);
-               ODScrnSetCursorPos(36, 24);
-               ODScrnPrintf("%lu", od_control.user_downloads);
-            }
-            else
-            {
-               ODScrnSetCursorPos(10, 24);
-               ODScrnPrintf("%luk (%lu)", od_control.user_upk,
-                  od_control.user_uploads);
-               ODScrnSetCursorPos(36,24);
-               ODScrnPrintf("%luk (%lu)", od_control.user_downk,
-                  od_control.user_downloads);
-            }
-         }
-         else
-         {
-            ODScrnDisplayString("                                                                                ");
-         }
-         ODScrnSetCursorPos(1, 25);
-         if(od_control.od_extended_info)
-         {
-            ODScrnDisplayString("Flags: (A):--------  (B):--------  (C):--------  (D):--------                  ");
-            ODScrnSetCursorPos(12, 25);
-            ODRADisplayFlags(od_control.user_flags[0]);
-            ODScrnSetCursorPos(26, 25);
-            ODRADisplayFlags(od_control.user_flags[1]);
-            ODScrnSetCursorPos(40, 25);
-            ODRADisplayFlags(od_control.user_flags[2]);
-            ODScrnSetCursorPos(54, 25);
-            ODRADisplayFlags(od_control.user_flags[3]);
-         }
-         else
-         {
-            ODScrnDisplayString("                                                                               ");
-         }
-         break;
-
-
-      case PEROP_DISPLAY4:
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("                                                                   (Time      ) ");
-         if(od_control.od_extended_info)
-         {
-            ODScrnSetCursorPos(1, 24);
-            ODScrnPrintf("Last Caller: %s    Total System Calls: %lu",
-               od_control.system_last_caller, od_control.system_calls);
-         }
-         ODRADisplayTime();
-
-         ODScrnSetCursorPos(1, 25);
-         if(od_control.od_extended_info || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnDisplayString("(Printer OFF)      (Local Screen ON )        Next Event                        ");
-            ODScrnSetCursorPos(57, 25);
-            if(od_control.event_status == ES_ENABLED
-               || btInfoType == DOORSYS_WILDCAT)
-            {
-               ODScrnPrintf("(%s, errorlevel %u)",od_control.event_starttime,od_control.event_errorlevel);
-            }
-            else
-            {
-               ODScrnDisplayString("none, errorlevel 0");
-            }
-         }
-         else
-         {
-            ODScrnDisplayString("                                                                               ");
-         }
-         break;
-
-
-      case PEROP_DISPLAY5:
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1, 24);
-         if(od_control.od_extended_info || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnDisplayString("Msgs posted    :           Highread :                                Group 1    ");
-            ODScrnSetCursorPos(18,24);
-            ODScrnPrintf("%u",od_control.user_messages);
-            ODScrnSetCursorPos(39,24);
-            ODScrnPrintf("%u",od_control.user_lastread);
-            if(btInfoType == RA1EXITINFO || btInfoType == RA2EXITINFO)
-            {
-               ODScrnSetCursorPos(76, 24);
-               ODScrnPrintf("%u", od_control.user_group);
-            }
-         }
-         else
-         {
-            ODScrnDisplayString("                                                                                ");
-         }
-
-         ODScrnSetCursorPos(1, 25);
-         if(od_control.od_extended_info || btInfoType == CHAINTXT
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnDisplayString("Credit         :           Handle   :                                          ");
-            if(btInfoType == EXITINFO || btInfoType == RA1EXITINFO
-               || btInfoType == RA2EXITINFO)
-            {
-               ODScrnSetCursorPos(18, 25);
-               ODScrnPrintf("%u.00", (unsigned int)od_control.user_net_credit);
-            }
-            if(btInfoType == CHAINTXT || btInfoType == RA1EXITINFO
-               || btInfoType == RA2EXITINFO || btInfoType == DOORSYS_WILDCAT)
-            {
-               ODScrnSetCursorPos(39, 25);
-               ODScrnDisplayString(od_control.user_handle);
-            }
-         }
-         else
-         {
-            ODScrnDisplayString("                                                                               ");
-         }
-         break;
-
-
-      case PEROP_DISPLAY6:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("                                                                                ");
-         ODScrnSetCursorPos(1, 25);
-         ODScrnDisplayString("                                                                               ");
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         if(btInfoType == RA1EXITINFO || btInfoType == RA2EXITINFO
-            || btInfoType == DOORSYS_WILDCAT)
-         {
-            ODScrnSetCursorPos(1, 24);
-            ODScrnDisplayString(od_control.user_comment);
-         }
-         if(od_control.user_wantchat
-            && strlen(od_control.user_reasonforchat) !=0 )
-         {
-            ODScrnSetCursorPos(1, 25);
-            strcpy(szStatusText, od_control.user_reasonforchat);
-            szStatusText[69 - strlen(od_control.user_name)] = '\0';
-            ODScrnPrintf("Chat (%s): %s", od_control.user_name, szStatusText);
-         }
-         break;
-
-      case PEROP_DISPLAY7:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("                                                                                ");
-         ODScrnSetCursorPos(1, 25);
-         ODScrnDisplayString("                                                                               ");
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         break;
-
-      case PEROP_DISPLAY8:
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString("ALT: (C)hat (H)angup (J)Shell (L)ockOut (K)eyboard (N)extOn (D)rop To BBS       ");
-         ODScrnDisplayString("                                   -Inc Time -Dec Time  (F1)-(F7)=Extra Stats");
-         break;
-
-      case PEROP_UPDATE1:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(24, 25);
-
-         ODScrnPrintf("%d mins   ", od_control.user_timelimit);
-
-         ODScrnSetCursorPos(42, 25);
-         if(od_control.user_ansi)
-         {
-            ODScrnDisplayString("(ANSI)");
-         }
-         else
-         {
-            ODScrnDisplayString("      ");
-         }
-
-         if(od_control.user_avatar)
-         {
-            ODScrnDisplayString("(AVT)");
-         }
-         else
-         {
-            ODScrnDisplayString("     ");
-         }
-
-         if(od_control.sysop_next)
-         {
-            ODScrnDisplayString("(SN)");
-         }
-         else
-         {
-            ODScrnDisplayString("    ");
-         }
-
-         if(od_control.user_wantchat)
-         {
-            ODScrnSetAttribute(0x99);
-            ODScrnDisplayString("(Wants Chat)");
-            ODScrnSetAttribute(0x70);
-         }
-         else
-         {
-            ODScrnDisplayString("            ");
-         }
-
-         ODRADisplayPageInfo();
-
-         if(od_control.od_user_keyboard_on && bRAPersHasBeenOn)
-         {
-            ODScrnSetCursorPos(49, 24);
-            ODScrnDisplayString("          ");
-         }
-         if(!od_control.od_user_keyboard_on)
-         {
-            bRAPersHasBeenOn = TRUE;
-            ODScrnSetCursorPos(49, 24);
-            ODScrnSetAttribute(0x99);
-            ODScrnDisplayString("(Keyboard)");
-            ODScrnSetAttribute(0x70);
-         }
-
-         break;
-
-      case PEROP_UPDATE4:
-         ODScrnSetAttribute(0x70);
-         ODRADisplayTime();
-         break;
-
-      case PEROP_INITIALIZE:
-         bRAStatus = TRUE;
-         od_control.key_hangup = 0x2300;
-         od_control.key_drop2bbs = 0x2000;
-         od_control.key_dosshell = 0x2400;
-         od_control.key_chat = 0x2e00;
-         od_control.key_sysopnext = 0x3100;
-         od_control.key_lockout = 0x2600;
-         od_control.key_status[0] = 0x3b00;
-         od_control.key_status[1] = 0x3c00;
-         od_control.key_status[2] = 0x3d00;
-         od_control.key_status[3] = 0x3e00;
-         od_control.key_status[4] = 0x3f00;
-         od_control.key_status[5] = 0x4000;
-         od_control.key_status[6] = 0x4100;
-         od_control.key_status[7] = 0x4300;
-         od_control.key_status[8] = 0x4400;
-         od_control.key_keyboardoff = 0x2500;
-         od_control.key_moretime = 0x4800;
-         od_control.key_lesstime = 0x5000;
-         od_control.od_page_statusline = 5;
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODRADisplayPageInfo()                               *** PRIVATE FUNCTION ***
- *
- * Displays the current sysop page information on the RemoteAccess status line,
- * at the appropriate position, and in the appropriate color.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODRADisplayPageInfo(void)
-{
-   time_t nUnixTime;
-   struct tm *TimeBlock;
-   BOOL bFailed = FALSE;
-   INT nMinute;
-
-   ODScrnSetCursorPos(60, 24);
-
-   switch(od_control.od_okaytopage)
-   {
-      case PAGE_ENABLE:
-         ODScrnSetAttribute(0x19);
-         ODScrnDisplayString("(PAGE ON) ");
-         ODScrnSetAttribute(0x70);
-         break;
-
-      case PAGE_DISABLE:
-         ODScrnSetAttribute(0x19);
-         ODScrnDisplayString("(PAGE OFF)");
-         ODScrnSetAttribute(0x70);
-         break;
-
-      case PAGE_USE_HOURS:
-         nUnixTime = time(NULL);
-         TimeBlock = localtime(&nUnixTime);
-         nMinute = (60 * TimeBlock->tm_hour) + TimeBlock->tm_min;
-         if(od_control.od_pagestartmin < od_control.od_pageendmin)
-         {
-            if(nMinute < od_control.od_pagestartmin
-               || nMinute >= od_control.od_pageendmin)
-            {
-               bFailed = TRUE;
-            }
-         }
-         else
-         {
-            if(nMinute < od_control.od_pagestartmin
-               && nMinute >= od_control.od_pageendmin)
-            {
-               bFailed=TRUE;
-            }
-         }
-
-         if(bFailed)
-         {
-            ODScrnDisplayString("(PAGE OFF)");
-         }
-         else
-         {
-            ODScrnDisplayString("(PAGE ON) ");
-         }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODRADisplayTime()                                   *** PRIVATE FUNCTION ***
- *
- * Displays the current time on the RemoteAccess status line, at the
- * appropriate position. The time is displayed in the current color.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODRADisplayTime(void)
-{
-   time_t nUnixTime;
-   struct tm *TimeBlock;
-
-   nUnixTime = time(NULL);
-   TimeBlock = localtime(&nUnixTime);
-   ODScrnSetCursorPos(74, 24);
-   ODScrnPrintf("%02.2d:%02.2d", TimeBlock->tm_hour, TimeBlock->tm_min);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODRADisplayDate()                                   *** PRIVATE FUNCTION ***
- *
- * Displays a date stored in a string on the RemoteAccess status line, if
- * the string represents a valid date. The date is displayed at the current
- * cursor location, in the current color.
- *
- * Parameters: pszDateString - Pointer to a string containing the date to
- *                             display.
- *
- *     Return: void
- */
-static void ODRADisplayDate(char *pszDateString)
-{
-   INT nMonth;
-   INT nTemp;
-
-   ASSERT(pszDateString != NULL);
-
-   if(strlen(pszDateString) != 8) return;
-
-   nMonth = atoi(pszDateString) - 1;
-   if(nMonth < 0 || nMonth > 11) return;
-
-   nTemp=atoi((char *)pszDateString + 3);
-   if(nTemp < 1 || nTemp > 31) return;
-
-   if(pszDateString[6] < '0' || pszDateString[6] > '9'
-      || pszDateString[7] < '0' || pszDateString[7] > '9')
-   {
-      return;
-   }
-
-   ODScrnDisplayChar(pszDateString[3]);
-   ODScrnDisplayChar(pszDateString[4]);
-   ODScrnDisplayChar('-');
-   ODScrnDisplayString(od_control.od_month[nMonth]);
-   ODScrnDisplayChar('-');
-   ODScrnDisplayChar(pszDateString[6]);
-   ODScrnDisplayChar(pszDateString[7]);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODRADisplayFlags()                                  *** PRIVATE FUNCTION ***
- *
- * Displays sysop-defined user flags on the status line. The flags are
- * displayed at the current cursor location, in the current color.
- *
- * Parameters: btFlags - Byte of eight flags to display.
- *
- *     Return: void
- */
-static void ODRADisplayFlags(BYTE btFlags)
-{
-   BYTE btMask = 0x01;
-   INT nFlag;
-
-   for(nFlag = 0; nFlag < 8; ++nFlag)
-   {
-      if(btFlags & btMask)
-      {
-         ODScrnDisplayChar('X');
-      }
-      else
-      {
-         ODScrnDisplayChar('-');
-      }
-      btMask <<= 1;
-   }
-}
diff --git a/src/odoors/ODRes.aps b/src/odoors/ODRes.aps
deleted file mode 100644
index 58cd4524c6fc1fe1d1cd7030cd4296039c63c842..0000000000000000000000000000000000000000
Binary files a/src/odoors/ODRes.aps and /dev/null differ
diff --git a/src/odoors/ODRes.h b/src/odoors/ODRes.h
deleted file mode 100644
index c1f7932508e78fcdea704c9e67b444543d43bd2e..0000000000000000000000000000000000000000
--- a/src/odoors/ODRes.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODRes.h
- *
- * Description: OpenDoors resource-related definitions. This file is only
- *              applicable when building the Win32 version of OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Dec 02, 1995  6.00  BP   Created.
- *              Jan 20, 1996  6.00  BP   Added login dialog box.
- *              Jan 21, 1996  6.00  BP   Added message dialog box.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 23, 1996  6.00  BP   Remove unused IDs.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 14, 1996  6.10  BP   Added configuration menu option.
- */
-
-/* Resource IDs. */
-#define IDR_FRAME_MENU                  200
-#define IDD_ABOUT                       201
-#define IDI_OPENDOORS                   202
-#define IDB_TOOLBAR                     203
-#define IDR_FRAME                       204
-#define IDD_LOGIN                       205
-#define IDI_MESSAGE_INFO                206
-#define IDD_MESSAGE                     207
-
-
-/* Dialog box control IDs. (The same values can safely be used by other */
-/* dialog boxes.)                                                       */
-/* Help dialog box. */
-#define IDC_DOORNAME                    1000
-#define IDC_COPYRIGHT                   1001
-#define IDC_VERSION                     1002
-
-/* Login dialog box. */
-#define IDC_USER_NAME                   1000
-
-/* Message dialog box. */
-#define IDC_MESSAGE_ICON                1000
-#define IDC_MESSAGE_TEXT1               1001
-
-
-/* Command IDs. */
-#define ID_DOOR_CHATMODE                50000
-#define ID_DOOR_USERKEYBOARDOFF         50001
-#define ID_DOOR_SYSOPNEXT               50002
-#define ID_DOOR_HANGUP                  50003
-#define ID_VIEW_STATUSBAR               50006
-#define ID_USER_ADDONEMINUTE            50007
-#define ID_USER_ADDFIVEMINUTES          50008
-#define ID_USER_SUBTRACTONEMINUTE       50009
-#define ID_USER_SUBTRACTFIVEMINUTES     50010
-#define ID_USER_INACTIVITYTIMER         50011
-#define ID_HELP_ABOUT                   50012
-#define ID_HELP_CONTENTS                50013
-#define ID_VIEW_TOOL_BAR                50014
-#define ID_DOOR_EXIT                    50015
-#define ID_DOOR_LOCKOUT                 50016
-#define ID_VIEW_STAT_BAR                50017
-#define ID_DOOR_CONFIG                  50018
diff --git a/src/odoors/ODRes.rc b/src/odoors/ODRes.rc
deleted file mode 100644
index ef8496d4dc7ba15d601caba77fd31625bcc402fc..0000000000000000000000000000000000000000
--- a/src/odoors/ODRes.rc
+++ /dev/null
@@ -1,181 +0,0 @@
-/* OpenDoors 6.10
- * (C) Copyright 1991 - 1997 by Brian Pirie. All Rights Reserved.
- *
- *
- *        File: ODRes.rc
- *
- * Description: OpenDoors resource script. Contains defintions for OpenDoors
- *              menus, dialog boxes, icons, bitmaps, accelerator table and
- *              string resources. This file is only applicable when building
- *              the Win32 version of OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Dec 02, 1995  6.00  BP   Created.
- *              Jan 01, 1996  6.00  BP   Changed copyright to 1996 in About Box
- *              Jan 20, 1996  6.00  BP   Added login dialog box.
- *              Jan 21, 1996  6.00  BP   Added message dialog box.
- *              Jan 21, 1996  6.00  BP   Renamed opendoor.ico to odapp.ico.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 14, 1996  6.10  BP   Added configuration menu option.
- */
-
-#include "windows.h"
-#include "ODRes.h"
-
-
-/* ========================================================================= */
-/* The OpenDoors frame window menu.                                          */
-/* ========================================================================= */
-
-IDR_FRAME_MENU MENU DISCARDABLE 
-BEGIN
-    POPUP "&Door"
-    BEGIN
-        MENUITEM "C&onfigure..."                ID_DOOR_CONFIG
-        MENUITEM "&Chat Mode\tCtrl+C",          ID_DOOR_CHATMODE
-        MENUITEM SEPARATOR
-        MENUITEM "User &Keyboard Off\tCtrl+K",  ID_DOOR_USERKEYBOARDOFF
-        MENUITEM "Sysop &Next\tCtrl+N",         ID_DOOR_SYSOPNEXT
-        MENUITEM SEPARATOR
-        MENUITEM "&Hangup\tCtrl+H",             ID_DOOR_HANGUP
-        MENUITEM "&Lockout\tCtrl+L",            ID_DOOR_LOCKOUT
-        MENUITEM SEPARATOR
-        MENUITEM "E&xit To BBS\tCtrl+X",        ID_DOOR_EXIT
-    END
-    POPUP "&View"
-    BEGIN
-        MENUITEM "&Toolbar",                    ID_VIEW_TOOL_BAR, CHECKED
-        MENUITEM "Status Bar",                  ID_VIEW_STAT_BAR, CHECKED
-    END
-    POPUP "&User"
-    BEGIN
-        MENUITEM "Add &One Minute\tShift+Up Arrow",   ID_USER_ADDONEMINUTE
-        MENUITEM "Add &Five Minutes\tCtrl+Up Arrow", ID_USER_ADDFIVEMINUTES
-        MENUITEM SEPARATOR
-        MENUITEM "&Subtract One Minute\tShift+Down Arrow", 
-                                                ID_USER_SUBTRACTONEMINUTE
-        MENUITEM "S&ubtract Five Minutes\tCtrl+Down Arrow", 
-                                                ID_USER_SUBTRACTFIVEMINUTES
-        MENUITEM SEPARATOR
-        MENUITEM "&Inactivity Timer",           ID_USER_INACTIVITYTIMER
-        , CHECKED
-    END
-    POPUP "&Help"
-    BEGIN
-        MENUITEM "&Contents\tF1"                ID_HELP_CONTENTS
-        MENUITEM "&About...",                   ID_HELP_ABOUT
-    END
-END
-
-
-/* ========================================================================= */
-/* Dialog Boxes.                                                             */
-/* ========================================================================= */
-
-IDD_ABOUT DIALOG DISCARDABLE  0, 0, 217, 89
-STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "MS Sans Serif"
-BEGIN
-    ICON            IDI_OPENDOORS,-1,6,7,18,20
-    LTEXT           "BBS Door Program",IDC_DOORNAME,32,5,120,8
-    LTEXT           "",IDC_VERSION,32,14,123,7
-    LTEXT           "",IDC_COPYRIGHT,32,23,119,8
-    LTEXT           "Written using:",-1,31,48,69,8
-    LTEXT           "OpenDoors 6.10, Win32 Edition",-1,31,57,127,8
-    LTEXT           "Copyright \251 1991-1997 by Brian Pirie.",-1,31,
-                    66,139,8,SS_NOPREFIX
-    LTEXT           "All Rights Reserved.",-1,31,75,90,8
-    DEFPUSHBUTTON   "OK",IDOK,161,6,50,14
-END
-
-IDD_LOGIN DIALOG DISCARDABLE  0, 0, 194, 80
-STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "OpenDoors"
-FONT 8, "MS Sans Serif"
-BEGIN
-    LTEXT           "This program has been started in local",-1,6,6,128,8
-    LTEXT           "mode, independently of a BBS system.",-1,6,14,128,8
-    LTEXT           "When operating in this mode, you may",-1,6,22,128,8
-    LTEXT           "specify what name you should be",-1,6,30,128,8
-    LTEXT           "known to the program by.",-1,6,38,128,8
-    LTEXT           "Your &name:",-1,6,52,42,8
-    EDITTEXT        IDC_USER_NAME,6,61,121,12,ES_AUTOHSCROLL
-    DEFPUSHBUTTON   "OK",IDOK,138,6,50,14
-    PUSHBUTTON      "Cancel",IDCANCEL,138,23,50,14
-END
-
-IDD_MESSAGE DIALOG DISCARDABLE  0, 0, 186, 31
-STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "OpenDoors"
-FONT 8, "MS Sans Serif"
-BEGIN
-    ICON            IDI_MESSAGE_INFO,IDC_MESSAGE_ICON,6,6,18,20
-    LTEXT           "",IDC_MESSAGE_TEXT1,32,10,149,8
-END
-
-
-/* ========================================================================= */
-/* Icons.                                                                    */
-/* ========================================================================= */
-
-IDI_OPENDOORS           ICON    DISCARDABLE     "odapp.ico"
-IDI_MESSAGE_INFO        ICON    DISCARDABLE     "odinfo.ico"
-
-
-/* ========================================================================= */
-/* Bitmaps.                                                                  */
-/* ========================================================================= */
-
-IDB_TOOLBAR             BITMAP  DISCARDABLE     "toolbar.bmp"
-
-
-/* ========================================================================= */
-/* Accelerator Table.                                                        */
-/* ========================================================================= */
-
-IDR_FRAME ACCELERATORS DISCARDABLE 
-BEGIN
-    "C",            ID_DOOR_CHATMODE,       VIRTKEY, CONTROL, NOINVERT
-    "H",            ID_DOOR_HANGUP,         VIRTKEY, CONTROL, NOINVERT
-    "K",            ID_DOOR_USERKEYBOARDOFF, VIRTKEY, CONTROL, NOINVERT
-    "L",            ID_DOOR_LOCKOUT,        VIRTKEY, CONTROL, NOINVERT
-    "N",            ID_DOOR_SYSOPNEXT,      VIRTKEY, CONTROL, NOINVERT
-    "X",            ID_DOOR_EXIT,           VIRTKEY, CONTROL, NOINVERT
-    VK_DOWN,        ID_USER_SUBTRACTFIVEMINUTES, VIRTKEY, CONTROL, NOINVERT
-    VK_DOWN,        ID_USER_SUBTRACTONEMINUTE, VIRTKEY, SHIFT, NOINVERT
-    VK_F1,          ID_HELP_CONTENTS,       VIRTKEY, NOINVERT
-    VK_UP,          ID_USER_ADDFIVEMINUTES, VIRTKEY, CONTROL, NOINVERT
-    VK_UP,          ID_USER_ADDONEMINUTE,   VIRTKEY, SHIFT, NOINVERT
-END
-
-
-/* ========================================================================= */
-/* String Resources.                                                         */
-/* ========================================================================= */
-
-STRINGTABLE DISCARDABLE 
-BEGIN
-    ID_DOOR_CHATMODE        "Enters or exits chat mode, allowing you to communicate with the remote user."
-    ID_DOOR_USERKEYBOARDOFF "Causes any keys or commands from the remote user to be ignored."
-    ID_DOOR_SYSOPNEXT       "Reserves the system for the sysop after this user logs off (if supported by BBS)."
-    ID_DOOR_HANGUP          "Hangs up the modem and exits the door."
-    ID_USER_ADDONEMINUTE    "Increases the user's time remaining by one minute."
-    ID_USER_ADDFIVEMINUTES  "Increases the user's time remaining by five minutes."
-    ID_USER_SUBTRACTONEMINUTE 
-                            "Decreases the user's time remaining by one minute."
-    ID_USER_SUBTRACTFIVEMINUTES 
-                            "Decreases the user's time remaining by five minutes."
-    ID_USER_INACTIVITYTIMER "Enables the timer that will log off the user after a long period of no activity."
-    ID_HELP_ABOUT           "Displays program information and copyright."
-    ID_VIEW_TOOL_BAR        "Shows or hides the toolbar."
-END
-
-STRINGTABLE DISCARDABLE 
-BEGIN
-    ID_DOOR_EXIT            "Exits the door without hanging up."
-    ID_DOOR_LOCKOUT         "Hangs up the modem, denying any further access to the user (if supported by BBS)."
-    ID_VIEW_STAT_BAR        "Shows or hides the status bar."
-END
diff --git a/src/odoors/ODScrn.c b/src/odoors/ODScrn.c
deleted file mode 100644
index b5c16cfcb1e04eba386f93ecf17a87137cc83052..0000000000000000000000000000000000000000
--- a/src/odoors/ODScrn.c
+++ /dev/null
@@ -1,2540 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODScrn.c
- *
- * Description: Functions used to access the local display screen buffer, which
- *              keeps a copy of the text that is displayed on the remote
- *              terminal. The local display screen buffer also displays the
- *              OpenDoors status lines on some platforms. In addition to
- *              maintaining the current screen buffer, the odscrn.c module
- *              also contains the code to display this buffer on the screen.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Dec 31, 1994  6.00  BP   Use new multitasker variable.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   32-bit portability.
- *              Nov 14, 1995  6.00  BP   Created odscrn.h.
- *              Nov 14, 1995  6.00  BP   Make screen size configurable.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 21, 1995  6.00  BP   Port to Win32.
- *              Jan 20, 1996  6.00  BP   Prompt for user name if force_local.
- *              Jan 21, 1996  6.00  BP   Added ODScrnShowMessage() and related.
- *              Jan 27, 1996  6.00  BP   Expand tab ('\t') characters.
- *              Jan 27, 1996  6.00  BP   Added ODScrollUpAndInvalidate().
- *              Jan 27, 1996  6.00  BP   Made text-mode window f'ns static.
- *              Jan 31, 1996  6.00  BP   Made them non-static again.
- *              Jan 31, 1996  6.00  BP   Added ODScrnLocalInput().
- *              Feb 06, 1996  6.00  BP   Added od_silent_mode.
- *              Feb 16, 1996  6.00  BP   Make caret visible after local login.
- *              Feb 17, 1996  6.00  BP   Recognize non-ASCII keys under Win32.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 21, 1996  6.00  BP   Forward SC_KEYMENU to frame thread.
- *              Feb 21, 1996  6.00  BP   Don't beep in "silent mode".
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 13, 1996  6.10  BP   Added od_local_win_col.
- *              Mar 17, 1996  6.10  BP   Terminate string in ODScrnLocalInput()
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODPlat.h"
-#include "ODScrn.h"
-#include "ODUtil.h"
-#include "ODFrame.h"
-#include "ODInEx.h"
-#ifdef ODPLAT_WIN32
-#include "ODKrnl.h"
-#include "ODRes.h"
-#endif /* ODPLAT_WIN32 */
-
-
-/* ========================================================================= */
-/* Definitions of variables used by the local screen module.                 */
-/* ========================================================================= */
-
-/* Manifest constants used in this module. */
-#define SCREEN_BUFFER_SIZE          (OD_SCREEN_WIDTH * OD_SCREEN_HEIGHT * 2)
-#define SCREEN_BUFFER_SEGMENT_SIZE  (SCREEN_BUFFER_SIZE / 16)
-#define BYTES_PER_CHAR              2
-#define BUFFER_LINE_BYTES           (OD_SCREEN_WIDTH * BYTES_PER_CHAR)
-#define LINE_BUFFER_SIZE            (OD_SCREEN_WIDTH + 1)
-
-
-/* Private variables used by the screen I/O functions. */
-
-/* Segment address of video buffer. */
-#ifdef ODPLAT_DOS
-static WORD wBufferSegment;
-static void *pAllocatedBufferMemory;
-#endif /* ODPLAT_DOS */
-
-/* Far pointer to video buffer. */
-static void ODFAR *pScrnBuffer;
-
-/* Current cursor position. */
-static BYTE btCursorColumn;
-static BYTE btCursorRow;
-
-/* Current output boundaries. */
-static BYTE btLeftBoundary;
-static BYTE btTopBoundary;
-static BYTE btRightBoundary;
-static BYTE btBottomBoundary;
-
-/* Current display color. */
-static BYTE btCurrentAttribute;
-
-/* Is scrolling enabled. */
-static BOOL bScrollEnabled;
-
-/* Display page to use. */
-static BYTE btDisplayPage;
-
-/* Is cursor currently on. */
-static BYTE bCaretOn;
-
-/* Static temporary working buffer. */
-static char szBuffer[LINE_BUFFER_SIZE];
-
-
-/* Private function prototypes. */
-static void ODScrnGetCursorPos(void);
-static void ODScrnUpdateCaretPos(void);
-static void ODScrnScrollUpOneLine(void);
-static void ODScrnScrollUpAndInvalidate(void);
-
-
-/* ========================================================================= */
-/* Implementation of the local screen window for the Win32 platform.         */
-/* ========================================================================= */
-
-#ifdef ODPLAT_WIN32
-
-/* Screen thread startup information. */
-typedef struct
-{
-   HWND hwndFrame;
-   HANDLE hInstance;
-} tODScrnThreadInfo;
-
-/* Handle to the screen window. */
-static HWND hwndScreenWindow;
-
-/* Does the screen window currently have input focus? */
-BOOL bScreenHasFocus;
-
-/* Current font-related information. */
-static HFONT hCurrentFont;
-static INT nFontCellWidth;
-static INT nFontCellHeight;
-
-/* Table to translate from PC text color values used in the screen buffer */
-/* to their corresponding RGB values.                                     */
-COLORREF acrPCTextColors[] =
-{
-   RGB(0x00, 0x00, 0x00),
-   RGB(0x00, 0x00, 0xc0),
-   RGB(0x00, 0xc0, 0x00),
-   RGB(0x00, 0xc0, 0xc0),
-   RGB(0xc0, 0x00, 0x00),
-   RGB(0xc0, 0x00, 0xc0),
-   RGB(0xc0, 0xc0, 0x00),
-   RGB(0xc0, 0xc0, 0xc0),
-   RGB(0x7f, 0x7f, 0x7f),
-   RGB(0x00, 0x00, 0xff),
-   RGB(0x00, 0xff, 0x00),
-   RGB(0x00, 0xff, 0xff),
-   RGB(0xff, 0x00, 0x00),
-   RGB(0xff, 0x00, 0xff),
-   RGB(0xff, 0xff, 0x00),
-   RGB(0xff, 0xff, 0xff),
-};
-
-/* Table to translate from Windows key codes to OpenDoors key codes. */
-typedef struct
-{
-   int nVirtKey;
-   BYTE btODKey;
-} tWinKeyToODKey;
-
-tWinKeyToODKey aWinKeyToODKey[] =
-{
-   {VK_UP,        OD_KEY_UP},
-   {VK_DOWN,      OD_KEY_DOWN},
-   {VK_LEFT,      OD_KEY_LEFT},
-   {VK_RIGHT,     OD_KEY_RIGHT},
-   {VK_INSERT,    OD_KEY_INSERT},
-   {VK_DELETE,    OD_KEY_DELETE},
-   {VK_END,       OD_KEY_END},
-   {VK_HOME,      OD_KEY_HOME},
-   {VK_PRIOR,     OD_KEY_PGUP},
-   {VK_NEXT,      OD_KEY_PGDN},
-   {VK_F1,        OD_KEY_F1},
-   {VK_F2,        OD_KEY_F2},
-   {VK_F3,        OD_KEY_F3},
-   {VK_F4,        OD_KEY_F4},
-   {VK_F5,        OD_KEY_F5},
-   {VK_F6,        OD_KEY_F6},
-   {VK_F7,        OD_KEY_F7},
-   {VK_F8,        OD_KEY_F8},
-   {VK_F9,        OD_KEY_F9},
-   {VK_F10,       OD_KEY_F10},
-};
-
-/* Utility macros. */
-#define COLUMN_AS_XPIXEL(nColumn)   (((INT)(nColumn)) * nFontCellWidth)
-#define ROW_AS_YPIXEL(nRow)         (((INT)(nRow)) * nFontCellHeight)
-#define XPIXEL_AS_COLUMN(nX)        (((INT)(nX)) / nFontCellWidth)
-#define YPIXEL_AS_ROW(nY)           (((INT)(nY)) / nFontCellHeight)
-
-/* User defined messages. */
-#define WM_MOVE_YOUR_CARET          (WM_USER + 1)
-#define WM_KEYDOWN_RELAY            (WM_USER + 2)
-
-/* Height of the flashing caret, in pixels. */
-#define CARET_HEIGHT   3
-
-/* Local function prototypes. */
-LRESULT CALLBACK ODScrnWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam);
-static HWND ODScrnCreateWin(HWND hwndFrame, HANDLE hInstance);
-static void ODScrnMessageLoop(HANDLE hInstance, HWND hwndScreen);
-DWORD OD_THREAD_FUNC ODScrnThreadProc(void *pParam);
-static void ODScrnPaint(HDC hdc, INT nLeft, INT nTop, INT nRight, INT nBottom);
-static void ODScrnInvalidate(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom);
-static void ODScrnSetCurrentFont(HWND hwndScreen, HFONT hNewFont);
-static void ODScrnSetWinCaretPos(void);
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnCreateWin()                                   *** PRIVATE FUNCTION ***
- *
- * Creates the local screen window, which covers the client area of the
- * OpenDoors frame window.
- *
- * Parameters: hwndFrame   - Handle to the frame window.
- *
- *             hInstance   - Handle to application instance.
- *
- *     Return: A handle to the newly created window, or NULL on failure.
- */
-static HWND ODScrnCreateWin(HWND hwndFrame, HANDLE hInstance)
-{
-   HWND hwndScreen = NULL;
-   WNDCLASS wcScreenWindow;
-
-   ASSERT(hwndFrame != NULL);
-   ASSERT(hInstance != NULL);
-
-   /* Register the screen window's window class. */
-   memset(&wcScreenWindow, 0, sizeof(wcScreenWindow));
-   wcScreenWindow.style = CS_HREDRAW | CS_VREDRAW;
-   wcScreenWindow.lpfnWndProc = ODScrnWindowProc;
-   wcScreenWindow.cbClsExtra = 0;
-   wcScreenWindow.cbWndExtra = 0;
-   wcScreenWindow.hInstance = hInstance;
-   wcScreenWindow.hIcon = NULL;
-   wcScreenWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
-   wcScreenWindow.hbrBackground = NULL;
-   wcScreenWindow.lpszMenuName = NULL;
-   wcScreenWindow.lpszClassName = "ODScreen";
-
-   RegisterClass(&wcScreenWindow);
-
-   /* Create the screen window. */
-   if((hwndScreen = CreateWindowEx(
-      WS_EX_CLIENTEDGE,
-      wcScreenWindow.lpszClassName,
-      "",
-      WS_CHILD | WS_BORDER,
-      0,
-      0,
-      500,
-      300,
-      hwndFrame,
-      NULL,
-      hInstance,
-      (LPVOID)hInstance)) == NULL)
-   {
-      /* On window creation failure, return NULL. */
-      return(NULL);
-   }
-
-   /* Store handle to screen window for access from screen. */
-   hwndScreenWindow = hwndScreen;
-
-   return(hwndScreen);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnWindowProc()                                  *** PRIVATE FUNCTION ***
- *
- * The local screen window proceedure.
- *
- * Parameters: hwnd   - Handle to the local screen window.
- *
- *             uMsg   - Specifies the message.
- *
- *             wParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *             lParam - Specifies additional message information. The content
- *                      of this parameter depends on the value of the uMsg
- *                      parameter.
- *
- *     Return: The return value is the result of the message processing and
- *             depends on the message.
- */
-LRESULT CALLBACK ODScrnWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
-   LPARAM lParam)
-{
-   HINSTANCE hInstance;
-
-   ASSERT(hwnd != NULL);
-
-   hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_USERDATA);
-
-   switch(uMsg)
-   {
-      case WM_SYSCOMMAND:
-         /* We move any SC_KEYMENU WM_SYSCOMMAND messages to the frame */
-         /* window's message queue so that the screen window thread    */
-         /* can continue to process messages when the menu is          */
-         /* activated from the keyboard when the screen window has     */
-         /* the keyboard focus. If this isn't done, the menu will not  */
-         /* behave correctly when activated this way.                  */
-         if(wParam == SC_KEYMENU)
-         {
-            PostMessage(GetParent(hwnd), uMsg, wParam, lParam);
-         }
-         else
-         {
-            return(DefWindowProc(hwnd, uMsg, wParam, lParam));
-         }
-         break;
-
-      case WM_CREATE:
-      {
-         CREATESTRUCT *pCreateStruct = (CREATESTRUCT *)lParam;
-         hInstance = (HINSTANCE)pCreateStruct->lpCreateParams;
-         SetWindowLong(hwnd, GWL_USERDATA, (LONG)hInstance);
-         break;
-      }
-
-      case WM_PAINT:
-      {
-         PAINTSTRUCT PaintStruct;
-         HDC hdc;
-
-         /* Obtain device context and paint information. */
-         hdc = BeginPaint(hwnd, &PaintStruct);
-
-         if(hdc != NULL)
-         {
-            /* Redraw the portion of the window that has been invalidated. */
-            ODScrnPaint(hdc,
-               XPIXEL_AS_COLUMN(PaintStruct.rcPaint.left),
-               YPIXEL_AS_ROW(PaintStruct.rcPaint.top),
-               XPIXEL_AS_COLUMN(PaintStruct.rcPaint.right),
-               YPIXEL_AS_ROW(PaintStruct.rcPaint.bottom));
-
-            /* Release device context. */
-            EndPaint(hwnd, &PaintStruct);
-         }
-         break;
-      }
-
-      case WM_MOVE_YOUR_CARET:
-         ODScrnSetWinCaretPos();
-         break;
-
-      case WM_LBUTTONDOWN:
-         SetFocus(hwnd);
-         break;
-
-      case WM_SETFOCUS:
-         /* Turn on the caret when we receive the input focus. */
-         /* First, create the caret. */
-         CreateCaret(hwnd, NULL, nFontCellWidth, CARET_HEIGHT);
-
-         /* Remember that we now have the input focus. */
-         bScreenHasFocus = TRUE;
-
-         /* Update the position of the caret. */
-         ODScrnSetWinCaretPos();
-
-         /* Now, make the caret visible. */
-         ShowCaret(hwnd);
-         break;
-
-      case WM_KILLFOCUS:
-         /* Remember that we no longer have the input focus. */
-         bScreenHasFocus = FALSE;
-
-         /* Turn off the caret when we loose the input focus. */
-         DestroyCaret();
-         break;
-
-      case WM_KEYDOWN_RELAY:
-      {
-         int nVirtKeyPressed = (int)wParam;
-         WORD wRepeatCount = LOWORD(lParam);
-         int nKeyTableIndex;
-         WORD wKey = 0;
-
-         /* Look for a matching key in the OpenDoors key table. */
-         for(nKeyTableIndex = 0; nKeyTableIndex < DIM(aWinKeyToODKey);
-            ++nKeyTableIndex)
-         {
-            if(aWinKeyToODKey[nKeyTableIndex].nVirtKey == nVirtKeyPressed)
-            {
-               wKey = MAKEWORD(0, aWinKeyToODKey[nKeyTableIndex].btODKey);
-               break;
-            }
-         }
-
-         /* If a matching key was found, then add it to the queue. */
-         if(wKey != 0)
-         {
-            while(wRepeatCount--)
-            {
-               ODKrnlHandleLocalKey(wKey);
-            }
-         }
-
-         break;
-      }
-
-      case WM_CHAR:
-      {
-         WORD wRepeatCount = LOWORD(lParam);
-         BYTE btScanCode = LOBYTE(HIWORD(lParam));
-         TCHAR chCharCode = (TCHAR)wParam;
-         WORD wKey;
-         
-         wKey = MAKEWORD(chCharCode, btScanCode);
-
-         /* Loop for each repitition of this key. */
-         while(wRepeatCount--)
-         {
-            ODKrnlHandleLocalKey(wKey);
-         }
-         break;
-      }
-
-      default:
-         /* Pass messages that we don't explicitly handle on to the */
-         /* default window proc.                                    */
-         return(DefWindowProc(hwnd, uMsg, wParam, lParam));
-   }
-
-   return(0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnPaint()                                       *** PRIVATE FUNCTION ***
- *
- * Draws the specified portion of the screen on the provided device context.
- *
- * Parameters: hdc     - Handle to the device context to draw on.
- *
- *             nLeft   - Left column to draw.
- *
- *             nTop    - Top row to draw.
- *
- *             nRight  - Right column to draw.
- *
- *             nBottom - Bottom row to draw.
- *
- *     Return: void.
- */
-static void ODScrnPaint(HDC hdc, INT nLeft, INT nTop, INT nRight, INT nBottom)
-{
-   INT nIDSavedState;
-   INT nCurrentLine;
-   INT nStartColumn;
-   INT nEndColumn;
-   BYTE *pbtBufferContents;
-   char achStringToOutput[OD_SCREEN_WIDTH];
-   char *pchNextChar;
-   BYTE btCurrentAttribute;
-
-   ASSERT(hdc != NULL);
-   ASSERT(nLeft >= 0);
-   ASSERT(nTop >= 0);
-   ASSERT(nRight >= nLeft);
-   ASSERT(nBottom >= nTop);
-
-   /* Ensure that parameters are within valid range. */
-   if(nRight >= OD_SCREEN_WIDTH) nRight = OD_SCREEN_WIDTH - 1;
-   if(nBottom >= OD_SCREEN_HEIGHT) nBottom = OD_SCREEN_HEIGHT - 1;
-
-   /* Save the current state of the device context so that we can restore */
-   /* it before returning.                                                */
-   nIDSavedState = SaveDC(hdc);
-
-   /* Setup device context for displaying text from the screen buffer. */
-   SetBkMode(hdc, OPAQUE);
-   SelectObject(hdc, hCurrentFont);
-
-   /* Loop through each line that is to be painted. */
-   for(nCurrentLine = nTop; nCurrentLine <= nBottom; ++nCurrentLine)
-   {
-      /* Obtain a pointer to the first byte representing this line in */
-      /* the screen buffer.                                           */
-      pbtBufferContents = (BYTE *)(pScrnBuffer) +
-         ((nCurrentLine * OD_SCREEN_WIDTH) + nLeft) * 2;
-
-      /* Loop for each portion of this line that can be drawn in a single */
-      /* TextOut() call.                                                  */
-      for(nStartColumn = nLeft; nStartColumn <= nRight;
-         nStartColumn = nEndColumn)
-      {
-         /* Begin constructing a string containing the text to output */
-         /* in this call to TextOut().                                */
-         pchNextChar = achStringToOutput;
-
-         /* Determine the color of this portion. */
-         btCurrentAttribute = pbtBufferContents[1];
-
-         /* Loop, finding the first column that has an incompatible color. */
-         for(nEndColumn = nStartColumn; nEndColumn <= nRight; ++nEndColumn)
-         {
-            /* Stop looping if we come to a non-equivalent color */
-            /* attribute.                                        */
-            if(btCurrentAttribute != pbtBufferContents[1])
-            {
-               break;
-            }
-
-            /* Otherwise, add this character to the string to output. */
-            *pchNextChar++ = *pbtBufferContents;
-
-            /* Move to the next position in the buffer. */
-            pbtBufferContents += 2;
-         }
-
-         /* Change current display colors to match the current color */
-         /* attribute.                                               */
-         SetTextColor(hdc, acrPCTextColors[btCurrentAttribute & 0x0f]);
-         SetBkColor(hdc, acrPCTextColors[(btCurrentAttribute & 0xf0) >> 4]);
-
-         /* Output the string. */
-         TextOut(hdc,
-            COLUMN_AS_XPIXEL(nStartColumn),
-            ROW_AS_YPIXEL(nCurrentLine),
-            achStringToOutput,
-            (nEndColumn - nStartColumn));
-      }
-   }
-
-   /* Restore the device context to its original state before this function */
-   /* was called.                                                           */
-   RestoreDC(hdc, nIDSavedState);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnInvalidate()                                  *** PRIVATE FUNCTION ***
- *
- * Marks the specified area of the screen window as invalid, forcing the
- * screen thread to redraw it.
- *
- * Parameters: btLeft   - The left most column to invalidate.
- *
- *             btTop    - The top most row to invalidate.
- *
- *             btRight  - The right most column to invalidate.
- *
- *             btBottom - The bottom most row to invalidate.
- *
- *     Return: void.
- */
-static void ODScrnInvalidate(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom)
-{
-   RECT rcToInvalidate;
-
-   /* If the screen window has not been created yet, then return without */
-   /* doing anything.                                                    */
-   if(hwndScreenWindow == NULL) return;
-
-   /* Obtain rectangle in client window coordinates, to be invalidated. */
-   rcToInvalidate.left = COLUMN_AS_XPIXEL(btLeft);
-   rcToInvalidate.top = ROW_AS_YPIXEL(btTop);
-   rcToInvalidate.right = COLUMN_AS_XPIXEL(btRight + 1);
-   rcToInvalidate.bottom = ROW_AS_YPIXEL(btBottom + 1);
-
-   /* Mark this rectangle as invalid. */
-   InvalidateRect(hwndScreenWindow, &rcToInvalidate, FALSE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetCurrentFont()                              *** PRIVATE FUNCTION ***
- *
- * Changes the current font to be used for drawing, updating anything that
- * needs updating.
- *
- * Parameters: hwndScreen - Handle to the screen window.
- *
- *             nNewFont   - Handle to the font to switch to.
- *
- *     Return: void.
- */
-static void ODScrnSetCurrentFont(HWND hwndScreen, HFONT hNewFont)
-{
-   HDC hdc;
-   INT nIDSavedState;
-   TEXTMETRIC TextMetrics;
-
-   /* Obtain a handle to the a device context for the screen window. */
-   hdc = GetDC(hwndScreen);
-
-   /* If we are unable to obtian a device context, then return without */
-   /* doing anything.                                                  */
-   if(hdc == NULL)
-   {
-      return;
-   }
-
-   /* Change the current font. */
-   hCurrentFont = hNewFont;
-
-   /* Obtain text metrics from the device context, and then release the */
-   /* device context.                                                   */
-   nIDSavedState = SaveDC(hdc);
-   SelectObject(hdc, hCurrentFont);
-   GetTextMetrics(hdc, &TextMetrics);
-   RestoreDC(hdc, nIDSavedState);
-   ReleaseDC(hwndScreen, hdc);
-
-   /* Determine the new size of a character cell. */
-   nFontCellWidth = TextMetrics.tmMaxCharWidth;
-   nFontCellHeight = TextMetrics.tmHeight;
-
-   /* Force window sizes to be adjusted for the new font size. */
-   ODScrnAdjustWindows();
-   ODScrnAdjustWindows();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnAdjustWindows()
- *
- * Resizes and repositions the screen window to the appropriate size based
- * on the current font, portions of the frame window's client area that are
- * in use, etc. Other windows whose size depends on the size of the screen
- * window are also updated.
- *
- * Parameters: None.
- *
- *     Return: void.
- */
-void ODScrnAdjustWindows(void)
-{
-   INT nNewClientWidth;
-   INT nNewClientHeight;
-   RECT rcClient;
-   RECT rcWindow;
-   INT nNonClientWidth;
-   INT nNonClientHeight;
-   INT nScreenWindowWidth;
-   INT nScreenWindowHeight;
-   HWND hwndFrame;
-   INT nTopFrameUsed;
-   INT nBottomFrameUsed;
-   HWND hwndScreen;
-
-   hwndScreen = hwndScreenWindow;
-   ASSERT(hwndScreen != NULL);
-
-   hwndFrame = GetParent(hwndScreen);
-   ASSERT(hwndFrame != NULL);
-
-   /* Determine areas of the frame window's client area that are already */
-   /* in use.                                                            */
-   nTopFrameUsed = ODFrameGetUsedClientAtTop(hwndFrame);
-   nBottomFrameUsed = ODFrameGetUsedClientAtBottom(hwndFrame);
-
-   /* Determine the new required size of the window's client area. */
-   nNewClientWidth = nFontCellWidth * OD_SCREEN_WIDTH;
-   nNewClientHeight = nFontCellHeight * OD_SCREEN_HEIGHT;
-
-   /* Determine the size of the window's non-client area. */
-   GetClientRect(hwndScreen, &rcClient);
-   GetWindowRect(hwndScreen, &rcWindow);
-   nNonClientWidth = (rcWindow.right - rcWindow.left)
-      - (rcClient.right - rcClient.left);
-   nNonClientHeight = (rcWindow.bottom - rcWindow.top)
-      - (rcClient.bottom - rcClient.top);
-
-   /* Determine the overall size required for the screen window. */
-   nScreenWindowWidth = nNewClientWidth + nNonClientWidth;
-   nScreenWindowHeight = nNewClientHeight + nNonClientHeight;
-
-   /* Resize the screen window accordingly. */
-   SetWindowPos(hwndScreen, NULL, 0, nTopFrameUsed, nScreenWindowWidth,
-      nScreenWindowHeight, SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOZORDER);
-
-   /* Resize the OpenDoors frame window (which is the screen window's  */
-   /* parent) so that the screen window just fill's the frame window's */
-   /* remaining client area.                                           */
-   GetClientRect(hwndFrame, &rcClient);
-   GetWindowRect(hwndFrame, &rcWindow);
-   nNonClientWidth = (rcWindow.right - rcWindow.left)
-      - (rcClient.right - rcClient.left);
-   nNonClientHeight = (rcWindow.bottom - rcWindow.top)
-      - (rcClient.bottom - rcClient.top);
-
-   SetWindowPos(hwndFrame, NULL, 0, 0, nScreenWindowWidth + nNonClientWidth,
-      nScreenWindowHeight + nNonClientHeight + nTopFrameUsed
-      + nBottomFrameUsed,
-      SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnMessageLoop()                                 *** PRIVATE FUNCTION ***
- *
- * Message loop for OpenDoors screen window thread.
- *
- * Parameters: hInstance   - Handle to current instance.
- *
- *             hwndScreen  - Handle to the screen window.
- *
- *     Return: void.
- */
-static void ODScrnMessageLoop(HANDLE hInstance, HWND hwndScreen)
-{
-   MSG msg;
-   HWND hwndFrame;
-
-   ASSERT(hInstance != NULL);
-   ASSERT(hwndScreen != NULL);
-
-   /* Obtain a handle to the OpenDoors main frame window. */
-   hwndFrame = GetParent(hwndScreen);
-
-   /* Loop, fetching, translating and dispatching messages for any windows */
-   /* created by this thread. (GetMessage() blocks when no messages are    */
-   /* available.)                                                          */
-   while(GetMessage(&msg, NULL, 0, 0))
-   {
-      if(!ODFrameTranslateAccelerator(hwndFrame, &msg))
-      {
-         TranslateMessage(&msg);
-         if(msg.message == WM_KEYDOWN)
-         {
-            PostMessage(hwndScreen, WM_KEYDOWN_RELAY, msg.wParam, msg.lParam);
-         }
-         DispatchMessage(&msg);
-      }
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnThreadProc()                                  *** PRIVATE FUNCTION ***
- *
- * Function that execute the OpenDoors screen window thread. This thread's
- * primary task is to draw the screen window contents, when needed.
- *
- * Parameters: pParam   - The thread parameter, which is a pointer to a
- *                        tODScrnThreadInfo structure.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-DWORD OD_THREAD_FUNC ODScrnThreadProc(void *pParam)
-{
-   tODScrnThreadInfo *pScrnThreadInfo = (tODScrnThreadInfo *)pParam;
-   HWND hwndScreen;
-   HANDLE hInstance = pScrnThreadInfo->hInstance;
-   HWND hwndFrame = pScrnThreadInfo->hwndFrame;
-
-   /* We are now done with the thread startup information structure, */
-   /* so deallocate it.                                              */
-   free(pScrnThreadInfo);
-
-   /* Create the screen window. */
-   hwndScreen = ODScrnCreateWin(hwndFrame, hInstance);
-
-   if(hwndScreen == NULL)
-   {
-      return(FALSE);
-   }
-
-   /* Set the current font for the window. This, in turn will force the  */
-   /* window to be adjusted to the appropriate size, and will adjust the */
-   /* size of the OpenDoors frame window accordingly.                    */
-   ODScrnSetCurrentFont(hwndScreen, GetStockObject(OEM_FIXED_FONT));
-
-   /* Prompt for the user's name before showing the windows, if required. */   
-#ifdef ODPLAT_WIN32
-   if(bPromptForUserName)
-   {
-      if(DialogBox(hInstance, MAKEINTRESOURCE(IDD_LOGIN), hwndFrame,
-         ODInitLoginDlgProc) == IDCANCEL)
-      {
-         exit(od_control.od_errorlevel[1]);
-      }
-
-      PostMessage(hwndScreen, WM_SETFOCUS, 0, 0L);
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Now, we can make the frame window visible. */
-   if(od_control.od_cmd_show == SW_MINIMIZE ||
-      od_control.od_cmd_show == SW_SHOWMINIMIZED ||
-      od_control.od_cmd_show == SW_SHOWMINNOACTIVE)
-   {
-      ShowWindow(hwndFrame, SW_SHOWMINNOACTIVE);
-   }
-   else
-   {
-      ShowWindow(hwndFrame, SW_RESTORE);
-   }
-
-   /* Now, show the screen window. */
-   ShowWindow(hwndScreen, SW_SHOW);
-
-   /* Loop, processing messages for the screen window. */
-   ODScrnMessageLoop(hInstance, hwndScreen);
-
-   /* Destroy the screen window. */
-   DestroyWindow(hwndScreen);
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnStartWindow()
- *
- * Function that starts up the screen window thread, which in turn creates
- * and manages the screen window.
- *
- * Parameters: hInstance      - Handle to the current application instance.
- *
- *             phScreenThread - Pointer to location where screen thread handle
- *                              should be stored.
- *
- *             hwndFrame      - Handle to already created frame window.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODScrnStartWindow(HANDLE hInstance, tODThreadHandle *phScreenThread,
-   HWND hwndFrame)
-{
-   tODScrnThreadInfo *pScrnThreadInfo;
-
-   ASSERT(hInstance != NULL);
-   ASSERT(phScreenThread != NULL);
-   ASSERT(hwndFrame != NULL);
-
-   /* Setup thread information to pass into the screen thread at startup. */
-   if((pScrnThreadInfo = malloc(sizeof(tODScrnThreadInfo))) == NULL)
-   {
-      return(kODRCNoMemory);
-   }
-
-   pScrnThreadInfo->hInstance = hInstance;
-   pScrnThreadInfo->hwndFrame = hwndFrame;
-
-   /* Create the screen thread. */
-   return(ODThreadCreate(phScreenThread, ODScrnThreadProc,
-      pScrnThreadInfo));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetFocusToWindow()
- *
- * Sets the current input focus to the screen window.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODScrnSetFocusToWindow(void)
-{
-   if(hwndScreenWindow != NULL)
-   {
-      SetFocus(hwndScreenWindow);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetWinCaretPos()
- *
- * Repositions the Windows caret to the position of our cursor, if
- * appropriate.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODScrnSetWinCaretPos(void)
-{
-   /* Only move the caret if we have focus, and thus we are the one who */
-   /* owns the caret.                                                   */
-   if(bScreenHasFocus)
-   {
-      SetCaretPos(COLUMN_AS_XPIXEL(btCursorColumn + btLeftBoundary),
-         ROW_AS_YPIXEL(btCursorRow + btTopBoundary + 1) - CARET_HEIGHT);
-   }
-}
-
-
-#endif /* ODPLAT_WIN32 */
-
-
-
-/* ========================================================================= */
-/* Functions used throughout OpenDoors to manipulate local screen buffer.    */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODScrnInitialize()
- *
- * Initializes the local screen module.
- *
- * Parameters: none
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODScrnInitialize(void)
-{
-   BOOL bClear = TRUE;
-
-#ifdef ODPLAT_DOS
-   BYTE btDisplayMode;
-
-   /* In silent mode, we perform all output in a block of memory that is */
-   /* never displayed.                                                   */
-   if(od_control.od_silent_mode)
-   {
-      /* Allocate memory for screen buffer, using standard pointer type */
-      /* for current memory model.                                      */
-      pAllocatedBufferMemory = malloc(SCREEN_BUFFER_SIZE);
-
-      if(pAllocatedBufferMemory == NULL)
-      {
-         return(kODRCNoMemory);
-      }
-
-      /* Set the screen buffer far pointer to point to the allocated */
-      /* buffer.                                                     */
-      pScrnBuffer = pAllocatedBufferMemory;
-   }
-   else
-   {
-      /* Get current video mode. */
-      ASM    push si
-      ASM    push di
-      ASM    mov ah, 0x0f
-      ASM    int 0x10
-      ASM    mov btDisplayMode, al
-      ASM    pop di
-      ASM    pop si
-
-      switch(btDisplayMode & 0x7f)
-      {
-         /* No need to change mode, already colour 80x25. */
-         case 0x02:
-         case 0x03:
-            wBufferSegment = 0xb800;
-            pScrnBuffer = (void ODFAR *)0xb8000000L;
-            bClear = TRUE;
-            break;
-
-         /* No need to change mode, already monochrome 80x25. */
-         case 0x07:
-            wBufferSegment = 0xb000;
-            pScrnBuffer = (void ODFAR *)0xb0000000L;
-            bClear = TRUE;
-            break;
-
-         /* Must change mode to monochrome 80x25. */
-         case 0x21:
-            wBufferSegment = 0xb000;
-            pScrnBuffer = (void ODFAR *)0xb0000000L;
-            bClear = FALSE;
-
-            /* set mode to 0x07 */
-            ASM    push si
-            ASM    push di
-            ASM    mov ax, 0x0007
-            ASM    int 0x10
-            ASM    pop di
-            ASM    pop si
-            break;
-
-         /* Must change mode to colour 80x25. */
-         default:
-            wBufferSegment = 0xb800;
-            pScrnBuffer = (void ODFAR *)0xb8000000L;
-            bClear = FALSE;
-
-            /* set mode to 0x03. */
-            ASM    push si
-            ASM    push di
-            ASM    mov ax, 0x0003
-            ASM    int 0x10
-            ASM    pop di
-            ASM    pop si
-      }
-
-
-
-      /* Adjust address for display page which is being used. */
-      ASM    push si
-      ASM    push di
-      ASM    mov ah, 0x0f
-      ASM    int 0x10
-      ASM    mov btDisplayPage, bh
-      ASM    pop di
-      ASM    pop si
-
-      if(btDisplayPage!=0)
-      {
-         wBufferSegment += (SCREEN_BUFFER_SEGMENT_SIZE * btDisplayPage);
-         ((char ODFAR *)pScrnBuffer) += (SCREEN_BUFFER_SIZE * btDisplayPage);
-      }
-
-      if(ODMultitasker == kMultitaskerDV)
-      {
-         /* Determine address of DV screen buffer. */
-         /* This doesn't check rows, bh = rows, bl = columns. */
-         ASM    mov ax, 0x2b02
-         ASM    mov cx, 0x4445
-         ASM    mov dx, 0x5351
-         ASM    int 0x21
-         ASM    cmp bx, 0x1950
-         ASM    jne no_change
-         ASM    mov wBufferSegment, dx
-
-         (long)pScrnBuffer = ODDWordShiftLeft((long)wBufferSegment, 16);
-   no_change: ;
-      }
-   }
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   /* Allocate memory for screen buffer. */
-   pScrnBuffer = malloc(SCREEN_BUFFER_SIZE);
-
-   if(pScrnBuffer == NULL)
-   {
-      return(kODRCNoMemory);
-   }
-#endif /* ODPLAT_WIN32 */
-
-   /* Initialize display system variables. */
-   btLeftBoundary = 0;
-   btRightBoundary = 79;
-   btTopBoundary = 0;
-   btBottomBoundary = 24;
-   btCurrentAttribute = 0x07;
-   bScrollEnabled = 1;
-
-   /* Clear local screen. */
-   if(bClear)
-   {
-      ODScrnClear();
-   }
-
-   /* Enable flashing cursor. */
-   bCaretOn = FALSE;
-   ODScrnEnableCaret(TRUE);
-
-   /* Return with success. */
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnShutdown()
- *
- * De-initializes the screen module.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODScrnShutdown(void)
-{
-#ifdef ODPLAT_WIN32
-   /* Deallocate screen buffer memory. */
-   if(pScrnBuffer != NULL)
-   {
-      free(pScrnBuffer);
-      pScrnBuffer = NULL;
-   }
-#else /* !ODPLAT_WIN32 */
-   /* In silent mode, we must deallocate screen buffer memory. */
-   if(od_control.od_silent_mode && pAllocatedBufferMemory != NULL)
-   {
-      free(pAllocatedBufferMemory);
-      pAllocatedBufferMemory = NULL;
-      pScrnBuffer = NULL;
-   }
-#endif
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetBoundary()
- *
- * Sets the current boundary area on the screen. All output is constrained
- * within this boundary area.
- *
- * Parameters: btLeft   - 1-based column number of the left edge of the area.
- *
- *             btTop    - 1-based row number of the top edge of the area.
- *
- *             btRight  - 1-based column number of the right edge of the area.
- *
- *             btBottom - 1-based row number of the bottom edge of the area.
- *
- *     Return: void
- */
-void ODScrnSetBoundary(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom)
-{
-   /* Set internal window location variables. */
-   btLeftBoundary = btLeft - 1;
-   btRightBoundary = btRight - 1;
-   btTopBoundary = btTop - 1;
-   btBottomBoundary = btBottom - 1;
-
-   /* Ensure that the cursor is located within the new window boundaries. */
-   if(btCursorColumn > btRightBoundary - btLeftBoundary)
-   {
-      btCursorColumn = btRightBoundary - btLeftBoundary;
-   }
-   else if(btCursorColumn < btLeftBoundary)
-   {
-      btCursorColumn = btLeftBoundary;
-   }
-
-   if(btCursorRow > btBottomBoundary - btTopBoundary)
-   {
-      btCursorRow = btBottomBoundary - btTopBoundary;
-   }
-   else if(btCursorRow < btTopBoundary)
-   {
-      btCursorRow = btTopBoundary;
-   }
-
-   /* Execute the position flashing cursor primitive. */
-   ODScrnUpdateCaretPos();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetCursorPos()
- *
- * Sets the current cursor position. The cursor position is where the caret
- * (flashing cursor) appears (if it is currently turned on), and is the
- * location where ODScrnDisplayChar(), ODScrnDisplayString() and ODScrnPrintf()
- * will perform their output. Each of these functions, update the cursor
- * position to the next character cell after the end of their output. Other
- * ODScrn...() functions may also change the current cursor position.
- *
- * Parameters: btColumn - The 1-based column number where the cursor will
- *                        be placed.
- *
- *     Return: void
- */
-void ODScrnSetCursorPos(BYTE btColumn, BYTE btRow)
-{
-   /* Set internal cursor position values. */
-   btCursorColumn = btColumn - 1;
-   btCursorRow = btRow - 1;
-
-   /* Ensure that cursor falls within the current output window. */
-   if(btCursorColumn > btRightBoundary - btLeftBoundary)
-      btCursorColumn = btRightBoundary - btLeftBoundary;
-
-   if(btCursorRow > btBottomBoundary - btTopBoundary)
-      btCursorRow = btBottomBoundary - btTopBoundary;
-
-   /* Execute the position flashing cursor primitive. */
-   ODScrnUpdateCaretPos();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnSetAttribute()
- *
- * Sets the current display attribute, to be used by ODScrnDisplayChar(),
- * ODScrnDisplayString(), ODScrnPrintf() and ODScrnClear(). The display
- * attribute byte is always in the IBM color attribute format, with the
- * lower 4 bits indicating the foreground color, and the next 3 bits
- * indicating the background color. The upper bit specifies whether the text
- * is flashing, although this code may not actually show flashing text on
- * all platforms.
- *
- * Parameters: btAttribute - The new color attribute to use.
- *
- *     Return: void
- */
-void ODScrnSetAttribute(BYTE btAttribute)
-{
-   /* Set internal display colour attribute. */
-   btCurrentAttribute = btAttribute;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnEnableScrolling()
- *
- * Enables or disables scrolling of text within the currently defined boundary
- * area when a carriage return is sent with the cursor located on the bottom
- * line of bounary area.
- *
- * Parameters: bEnable - TRUE to enable scrolling, FALSE to disable scrolling.
- *
- *     Return: void
- */
-void ODScrnEnableScrolling(BOOL bEnable)
-{
-   /* Stores the current scrolling setting. */
-   bScrollEnabled = bEnable;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnEnableCaret()
- *
- * Turns the caret (flashing indicator of the current cursor location) on or
- * off. Under the Win32 platform, the caret is always active when the
- * window has input focus, and inactive at any other time. Hene, under
- * Win32, this function has no effect.
- *
- * Parameters: bEnable - TRUE to turn on the flashing caret, FALSE to turn it
- *                       off.
- *
- *     Return: void
- */
-void ODScrnEnableCaret(BOOL bEnable)
-{
-#ifdef ODPLAT_DOS
-   if(bCaretOn == bEnable) return;
-
-   bCaretOn = bEnable;
-
-   /* Execute the cursor on / off primitive. */
-   ASM    push si
-   ASM    push di
-   ASM    mov ah, 0x03
-   ASM    mov bh, btDisplayPage
-   ASM    int 0x10
-
-   /* ch = start line, cl = end line. */
-   ASM    push cx                
-   ASM    mov ah, 0x0f
-   ASM    int 0x10
-   ASM    pop cx
-
-   /* al = video mode. */
-   ASM    push ax
-   ASM    and ch, 0x1f
-   ASM    mov al, bCaretOn
-   ASM    and al, al
-   ASM    jnz set_cursor
-   /* ch bits 5-6 = blink attr */
-   /*               00 = normal */
-   /*               01 = invisible */
-   ASM    or ch, 0x20
-set_cursor:
-   ASM    pop ax
-   ASM    mov bh, btDisplayPage
-   ASM    mov ah, 0x01
-   ASM    int 0x10
-   ASM    pop di
-   ASM    pop si
-
-
-   if(bCaretOn)
-   {
-      /* Turn on the local caret, updating its position. */
-      ODScrnUpdateCaretPos();
-   }
-   else
-   {
-      /* Turn off the local caret. */
-      ASM    mov ah, 0x02
-      ASM    mov bh, btDisplayPage
-      ASM    mov dh, OD_SCREEN_HEIGHT
-      ASM    mov dl, OD_SCREEN_WIDTH
-      ASM    push si
-      ASM    push di
-      ASM    int 0x10
-      ASM    pop di
-      ASM    pop si
-   }
-#endif /* ODPLAT_DOS */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnGetTextInfo()
- *
- * Fills a structure with information about the current display settings,
- * including the position of the current boundary area (output window),
- * color attribute and cursor location.
- *
- * Parameters: pTextInfo - Pointer to the structure to store the current text
- *                         settings information in.
- *
- *     Return: void
- */
-void ODScrnGetTextInfo(tODScrnTextInfo *pTextInfo)
-{
-   pTextInfo->wintop = btTopBoundary + 1;
-   pTextInfo->winleft = btLeftBoundary + 1;
-   pTextInfo->winright = btRightBoundary + 1;
-   pTextInfo->winbottom = btBottomBoundary + 1;
-   pTextInfo->attribute = btCurrentAttribute;
-   pTextInfo->curx = btCursorColumn + 1;
-   pTextInfo->cury = btCursorRow + 1;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnPrintf()
- *
- * Performs formatted output within the current boundary area.
- *
- * Parameters: pszFormat - Format string, which is in the same format as is
- *                         used by the standard C printf() function.
- *
- *             The semantics of additional parameters is specified by the
- *             contents of the pszFormat string.
- *
- *     Return: The standard printf() return value.
- */
-INT ODScrnPrintf(char *pszFormat, ...)
-{
-   va_list pArgumentList;
-   INT nToReturn;
-
-   /* Generate string to display. */
-   va_start(pArgumentList, pszFormat);
-   nToReturn = vsprintf(szBuffer, pszFormat, pArgumentList);
-   va_end(pArgumentList);
-
-   /* Ensure that we didn't overrun the buffer. */
-   ASSERT(strlen(szBuffer) <= sizeof(szBuffer) - 1);
-
-   /* Display generated string. */
-   ODScrnDisplayString(szBuffer);
-
-   /* Return appropriate value. */
-   return (nToReturn);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnDisplayChar()
- *
- * Writes a single character within the current boundary area, advancing the
- * cursor.
- *
- * Parameters: chToOutput  - The character to display.
- *
- *     Return: void
- */
-void ODScrnDisplayChar(unsigned char chToOutput)
-{
-   BYTE ODFAR *pbtDest;
-   
-   ODScrnGetCursorPos();
-
-   if(btCursorColumn > btRightBoundary - btLeftBoundary)
-   {
-      btCursorColumn = btRightBoundary - btLeftBoundary;
-   }
-
-   if(btCursorRow > btBottomBoundary - btTopBoundary)
-   {
-      btCursorRow = btBottomBoundary - btTopBoundary;
-   }
-
-   switch(chToOutput)
-   {
-      /* If character is a carriage return. */
-      case '\r':
-         btCursorColumn = 0;
-         break;
-
-      /* If character is a line feed. */
-      case '\n':
-         /* If cursor is at bottom of output window. */
-         if(btCursorRow == btBottomBoundary - btTopBoundary)
-         {
-            /* Scroll the screen up by one line. */
-            ODScrnScrollUpAndInvalidate();
-         }
-         /* If cursor is not at bottom of output window. */
-         else
-         {
-            /* Move the cursor down one line. */
-            ++btCursorRow;
-         }
-         break;
-
-      case '\b':
-         /* If backspace. */
-         if(btCursorColumn != 0) --btCursorColumn;
-         break;
-
-      case '\t':
-         /* If tab character. */
-         btCursorColumn = ((btCursorColumn / 8) + 1) * 8;
-         if(btCursorColumn > btRightBoundary - btLeftBoundary)
-         {
-            btCursorColumn = 0;
-
-            /* If moving cursor down one line advances past end of window. */
-            if(++btCursorRow > btBottomBoundary - btTopBoundary)
-            {
-               /* Move cursor back to bottom line of window. */
-               btCursorRow = btBottomBoundary - btTopBoundary;
-
-               /* Scroll the screen up by one line. */
-               ODScrnScrollUpAndInvalidate();
-            }
-         }
-         break;
-
-      case '\a':
-         /* If bell. */
-         if(!od_control.od_silent_mode)
-         {
-#ifdef ODPLAT_DOS
-            ASM    mov ah, 0x02
-            ASM    mov dl, 7
-            ASM    int 0x21
-#endif /* ODPLAT_DOS */
-#ifdef ODPLAT_WIN32
-            MessageBeep(0xffffffff);
-#endif /* ODPLAT_WIN32 */
-         }
-         break;
-
-      /* If character is not a control character. */
-      default:
-         /* Output character to display buffer. */
-         pbtDest = (BYTE ODFAR *)pScrnBuffer
-            + ((btTopBoundary + btCursorRow) * BUFFER_LINE_BYTES
-            + (btLeftBoundary + btCursorColumn) * BYTES_PER_CHAR);
-         *pbtDest++ = chToOutput;
-         *pbtDest = btCurrentAttribute;
-
-         ASSERT(pbtDest >= (BYTE ODFAR *)pScrnBuffer);
-         ASSERT(pbtDest < (BYTE ODFAR *)pScrnBuffer + SCREEN_BUFFER_SIZE);
-
-#ifdef ODPLAT_WIN32
-         /* Force the updated area of the screen window to be redrawn. */
-         ODScrnInvalidate((BYTE)(btCursorColumn + btLeftBoundary),
-            (BYTE)(btCursorRow + btTopBoundary),
-            (BYTE)(btCursorColumn + btLeftBoundary),
-            (BYTE)(btCursorRow + btTopBoundary));
-#endif /* ODPLAT_WIN32 */
-
-         /* Advance cursor. If at end of line ... */
-         if(++btCursorColumn > btRightBoundary - btLeftBoundary)
-         {
-            /* Wrap cursor if necessary. */
-            btCursorColumn = 0;
-
-            /* If moving cursor down one line advances past end of window. */
-            if(++btCursorRow > btBottomBoundary - btTopBoundary)
-            {
-               /* Move cursor back to bottom line of window. */
-               btCursorRow = btBottomBoundary - btTopBoundary;
-
-               /* Scroll the screen up by one line. */
-               ODScrnScrollUpAndInvalidate();
-            }
-         }
-   }
-
-   /* Execute the update flashing cursor primitive. */
-   ODScrnUpdateCaretPos();
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnGetCursorPos()                                *** PRIVATE FUNCTION ***
- *
- * Updates the current cursor position (output position) from the location of
- * the caret (flashing cursor). This function doesn't do anything on the
- * Win32 platform, since we nobody else can reposition the cursor.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODScrnGetCursorPos(void)
-{
-#ifdef ODPLAT_DOS
-   if(!bCaretOn) return;
-
-   ASM    mov ah, 0x03
-   ASM    mov bh, btDisplayPage
-   ASM    push si
-   ASM    push di
-   ASM    int 0x10
-   ASM    pop di
-   ASM    pop si
-   ASM    sub dh, btTopBoundary
-   ASM    mov btCursorRow, dh
-   ASM    sub dl, btLeftBoundary
-   ASM    mov btCursorColumn, dl
-#endif /* ODPLAT_DOS */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnUpdateCaretPos()                              *** PRIVATE FUNCTION ***
- *
- * Updates the position of the caret (flashing cursor) from the current cursor
- * location (output position).
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODScrnUpdateCaretPos(void)
-{
-#ifdef ODPLAT_DOS
-   if(!bCaretOn) return;
-
-   /* Update position of flashing cursor on screen */
-   ASM    mov ah, 0x02
-   ASM    mov bh, btDisplayPage
-   ASM    mov dh, btCursorRow
-   ASM    add dh, btTopBoundary
-   ASM    mov dl, btCursorColumn
-   ASM    add dl, btLeftBoundary
-   ASM    push si
-   ASM    push di
-   ASM    int 0x10
-   ASM    pop di
-   ASM    pop si
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   if(hwndScreenWindow != NULL)
-   {
-      PostMessage(hwndScreenWindow, WM_MOVE_YOUR_CARET, 0, 0);
-   }
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnClear()
- *
- * Clears the text within the currently defined boundary area, setting the
- * display attribute of the entire boundary area to the current display
- * color.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODScrnClear(void)
-{
-   WORD ODFAR *pDest = (WORD ODFAR *)pScrnBuffer +
-      ((btTopBoundary * OD_SCREEN_WIDTH) + btLeftBoundary);
-   WORD wBlank = (((WORD)btCurrentAttribute) << 8) | 32;
-   BYTE btCurColumn;
-   BYTE btCurLine = (btBottomBoundary - btTopBoundary) + 1;
-   BYTE btColumnStart = (btRightBoundary - btLeftBoundary) + 1;
-   BYTE btSkip = OD_SCREEN_WIDTH - btColumnStart;
-
-   /* Clear contents of current window. */
-   do
-   {
-      btCurColumn = btColumnStart;
-      do
-      {
-         ASSERT(pDest >= (WORD ODFAR *)pScrnBuffer);
-         ASSERT(pDest <= (WORD ODFAR *)pScrnBuffer + 2000);
-         *(pDest++) = wBlank;
-      } while ((--btCurColumn) != 0);
-      pDest += btSkip;
-   } while((--btCurLine) != 0);
-
-   /* Move cursor to top left-hand corner of current window. */
-   btCursorColumn = btCursorRow = 0;
-
-   /* Execute the update flashing cursor primitive. */
-   ODScrnUpdateCaretPos();
-
-#ifdef ODPLAT_WIN32
-   /* Force the updated area of the screen window to be redrawn. */
-   ODScrnInvalidate(btLeftBoundary, btTopBoundary, btRightBoundary,
-      btBottomBoundary);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnScrollUpAndInvalidate()                       *** PRIVATE FUNCTION ***
- *
- * Scrolls the entire screen up by one line, only if scrolling is enabled.
- * If scrolling is performed, invalidates area that was scrolled. Scrolling
- * is accomplished using ODScrnScrollUpOneLine().
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODScrnScrollUpAndInvalidate(void)
-{
-   /* If scrolling is enabled. */
-   if(bScrollEnabled)
-   {
-      /* Execute the scroll primitive. */
-      ODScrnScrollUpOneLine();
-
-#ifdef ODPLAT_WIN32
-      /* Force the updated area of the screen window to be redrawn. */
-      ODScrnInvalidate(btLeftBoundary, btTopBoundary, btRightBoundary,
-         btBottomBoundary);
-#endif /* ODPLAT_WIN32 */
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnScrollUpOneLine()                             *** PRIVATE FUNCTION ***
- *
- * Scrolls the area within the current output boundary up one line, leaving the
- * newly created line at the bottom of the area blank, with the current display
- * attribute.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void ODScrnScrollUpOneLine(void)
-{
-   WORD ODFAR *pwDest = (WORD ODFAR *)pScrnBuffer
-      + (btTopBoundary * OD_SCREEN_WIDTH + btLeftBoundary);
-   WORD ODFAR *pwSource;
-   BYTE btCurColumn;
-   BYTE btCurLine = btBottomBoundary - btTopBoundary;
-   BYTE btColumnStart = btRightBoundary - btLeftBoundary + 1;
-   BYTE btSkip = OD_SCREEN_WIDTH - btColumnStart;
-   WORD wBlank = (((WORD)btCurrentAttribute) << 8) | 32;
-
-   pwSource = pwDest + OD_SCREEN_WIDTH;
-
-   ASSERT(btSkip >= 0 && btSkip <= OD_SCREEN_WIDTH);
-
-   /* Move text in area of window up one line. */
-   do
-   {
-      btCurColumn = btColumnStart;
-      do
-      {
-         ASSERT(pwDest >= (WORD ODFAR *)pScrnBuffer);
-         ASSERT(pwDest <= (WORD ODFAR *)pScrnBuffer + 2000);
-         ASSERT(pwSource >= (WORD ODFAR *)pScrnBuffer);
-         ASSERT(pwSource <= (WORD ODFAR *)pScrnBuffer+2000);
-         *(pwDest++) = *(pwSource++);
-      } while((--btCurColumn) != 0);
-      pwDest += btSkip;
-      pwSource += btSkip;
-   } while ((--btCurLine) != 0);
-
-   /* Clear newly created line at bottom of window. */
-   btCurColumn = btColumnStart;
-   do
-   {
-      ASSERT(pwDest >= (WORD ODFAR *)pScrnBuffer);
-      ASSERT(pwDest <= (WORD ODFAR *)pScrnBuffer + 2000);
-      *(pwDest++) = wBlank;
-   } while((--btCurColumn) != 0);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnGetText()
- *
- * Copies a portion of the currently displayed text and corresponding color
- * attributes to a buffer provided by the caller.
- *
- * Parameters: btLeft    - Column number of the left edge of the area to copy
- *                         from.
- *
- *             btTop     - Row number of the top edge of the area to copy from.
- *
- *             btRight   - Column number of the right edge of the area to copy
- *                         from.
- *
- *             btBottom  - Row number of the bottom edge of the area to copy
- *                         from.
- *
- *             pbtBuffer - A pointer to the buffer to copy to. It is the
- *                         caller's responsibility to ensure that this buffer
- *                         is large enough. This buffer must be at least
- *                         2 x (Width of area) x (Height of area) bytes in size.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-BOOL ODScrnGetText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   void *pbtBuffer)
-{
-   WORD *pwBuffer = (WORD *)pbtBuffer;
-   WORD ODFAR *pSource = (WORD ODFAR *)pScrnBuffer
-      + ((((--btTop) + btTopBoundary)
-      * OD_SCREEN_WIDTH) + btLeftBoundary + (--btLeft));
-   BYTE btCurColumn;
-   BYTE btCurLine = (--btBottom) - btTop + 1;
-   BYTE btColumnStart = (--btRight) - btLeft + 1;
-   BYTE btSkip = OD_SCREEN_WIDTH - btColumnStart;
-
-   ASSERT(btLeft >= 0);
-   ASSERT(btTop >= 0);
-   ASSERT(btRight <= btRightBoundary - btLeftBoundary);
-   ASSERT(btBottom <= btBottomBoundary - btTopBoundary);
-   ASSERT(pbtBuffer);
-
-   /* Copy contents of screen block to buffer */
-   do 
-   {
-      btCurColumn = btColumnStart;
-      do
-      {
-         ASSERT(pSource >= (WORD ODFAR *)pScrnBuffer);
-         ASSERT(pSource <= (WORD ODFAR *)pScrnBuffer + 2000);
-         ASSERT(pwBuffer >= (WORD *)pbtBuffer);
-         ASSERT(pwBuffer <= (WORD *)pbtBuffer + 2000);
-         *(pwBuffer++) = *(pSource++);
-      } while ((--btCurColumn) != 0);
-      pSource += btSkip;
-   } while((--btCurLine) != 0);
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnPutText()
- *
- * Changes the currently displayed text and corresponding color attributes in
- * the specified area, to the values taken from the buffer. This buffer is in
- * the same format as is produce by the ODScrnGetText() function.
- *
- * Parameters: btLeft    - Column number of the left edge of the area to copy
- *                         to.
- *
- *             btTop     - Row number of the top edge of the area to copy to.
- *
- *             btRight   - Column number of the right edge of the area to copy
- *                         to.
- *
- *             btBottom  - Row number of the bottom edge of the area to copy
- *                         to.
- *
- *             pbtBuffer - A pointer to the buffer to copy from.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-BOOL ODScrnPutText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   void *pbtBuffer)
-{
-   WORD *pwBuffer = (WORD *)pbtBuffer;
-   WORD ODFAR *pDest = (WORD ODFAR *)pScrnBuffer
-      + ((((--btTop) + btTopBoundary)
-      * OD_SCREEN_WIDTH) + btLeftBoundary + (--btLeft));
-   BYTE btCurColumn;
-   BYTE btCurLine = (--btBottom) - btTop + 1;
-   BYTE btColumnStart = (--btRight) - btLeft + 1;
-   BYTE btSkip = OD_SCREEN_WIDTH - btColumnStart;
-
-   ASSERT(btLeft >= 0 && btTop >= 0);
-   ASSERT(btLeft <= btRightBoundary - btLeftBoundary);
-   ASSERT(btTop <= btBottomBoundary - btTopBoundary);
-   ASSERT(btRight >= 0 && btBottom >= 0);
-   ASSERT(btRight <= btRightBoundary - btLeftBoundary);
-   ASSERT(btBottom <= btBottomBoundary - btTopBoundary);
-   ASSERT(pbtBuffer != NULL);
-
-   /* Copy contents of screen block to buffer. */
-   do
-   {
-      btCurColumn = btColumnStart;
-      do
-      {
-         ASSERT(pDest >= (WORD ODFAR *)pScrnBuffer);
-         ASSERT(pDest <= (WORD ODFAR *)pScrnBuffer + 2000);
-         ASSERT(pwBuffer >= (WORD *)pbtBuffer);
-         ASSERT(pwBuffer <= (WORD *)pbtBuffer + 2000);
-         *(pDest++) = *(pwBuffer++);
-      } while ((--btCurColumn) != 0);
-      pDest += btSkip;
-   } while((--btCurLine) != 0);
-
-#ifdef ODPLAT_WIN32
-   /* Force the updated area of the screen window to be redrawn. */
-   ODScrnInvalidate((BYTE)(btLeftBoundary + btLeft), 
-      (BYTE)(btTopBoundary + btTop),
-      (BYTE)(btRightBoundary + btRight),
-      (BYTE)(btBottomBoundary + btBottom));
-#endif /* ODPLAT_WIN32 */
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnDisplayString()
- *
- * Copies the contents of a string to the display, using the currently set
- * color attributes. The cursor location is updated to the end of the string
- * on the screen.
- *
- * Parameters: pszString - Pointer to the string to display.
- *
- *     Return: void.
- */
-void ODScrnDisplayString(char *pszString)
-{
-   ODScrnDisplayBuffer(pszString, strlen(pszString));
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnDisplayBuffer()
- *
- * Copies the contents of a buffer to the display, using the currently set
- * color attributes. The cursor location is updated to the end of the text
- * displayed to the screen.
- *
- * Parameters: pBuffer         - Pointer to a buffer containing the
- *                               character(s) to display.
- *
- *             nCharsToDisplay - Count of number of characters to display from
- *                               the buffer.
- *
- *     Return: void.
- */
-void ODScrnDisplayBuffer(char *pBuffer, INT nCharsToDisplay)
-{
-   char *pchCurrentChar = pBuffer;
-   INT nCharsLeft = nCharsToDisplay;
-   BYTE ODFAR *pDest;
-   BYTE btLeftColumn;
-   BYTE btAttribute = btCurrentAttribute;
-   BYTE btCurrentColumn;
-   BYTE btBottom = btBottomBoundary - btTopBoundary;
-#ifdef ODPLAT_WIN32
-   BOOL bAnythingInvalid = FALSE;
-   BYTE btLeftMost;
-   BYTE btRightMost;
-   BYTE btTopMost;
-   BYTE btBottomMost;
-#endif /* ODPLAT_WIN32 */
-
-   ASSERT(pBuffer != NULL);
-   ASSERT(nCharsToDisplay >= 0);
-
-   ODScrnGetCursorPos();
-
-   if(btCursorColumn > btRightBoundary - btLeftBoundary)
-   {
-      btCursorColumn = btRightBoundary - btLeftBoundary;
-   }
-
-   if(btCursorRow > btBottomBoundary - btTopBoundary)
-   {
-      btCursorRow = btBottomBoundary - btTopBoundary;
-   }
-
-   btCurrentColumn = btCursorColumn;
-
-   btLeftColumn = btRightBoundary - (btCurrentColumn + btLeftBoundary);
-   pDest = (BYTE ODFAR *) pScrnBuffer + (((btTopBoundary + btCursorRow)
-      * BUFFER_LINE_BYTES)
-      + (btLeftBoundary + btCursorColumn) * BYTES_PER_CHAR);
-
-   while(nCharsLeft--)
-   {
-      ASSERT(pDest >= (BYTE ODFAR *)pScrnBuffer);
-      ASSERT(pDest <= (BYTE ODFAR *)pScrnBuffer + SCREEN_BUFFER_SIZE);
-      switch(*pchCurrentChar)
-      {
-         case '\r':
-            btCurrentColumn = 0;
-            btLeftColumn = btRightBoundary - btLeftBoundary;
-            pDest = (BYTE ODFAR *)pScrnBuffer + ((btTopBoundary + btCursorRow)
-               * BUFFER_LINE_BYTES + btLeftBoundary * BYTES_PER_CHAR);
-            pchCurrentChar++;
-            break;
-         case '\n':
-            if (btCursorRow < btBottom)
-            {
-               ++btCursorRow;
-               pDest += BUFFER_LINE_BYTES;
-            }
-            else if(bScrollEnabled)
-            {
-               ODScrnScrollUpOneLine();
-#ifdef ODPLAT_WIN32
-               /* Entire boundary area is now invalid. */
-               bAnythingInvalid = TRUE;
-               btLeftMost = btLeftBoundary;
-               btRightMost = btRightBoundary;
-               btTopMost = btTopBoundary;
-               btBottomMost = btBottomBoundary;
-#endif /* ODPLAT_WIN32 */
-            }
-            pchCurrentChar++;
-            break;
-
-         case '\a':
-            /* If bell */
-            if(!od_control.od_silent_mode)
-            {
-#ifdef ODPLAT_DOS
-               ASM    mov ah, 0x02
-               ASM    mov dl, 7
-               ASM    int 0x21
-#endif /* ODPLAT_DOS */
-#ifdef ODPLAT_WIN32
-               MessageBeep(0xffffffff);
-#endif /* ODPLAT_WIN32 */
-               pchCurrentChar++;
-            }
-            break;
-
-         case '\t':
-            /* If tab character. */
-            btCurrentColumn = ((btCurrentColumn / 8) + 1) * 8;
-            if(btCurrentColumn > btRightBoundary - btLeftBoundary)
-            {
-               btCurrentColumn = 0;
-
-               /* If moving cursor down one line advances past end of window. */
-               if(++btCursorRow > btBottomBoundary - btTopBoundary)
-               {
-                  /* Move cursor back to bottom line of window. */
-                  btCursorRow = btBottomBoundary - btTopBoundary;
-
-                  /* If scrolling is enabled. */
-                  if(bScrollEnabled)
-                  {
-                     /* Execute the scroll primitive .*/
-                     ODScrnScrollUpOneLine();
-#ifdef ODPLAT_WIN32
-                     /* Entire boundary area is now invalid. */
-                     bAnythingInvalid = TRUE;
-                     btLeftMost = btLeftBoundary;
-                     btRightMost = btRightBoundary;
-                     btTopMost = btTopBoundary;
-                     btBottomMost = btBottomBoundary;
-#endif /* ODPLAT_WIN32 */
-                  }
-               }
-            }
-
-            /* Determine new buffer destination address. */
-            pDest = (BYTE ODFAR *) pScrnBuffer
-               + (((btTopBoundary + btCursorRow) * BUFFER_LINE_BYTES)
-               + (btLeftBoundary + btCursorColumn) * BYTES_PER_CHAR);
-            break;
-
-         case '\b':
-            if(btCurrentColumn > 0)
-            {
-               --btCurrentColumn;
-               pDest-=2;
-               btLeftColumn++;
-            }
-            pchCurrentChar++;
-            break;
-
-         default:
-            *(pDest++) = *(pchCurrentChar++);
-            *(pDest++) = btAttribute;
-
-#ifdef ODPLAT_WIN32
-            /* Expand area to invalidate, if needed. */
-            if(!bAnythingInvalid)
-            {
-               bAnythingInvalid = TRUE;
-               btLeftMost = btLeftBoundary + btCurrentColumn;
-               btRightMost = btLeftBoundary + btCurrentColumn;
-               btTopMost = btTopBoundary + btCursorRow;
-               btBottomMost = btTopBoundary + btCursorRow;
-            }
-            else
-            {
-               BYTE btColumn = btLeftBoundary + btCurrentColumn;
-               BYTE btRow = btTopBoundary + btCursorRow;
-
-               if(btColumn < btLeftMost) btLeftMost = btColumn;
-               if(btColumn > btRightMost) btRightMost = btColumn;
-               if(btRow < btTopMost) btTopMost = btRow;
-               if(btRow > btBottomMost) btBottomMost = btRow;
-            }
-#endif /* ODPLAT_WIN32 */
-
-            if(btLeftColumn--)
-            {
-               ++btCurrentColumn;
-            }
-            else
-            {
-               btCurrentColumn = 0;
-               btLeftColumn = btRightBoundary - btLeftBoundary;
-
-               if(btCursorRow < btBottom)
-               {
-                  ++btCursorRow;
-               }
-               else if(bScrollEnabled)
-               {
-                  ODScrnScrollUpOneLine();
-#ifdef ODPLAT_WIN32
-                  /* Entire boundary area is now invalid. */
-                  bAnythingInvalid = TRUE;
-                  btLeftMost = btLeftBoundary;
-                  btRightMost = btRightBoundary;
-                  btTopMost = btTopBoundary;
-                  btBottomMost = btBottomBoundary;
-#endif /* ODPLAT_WIN32 */
-               }
-
-               pDest = (BYTE ODFAR *)pScrnBuffer
-                  + ((btTopBoundary + btCursorRow)
-                  * BUFFER_LINE_BYTES + btLeftBoundary * BYTES_PER_CHAR);
-            }
-      }
-   }
-
-   btCursorColumn = btCurrentColumn;
-   ODScrnUpdateCaretPos();
-
-#ifdef ODPLAT_WIN32
-   if(bAnythingInvalid)
-   {
-      /* Force the updated area of the screen window to be redrawn. */
-      ODScrnInvalidate(btLeftMost, btTopMost, btRightMost,
-         btBottomMost);
-   }
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnCopyText()
- *
- * Copies the contents of the specified area on the screen to another location
- * on the screen. The destination location must be such that the entire area
- * specified as the source can be displayed without falling off the edge of the
- * screen.
- *
- * Parameters: btLeft       - Column number of the left edge of the area to
- *                            copy from.
- *
- *             btTop        - Row number of the top edge of the area to copy
- *                            from.
- *
- *             btRight      - Column number of the right edge of the area to
- *                            copy from.
- *
- *             btBottom     - Row number of the bottom edge of the area to
- *                            copy from.
- *
- *             btDestColumn - Column number where the upper right corner of
- *                            the area should be copied to.
- *
- *             btDestRow    - Row number where the upper right cornder of the
- *                            area should be copied to.
- *
- *     Return: TRUE on success, or FALSE on failure. May fail due to
- *             insufficient available memory.
- */
-BOOL ODScrnCopyText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   BYTE btDestColumn, BYTE btDestRow)
-{
-   void *pScrnBuffer;
-
-   ASSERT(btLeft >= 0 && btTop >= 0);
-   ASSERT(btLeft <= btRightBoundary - btLeftBoundary);
-   ASSERT(btTop <= btBottomBoundary - btTopBoundary);
-   ASSERT(btRight >= 0 && btBottom >= 0);
-   ASSERT(btRight <= btRightBoundary - btLeftBoundary);
-   ASSERT(btBottom <= btBottomBoundary - btTopBoundary);
-   ASSERT(btDestColumn >= 0 && btDestRow >= 0);
-   ASSERT(btDestColumn <= btRightBoundary - btLeftBoundary);
-   ASSERT(btDestRow <= btBottomBoundary - btTopBoundary);
-
-   if(   !(btLeft <= btRightBoundary - btLeftBoundary
-         && btTop <= btBottomBoundary - btTopBoundary)
-      || !(btRight <= btRightBoundary - btLeftBoundary
-         && btBottom <= btBottomBoundary - btTopBoundary)
-      || !(btDestColumn <= btRightBoundary - btLeftBoundary
-         && btDestRow <= btBottomBoundary - btTopBoundary))
-   {
-      return(FALSE);
-   }
-
-
-   if((pScrnBuffer = malloc((btRight - btLeft + 1) * (btBottom - btTop + 1)
-      * BYTES_PER_CHAR)) == NULL)
-   {
-      /* Insufficient memory, return with failure. */
-      return (FALSE);
-   }
-
-   ODScrnGetText(btLeft, btTop, btRight, btBottom, pScrnBuffer);
-   ODScrnPutText(btDestColumn, btDestRow,
-      (BYTE)(btRight + (btDestColumn - btLeft)),
-      (BYTE)(btBottom + (btDestRow - btTop)), pScrnBuffer);
-   free(pScrnBuffer);
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnClearToEndOfLine()
- *
- * Clears the contents of the current line, from the current cursor location
- * to the end of the line.
- *
- * Parameters: none
- *
- *     Return: void
- */
-void ODScrnClearToEndOfLine(void)
-{
-   unsigned char btCharsToDelete = btRightBoundary
-      - (btLeftBoundary + btCursorColumn);
-   BYTE ODFAR *pDest = (BYTE ODFAR *) pScrnBuffer
-      + (((btTopBoundary + btCursorRow) * BUFFER_LINE_BYTES)
-      + (btLeftBoundary + btCursorColumn) * BYTES_PER_CHAR);
-   BYTE btAttribute = btCurrentAttribute;
-
-   while(btCharsToDelete--)
-   {
-      *(pDest++) = ' ';
-      *(pDest++) = btAttribute;
-   }
-
-#ifdef ODPLAT_WIN32
-   /* Force the updated area of the screen window to be redrawn. */
-   ODScrnInvalidate((BYTE)(btLeftBoundary + btCursorColumn),
-      (BYTE)(btTopBoundary + btCursorRow), btRightBoundary,
-      (BYTE)(btTopBoundary + btCursorRow));
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnCreateWindow()
- *
- * Creates a text-based window on the local terminal.
- *
- * Parameters: btLeft           - Column numebr of the left of the window.
- *
- *             btTop            - Row number of the top of the window.
- *
- *             btRight          - Column number of the right of the window.
- *
- *             btBottom         - Row number of the bottom of the window.
- *
- *             btAttribute      - Display attribute for the window boarder and
- *                                the area inside the window.
- *
- *             pszTitle         - Pointer to a string containing the title to
- *                                display, or "" for none.
- *
- *             btTitleAttribute - Display attribute for the title text.
- *
- *     Return: void
- */
-#ifdef OD_TEXTMODE
-void *ODScrnCreateWindow(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom, BYTE btAttribute, char *pszTitle, BYTE btTitleAttribute)
-{
-   void *pUnder;
-   INT nBetween;
-   INT nCount;
-   INT nFirst;
-   char *pszString;
-   int nTitleWidth;
-
-   ASSERT(pszTitle != NULL);
-
-   /* Alocate space to store screen contents "under" window. */
-   if((pUnder = malloc((btRight - btLeft + 1) * (btBottom - btTop + 1)
-      * BYTES_PER_CHAR + 4 * sizeof(BYTE))) == NULL)
-   {
-      return(NULL);
-   }
-
-   /* Store the window's position in the buffer. */
-   ((BYTE *)pUnder)[0] = btLeft;
-   ((BYTE *)pUnder)[1] = btTop;
-   ((BYTE *)pUnder)[2] = btRight;
-   ((BYTE *)pUnder)[3] = btBottom;
-
-   /* Retrieve screen contents in window area. */
-   ODScrnGetText(btLeft, btTop, btRight, btBottom, ((BYTE *)pUnder) + 4);
-
-   /* Determine area between left & right of window, distance of line before */
-   /* title, and distance of line after title.                               */
-   if(strlen(pszTitle) == 0)
-   {
-      nTitleWidth = 0;
-   }
-   else
-   {
-      nTitleWidth = strlen(pszTitle) + 2;
-   }
-   nCount = (nBetween = btRight - btLeft - 1) - nTitleWidth;
-   nCount -= (nFirst = nCount / 2);
-
-   /* Prepare to begin drawing window at upper left corner */
-   ODScrnSetCursorPos(btLeft, btTop);
-   ODScrnSetAttribute(btAttribute);
-
-   /* Draw first line of window */
-   ODScrnDisplayChar((unsigned char)214);
-   while(nFirst--) ODScrnDisplayChar((unsigned char)196);
-   if(strlen(pszTitle) != 0)
-   {
-      ODScrnSetAttribute(btTitleAttribute);
-      ODScrnDisplayChar(' ');
-      ODScrnDisplayString(pszTitle);
-      ODScrnDisplayChar(' ');
-      ODScrnSetAttribute(btAttribute);
-   }
-   while(nCount--) ODScrnDisplayChar((unsigned char)196);
-   ODScrnDisplayChar((unsigned char)183);
-
-   /* Build string for working lines */
-   pszString = szBuffer;
-   *pszString++ = (unsigned char)186;
-   nCount = nBetween;
-   while(nCount--) *pszString++ = ' ';
-   *pszString++ = (unsigned char)186;
-   *pszString++ = '\0';
-
-   /* Draw working lines of window */
-   for(nCount = btTop + 1; nCount < btBottom; ++nCount)
-   {
-      ODScrnSetCursorPos(btLeft, (BYTE)nCount);
-      ODScrnDisplayString(szBuffer);
-   }
-
-   /* Draw last line of window */
-   ODScrnSetCursorPos(btLeft, btBottom);
-   ODScrnDisplayChar((unsigned char)211);
-   while(nBetween--) ODScrnDisplayChar((unsigned char)196);
-   ODScrnDisplayChar((unsigned char)189);
-
-   /* return pointer to buffer */
-   return(pUnder);
-}
-#endif /* OD_TEXTMODE */
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnDestroyWindow()
- *
- * Removes a text-based window that was created by ODScrnCreateWindow().
- *
- * Parameters: pWindow   - Pointer to the buffer returned by the corresponding
- *                         call to ODScrnCreateWindow().
- *
- *     Return: void
- */
-#ifdef OD_TEXTMODE
-void ODScrnDestroyWindow(void *pWindow)
-{
-   BYTE btLeft;
-   BYTE btTop;
-   BYTE btRight;
-   BYTE btBottom;
-   BYTE *pabtWindow = (BYTE *)pWindow;
-
-   ASSERT(pWindow != NULL);
-
-   /* Determine the location of the window. */
-   btLeft = pabtWindow[0];
-   btTop = pabtWindow[1];
-   btRight = pabtWindow[2];
-   btBottom = pabtWindow[3];
-
-   /* Restore original screen contents under the window. */
-   ODScrnPutText(btLeft, btTop, btRight, btBottom, ((BYTE *)pWindow) + 4);
-
-   /* Deallocate window buffer. */
-   free(pWindow);
-}
-#endif /* OD_TEXTMODE */
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnLocalInput()
- *
- * Inputs a string, only displaying input on local screen.
- *
- * Parameters: btLeft    - Column number of the left end of the input
- *                         field.
- *
- *             btRow     - Row number where the input field appears.
- *
- *             pszString - Location where user's input should be stored. Must
- *                         be initialized.
- *
- *             nMaxChars - The maximum number of characters that may be
- *                         accepted for input into the string.
- *
- *     Return: void
- */
-#ifdef OD_TEXTMODE
-void ODScrnLocalInput(BYTE btLeft, BYTE btRow, char *pszString,
-   BYTE btMaxChars)
-{
-   BYTE btCount;
-   BYTE btCurrentPos;
-   BOOL bAnyKeysPressed = FALSE;
-   tODInputEvent InputEvent;
-
-   /* Draw initial input field. */
-   ODScrnSetCursorPos(btLeft, btRow);
-   ODScrnDisplayString(pszString);
-   for(btCount = strlen(pszString); btCount <= btMaxChars; ++btCount)
-   {
-      ODScrnDisplayChar(177);
-   }
-
-   /* Start with the cursor at the end of the input field. */
-   btCurrentPos = strlen(pszString);
-
-   /* Loop until the user presses enter. */
-   for(;;)
-   {
-      /* Position the cursor at the appropriate location. */
-      ODScrnSetCursorPos((BYTE)(btLeft + btCurrentPos), btRow);
-
-      /* Obtain the next input event. */
-      ODInQueueGetNextEvent(hODInputQueue, &InputEvent, OD_NO_TIMEOUT);
-
-      switch(InputEvent.chKeyPress)
-      {
-         case '\b':
-            /* If user presses [Backspace], then move back if we are not at */
-            /* the left of the input field.                                 */
-            if(btCurrentPos > 0)
-            {
-               /* Backspace, removing last character from string. */
-               btCurrentPos--;
-               ODScrnSetCursorPos((BYTE)(btLeft + btCurrentPos), btRow);
-               ODScrnDisplayChar(177);
-               pszString[btCurrentPos] = '\0';
-            }
-            break;
-
-         case '\n':
-         case '\r':
-            /* If user presses [Enter], then exit from the function. */
-            return;
-
-         case '\0':
-            /* In the case of a multi-character sequence, skip the next */
-            /* character from the input queue.                          */
-            ODInQueueGetNextEvent(hODInputQueue, &InputEvent, OD_NO_TIMEOUT);
-            break;
-
-         default:
-            /* If this is a valid string character for the string. */
-            if(InputEvent.chKeyPress >= ' ')
-            {
-               /* If no keys have been pressed yet, then erase the entire */
-               /* string first.                                           */
-               if(!bAnyKeysPressed)
-               {
-                  btCurrentPos = 0;
-                  ODScrnSetCursorPos(btLeft, btRow);
-                  for(btCount = 0; btCount <= btMaxChars; ++btCount)
-                  {
-                     ODScrnDisplayChar(177);
-                  }
-                  ODScrnSetCursorPos(btLeft, btRow);
-               }
-
-               /* If we are not at the end of the string, then add the */
-               /* character to the string.                             */
-               if(btCurrentPos < btMaxChars)
-               {
-                  /* Display the new character. */
-                  ODScrnDisplayChar(InputEvent.chKeyPress);
-
-                  /* Add the character to the string. */
-                  pszString[btCurrentPos] = InputEvent.chKeyPress;
-
-                  /* Update the current cursor position. */
-                  ++btCurrentPos;
-
-                  /* Terminate the string. */
-                  pszString[btCurrentPos] = '\0';
-               }
-            }
-      }
-
-      /* Note that a key has now been pressed. */
-      bAnyKeysPressed = TRUE;
-   }
-}
-#endif /* OD_TEXTMODE */
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnShowMessage()
- *
- * Displays a message window with the specified message text. Unlike the
- * Windows MessageBox() function, this message box is removed by the caller
- * of the function rather than the user.
- *
- * Parameters: pszText - Pointer to message text to be displayed. This string
- *                       must continue to exist until after the
- *                       ODScrnRemoveMessage() function is called.
- *
- *             nFlags  - Currently unused, must be 0.
- *
- *     Return: A pointer which must be passed to ODScrnRemoveMessage() in
- *             order to remove this message from the screen. A return value
- *             of NULL does not necessarily indicate window creation failure,
- *             and should still be passed to a corresponding call to
- *             ODScrnRemoveMessage().
- */
-void *ODScrnShowMessage(char *pszText, int nFlags)
-{
-   ASSERT(pszText != NULL);
-   ASSERT(nFlags == 0);
-
-   /* In silent mode, this function does nothing. */
-   if(od_control.od_silent_mode) return(NULL);
-
-#ifdef ODPLAT_WIN32
-
-   /* Place a message in the frame window's message queue, asking it to  */
-   /* create the message window.                                         */
-   PostMessage(GetParent(hwndScreenWindow), WM_SHOW_MESSAGE, (WPARAM)nFlags,
-      (LPARAM)pszText);
-
-   return(NULL);
-
-#else /* !ODPLAT_WIN32 */
-   {
-      int nWindowWidth;
-      int nLeftColumn;
-      char szMessage[74];
-      void *pWindow;
-
-      UNUSED(nFlags);
-
-      ODStringCopy(szMessage, pszText, sizeof(szMessage));
-
-      ODStoreTextInfo();
-
-      nWindowWidth = strlen(szMessage) + 4;
-      nLeftColumn = 40 - (nWindowWidth / 2);
-      if((pWindow = ODScrnCreateWindow((BYTE)nLeftColumn, 10,
-         (BYTE)(nLeftColumn + (nWindowWidth - 1)), 14,
-         od_control.od_local_win_col, "", od_control.od_local_win_col))
-         == NULL)
-      {
-         return(NULL);
-      }
-
-      ODScrnSetCursorPos((BYTE)(42 - (nWindowWidth / 2)), 12);
-      ODScrnDisplayString(szMessage);
-      ODRestoreTextInfo();
-
-      ODScrnEnableCaret(FALSE);
-
-      return(pWindow);
-   }
-#endif /* !ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODScrnRemoveMessage()
- *
- * Removes a message that was shown by a previous call to ODScrnShowMessage().
- *
- * Parameters: pMessageInfo - Pointer to the buffer returned by the
- *                            corresponding call to ODScrnShowMessage().
- *
- *     Return: void
- */
-void ODScrnRemoveMessage(void *pMessageInfo)
-{
-   /* In silent mode, this function does nothing. */
-   if(od_control.od_silent_mode) return;
-
-#ifdef ODPLAT_WIN32
-   /* Place a message in the frame window's message queue, asking it to  */
-   /* remove the message window.                                         */
-   SendMessage(GetParent(hwndScreenWindow), WM_REMOVE_MESSAGE, 0, 0L);
-#else /* !ODPLAT_WIN32 */
-   /* If pMessageInfo is NULL, then we do nothing. */
-   if(pMessageInfo == NULL) return;
-
-   ODStoreTextInfo();
-   ODScrnDestroyWindow(pMessageInfo);
-   ODRestoreTextInfo();
-   ODScrnEnableCaret(TRUE);
-#endif /* !ODPLAT_WIN32 */
-}
diff --git a/src/odoors/ODScrn.h b/src/odoors/ODScrn.h
deleted file mode 100644
index 28c507e699f7b6b7e93c53037e199094621d8f1b..0000000000000000000000000000000000000000
--- a/src/odoors/ODScrn.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODScrn.h
- *
- * Description: Functions used to access the local display screen buffer, which
- *              keeps a copy of the text that is displayed on the remote
- *              terminal. The local display screen buffer also displays the
- *              OpenDoors status lines on some platforms. In addition to
- *              maintaining the current screen buffer, the odscrn.c module
- *              also contains the code to display this buffer on the screen.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 14, 1995  6.00  BP   Created.
- *              Jan 21, 1996  6.00  BP   Added ODScrnShowMessage() and related.
- *              Jan 27, 1996  6.00  BP   Made text-mode window f'ns static.
- *              Jan 31, 1996  6.00  BP   Made them non-static again.
- *              Jan 31, 1996  6.00  BP   Added ODScrnLocalInput().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#ifndef _INC_ODSCRN
-#define _INC_ODSCRN
-
-#include "ODTypes.h"
-#include "ODPlat.h"
-
-/* Text information structure. */
-typedef struct
-{
-   unsigned char winleft;
-   unsigned char wintop;
-   unsigned char winright;
-   unsigned char winbottom;
-   unsigned char attribute;
-   unsigned char curx;
-   unsigned char cury;
-} tODScrnTextInfo;
-
-
-/* Screen buffer initialization and shutdown functions. */
-tODResult ODScrnInitialize(void);
-void ODScrnShutdown(void);
-
-/* Basic text output functions. */
-void ODScrnDisplayChar(unsigned char chToOutput);
-void ODScrnDisplayBuffer(char *pBuffer, INT nCharsToDisplay);
-void ODScrnDisplayString(char *pszString);
-INT ODScrnPrintf(char *pszFormat, ...);
-
-/* Functions for manipulating rectangular areas of the screen buffer. */
-BOOL ODScrnGetText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   void *pbtBuffer);
-BOOL ODScrnPutText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   void *pbtBuffer);
-BOOL ODScrnCopyText(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom,
-   BYTE btDestColumn, BYTE btDestRow);
-
-/* Functions for clearing portions of the screen buffer. */
-void ODScrnClear(void);
-void ODScrnClearToEndOfLine(void);
-
-/* Functions for setting or obtaining current display settings. */
-void ODScrnSetBoundary(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE btBottom);
-void ODScrnSetCursorPos(BYTE btColumn, BYTE btRow);
-void ODScrnSetAttribute(BYTE btAttribute);
-void ODScrnEnableScrolling(BOOL bEnable);
-void ODScrnEnableCaret(BOOL bEnable);
-void ODScrnGetTextInfo(tODScrnTextInfo *pTextInfo);
-
-/* Functions for displaying OpenDoors message window. */
-void *ODScrnShowMessage(char *pszText, int nFlags);
-void ODScrnRemoveMessage(void *pMessageInfo);
-
-/* Additional local output functions for text mode based versions. */
-#ifdef OD_TEXTMODE
-void *ODScrnCreateWindow(BYTE btLeft, BYTE btTop, BYTE btRight,
-   BYTE btBottom, BYTE btAttribute, char *pszTitle, BYTE btTitleAttribute);
-void ODScrnDestroyWindow(void *pWindow);
-void ODScrnLocalInput(BYTE btLeft, BYTE btRow, char *pszString,
-   BYTE btMaxChars);
-#endif /* OD_TEXTMODE */
-
-/* Functions for local screen window under Win32 version. */
-#ifdef ODPLAT_WIN32
-tODResult ODScrnStartWindow(HANDLE hInstance, tODThreadHandle *phScreenThread,
-   HWND hwndFrame);
-void ODScrnSetFocusToWindow(void);
-void ODScrnAdjustWindows(void);
-#endif /* ODPLAT_WIN32 */
-
-#endif /* _INC_ODSCRN */
diff --git a/src/odoors/ODSpawn.c b/src/odoors/ODSpawn.c
deleted file mode 100644
index a82c4997d2cb27a338a876c4ba567a1d4e88f716..0000000000000000000000000000000000000000
--- a/src/odoors/ODSpawn.c
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODSpawn.c
- *
- * Description: Implements the od_spawn...() functions for suspending this
- *              program and executing a sub-program. Can be called by the
- *              user explicitly, or invoked for sysop OS shell.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Oct 21, 1994  6.00  BP   Further isolated com routines.
- *              Dec 09, 1994  6.00  BP   Use new directory access functions.
- *              Dec 13, 1994  6.00  BP   Standardized coding style.
- *              Dec 31, 1994  6.00  BP   Remove #ifndef USEINLINE DOS code.
- *              Jan 01, 1995  6.00  BP   _waitdrain -> ODWaitDrain()
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 11, 1995  6.00  BP   Removed register keyword.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Nov 17, 1995  6.00  BP   Use new input queue mechanism.
- *              Nov 21, 1995  6.00  BP   Ported to Win32.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 23, 1996  6.00  BP   Finished port to Win32.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 23, 1996  6.00  BP   Enable and test under Win32.
- *              Feb 27, 1996  6.00  BP   Store screen info in our own struct.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <time.h>
-#include <errno.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODCom.h"
-#include "ODPlat.h"
-#include "ODScrn.h"
-#include "ODInQue.h"
-#include "ODInEx.h"
-#include "ODUtil.h"
-#include "ODKrnl.h"
-#include "ODSwap.h"
-
-#ifdef ODPLAT_WIN32
-#include "ODFrame.h"
-#endif /* ODPLAT_WIN32 */
-
-#if defined(ODPLAT_WIN32) && defined(_MSC_VER)
-#undef P_WAIT
-#undef P_NOWAIT
-#include <process.h>
-#endif /* ODPLAT_WIN32 && _MSC_VER */
-
-#ifdef ODPLAT_DOS
-
-/* Local and global variables for memory swapping spawn routines. */
-
-int _swap = 0;                     /* if 0, do swap */
-char *_swappath = NULL;            /* swap path */
-int _useems = 0;                   /* if 0, use EMS */
-int _required = 0;                 /* child memory requirement in K */
-static long swapsize;              /* swap size requirement in bytes */
-static int ems = 2;                /* if 0, EMS is available */
-static int mapsize;                /* size of page map information */
-static unsigned int tempno = 1;    /* tempfile number */
-static char errtab[] =             /* error table */
-{
-   0,
-   EINVAL,
-   ENOENT,
-   ENOENT,
-   EMFILE,
-   EACCES,
-   EBADF,
-   ENOMEM,
-   ENOMEM,
-   ENOMEM,
-   E2BIG,
-   ENOEXEC,
-   EINVAL,
-   EINVAL,
-   -1,
-   EXDEV,
-   EACCES,
-   EXDEV,
-   ENOENT,
-   -1
-};
-
-static VECTOR vectab1[]=
-{
-    0,    1,     0,  0,
-    1,    1,     0,  0,
-    2,    1,     0,  0,
-    3,    1,     0,  0,
-    0x1B, 1,     0,  0,
-    0x23, 1,     0,  0,
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    2,     0,  0,            /* free record */
-    0,    3,     0,  0          /* end record */
-};
-
-static VECTOR vectab2[(sizeof vectab1)/(sizeof vectab1[0])];
-
-/* Location function prototypes. */
-int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
-   char *papszEnviron[]);
-int _spawnve(int nModeFlag, char *pszPath, char *papszArgs[],
-   char * papszEnviron[]);
-static void savevect(void);
-
-
-#endif /* ODPLAT_DOS */
-
-
-/* ----------------------------------------------------------------------------
- * od_spawn()
- *
- * Executes the specified command line, suspending OpenDoors operations while
- * the spawned-to program is running.
- *
- * Parameters: pszCommandLine - Command to execute along with any parameters.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_spawn(char *pszCommandLine)
-{
-#ifdef ODPLAT_DOS
-   char *apszArgs[4];
-   INT16 nReturnCode;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_spawn()");
-
-   *apszArgs=getenv("COMSPEC");
-
-   apszArgs[1] = "/c";
-   apszArgs[2] = pszCommandLine;
-   apszArgs[3] = NULL;
-   
-   if(*apszArgs != NULL)
-   {
-      if((nReturnCode = od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL)) != -1
-         || errno != ENOENT)
-      {
-         return(nReturnCode != -1);
-      }
-   }
-
-   *apszArgs = "command.com";
-
-   return(od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL) != -1);
-#endif /* ODPLAT_DOS */
-
-#ifdef ODPLAT_WIN32
-   char *pch;
-   char *apszArgs[3];
-   char szProgName[80];
-
-   /* Build command and arguments list. */
-   /* Build program name. */
-   ODStringCopy(szProgName, pszCommandLine, sizeof(szProgName));
-   pch = strchr(szProgName, ' ');
-   if(pch != NULL) *pch = '\0';
-   apszArgs[0] = szProgName;
-
-   /* Build arguments. */
-   pch = strchr(pszCommandLine, ' ');
-   if(pch == NULL)
-   {
-      apszArgs[1] = NULL;
-   }
-   else
-   {
-      apszArgs[1] = pch + 1;
-      apszArgs[2] = NULL;
-   }
-
-   /* Now, call od_spawnvpe(). */
-   return(od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL) != -1);
-#endif /* ODPLAT_WIN32 */
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_spawnvpe()
- *
- * Executes the specified program, using the specified arguments and
- * environment variables, optionally suspending OpenDoors operations while
- * the spawned-to program is running.
- *
- * Parameters: nModeFlag - P_WAIT to for OpenDoors operations to be suspended
- *                         while the spawned-to program is running, or
- *                         P_NOWAIT if the calling program should continue to
- *                         run while the spawned-to program is running. In
- *                         non-multitasking environments, the only valid value
- *                         of this parameters is P_WAIT.
- *
- *             pszPath   - Complete path and filename of the program to
- *                         exectute.
- *
- *             papszArg  - Array of string pointers to command line arguments.
- *
- *             papszEnv  - Array of string pointers to environment variables.
- *
- *     Return: -1 on failure or the spawned-to program's return value on
- *             success.
- */
-ODAPIDEF INT16 ODCALL od_spawnvpe(INT16 nModeFlag, char *pszPath,
-   char *papszArg[], char *papszEnv[])
-{
-   INT16 nToReturn;
-   time_t nStartUnixTime;
-   DWORD dwQuotient;
-#ifdef ODPLAT_WIN32
-   void *pWindow;
-#endif /* ODPLAT_WIN32 */   
-#ifdef ODPLAT_DOS
-   char *pszDir;
-   BYTE *abtScreenBuffer;
-   INT nDrive;
-   tODScrnTextInfo TextInfo;
-#endif /* ODPLAT_DOS */
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_spawnvpe()");
-
-   /* Initialize OpenDoors if it hasn't already been done. */
-   if(!bODInitialized) od_init();
-
-#ifdef ODPLAT_DOS
-   /* Ensure the nModeFlag is P_WAIT, which is the only valid value for */
-   /* the MS-DOS version of OpenDoors.                                  */
-   if(nModeFlag != P_WAIT)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      return(-1);
-   }
-
-   /* Store current screen contents. */
-   if((abtScreenBuffer = malloc(4000)) == NULL)
-   {
-      od_control.od_error = ERR_MEMORY;
-      return(-1);
-   }
-   if((pszDir = malloc(256)) == NULL)
-   {
-      od_control.od_error = ERR_MEMORY;
-      free(abtScreenBuffer);
-      return(-1);
-   }
-
-   /* Store current display settings. */
-   ODScrnGetTextInfo(&TextInfo);
-
-   /* Set current output area to the full screen. */
-   ODScrnSetBoundary(1,1,80,25);
-
-   /* Store contents of entire screen. */   
-   ODScrnGetText(1, 1, 80, 25, (char *)abtScreenBuffer);
-
-   /* Set the current display colour to grey on black. */
-   ODScrnSetAttribute(0x07);
-
-   /* Clear the screen if required. Otherwise, move the cursor to the */
-   /* upper left corner of the screen.                                */
-   if(od_control.od_clear_on_exit)
-   {
-      ODScrnClear();
-   }
-   else
-   {
-      ODScrnSetCursorPos(1, 1);
-   }
-
-   /* Store current directory. */
-   strcpy(pszDir, "X:\\");
-   pszDir[0] = 'A' + (nDrive = _getdrv());
-   _getcd(0, (char *)pszDir + 3);
-#endif /* ODPLAT_DOS */
-
-   /* Remember when spawned to program was executed. */
-   nStartUnixTime = time(NULL);
-
-   if(nModeFlag == P_WAIT)
-   {
-      /* Display the spawn message box under Win32. */
-#ifdef ODPLAT_WIN32
-      pWindow = ODScrnShowMessage("Running sub-program...", 0);
-#endif /* ODPLAT_WIN32 */
-
-      /* Wait for up to ten seconds for outbound buffer to drain. */
-      ODWaitDrain(10000);
-
-#ifdef OD_MULTITHREADED
-      /* Mutlithreaded versions of OpenDoors must shutdown the kernel */
-      /* before closing the serial port.                              */
-      ODKrnlShutdown();
-#endif /* OD_MULTITHREADED */
-
-      /* Close serial port. */
-      if(od_control.baud != 0)
-      {
-#ifdef ODPLAT_WIN32
-         /* Disable DTR response by the modem before closing the serial */
-         /* port, if this is required.                                  */
-         ODInExDisableDTR();
-#endif /* ODPLAT_WIN32 */         
-         ODComClose(hSerialPort);
-      }
-   }
-
-   /* Execute specified program with the specified arguments. */
-   nToReturn = _spawnvpe(nModeFlag, pszPath, papszArg, papszEnv);
-
-   if(nModeFlag == P_WAIT)
-   {
-      /* Re-open serial port. */
-      if(od_control.baud != 0)
-      {
-         ODComOpen(hSerialPort);
-      }
-
-#ifdef OD_MULTITHREADED
-      /* Mutlithreaded versions of OpenDoors must shutdown the kernel    */
-      /* before closing the serial port, so reinitialize the kernel now. */
-      ODKrnlInitialize();
-#endif /* OD_MULTITHREADED */
-
-      if(!(bIsShell || od_control.od_spawn_freeze_time))
-      {
-        ODDWordDivide(&dwQuotient, NULL, time(NULL) - nStartUnixTime, 60L);
-        od_control.user_timelimit -= (int)dwQuotient;
-      }
-      else
-      {
-        nNextTimeDeductTime += time(NULL) - nStartUnixTime;
-      }
-
-      /* Reset the time of the last input activity to the current time. */
-      /* This will prevent an immediate inactity timeout, regardless of */
-      /* how long the spawned-to program was active.                    */
-      ODInQueueResetLastActivity(hODInputQueue);
-
-      /* Clear inbound buffer. */
-      od_clear_keybuffer();
-
-      /* Remove the spawn message box under Win32. */
-#ifdef ODPLAT_WIN32
-      ODScrnRemoveMessage(pWindow);
-#endif /* ODPLAT_WIN32 */
-   }
-
-#ifdef ODPLAT_DOS
-   /* Redisplay the door screen. */
-   ODScrnPutText(1, 1, 80, 25, (char *)abtScreenBuffer);
-
-   /* Restore cursor to old position. */
-   ODScrnSetBoundary(TextInfo.winleft, TextInfo.wintop,
-      TextInfo.winright, TextInfo.winbottom);
-   ODScrnSetAttribute(TextInfo.attribute);
-   ODScrnSetCursorPos(TextInfo.curx, TextInfo.cury);
-
-   _setdrvcd(nDrive, pszDir);
-
-   /* Free allocated space. */
-   free(abtScreenBuffer);
-   free(pszDir);
-#endif /* ODPLAT_DOS */
-
-   /* Return appropriate value. */
-   return(nToReturn);
-}
-
-
-#ifdef ODPLAT_DOS
-
-/* ----------------------------------------------------------------------------
- * _spawnvpe()                                         *** PRIVATE FUNCTION ***
- *
- * Executes a child program in the MS-DOS environment, swapping the calling
- * program out of memory if enabled.
- *
- * Parameters: nModeFlag    - Must be P_WAIT.
- *
- *             pszPath      - Name of program to execute.
- *
- *             papszArgs    - Array of command-line arguments.
- *
- *             papszEnviron - Array of environment variables.
- *
- *     Return: -1 on failure or the spawned-to program's return value on
- *             success.
- */
-int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
-   char *papszEnviron[])
-{
-   char *e;
-   char *p;
-   char buf[80];
-   int nReturnCode;
-
-
-   _swappath = (char *)(strlen(od_control.od_swapping_path) == 0 ? NULL 
-      : (char *)od_control.od_swapping_path);
-   _useems = od_control.od_swapping_noems;
-   _swap = od_control.od_swapping_disable;
-
-   if((nReturnCode=_spawnve(nModeFlag, pszPath, papszArgs, papszEnviron))!=-1
-       || errno!=ENOENT || *pszPath=='\\' || *pszPath=='/'
-       || *pszPath && *(pszPath+1)==':' || (e=getenv("PATH"))==NULL)
-   {
-      return(nReturnCode);
-   }
-
-   for (;;e++)
-   {
-      if((p=strchr(e,';'))!=NULL)
-      {
-     if(p-e > 66)
-         {
-        e=p;
-        continue;
-         }
-      }
-      else if(strlen(e)>66)
-      {
-     return( -1 );
-      }
-
-      p=buf;
-
-      while(*e && *e!=';') *p++=*e++;
-
-      if(p>buf)
-      {
-     if(*(p-1)!='\\' && *(p-1)!='/') *p++ = '\\';
-     strcpy(p,pszPath);
-
-     if((nReturnCode=_spawnve(nModeFlag,buf,papszArgs,papszEnviron))!=-1 || errno!=ENOENT)
-         {
-        return(nReturnCode);
-         }
-      }
-      if(*e=='\0') return(-1);
-   }
-}
-
-
-/* ----------------------------------------------------------------------------
- * addvect()                                           *** PRIVATE FUNCTION ***
- *
- * Adds a vector to the vector table.
- *
- * Parameters: number - The vector number.
- *
- *             opcode - Vector flags.
- *
- *     Return: -1 on failure, or 0 on success.
- */
-int addvect(int number, int opcode)
-{
-    VECTOR *vect = vectab1;
-
-    if ( number < 0 || number > 0xFF ||
-    ( opcode != IRET && opcode != CURRENT ))
-    {
-    errno = EINVAL;
-    return( -1 );
-    }
-
-    /* see if number is already in table */
-    while ( vect->flag != 3 && ( vect->flag == 2 ||
-    vect->number != ( char )number ))
-    {
-    vect++;
-    }
-
-    if ( vect->flag == 3 )
-    {
-    /* look for a free record */
-    vect = vectab1;
-    while ( vect->flag == CURRENT || vect->flag == IRET )
-        vect++;
-    }
-
-    if ( vect->flag != 3 )
-    {
-    vect->number = ( char )number;
-    vect->flag = ( char )opcode;
-    if ( opcode == CURRENT )
-    _getvect( number, &vect->vseg, &vect->voff );
-    return( 0 );
-    }
-
-    errno = ENOMEM;
-    return( -1 );
-}
-
-
-/* ----------------------------------------------------------------------------
- * savevect()                                          *** PRIVATE FUNCTION ***
- *
- * Saves current vector in vector table.
- *
- * Parameters: none
- *
- *     Return: void
- */
-static void savevect(void)
-{
-    VECTOR *vect1 = vectab1;
-    VECTOR *vect2 = vectab2;
-
-    while ( vect1->flag != 3 )
-    {
-    if ( vect1->flag != 2 )
-    {
-        vect2->number = vect1->number;
-        vect2->flag = CURRENT;
-        _getvect( vect1->number, &vect2->vseg, &vect2->voff );
-    }
-    else
-        vect2->flag = 2;           /* free */
-    vect1++;
-    vect2++;
-    }
-    vect2->flag = 3;               /* end */
-}
-
-
-/* ----------------------------------------------------------------------------
- * testfile()                                          *** PRIVATE FUNCTION ***
- *
- * Tests swap file.
- *
- * Parameters: p      - Path.
- *
- *             file   - File name.
- *
- *             handle - File handle.
- *
- *     Return: 1 on failure.
- */
-static int testfile(char *p, char *file, int *handle)
-{
-    unsigned int startno = tempno;
-    int nDrive = ( *file | 32 ) - 96;   /* a = 1, b = 2, etc. */
-    int root;
-    unsigned int bytes;            /* bytes per cluster */
-    unsigned int clusters;         /* free clusters */
-    int need;                  /* clusters needed for swap file */
-    int nReturnCode;                /* return code */
-    unsigned long dwQuotient;
-    unsigned long remainder;
-
-    if ( file + 2 == p )
-    {
-    *p++ = '\\';
-    if ( _getcd( nDrive, p ))       /* get current directory */
-        return( 1 );           /* invalid drive */
-    p = file + strlen( file );
-    }
-    else
-    {
-    *p = '\0';
-    if ( ODFileAccessMode( file, 0 ))
-        return( 1 );           /* path does not exist */
-    }
-    if ( *( p - 1 ) != '\\' && *( p - 1 ) != '/' )
-    *p++ = '\\';
-    if ( p - file == 3 )
-    root = 1;              /* is root directory */
-    else
-    root = 0;              /* is not root directory */
-    strcpy( p, "swp" );
-    p += 3;
-
-    if ( _dskspace( nDrive, &bytes, &clusters ) != 0 )
-    return( 1 );               /* invalid drive */
-
-
-
-    ODDWordDivide(&dwQuotient, &remainder, swapsize, bytes);
-    need = (int)dwQuotient;
-
-    if ( remainder )
-    need++;
-    if ( root == 0 )               /* if subdirectory */
-    need++;                /* in case the directory needs space */
-    if ( clusters < ( unsigned int )need )
-    return( 1 );               /* insufficient free disk space */
-
-    do
-    {
-again:  tempno = ( ++tempno ) ? tempno : 1;
-    if ( tempno == startno )
-        return( 1 );           /* extremely unlikely */
-    ltoa(( long )tempno, p, 10 );
-    }
-    while ( !ODFileAccessMode( file, 0 ));
-
-/*
- *  The return code from _create will equal 80 if the user is running DOS 3.0
- *  or above and the file was created by another program between the access
- *  call and the _create call.
- */
-
-    if (( nReturnCode = _create( file, handle )) == 80 )
-    goto again;
-    return( nReturnCode );
-}
-
-
-/* ----------------------------------------------------------------------------
- * tempfile()                                          *** PRIVATE FUNCTION ***
- *
- * Creates a temporary swap file.
- *
- * Parameters: file   - Filename
- *
- *             handle - Handle to file.
- *
- *     Return: 0 on success, or 1 on failure.
- */
-static int tempfile(char *file, int *handle)
-{
-    char *s = _swappath;
-    char *p = file;
-
-    if ( s )
-    {
-    for ( ;; s++ )
-    {
-        while ( *s && *s != ';' )
-        *p++ = *s++;
-        if ( p > file )
-        {
-        if ( p == file + 1 || file[ 1 ] != ':' )
-        {
-            memmove( file + 2, file, ( int )( p - file ));
-            *file = ( char )( _getdrv() + 'a' );
-            file[ 1 ] = ':';
-            p += 2;
-        }
-        if ( testfile( p, file, handle ) == 0 )
-            return( 0 );
-        p = file;
-        }
-        if ( *s == '\0' )
-        break;
-    }
-    }
-    else                   /* try the current directory */
-    {
-    *p++ = ( char )( _getdrv() + 'a' );
-    *p++ = ':';
-    if ( testfile( p, file, handle ) == 0 )
-        return( 0 );
-    }
-
-    errno = EACCES;
-    return( 1 );
-}
-
-
-/* ----------------------------------------------------------------------------
- * cmdenv()                                            *** PRIVATE FUNCTION ***
- *
- * Constructs environment.
- *
- * Parameters: papszArgs     - Array of arguments.
- *
- *             papszEnviron  - Array of environment variables to add.
- *
- *             command       - The command specified.
- *
- *             env           - Pointer to environment.
- *
- *             memory        - Allocated memory.
- *
- *     Return: Environment length.
- */
-static int cmdenv(char **papszArgs, char **papszEnviron, char *command,
-   char **env, char **memory)
-{
-    char **vp;
-    unsigned int elen = 0;         /* environment length */
-    char *p;
-    int cnt;
-    int len;
-
-    /* construct environment */
-
-    if ( papszEnviron == NULL )
-    {
-       char far *parent_env;
-       char far *env_ptr;
-       int nul_count;
-
-       ASM mov ah, 0x62
-       ASM int 0x21
-       ASM push es
-       ASM mov es, bx
-       ASM mov ax, es:[0x2c]
-       ASM pop es
-       ASM mov word ptr parent_env, 0
-       ASM mov word ptr parent_env + 2, ax
-
-       env_ptr = parent_env;
-       nul_count = 0;
-       while(nul_count < 2)
-       {
-      if(*env_ptr)
-      {
-         nul_count = 0;
-      }
-      else
-      {
-         ++nul_count;
-      }
-
-      ++env_ptr;
-      ++elen;
-       }
-
-       if ( elen > 32766 )    /* 32K - 2 */
-       {
-      errno = E2BIG;
-      return( -1 );
-       }
-
-       if (( p = malloc(elen + 15 )) == NULL )
-       {
-       errno = ENOMEM;
-       return( -1 );
-       }
-       *memory = p;
-
-       *( unsigned int * )&p = *( unsigned int * )&p + 15 & ~15;
-       *env = p;
-
-       len = elen;
-       while(len--)
-       {
-      *p++ = *parent_env++;
-       }
-    }
-    else
-    {
-       for ( vp = papszEnviron; *vp; vp++ )
-       {
-       elen += strlen( *vp ) + 1;
-       if ( elen > 32766 )        /* 32K - 2 */
-       {
-           errno = E2BIG;
-           return( -1 );
-       }
-       }
-
-       if (( p = malloc( ++elen + 15 )) == NULL )
-       {
-       errno = ENOMEM;
-       return( -1 );
-       }
-       *memory = p;
-
-       *( unsigned int * )&p = *( unsigned int * )&p + 15 & ~15;
-       *env = p;
-
-       for ( vp = papszEnviron; *vp; vp++ )
-       p = strchr( strcpy( p, *vp ), '\0' ) + 1;
-
-       *p = '\0';                         /* final element */
-    }
-
-
-    /* construct command-line */
-
-    vp = papszArgs;
-    p = command + 1;
-    cnt = 0;
-
-    if (vp!=NULL &&  *vp )
-    {
-    while ( *++vp )
-    {
-        *p++ = ' ';
-        cnt++;
-        len = strlen( *vp );
-        if ( cnt + len > 125 )
-        {
-        errno = E2BIG;
-        free( *memory );
-        return( -1 );
-        }
-        strcpy( p, *vp );
-        p += len;
-        cnt += len;
-    }
-    }
-
-    *p = '\r';
-    *command = ( char )cnt;
-
-    return(( int )elen );          /* return environment length */
-}
-
-
-/* ----------------------------------------------------------------------------
- * doxspawn()                                          *** PRIVATE FUNCTION ***
- *
- * Performs spawn using memory swapping.
- *
- * Parameters: pszPath      - Path to command to exectute.
- *
- *             papszArg     - Array of arugments.
- *
- *             papszEnviron - Pointer to the environment.
- *
- *     Return: 0 on success, or -1 on failure.
- */
-static int doxspawn(char *pszPath, char *papszArgs[], char *papszEnviron[])
-{
-    int nReturnCode = 0;        /* assume do xspawn */
-    int doswap = 0;            /* assume do swap */
-    int elen;                  /* environment length */
-    char *memory;
-    char *env;                 /* environment */
-    char command[ 128 ];           /* command-line */
-    long totalsize;            /* parent and free memory in bytes */
-    int handle;
-    int pages;
-    char file[ 79 ];
-    char *mapbuf = NULL;           /* buffer for map information */
-
-    /* construct the command-line and the environment */
-    if (( elen = cmdenv( papszArgs, papszEnviron, command, &env, &memory )) == -1 )
-    return( -1 );
-
-    if ( _swap == 0 )
-    {
-    if ( _useems == 0 )
-    {
-        if ( ems == 2 )
-        ems = _chkems( "EMMXXXX0", &mapsize );
-        if ( ems == 0 && ( mapbuf = malloc( mapsize )) == NULL )
-        {
-        errno = ENOMEM;
-        free( memory );
-        return( -1 );
-        }
-    }
-    if (( nReturnCode = _xsize( _psp, &swapsize, &totalsize )) == 0 )
-    {
-        if ( _required == 0 || totalsize - swapsize - 272
-           < (long)ODDWordShiftLeft(( long )_required , 10 ))
-        {
-        if ( ems == 0 && _useems == 0 )
-        {
-            pages = ( int )ODDWordShiftRight( swapsize , 14);
-            if ((long)ODDWordShiftLeft(( long )pages , 14 ) < swapsize )
-            pages++;
-            if ( _savemap( mapbuf ) == 0 &&
-            _getems( pages, &handle ) == 0 )
-            *file = '\0';  /* use EMS */
-            else if ( tempfile( file, &handle ) != 0 )
-            nReturnCode = -1;       /* don't do xspawn */
-        }
-        else if ( tempfile( file, &handle ) != 0 )
-            nReturnCode = -1;           /* don't do xspawn */
-        }
-        else
-        doswap = 1;        /* don't do swap */
-    }
-    else
-    {
-        errno = errtab[ nReturnCode ];
-        nReturnCode = -1;               /* don't do xspawn */
-    }
-    }
-    else
-    doswap = 1;            /* don't do swap */
-
-    if ( nReturnCode == 0 )
-    {
-    savevect();            /* save current vectors */
-    nReturnCode = _xspawn( pszPath, command, env, vectab1, doswap, elen, file,
-        handle );
-    _setvect( vectab2 );           /* restore saved vectors */
-        if ( nReturnCode == 0 )
-            nReturnCode = _getrc();         /* get child return code */
-    else
-    {
-        errno = errtab[ nReturnCode ];
-        nReturnCode = -1;
-    }
-    /*
-     *  If EMS was used, restore the page-mapping state of the expanded
-     *  memory hardware.
-     */
-    if ( doswap == 0 && *file == '\0' && _restmap( mapbuf ) != 0 )
-    {
-        errno = EACCES;
-        nReturnCode = -1;
-    }
-    }
-
-    if ( mapbuf )
-    free( mapbuf );
-    free( memory );
-    return( nReturnCode );
-}
-
-
-/* ----------------------------------------------------------------------------
- * _spawnve()                                          *** PRIVATE FUNCTION ***
- *
- * Performs a spawn.
- *
- * Parameters: nModeFlag    - Must be P_WAIT
- *
- *             pszPath      - Command to execute.
- *
- *             papszArgs    - Command line arguments.
- *
- *             papszEnviron - Pointer to environment.
- *
- *     Return: void
- */
-int _spawnve(int nModeFlag, char *pszPath, char *papszArgs[],
-   char * papszEnviron[])
-{
-    char *p;
-    char *s;
-    int nReturnCode = -1;
-    char buf[ 80 ];
-
-    if ( nModeFlag != P_WAIT )
-    {
-    errno = EINVAL;
-    return( -1 );
-    }
-
-    p = strrchr( pszPath, '\\' );
-    s = strrchr( pszPath, '/' );
-    if ( p == NULL && s == NULL )
-    p = pszPath;
-    else if ( p == NULL || s > p )
-    p = s;
-
-    if ( strchr( p, '.' ))
-    {
-    if ( !ODFileAccessMode( pszPath, 0 ))
-        nReturnCode = doxspawn( pszPath, papszArgs, papszEnviron );
-    /* If file not found, access will have set errno to ENOENT. */
-    }
-    else
-    {
-    strcpy( buf, pszPath );
-    strcat( buf, ".com" );
-    if ( !ODFileAccessMode( buf, 0 ))
-        nReturnCode = doxspawn( buf, papszArgs, papszEnviron );
-    else
-    {
-        strcpy( strrchr( buf, '.' ), ".exe" );
-        if ( !ODFileAccessMode( buf, 0 ))
-        nReturnCode = doxspawn( buf, papszArgs, papszEnviron );
-        /* If file not found, access will have set errno to ENOENT. */
-    }
-    }
-
-    return( nReturnCode );
-}
-
-#endif /* ODPLAT_DOS */
diff --git a/src/odoors/ODStand.c b/src/odoors/ODStand.c
deleted file mode 100644
index b631b68ea6b1530c2ee1e639a6cf7f4f2482233f..0000000000000000000000000000000000000000
--- a/src/odoors/ODStand.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODStand.c
- *
- * Description: Implements the OpenDoors standard (default) personality.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Nov 13, 1995  6.00  BP   32-bit portability.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Dec 24, 1995  6.00  BP   Fixed black square at pos 25x80.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODInEx.h"
-
-
-/* ----------------------------------------------------------------------------
- * pdef_opendoors()
- *
- * Personality function for the OpenDoors standard status line / function key
- * personality.
- *
- * Parameters: btOperation - Indicates personality operation to be performed.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL pdef_opendoors(BYTE btOperation)
-{
-   switch(btOperation)
-   {
-      case PEROP_DISPLAY1:
-         /* Display standard status line. */
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnDisplayString(od_control.od_status_line[0]);
-         ODScrnSetCursorPos(1, 24);
-         ODScrnPrintf(od_control.od_status_line[1], od_control.user_name,
-            od_control.user_location, od_control.od_connect_speed);
-         ODScrnSetCursorPos(77, 24);
-         if(od_control.od_node < 1000)
-         {
-            ODScrnPrintf("%d]", od_control.od_node);
-         }
-         else
-         {
-            ODScrnDisplayString("?]");
-         }
-         ODScrnSetCursorPos(1,25);
-         ODScrnDisplayString(od_control.od_status_line[2]);
-
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-
-         ODScrnSetCursorPos(11,25);
-         ODScrnPrintf("%u",od_control.user_security);
-         ODScrnSetCursorPos(24,25);
-         ODScrnPrintf(od_control.od_time_left,od_control.user_timelimit);
-         if(od_control.user_ansi)
-         {
-            ODScrnSetCursorPos(40,25);
-            ODScrnDisplayString("[ANSI]");
-         }
-
-         if(od_control.user_avatar)
-         {
-            ODScrnSetCursorPos(47,25);
-            ODScrnDisplayString("[AVT]");
-         }
-
-         if(od_control.sysop_next)
-         {
-            ODScrnSetCursorPos(35,25);
-            ODScrnDisplayString(od_control.od_sysop_next);
-         }
-
-         if(od_control.user_wantchat)
-         {
-            ODScrnSetCursorPos(57,25);
-            ODScrnSetAttribute(0xf0);
-            ODScrnDisplayString(od_control.od_want_chat);
-         }
-
-         if(!od_control.od_user_keyboard_on)
-         {
-            ODScrnSetCursorPos(58,24);
-            ODScrnSetAttribute(0xf0);
-            ODScrnDisplayString(od_control.od_no_keyboard);
-         }
-         break;
-
-      case PEROP_DISPLAY8:
-         /* Display help status line. */
-         ODScrnSetAttribute(0x70);
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-         ODScrnSetCursorPos(1,24);
-         ODScrnDisplayString(od_control.od_help_text);
-         ODScrnSetCursorPos(1,25);
-         /* Display copyright inforomation. */
-         if(bUserFull)/**/
-         {
-            ODScrnDisplayString(od_control.od_help_text2);
-         }
-         else
-         {
-            ODScrnDisplayString(OD_VER_UNREG_STAT);
-         }
-         break;
-
-      case PEROP_UPDATE1:
-         /* Update primary status line. */
-         ODScrnSetAttribute(0x70);
-
-         /* Update user's time limit. */
-         ODScrnSetCursorPos(24,25);
-         ODScrnPrintf(od_control.od_time_left,od_control.user_timelimit);
-
-         /* Update "sysop next" setting. */
-         ODScrnSetCursorPos(35,25);
-         if(od_control.sysop_next)
-         {
-            ODScrnDisplayString(od_control.od_sysop_next);
-         }
-         else
-         {
-            ODScrnDisplayString("     ");
-         }
-
-         /* Update ANSI mode indicator. */
-         if(od_control.user_ansi)
-         {
-            ODScrnDisplayString("[ANSI] ");
-         }
-         else
-         {
-            ODScrnDisplayString("       ");
-         }
-
-         /* Update AVATAR mode indicator. */
-         if(od_control.user_avatar)
-         {
-            ODScrnDisplayString("[AVT] ");
-         }
-         else
-         {
-            ODScrnDisplayString("      ");
-         }
-
-         /* Update keyboard-off indicator. */
-         ODScrnSetCursorPos(58,24);
-         if(od_control.od_user_keyboard_on)
-         {
-            ODScrnDisplayString("          ");
-         }
-         else
-         {
-            ODScrnSetAttribute(0xf0);
-            ODScrnDisplayString(od_control.od_no_keyboard);
-         }
-
-         /* Update want-chat indicator. */
-         ODScrnSetCursorPos(57,25);
-         if(od_control.user_wantchat)
-         {
-            ODScrnSetAttribute(0xf0);
-            ODScrnDisplayString(od_control.od_want_chat);
-         }
-         else
-         {
-            ODScrnDisplayString("           ");
-         }
-         break;
-
-      case PEROP_INITIALIZE:
-         od_control.key_hangup=0x2300;
-         od_control.key_drop2bbs=0x2000;
-         od_control.key_dosshell=0x2400;
-         od_control.key_chat=0x2e00;
-         od_control.key_sysopnext=0x3100;
-         od_control.key_lockout=0x2600;
-         od_control.key_status[0]=0x3b00;
-         od_control.key_status[1]=0x0000;
-         od_control.key_status[2]=0x0000;
-         od_control.key_status[3]=0x0000;
-         od_control.key_status[4]=0x0000;
-         od_control.key_status[5]=0x0000;
-         od_control.key_status[6]=0x0000;
-         od_control.key_status[7]=0x4300;
-         od_control.key_status[8]=0x4400;
-         od_control.key_keyboardoff=0x2500;
-         od_control.key_moretime=0x4800;
-         od_control.key_lesstime=0x5000;
-         od_control.od_page_statusline=-1;
-         break;
-   }
-}
diff --git a/src/odoors/ODStat.c b/src/odoors/ODStat.c
deleted file mode 100644
index 0063382557b6cf772bdda12e10614aedbb6e2e0e..0000000000000000000000000000000000000000
--- a/src/odoors/ODStat.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODStat.c
- *
- * Description: Helper functions used by various built-in personalities.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Jul 18, 1995  6.00  BP   Fix ODStatGetUserAge() bug.
- *              Nov 13, 1995  6.00  BP   32-bit portability.
- *              Nov 13, 1995  6.00  BP   Created odstat.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Jan 12, 1996  6.00  BP   Added ODStatStartArrowUse(), etc.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 13, 1996  6.10  BP   bOnlyShiftArrow -> nArrowUseCount.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODCore.h"
-#include "ODGen.h"
-#include "ODStat.h"
-#include "ODKrnl.h"
-
-
-/* Global working string available to all personalities for status line */
-/* generation.                                                          */
-char szStatusText[80];
-
-
-/* ----------------------------------------------------------------------------
- * ODStatAddKey()
- *
- * Adds another hot key to the array of custom local keys.
- *
- * Parameters: wKeyCode - IBM scan-code/ASCII-code style key identification
- *                         code to add.
- *
- *     Return: void
- */
-void ODStatAddKey(WORD wKeyCode)
-{
-   if(od_control.od_num_keys < 16)
-      od_control.od_hot_key[od_control.od_num_keys++] = wKeyCode;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStatRemoveKey()
- *
- * Removes a custom sysop hotkey that was previously added with ODStatAddKey().
- *
- * Parameters: wKeyCode - The scan code / ASCII code key identification code
- *                        to remove.
- *
- *     Return: void
- */
-void ODStatRemoveKey(WORD wKeyCode)
-{
-   INT nCount;
-
-   for(nCount = 0; nCount < od_control.od_num_keys; ++nCount)
-      if((WORD)od_control.od_hot_key[nCount] == wKeyCode)
-      {
-         if(nCount != od_control.od_num_keys - 1)
-         {
-            od_control.od_hot_key[nCount] =
-               od_control.od_hot_key[od_control.od_num_keys-1];
-         }
-         --od_control.od_num_keys;
-         return;
-      }
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStatGetUserAge()
- *
- * Generates a string containing the age, in years, of the current
- * user, based on the current date and the user's birthday.
- *
- * Parameters: pszAge - Pointer to a string where user's age should be stored.
- *
- *     Return: void
- */
-void ODStatGetUserAge(char *pszAge)
-{
-   INT nAge;
-   INT n;
-   time_t Time;
-   struct tm *TimeBlock;
-
-   if(od_control.od_info_type==RA2EXITINFO || od_control.od_info_type==DOORSYS_WILDCAT)
-   {
-      nAge = atoi(od_control.user_birthday) - 1;
-
-      if(strlen(od_control.user_birthday) == 8 && nAge <= 11)
-      {
-         if(od_control.user_birthday[6] >= '0'
-            && od_control.user_birthday[6] <= '9'
-            && od_control.user_birthday[7] >= '0'
-            && od_control.user_birthday[7] <= '9')
-         {
-            if(od_control.user_birthday[3] >= '0'
-               && od_control.user_birthday[3] <= '3'
-               && od_control.user_birthday[4] >= '0'
-               && od_control.user_birthday[4] <= '9')
-            {
-               Time = time(NULL);
-               TimeBlock = localtime(&Time);
-
-               n = (TimeBlock->tm_year % 100)
-                  - atoi((char *)od_control.user_birthday + 6);
-
-               if(n < 0) nAge = n + 100; else nAge = n;
-
-               n = atoi(od_control.user_birthday) - 1;
-               if(TimeBlock->tm_mon < n)
-                  --nAge;
-               else if(TimeBlock->tm_mon == n)
-               {
-                  n=atoi((char *)od_control.user_birthday + 3);
-
-                  if(TimeBlock->tm_mday < n) --nAge;
-               }
-
-               sprintf(pszAge, "%d", nAge);
-               return;
-              }
-           }
-      }
-   }
-
-   strcpy(pszAge, "?");
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStatStartArrowUse()
- *
- * Called by OpenDoors when it needs to use the arrow keys, and so they
- * shouldn't be used by the status line.
- *
- * Parameters: None
- *
- *     Return: void
- */
-void ODStatStartArrowUse(void)
-{
-   ++nArrowUseCount;
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStatEndArrowUse()
- *
- * Called by OpenDoors when it no longer needs to use the arrow keys, and so
- * they can again be used by the status line.
- *
- * Parameters: None
- *
- *     Return: void
- */
-void ODStatEndArrowUse(void)
-{
-   ASSERT(nArrowUseCount > 0);
-   --nArrowUseCount;
-}
diff --git a/src/odoors/ODStat.h b/src/odoors/ODStat.h
deleted file mode 100644
index 34aee89367b6453cbbdc14fe3020039160420e8b..0000000000000000000000000000000000000000
--- a/src/odoors/ODStat.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODStat.h
- *
- * Description: Public functions provided by the odstat.c module, for status
- *              line functions shared among personalities.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 13, 1995  6.00  BP   Created.
- *              Jan 12, 1996  6.00  BP   Added ODStatStartArrowUse(), etc.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODSTAT
-#define _INC_ODSTAT
-
-
-/* Global working string available to all personalities for status line */
-/* generation.                                                          */
-extern char szStatusText[80];
-
-
-/* Public status line function prototypes. */
-void ODStatAddKey(WORD wKeyCode);
-void ODStatRemoveKey(WORD wKeyCode);
-void ODStatGetUserAge(char *pszAge);
-void ODStatStartArrowUse(void);
-void ODStatEndArrowUse(void);
-
-
-#endif /* _INC_ODSTAT */
diff --git a/src/odoors/ODSwap.asm b/src/odoors/ODSwap.asm
deleted file mode 100644
index b147d4256cd7d635838bfe72327ab48998cd239b..0000000000000000000000000000000000000000
--- a/src/odoors/ODSwap.asm
+++ /dev/null
@@ -1,1453 +0,0 @@
-;  OpenDoors Online Software Programming Toolkit
-;  (C) Copyright 1991 - 1999 by Brian Pirie.
-; 
-;  This library is free software; you can redistribute it and/or
-;  modify it under the terms of the GNU Lesser General Public
-;  License as published by the Free Software Foundation; either
-;  version 2 of the License, or (at your option) any later version.
-; 
-;  This library is distributed in the hope that it will be useful,
-;  but WITHOUT ANY WARRANTY; without even the implied warranty of
-;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;  Lesser General Public License for more details.
-; 
-;  You should have received a copy of the GNU Lesser General Public
-;  License along with this library; if not, write to the Free Software
-;  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-;
-;
-;         File: ODSwap.asm
-;
-;  Description: Performs EMS/disk swapping and low level spawning
-;               activities. This file should only be included when building
-;               the MS-DOS version of OpenDoors.
-;
-;    Revisions: Date          Ver   Who  Change
-;               ---------------------------------------------------------------
-;               Oct 13, 1994  6.00  BP   New file header format.
-;               Feb 19, 1996  6.00  BP   Changed version number to 6.00.
-;               Mar 03, 1996  6.10  BP   Begin version 6.10.
-
-
-; If you have increased the file handle table size so that more than 20 files
-; may be open in the parent process, set FHTSZ to the new size.
-
-FHTSZ           EQU     20
-
-IFDEF LCODE
-ARG_1           EQU     6
-ELSE
-ARG_1           EQU     4
-ENDIF
-
-arena           struc                           ; arena header
-sig             db      0                       ; 'M' or 'Z' if last block
-own             dw      0                       ; PSP of owner or 0 if free
-siz             dw      0                       ; size not including header
-arena           ends
-
-vector          struc
-number          db      0                       ; vector number
-flag            db      0                       ; 0-CURRENT,1-IRET,2-free,3-end
-vseg            dw      0                       ; vector segment
-voff            dw      0                       ; vector offset
-vector          ends
-
-_TEXT           SEGMENT word public 'CODE'
-                ASSUME  cs:_TEXT
-                ASSUME  ds:nothing
-                ASSUME  es:nothing
-                ASSUME  ss:nothing
-
-; The code between slidetop and slidebot constitutes the spawn kernel.  The
-; kernel is copied to the front of the parent process immediately following the
-; parent's PSP.  The environment passed to the child is copied to immediately
-; following the kernel.
-
-slidetop:
-
-path            db      79 dup (0)              ; program to execute
-command         db      128 dup (0)             ; command-line
-file            db      79 dup (0)              ; swap file
-
-parmblk         label   byte                    ; parameter block
-environ         dw      0                       ; environment block
-cmd             dw      0,0                     ; command-line tail
-fcb1            dw      0,0                     ; first file control block
-fcb2            dw      0,0                     ; second file control block
-
-fcb5c           db      10h dup (0)             ; first file control block
-fcb6c           db      10h dup (0)             ; second file control block
-
-cntsvl          dw      0                       ; count save low
-cntsvh          dw      0                       ; count save high
-tmpcode         dw      0                       ; temporary return code
-env             dw      0                       ; environment segment
-envlen          dw      0                       ; environment length
-parsz           dw      0                       ; parent size
-ttlsz           dw      0                       ; total size
-oldsz           dw      0                       ; old size
-newsz           dw      0                       ; new size
-emsseg          dw      0                       ; EMS page frame segment
-handle          dw      0                       ; EMS handle
-useems          db      0                       ; if 0, use EMS
-save            db      4 dup (0)               ; save 4 bytes at DS:[2Eh]
-f1add           dd      0                       ; fnish1 address
-last            db      0                       ; if 0, last block swap
-IF FHTSZ - 20
-fhtsv           db      FHTSZ dup (0)           ; file handle table save
-ENDIF
-
-errmsg          db      'spawn error',0Dh,0Ah
-msglen          EQU     $-errmsg
-
-                EVEN
-lclstk          dw      64 dup (0)              ; local stack
-stktop          label   word                    ; stack top
-
-slide1:         mov     ax,cs                   ; install local stack
-                cli
-                mov     ss,ax
-                mov     sp,offset stktop - offset slidetop + 100h
-                sti
-
-; copy environment
-
-                mov     bx,offset slidebot - offset slidetop + 15 + 100h
-                mov     cl,4
-                shr     bx,cl                   ; convert to paragraphs
-                add     bx,ax                   ; add CS (actually PSP)
-index = offset environ - offset slidetop + 100h
-                mov     cs:[index],bx           ; parameter block
-                mov     es,bx
-                xor     di,di
-index = offset env - offset slidetop + 100h
-                mov     ds,cs:[index]
-                xor     si,si
-index = offset envlen - offset slidetop + 100h
-                mov     cx,cs:[index]
-                shr     cx,1                    ; translate to word count
-                rep     movsw                   ; CF set if one byte left over
-                adc     cx,cx                   ; CX = 1 or 0, depending CF
-                rep     movsb                   ; possible final byte
-
-                dec     ax                      ; PSP segment
-                mov     es,ax                   ; program arena header
-                mov     bx,es:[siz]
-index = offset oldsz - offset slidetop + 100h
-                mov     cs:[index],bx           ; old size
-                mov     byte ptr es:[sig],'M'   ; not last
-index = offset newsz - offset slidetop + 100h
-                mov     bx,cs:[index]           ; new size
-                mov     es:[siz],bx
-
-                inc     ax                      ; PSP segment
-                add     ax,bx                   ; add new size
-                mov     es,ax                   ; new last arena header
-                mov     byte ptr es:[sig],'Z'   ; last
-index = offset last - offset slidetop + 100h
-                cmp     byte ptr cs:[index],0
-                je      slide2                  ; jump if last block swap
-                mov     byte ptr es:[sig],'M'   ; not last
-
-slide2:         mov     word ptr es:[own],0     ; free
-index = offset ttlsz - offset slidetop + 100h
-                mov     ax,cs:[index]           ; total size
-                sub     ax,bx                   ; subtract new size
-                dec     ax                      ; account for arena header
-                mov     es:[siz],ax
-
-; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
-
-                mov     ax,cs                   ; PSP segment
-                mov     es,ax
-                mov     bx,es:[2Eh]
-index = offset save - offset slidetop + 100h
-                mov     cs:[index],bx
-                mov     bx,es:[30h]
-index = offset save - offset slidetop + 102h
-                mov     cs:[index],bx
-
-                mov     bx,offset parmblk - offset slidetop + 100h
-                mov     ds,ax                   ; PSP segment
-                mov     dx,100h                 ; offset path
-                mov     ax,4B00h                ; load and execute program
-                int     21h
-                jnc     slide3                  ; jump if no error
-index = offset tmpcode - offset slidetop + 100h
-                mov     cs:[index],ax           ; temporary return code
-
-slide3:         mov     ax,cs                   ; install local stack
-                cli
-                mov     ss,ax
-                mov     sp,offset stktop - offset slidetop + 100h
-                sti
-
-; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
-
-                mov     es,ax                   ; PSP segment
-index = offset save - offset slidetop + 100h
-                mov     bx,cs:[index]
-                mov     es:[2Eh],bx
-index = offset save - offset slidetop + 102h
-                mov     bx,cs:[index]
-                mov     es:[30h],bx
-
-index = offset oldsz - offset slidetop + 100h
-                mov     bx,cs:[index]           ; old size
-                mov     ah,4Ah                  ; resize memory block
-                int     21h
-                jnc     slide7
-
-index = offset useems - offset slidetop + 100h
-slide4:         cmp     byte ptr cs:[index],0
-                jne     slide6                  ; jump if don't use EMS
-index = offset handle - offset slidetop + 100h
-                mov     dx,cs:[index]           ; EMS handle
-
-slide5:         mov     ah,45h                  ; release handle and memory
-                int     67h
-                cmp     ah,82h                  ; memory manager busy?
-                je      slide5                  ; jump if busy
-
-slide6:         jmp     slide18                 ; exit
-
-index = offset parsz - offset slidetop + 100h
-slide7:         mov     bx,cs:[index]           ; parent size
-index = offset ttlsz - offset slidetop + 100h
-                mov     ax,cs:[index]           ; total size
-                sub     ax,bx                   ; subtract parent size
-                or      ax,ax
-                jz      slide9
-                mov     dx,cs                   ; PSP segment
-                add     dx,bx                   ; add parent size
-                mov     es,dx                   ; new last arena header
-                mov     byte ptr es:[sig],'Z'   ; last
-index = offset last - offset slidetop + 100h
-                cmp     byte ptr cs:[index],0
-                je      slide8                  ; jump if last block swap
-                mov     byte ptr es:[sig],'M'   ; not last
-
-slide8:         mov     word ptr es:[own],0     ; free
-                dec     ax                      ; account for arena header
-                mov     es:[siz],ax
-
-slide9:         push    cs                      ; PSP segment
-index = offset useems - offset slidetop + 100h
-                cmp     byte ptr cs:[index],0
-                jne     slide14                 ; jump if don't use EMS
-                pop     es                      ; PSP segment
-                mov     di,offset slidebot - offset slidetop + 100h
-index = offset emsseg - offset slidetop + 100h
-                mov     ds,cs:[index]           ; EMS page frame segment
-                mov     si,offset slidebot - offset slidetop
-index = offset handle - offset slidetop + 100h
-                mov     dx,cs:[index]           ; EMS handle
-                xor     bx,bx                   ; logical page number
-                mov     cx,16384 - ( offset slidebot - offset slidetop )
-                jmp     short slide13
-
-index = offset cntsvl - offset slidetop + 100h
-slide10:        sub     cs:[index],cx
-index = offset cntsvh - offset slidetop + 100h
-                sbb     word ptr cs:[index],0
-                xor     al,al                   ; physical page number
-
-slide11:        mov     ah,44h                  ; map memory
-                int     67h
-                or      ah,ah
-                jz      slide12
-                cmp     ah,82h                  ; memory manager busy?
-                je      slide11                 ; jump if busy
-                jmp     slide4                  ; exit
-
-slide12:        shr     cx,1                    ; translate to word count
-                rep     movsw                   ; CF set if one byte left over
-                adc     cx,cx                   ; CX = 1 or 0, depending CF
-                rep     movsb                   ; possible final byte
-                xor     si,si
-                mov     cx,16384                ; assume copy full block
-                inc     bx                      ; logical page number
-                cmp     bx,1
-                je      slide13
-                mov     ax,es
-                add     ax,1024                 ; 16384 bytes
-                mov     es,ax
-                mov     di,16640                ; 16384 + 100h
-
-index = offset cntsvh - offset slidetop + 100h
-slide13:        cmp     word ptr cs:[index],0
-                jne     slide10                 ; jump if more than full block
-index = offset cntsvl - offset slidetop + 100h
-                cmp     cs:[index],cx
-                jae     slide10                 ; jump if at least full block
-                mov     cx,cs:[index]           ; CX = cntsvl
-                cmp     cx,0
-                jne     slide10                 ; jump if more left to copy
-                jmp     short slide17
-
-slide14:        pop     ds                      ; PSP segment
-IF FHTSZ - 20
-
-; restore the file handle table from the kernel
-
-                mov     si,offset fhtsv - offset slidetop + 100h
-                mov     es,ds:[36h]             ; file handle table segment
-                mov     di,ds:[34h]             ; file handle table offset
-                mov     cx,FHTSZ                ; file handle table size
-                rep     movsb
-ENDIF
-                mov     dx,offset file - offset slidetop + 100h
-                mov     ax,3D00h                ; open file read only
-                int     21h
-                jc      slide18                 ; exit if error
-                mov     bx,ax                   ; handle
-
-                xor     cx,cx
-                mov     dx,offset slidebot - offset slidetop
-                mov     ax,4200h                ; move file pointer
-                int     21h                     ;  from beginning of file
-
-                mov     dx,offset slidebot - offset slidetop + 100h
-                mov     cx,65520                ; assume read full block
-                jmp     short slide16
-
-index = offset cntsvl - offset slidetop + 100h
-slide15:        sub     cs:[index],cx
-index = offset cntsvh - offset slidetop + 100h
-                sbb     word ptr cs:[index],0
-                mov     ah,3Fh                  ; read file
-                int     21h
-                jc      slide18                 ; exit if error
-                cmp     ax,cx
-                jne     slide18                 ; exit if not all read
-
-                mov     ax,ds
-                add     ax,4095                 ; 65520 bytes
-                mov     ds,ax
-
-index = offset cntsvh - offset slidetop + 100h
-slide16:        cmp     word ptr cs:[index],0
-                jne     slide15                 ; jump if more than full block
-index = offset cntsvl - offset slidetop + 100h
-                cmp     word ptr cs:[index],65520
-                jae     slide15                 ; jump if at least full block
-                mov     cx,cs:[index]           ; CX = cntsvl
-                cmp     cx,0
-                jne     slide15                 ; jump if more left to read
-
-index = offset tmpcode - offset slidetop + 100h
-slide17:        mov     ax,cs:[index]           ; temporary return code
-index = offset f1add - offset slidetop + 100h
-                jmp     dword ptr cs:[index]
-
-slide18:        push    cs                      ; PSP segment
-                pop     ds
-                mov     dx,offset errmsg - offset slidetop + 100h
-                mov     cx,msglen               ; errmsg length
-                mov     bx,2                    ; standard error device handle
-                mov     ah,40h                  ; write error message
-                int     21h
-                mov     ax,4C01h                ; terminate with return code
-                int     21h
-
-handler:        iret                            ; interrupt handler
-
-slidebot:
-
-cntl            dw      0                       ; count low
-cnth            dw      0                       ; count high
-stks            dw      0                       ; original SS contents
-stkp            dw      0                       ; original SP contents
-psp             dw      0                       ; PSP segment
-s1add           dd      0                       ; slide1 address
-rcode           dw      0                       ; return code
-useems2         db      0                       ; if 0, use EMS
-vtabseg         dw      0                       ; vectab1 segment
-vtaboff         dw      0                       ; vectab1 offset
-
-errmsg2         db      'spawn error',0Dh,0Ah
-msglen2         EQU     $-errmsg2
-
-;
-; int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
-;
-
-                PUBLIC  __xspawn
-IFDEF LCODE
-__xspawn        PROC    far
-ELSE
-__xspawn        PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    di                      ; preserve register variables
-                push    si
-                push    ds
-
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1]
-ELSE
-                mov     si,word ptr [bp+ARG_1]
-ENDIF
-                mov     di,offset path
-
-start1:         mov     al,ds:[si]              ; copy path string
-                mov     cs:[di],al              ;  to code segment
-                inc     si
-                inc     di
-                or      al,al                   ; null char?
-                jnz     start1                  ; no, get next char
-
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+4]
-ELSE
-                mov     si,word ptr [bp+ARG_1+2]
-ENDIF
-                mov     bx,si                   ; preserve si
-                mov     di,offset command
-                mov     cx,2                    ; account for count and '\r'
-                add     cl,byte ptr ds:[bx]     ; add count byte
-
-start2:         mov     al,ds:[bx]              ; copy command
-                mov     cs:[di],al              ;  to code segment
-                inc     bx
-                inc     di
-                loop    start2                  ; get next char
-
-                inc     si                      ; skip count byte
-                push    cs
-                pop     es
-                mov     di,offset fcb5c
-                mov     ax,2901h                ; parse filename
-                int     21h                     ;  skip leading separators
-                mov     di,offset fcb6c
-                mov     al,1                    ; parse filename
-                int     21h                     ;  skip leading separators
-
-IFDEF LDATA
-                mov     ax,word ptr [bp+ARG_1+8]
-ELSE
-                mov     ax,word ptr [bp+ARG_1+4]
-ENDIF
-                mov     cl,4
-                shr     ax,cl                   ; convert to paragraphs
-IFDEF LDATA
-                mov     bx,word ptr [bp+ARG_1+10]
-ELSE
-                mov     bx,ds
-ENDIF
-                add     ax,bx
-                mov     cs:[env],ax             ; environment segment
-
-IFDEF LDATA
-                lds     bx,dword ptr [bp+ARG_1+12] ; vectab1
-ELSE
-                mov     bx,word ptr [bp+ARG_1+6] ; vectab1
-ENDIF
-                mov     cs:[vtabseg],ds         ; vectab1 segment
-                mov     cs:[vtaboff],bx         ; vectab1 offset
-
-                mov     cs:[stks],ss            ; original SS contents
-                mov     cs:[stkp],sp            ; original SP contents
-                mov     cs:[rcode],0            ; assume success
-
-IFDEF LDATA
-                mov     ax,word ptr [bp+ARG_1+16]
-ELSE
-                mov     ax,word ptr [bp+ARG_1+8]
-ENDIF
-                or      ax,ax                   ; do swap?
-                jz      start3                  ; yes, jump
-                jmp     noswap1
-
-IFDEF LDATA
-start3:         mov     ax,word ptr [bp+ARG_1+18]
-ELSE
-start3:         mov     ax,word ptr [bp+ARG_1+10]
-ENDIF
-                mov     cs:[envlen],ax          ; environment length
-                add     ax,offset slidebot - offset slidetop + 30 + 100h
-                mov     cl,4
-                shr     ax,cl                   ; convert to paragraphs
-                mov     cs:[newsz],ax           ; new size
-
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+20]
-ELSE
-                mov     si,word ptr [bp+ARG_1+12]
-ENDIF
-                mov     di,offset file
-                mov     cs:[useems2],1          ; assume don't use EMS
-                cmp     byte ptr ds:[si],0
-                jne     start4
-                mov     cs:[useems2],0          ; use EMS
-
-start4:         mov     al,ds:[si]              ; copy file string
-                mov     cs:[di],al              ;  to code segment
-                inc     si
-                inc     di
-                or      al,al                   ; null char?
-                jnz     start4                  ; no, get next char
-
-; save fnish1 address
-
-                mov     word ptr cs:[f1add+2],cs
-                mov     word ptr cs:[f1add],offset fnish1
-
-; initialize parameter block
-
-                mov     ax,cs:[psp]             ; PSP segment
-                mov     cs:[cmd],offset command - offset slidetop + 100h
-                mov     cs:[cmd+2],ax
-                mov     cs:[fcb1],offset fcb5c - offset slidetop + 100h
-                mov     cs:[fcb1+2],ax
-                mov     cs:[fcb2],offset fcb6c - offset slidetop + 100h
-                mov     cs:[fcb2+2],ax
-
-                cld                             ; left to right direction
-
-                mov     ds,ax                   ; PSP segment
-IFDEF LDATA
-                mov     dx,word ptr [bp+ARG_1+24]
-ELSE
-                mov     dx,word ptr [bp+ARG_1+14]
-ENDIF
-IF FHTSZ - 20
-                cmp     word ptr ds:[32h],FHTSZ ; file handle table size
-                je      start5                  ; jump if OK
-                mov     cs:[rcode],5
-                jmp     short start6
-ENDIF
-
-start5:         mov     ax,cs:[newsz]           ; new size
-                cmp     ax,cs:[ttlsz]           ; new size < total size?
-                jb      start8                  ; yes, jump
-                mov     cs:[rcode],7            ; extremely unlikely
-
-start6:         cmp     cs:[useems2],0
-                jne     start7                  ; jump if don't use EMS
-                jmp     fnish2
-
-start7:         mov     bx,dx                   ; file handle
-                jmp     fnish6
-
-start8:         cmp     cs:[useems2],0
-                jne     start12                 ; jump if don't use EMS
-                mov     cs:[useems],0           ; use EMS
-                mov     cs:[handle],dx          ; EMS handle
-                mov     es,cs:[emsseg]          ; EMS page frame segment
-                xor     bx,bx                   ; logical page number
-                jmp     short start11
-
-start9:         sub     cs:[cntl],cx
-                sbb     cs:[cnth],0
-                call    mapems
-                or      ah,ah
-                jz      start10                 ; jump if map succeeded
-                jmp     fnish2
-
-start10:        mov     si,100h
-                xor     di,di
-                shr     cx,1                    ; translate to word count
-                rep     movsw                   ; CF set if one byte left over
-                adc     cx,cx                   ; CX = 1 or 0, depending CF
-                rep     movsb                   ; possible final byte
-                inc     bx                      ; logical page number
-                mov     ax,ds
-                add     ax,1024                 ; 16384 bytes
-                mov     ds,ax
-
-start11:        mov     cx,16384                ; assume copy full block
-                cmp     cs:[cnth],0
-                jne     start9                  ; jump if more than full block
-                cmp     cs:[cntl],16384
-                jae     start9                  ; jump if at least full block
-                mov     cx,cs:[cntl]
-                cmp     cx,0
-                jne     start9                  ; jump if more left to copy
-                jmp     short start17
-
-start12:        mov     cs:[useems],1           ; don't use EMS
-                mov     bx,dx                   ; handle
-                mov     dx,100h                 ; DS:DX segment:offset buffer
-                mov     cx,65520                ; assume write full block
-                jmp     short start16
-
-start13:        sub     cs:[cntl],cx
-                sbb     cs:[cnth],0
-                mov     ah,40h                  ; write file
-                int     21h
-                jc      start14                 ; jump if error
-                cmp     ax,cx
-                je      start15                 ; jump if all written
-
-start14:        mov     ah,3Eh                  ; close file
-                int     21h
-                mov     cs:[rcode],5
-                jmp     fnish7
-
-start15:        mov     ax,ds
-                add     ax,4095                 ; 65520 bytes
-                mov     ds,ax
-
-start16:        cmp     cs:[cnth],0
-                jne     start13                 ; jump if more than full block
-                cmp     cs:[cntl],65520
-                jae     start13                 ; jump if at least full block
-                mov     cx,cs:[cntl]
-                cmp     cx,0
-                jne     start13                 ; jump if more left to write
-
-                mov     ah,3Eh                  ; close file
-                int     21h
-IF FHTSZ - 20
-
-; save the file handle table in the kernel
-
-                mov     es,cs:[psp]             ; PSP segment
-                mov     ds,es:[36h]             ; file handle table segment
-                mov     si,es:[34h]             ; file handle table offset
-                push    cs
-                pop     es
-                mov     di,offset fhtsv         ; file handle table save
-                mov     cx,FHTSZ                ; file handle table size
-                rep     movsb
-ENDIF
-
-start17:        mov     cx,cs
-                mov     dx,offset handler       ; interrupt handler offset
-                call    safevect                ; set vectors in vectab1
-
-; time to copy the kernel
-
-                mov     es,cs:[psp]             ; PSP segment
-                mov     di,100h
-                mov     ds,cx                   ; DS = CS
-                mov     si,offset slidetop
-                mov     cx,offset slidebot - offset slidetop
-                shr     cx,1                    ; translate to word count
-                rep     movsw                   ; CF set if one byte left over
-                adc     cx,cx                   ; CX = 1 or 0, depending CF
-                rep     movsb                   ; possible final byte
-
-                mov     word ptr cs:[s1add+2],es ; PSP segment
-index = offset slide1 - offset slidetop + 100h
-                mov     word ptr cs:[s1add],index ; slide1 offset
-
-                mov     cx,es                   ; PSP segment
-index = offset handler - offset slidetop + 100h
-                mov     dx,index                ; interrupt handler offset
-                call    safevect                ; set vectors in vectab1
-
-                jmp     dword ptr cs:[s1add]    ; jump to the kernel
-
-; If all goes well, this is where we come back to from the kernel.
-
-fnish1:         mov     cs:[rcode],ax           ; return code
-
-                cli                             ; restore original stack
-                mov     ss,cs:[stks]
-                mov     sp,cs:[stkp]
-                sti
-
-                push    ds                      ; maybe EMS page frame segment
-                push    dx                      ; maybe EMS handle
-                push    bx                      ; maybe swap file handle
-                mov     cx,cs
-                mov     dx,offset handler       ; interrupt handler offset
-                call    safevect                ; set vectors in vectab1
-                pop     bx
-                pop     dx
-                pop     ds
-
-                cmp     cs:[useems2],0
-                jne     fnish4                  ; jump if don't use EMS
-
-; DS = EMS page frame segment
-; DX = EMS handle
-
-                mov     cx,offset slidebot - offset slidetop
-                mov     es,cs:[psp]             ; PSP segment
-                mov     di,100h
-                xor     si,si
-                xor     bx,bx                   ; logical page number
-                call    mapems
-                or      ah,ah
-                jnz     fnish3                  ; jump if map failed
-                shr     cx,1                    ; translate to word count
-                rep     movsw                   ; CF set if one byte left over
-                adc     cx,cx                   ; CX = 1 or 0, depending CF
-                rep     movsb                   ; possible final byte
-
-fnish2:         mov     ah,45h                  ; release handle and memory
-                int     67h
-                cmp     ah,82h                  ; memory manager busy?
-                je      fnish2                  ; jump if busy
-                jmp     short fnish7
-
-fnish3:         mov     ah,45h                  ; release handle and memory
-                int     67h
-                cmp     ah,82h                  ; memory manager busy?
-                je      fnish3                  ; jump if busy
-                jmp     short fnish5            ; exit
-
-; BX = swap file handle
-
-fnish4:         xor     cx,cx                   ; offset 0
-                xor     dx,dx                   ; offset 0
-                mov     ax,4200h                ; move file pointer
-                int     21h                     ;  from beginning of file
-
-                mov     cx,offset slidebot - offset slidetop
-                mov     ds,cs:[psp]             ; PSP segment
-                mov     dx,100h
-                mov     ah,3Fh                  ; read file
-                int     21h
-                jc      fnish5                  ; exit if error
-                cmp     ax,cx
-                je      fnish6
-
-fnish5:         push    cs
-                pop     ds
-                mov     dx,offset errmsg2
-                mov     cx,msglen2              ; errmsg2 length
-                mov     bx,2                    ; standard error device handle
-                mov     ah,40h                  ; write error message
-                int     21h
-                mov     ax,4C01h                ; terminate with return code
-                int     21h
-
-fnish6:         mov     ah,3Eh                  ; close file
-                int     21h
-                push    cs
-                pop     ds
-                mov     dx,offset file
-                mov     ah,41h                  ; delete file
-                int     21h
-
-fnish7:         pop     ds
-                pop     si                      ; restore register variables
-                pop     di
-                pop     bp
-
-                mov     ax,cs:[rcode]           ; return code
-                or      ax,ax
-                jz      fnish11
-                push    ax
-                mov     ax,3000h                ; get DOS version number
-                int     21h
-                cmp     al,3                    ; major version number
-                pop     ax
-                jb      fnish8
-                cmp     al,34                   ; unknown error - 3.0
-                jae     fnish9
-                cmp     al,32                   ; sharing violation
-                jb      fnish8
-                mov     al,5                    ; access denied
-                jmp     short fnish10
-
-fnish8:         cmp     al,19                   ; unknown error - 2.0
-                jbe     fnish10
-
-fnish9:         mov     al,19                   ; unknown error - 2.0
-
-fnish10:        xor     ah,ah
-
-fnish11:        ret
-
-; If we are not swapping, we jump here.
-
-noswap1:        mov     ax,cs
-
-; initialize parameter block
-
-                mov     bx,cs:[env]
-                mov     cs:[environ],bx
-                mov     cs:[cmd],offset command
-                mov     cs:[cmd+2],ax
-                mov     cs:[fcb1],offset fcb5c
-                mov     cs:[fcb1+2],ax
-                mov     cs:[fcb2],offset fcb6c
-                mov     cs:[fcb2+2],ax
-
-; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
-
-                mov     si,cs:[2Eh]
-                mov     word ptr cs:[save],si
-                mov     si,cs:[30h]
-                mov     word ptr cs:[save+2],si
-
-                mov     cx,cs
-                mov     dx,offset handler       ; interrupt handler offset
-                call    safevect                ; set vectors in vectab1
-
-                mov     es,cx                   ; ES = CS
-                mov     bx,offset parmblk
-                mov     ds,cx                   ; DS = CS
-                mov     dx,offset path
-                mov     ax,4B00h                ; load and execute program
-                int     21h
-                jnc     noswap2                 ; jump if no error
-                mov     cs:[rcode],ax           ; return code
-
-noswap2:        cli                             ; restore original stack
-                mov     ss,cs:[stks]
-                mov     sp,cs:[stkp]
-                sti
-
-; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
-
-                mov     si,word ptr cs:[save]
-                mov     cs:[2Eh],si
-                mov     si,word ptr cs:[save+2]
-                mov     cs:[30h],si
-
-                jmp     fnish7
-
-__xspawn        ENDP
-
-mapems          PROC    near
-
-; DX = handle
-; BX = logical page number
-
-                xor     al,al                   ; physical page number
-
-map1:           mov     ah,44h                  ; map memory
-                int     67h
-                cmp     ah,82h                  ; memory manager busy?
-                je      map1                    ; jump if busy
-
-                ret
-
-mapems          ENDP
-
-setvectsub      PROC    near
-
-; ES = vector table segment
-; BX = vector table offset
-
-                mov     ah,25h                  ; set interrupt vector
-
-setvectsub1:    mov     al,es:[bx+flag]         ; 0-CURRENT,1-IRET,2-free,3-end
-                cmp     al,3                    ; is it the end?
-                je      setvectsub3             ; yes, jump
-                cmp     al,2                    ; is it free?
-                je      setvectsub2             ; yes, jump
-                mov     al,es:[bx+number]       ; vector number
-                mov     ds,es:[bx+vseg]         ; vector segment
-                mov     dx,es:[bx+voff]         ; vector offset
-                int     21h                     ; set interrupt vector
-
-setvectsub2:    add     bx,6                    ; size of vector structure
-                jmp     setvectsub1             ; next
-
-setvectsub3:    ret
-
-setvectsub      ENDP
-
-safevect        PROC    near
-
-; CX = handler segment
-; DX = handler offset
-
-                mov     es,cs:[vtabseg]         ; vectab1 segment
-                mov     bx,cs:[vtaboff]         ; vectab1 offset
-
-safevect1:      mov     al,es:[bx+flag]         ; 0-CURRENT,1-IRET,2-free,3-end
-                cmp     al,3                    ; is it the end?
-                je      safevect3               ; yes, jump
-                cmp     al,1                    ; is it IRET?
-                jne     safevect2               ; no, jump
-                mov     es:[bx+vseg],cx         ; handler segment
-                mov     es:[bx+voff],dx         ; handler offset
-
-safevect2:      add     bx,6                    ; size of vector structure
-                jmp     safevect1               ; next
-
-safevect3:      mov     bx,cs:[vtaboff]         ; vectab1 offset
-                call    setvectsub
-
-                ret
-
-safevect        ENDP
-
-;
-; int _xsize( unsigned int, long *, long * );
-;
-
-                PUBLIC  __xsize
-IFDEF LCODE
-__xsize         PROC    far
-ELSE
-__xsize         PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    di                      ; preserve register variables
-                push    si
-                push    ds
-
-                mov     cs:[last],0             ; assume last block swap
-                mov     bx,word ptr [bp+ARG_1]  ; PSP segment
-                mov     cs:[psp],bx
-                mov     dx,bx
-                dec     bx                      ; program arena header
-
-size1:          mov     es,bx                   ; current arena header
-                mov     ax,es:[own]
-                or      ax,ax                   ; is it free?
-                jz      size2                   ; yes, count it
-                cmp     ax,dx                   ; do we own it?
-                jne     size4                   ; no, jump
-                mov     cx,bx                   ; last owned block
-
-size2:          inc     bx
-                add     bx,es:[siz]             ; block size
-                jc      size3                   ; carry, arena is trashed
-                mov     al,es:[sig]             ; get arena signature
-                cmp     al,'M'                  ; are we at end of memory?
-                je      size1                   ; no, jump
-                cmp     al,'Z'
-                je      size5
-
-size3:          mov     bx,-1                   ; request maximum memory
-                mov     ah,48h                  ; allocate memory block
-                int     21h
-                mov     cs:[rcode],7
-                jmp     fnish7
-
-size4:          mov     cs:[last],1             ; not last block swap
-
-size5:          sub     bx,dx                   ; subtract PSP segment
-                mov     ax,cx                   ; last owned block
-                mov     es,cx
-                inc     ax
-                add     ax,es:[siz]             ; block size
-                sub     ax,dx                   ; subtract PSP segment
-                mov     cs:[parsz],ax           ; parent size
-                sub     ax,10h                  ; subtract PSP size
-                xor     dx,dx                   ; convert to bytes
-                mov     cx,4
-
-size6:          shl     ax,1
-                rcl     dx,1
-                loop    size6
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+2]
-ELSE
-                mov     si,word ptr [bp+ARG_1+2]
-ENDIF
-                mov     ds:[si],ax              ; swap size requirement
-                mov     ds:[si+2],dx
-                mov     cs:[cntl],ax            ; count low
-                mov     cs:[cnth],dx            ; count high
-                mov     cx,offset slidebot - offset slidetop
-                sub     ax,cx
-                sbb     dx,0
-                mov     cs:[cntsvl],ax          ; count save low
-                mov     cs:[cntsvh],dx          ; count save high
-                mov     cs:[ttlsz],bx           ; total size
-                xor     dx,dx                   ; convert to bytes
-                mov     cx,4
-
-size7:          shl     bx,1
-                rcl     dx,1
-                loop    size7
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+6]
-ELSE
-                mov     si,word ptr [bp+ARG_1+4]
-ENDIF
-                mov     ds:[si],bx              ; parent and free memory
-                mov     ds:[si+2],dx
-
-                pop     ds
-                pop     si                      ; restore register variables
-                pop     di
-                pop     bp
-                xor     ax,ax
-                ret
-
-__xsize         ENDP
-
-;
-; int _chkems( char *, int * );
-;
-
-                PUBLIC  __chkems
-IFDEF LCODE
-__chkems        PROC    far
-ELSE
-__chkems        PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-
-; determine whether expanded memory is available
-
-IFDEF LDATA
-                push    ds
-                lds     dx,dword ptr [bp+ARG_1] ; EMM device driver name
-ELSE
-                mov     dx,word ptr [bp+ARG_1]  ; EMM device driver name
-ENDIF
-                mov     ax,3D00h                ; open file read only
-                int     21h
-IFDEF LDATA
-                pop     ds
-ENDIF
-                jc      check2                  ; expanded memory unavailable
-
-; determine whether we opened the EMM device driver or a file
-
-                mov     bx,ax                   ; handle
-                mov     ax,4400h                ; IOCTL - get device info
-                int     21h
-                jc      check1                  ; expanded memory unavailable
-                test    dx,80h                  ; test bit 7
-                jz      check1                  ; expanded memory unavailable
-
-                mov     ax,4407h                ; IOCTL - get output status
-                int     21h
-                jc      check1                  ; expanded memory unavailable
-                or      al,al
-                jz      check1                  ; expanded memory unavailable
-
-; close EMM device driver to reclaim handle
-
-                mov     ah,3Eh                  ; close file
-                int     21h
-
-; determine whether the EMM is functional
-
-                mov     ah,40h                  ; get manager status
-                int     67h
-                or      ah,ah
-                jnz     check2                  ; expanded memory unavailable
-
-; check EMM version
-
-                mov     ah,46h                  ; get EMM version
-                int     67h
-                or      ah,ah
-                jnz     check2                  ; expanded memory unavailable
-                cmp     al,32h                  ; version 3.2
-                jb      check2                  ; expanded memory unavailable
-
-; get page frame segment
-
-                mov     ah,41h                  ; get page frame segment
-                int     67h
-                or      ah,ah
-                jnz     check2                  ; expanded memory unavailable
-                mov     cs:[emsseg],bx          ; segment
-
-; get size of page map information
-
-                mov     ax,4E03h                ; get size of page map info
-                int     67h
-                or      ah,ah
-                jnz     check2                  ; expanded memory unavailable
-IFDEF LDATA
-                les     bx,dword ptr [bp+ARG_1+4] ; mapsize address
-                mov     es:[bx],ax
-ELSE
-                mov     bx,word ptr [bp+ARG_1+2] ; mapsize address
-                mov     ds:[bx],ax
-ENDIF
-                xor     ax,ax                   ; expanded memory available
-                pop     bp
-                ret
-
-; close EMM device driver or file to reclaim handle
-
-check1:         mov     ah,3Eh                  ; close file
-                int     21h
-
-check2:         mov     ax,1                    ; expanded memory unavailable
-                pop     bp
-                ret
-
-__chkems        ENDP
-
-;
-; int _savemap( char * );
-;
-
-                PUBLIC  __savemap
-IFDEF LCODE
-__savemap       PROC    far
-ELSE
-__savemap       PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    di                      ; preserve register variable
-
-IFDEF LDATA
-                les     di,dword ptr [bp+ARG_1] ; buffer address
-ELSE
-                mov     di,word ptr [bp+ARG_1]  ; buffer address
-                push    ds
-                pop     es
-ENDIF
-                mov     ax,4E00h                ; save page map
-                int     67h
-
-                pop     di                      ; restore register variable
-                pop     bp
-                ret
-
-__savemap       ENDP
-
-;
-; int _restmap( char * );
-;
-
-                PUBLIC  __restmap
-IFDEF LCODE
-__restmap       PROC    far
-ELSE
-__restmap       PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    ds
-                push    si                      ; preserve register variable
-
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1] ; buffer address
-ELSE
-                mov     si,word ptr [bp+ARG_1]  ; buffer address
-ENDIF
-                mov     ax,4E01h                ; restore page map
-                int     67h
-                xor     al,al
-
-                pop     si                      ; restore register variable
-                pop     ds
-                pop     bp
-                ret
-
-__restmap       ENDP
-
-;
-; int _getems( int, int * );
-;
-
-                PUBLIC  __getems
-IFDEF LCODE
-__getems        PROC    far
-ELSE
-__getems        PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-
-                mov     bx,word ptr [bp+ARG_1]  ; number of pages
-                mov     ah,43h                  ; get handle and allocate
-                                                ;  memory
-                int     67h
-IFDEF LDATA
-                les     bx,dword ptr [bp+ARG_1+2] ; handle address
-                mov     es:[bx],dx              ; handle
-ELSE
-                mov     bx,word ptr [bp+ARG_1+2] ; handle address
-                mov     ds:[bx],dx              ; handle
-ENDIF
-                xor     al,al
-                pop     bp
-                ret
-
-__getems        ENDP
-
-;
-; int _dskspace( int, unsigned int *, unsigned int * );
-;
-
-                PUBLIC  __dskspace
-IFDEF LCODE
-__dskspace      PROC    far
-ELSE
-__dskspace      PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    di                      ; preserve register variable
-
-                mov     ah,36h                  ; get free disk space
-                mov     dl,byte ptr [bp+ARG_1]  ; drive code (0=default, 1=A)
-                int     21h
-                cmp     ax,0FFFFh               ; was drive invalid?
-                je      space1                  ; yes, jump
-                mul     cx                      ; bytes per sector *
-                                                ;  sectors per cluster
-IFDEF LDATA
-                les     di,dword ptr [bp+ARG_1+2]
-                mov     es:[di],ax              ; bytes per cluster
-ELSE
-                mov     di,word ptr [bp+ARG_1+2]
-                mov     ds:[di],ax              ; bytes per cluster
-ENDIF
-IFDEF LDATA
-                les     di,dword ptr [bp+ARG_1+6]
-                mov     es:[di],bx              ; number of available clusters
-ELSE
-                mov     di,word ptr [bp+ARG_1+4]
-                mov     ds:[di],bx              ; number of available clusters
-ENDIF
-                xor     ax,ax
-
-space1:         pop     di                      ; restore register variable
-                pop     bp
-                ret
-
-__dskspace      ENDP
-
-;
-; int _getrc( void );
-;
-
-                PUBLIC  __getrc
-IFDEF LCODE
-__getrc         PROC    far
-ELSE
-__getrc         PROC    near
-ENDIF
-
-                mov     ah,4Dh                  ; get child return code
-                int     21h
-
-                ret
-
-__getrc         ENDP
-
-;
-; int _create( char *, int * );
-;
-
-                PUBLIC  __create
-IFDEF LCODE
-__create        PROC    far
-ELSE
-__create        PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-IFDEF LDATA
-                push    ds
-ENDIF
-
-                mov     ax,3000h                ; get DOS version number
-                int     21h
-IFDEF LDATA
-                lds     dx,dword ptr [bp+ARG_1] ; file
-ELSE
-                mov     dx,word ptr [bp+ARG_1]  ; file
-ENDIF
-                xor     cx,cx                   ; normal attribute
-                mov     ah,5Bh                  ; create new file
-                cmp     al,3                    ; major version number
-                jae     create1
-                mov     ah,3Ch                  ; create file
-
-create1:        int     21h
-                jc      create2
-IFDEF LDATA
-                lds     bx,dword ptr [bp+ARG_1+4] ; handle address
-ELSE
-                mov     bx,word ptr [bp+ARG_1+2] ; handle address
-ENDIF
-                mov     ds:[bx],ax
-                xor     ax,ax
-
-create2:
-IFDEF LDATA
-                pop     ds
-ENDIF
-                pop     bp
-                ret
-
-__create        ENDP
-
-
-;
-; int _getcd( int, char * );
-;
-
-
-                PUBLIC  __getcd
-IFDEF LCODE
-__getcd         PROC    far
-ELSE
-__getcd         PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    si                      ; preserve register variable
-IFDEF LDATA
-                push    ds
-ENDIF
-
-                mov     dl,byte ptr [bp+ARG_1]  ; drive code (0=default, 1=A)
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+2] ; buffer
-ELSE
-                mov     si,word ptr [bp+ARG_1+2] ; buffer
-ENDIF
-                mov     ah,47h                  ; get current directory
-                int     21h
-                jc      getcd1
-                xor     ax,ax
-
-getcd1:
-IFDEF LDATA
-                pop     ds
-ENDIF
-                pop     si                      ; restore register variable
-                pop     bp
-                ret
-
-__getcd         ENDP
-
-;
-; int _getdrv( void );
-;
-
-                PUBLIC  __getdrv
-IFDEF LCODE
-__getdrv        PROC    far
-ELSE
-__getdrv        PROC    near
-ENDIF
-
-                mov     ah,19h                  ; get default disk drive
-                int     21h
-                xor     ah,ah
-
-; AX = drive (0 = A, 1 = B, etc.)
-
-                ret
-
-__getdrv        ENDP
-
-;
-; void _getvect( int, unsigned int *, unsigned int * );
-;
-
-                PUBLIC  __getvect
-IFDEF LCODE
-__getvect       PROC    far
-ELSE
-__getvect       PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    ds
-                push    si                      ; preserve register variable
-
-                mov     ah,35h                  ; get interrupt vector
-                mov     al,byte ptr [bp+ARG_1]  ; interrupt number
-                int     21h
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+2]
-ELSE
-                mov     si,word ptr [bp+ARG_1+2]
-ENDIF
-                mov     ds:[si],es              ; segment
-IFDEF LDATA
-                lds     si,dword ptr [bp+ARG_1+6]
-ELSE
-                mov     si,word ptr [bp+ARG_1+4]
-ENDIF
-                mov     ds:[si],bx              ; offset
-
-                pop     si                      ; restore register variable
-                pop     ds
-                pop     bp
-                ret
-
-__getvect       ENDP
-
-;
-; void _setvect( VECTOR * );
-;
-
-                PUBLIC  __setvect
-IFDEF LCODE
-__setvect       PROC    far
-ELSE
-__setvect       PROC    near
-ENDIF
-
-                push    bp
-                mov     bp,sp
-                push    ds                      ; modified in setvectsub
-
-IFDEF LDATA
-                les     bx,dword ptr [bp+ARG_1] ; vector table
-ELSE
-                mov     bx,word ptr [bp+ARG_1]  ; vector table
-                push    ds
-                pop     es
-ENDIF
-
-                call    setvectsub
-
-                pop     ds
-                pop     bp
-                ret
-
-__setvect       ENDP
-
-
-;
-; void _setdrvcd(int drive, char * string);
-;
-
-                PUBLIC  __setdrvcd
-IFDEF LCODE
-__setdrvcd      PROC    far
-ELSE
-__setdrvcd      PROC    near
-ENDIF
-                push    bp
-                mov     bp,sp
-IFDEF LDATA
-                push    ds
-ENDIF
-                mov     dl,byte ptr [bp+ARG_1]  ; drive code (0=A, 1=B)
-                mov     ah,0eh
-                int     21h
-IFDEF LDATA
-                lds     dx,dword ptr [bp+ARG_1+2] ; buffer
-ELSE
-                mov     dx,word ptr [bp+ARG_1+2] ; buffer
-ENDIF
-                mov     ah,3bh                  ; set current directory
-                int     21h
-
-IFDEF LDATA
-                pop     ds
-ENDIF
-                pop     bp
-                ret
-
-__setdrvcd      ENDP
-
-_TEXT           ENDS
-
-                END
-
diff --git a/src/odoors/ODSwap.h b/src/odoors/ODSwap.h
deleted file mode 100644
index d1d0e16d1438b3de34abaefbbfbf927baf0a79f2..0000000000000000000000000000000000000000
--- a/src/odoors/ODSwap.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODSwap.h
- *
- * Description: Provides memory swapping, spawning and certain other low-
- *              level assembly routines needed by OpenDoors. This file is only
- *              applicable when building the MS-DOS version of OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 25, 1995  6.00  BP   Created.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODSWAP
-#define _INC_ODSWAP
-
-#ifdef ODPLAT_DOS
-
-/* Data types. */
-typedef struct _vector
-{
-   char number;                        /* vector number */
-   char flag;                          /* 0-CURRENT, 1-IRET, 2-free, 3-end */
-   unsigned int vseg;                  /* vector segment */
-   unsigned int voff;                  /* vector offset */
-} VECTOR;
-
-/* Global variables. */
-extern char **environ;
-
-/* Public functions. */
-int _chkems(char *, int *);
-int _create(char *, int *);
-int _dskspace(int, unsigned int *, unsigned int *);
-int _getcd(int, char *);
-int _getdrv(void);
-int _getems(int, int *);
-int _getrc(void);
-void _getvect(int, unsigned int *, unsigned int *);
-int _restmap(char *);
-int _savemap(char *);
-void _setdrvcd(int, char * );
-void _setvect(VECTOR *);
-int _xsize(unsigned int, long *, long *);
-int _xspawn(char *, char *, char *, VECTOR *, int, int, char *, int);
-
-#endif /* ODPLAT_DOS */
-
-
-#endif /* _INC_ODSWAP */
diff --git a/src/odoors/ODTypes.h b/src/odoors/ODTypes.h
deleted file mode 100644
index 89595ac40d983d7b9505b3544c17ad1eb35b9ea2..0000000000000000000000000000000000000000
--- a/src/odoors/ODTypes.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODTypes.c
- *
- * Description: Defines special data types used by OpenDoors.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 15, 1994  6.00  BP   Created.
- *              Jan 30, 1996  6.00  BP   Added kODRCTimeout.
- *              Feb 08, 1996  6.00  BP   Added kODRCSafeFailure.
- *              Feb 08, 1996  6.00  BP   Added kODRCUnrecoverableFailure.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#ifndef _INC_ODTYPES
-#define _INC_ODTYPES
-
-/* Generic handle data type. */
-typedef void * tODHandle;
-#define ODHANDLE2PTR(h, t) ((t *) h)
-#define ODPTR2HANDLE(p, t) ((tODHandle) p)
-
-/* OpenDoors function call result codes. */
-typedef enum
-{
-   kODRCSuccess,
-   kODRCGeneralFailure,
-   kODRCNoMemory,
-   kODRCNothingWaiting,
-   kODRCNoMatch,
-   kODRCEndOfFile,
-   kODRCNoPortAddress,
-   kODRCNoUART,
-   kODRCInvalidCall,
-   kODRCFileAccessError,
-   kODRCFilenameTooLong,
-   kODRCTimeout,
-   kODRCSafeFailure,
-   kODRCUnrecoverableFailure,
-   kODRCUnsupported,
-} tODResult;
-
-/* Callback function types. */
-#ifdef _MSC_VER
-typedef void ODCALL OD_COMPONENT_CALLBACK(void);
-typedef void ODCALL OD_PERSONALITY_CALLBACK(BYTE btOperation);
-#else /* !_MSC_VER */
-typedef void OD_COMPONENT_CALLBACK(void);
-typedef void OD_PERSONALITY_CALLBACK(BYTE btOperation);
-#endif /* !_MSC_VER */
-
-#endif /* !_INC_ODTYPES */
diff --git a/src/odoors/ODUtil.c b/src/odoors/ODUtil.c
deleted file mode 100644
index 053ae063aa482b408f1395033fb4c4a10d151b52..0000000000000000000000000000000000000000
--- a/src/odoors/ODUtil.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODUtil.c
- *
- * Description: Implements the non-platform specific utility functions that
- *              are defined in odutil.h. Platform specific utility functions
- *              are implemented in odplat.c.
- *
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 01, 1994  6.00  BP   Created.
- *              Dec 31, 1994  6.00  BP   Added ODMakeFilename().
- *              Nov 13, 1995  6.00  BP   32-bit portability.
- *              Nov 23, 1995  6.00  BP   Added ODDWordDivide().
- *              Nov 23, 1995  6.00  BP   Added ODDStringHasTail().
- *              Nov 23, 1995  6.00  BP   Added ODFileSize().
- *              Nov 24, 1995  6.00  BP   ODMakeFilename(): handle empty path.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Added ODDWordMultiply().
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODUtil.h"
-#include "ODGen.h"
-
-
-/* ========================================================================= */
-/* General string manipulation functions.                                    */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODStringCopy()
- *
- * Safely copies one string to another. Unlike strncpy(), ODStringCopy()
- * ensures that the destination string is always '\0' terminated.
- *
- * Parameters: pszDest     - Pointer to destination string to which to copy
- *                           characters.
- *
- *             pszSource   - Pointer to source string from which to copy
- *                           characters.
- *
- *             nSizeOfDest - Maximum number of characters to place in pszDest,
- *                           INCLUDING the '\0' string terminator.
- *
- *     Return: void
- */
-void ODStringCopy(char *pszDest, CONST char *pszSource, INT nSizeofDest)
-{
-   ASSERT(pszDest != NULL);
-   ASSERT(pszSource != NULL);
-   ASSERT(nSizeofDest > 0);
-
-   /* Copy at most the specified number of bytes from source to dest, using */
-   /* (presumably well optimized) strncpy().                                */
-   strncpy(pszDest, pszSource, nSizeofDest);
-
-   /* Ensure that destination string is '\0' terminated. This will not */
-   /* already be the case if strlen(pszSource) >= nSizeofDest.         */
-   pszDest[nSizeofDest - 1] = '\0';
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStringCToPascal()
- *
- * Converts a string from C's zero-terminated string format to Pascal's
- * length byte + string data format.
- *
- * Parameters: psPascalString    - Pointer to the destination string.
- *
- *             btMaxPascalLength - Size of the destination string, as declared
- *                                 in Pascal.
- *
- *             pszCString        - Pointer to the source string, in C format.
- *
- *     Return: A pointer to psPascalString.
- */
-char *ODStringCToPascal(char *psPascalString, BYTE btMaxPascalLength,
-   char *pszCString)
-{
-   BYTE btCStringLength = strlen(pszCString);
-
-   ASSERT(psPascalString != NULL);
-   ASSERT(btMaxPascalLength > 0);
-   ASSERT(pszCString != NULL);
-
-   memcpy((char *)psPascalString + 1,
-      pszCString, *psPascalString = (btCStringLength < btMaxPascalLength)
-      ? btCStringLength : btMaxPascalLength);
-   return(psPascalString);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStringPascalToC()
- *
- * Converts a string from Pascal's length byte + string data format to C's
- * zero-terminated string format.
- *
- * Parameters: pszCString     - Pointer to destination string.
- *
- *             psPascalString - Pointer to Pascal format source string.
- *
- *             btMaxLength    - Length of C string.
- *
- *     Return: A pointer to pszCString.
- */
-char *ODStringPascalToC(char *pszCString, char *psPascalString,
-   BYTE btMaxLength)
-{
-   ASSERT(pszCString != NULL);
-   ASSERT(psPascalString != NULL);
-   ASSERT(btMaxLength > 0);
-
-   if(*(BYTE *)psPascalString <= btMaxLength)
-   {
-      memcpy(pszCString, (char *)psPascalString + 1, *psPascalString);
-      pszCString[*psPascalString] = '\0';
-   }
-   else
-   {
-      pszCString[0] = '\0';
-   }
-   return(pszCString);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODStringHasTail()
- *
- * Determines whether a string ends in exactly the specified sequence of
- * characters.
- *
- * Parameters: pszFullString  - String to examine.
- *
- *             pszTail        - String to look for at the end of
- *                              pszFullString.
- *
- *     Return: TRUE if the pszFullString does end with pszTail, FALSE if
- *             it does not.
- */
-BOOL ODStringHasTail(char *pszFullString, char *pszTail)
-{
-   INT nTailLength = strlen(pszTail);
-   INT nFullStringLength = strlen(pszFullString);
-
-   ASSERT(pszFullString != NULL);
-   ASSERT(pszTail != NULL);
-
-   if(nFullStringLength < nTailLength)
-   {
-      return(FALSE);
-   }
-
-   return(stricmp(pszFullString + (nFullStringLength - nTailLength), pszTail) == 0);
-}
-
-
-/* ========================================================================= */
-/* File-related functions.                                                   */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODMakeFilename()
- *
- * Generates a fully-qualified filename from a path and base filename.
- *
- * Parameters: pszOut      - String to store generated filename in.
- *
- *             pszPath     - Directory name. May be the same as pszOut, or
- *                           may be different.
- *
- *             pszFilename - Base filename.
- *
- *             nMaxOutSize - Size of pszOut. This value should be one more
- *                           than the maximum number of characters to be
- *                           stored in the output string.
- *
- *     Return: kODRCSuccess on success, or an error code on failure.
- */
-tODResult ODMakeFilename(char *pszOut, CONST char *pszPath,
-   CONST char *pszFilename, INT nMaxOutSize)
-{
-   /* Validate parameters in debug mode */
-   ASSERT(pszPath != NULL);
-   ASSERT(pszFilename != NULL);
-   ASSERT(pszOut != NULL);
-   ASSERT(pszFilename != pszOut);
-   ASSERT(nMaxOutSize > 0);
-
-   /* Check that there is enough room in the destination string to hold */
-   /* both source strings plus possibly an additional \-seperator.      */
-   if((INT)(strlen(pszPath) + strlen(pszFilename) + 1) > nMaxOutSize - 1)
-   {
-      return(kODRCFilenameTooLong);
-   }
-
-   /* Copy path to output filename, if the addresses are different. */
-   if(pszPath != pszOut)
-   {
-      strcpy(pszOut, pszPath);
-   }
-
-   /* Ensure there is a trailing backslash, if path was not empty. */
-   if(pszOut[strlen(pszOut) - 1] != '\\' && strlen(pszOut) > 0)
-   {
-      strcat(pszOut, "\\");
-   }
-
-   /* Append base filename. */
-   strcat(pszOut, pszFilename);
-
-   return(kODRCSuccess);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODFileSize()
- *
- * Determines the size of a currently open file.
- *
- * Parameters: pfFile - Pointer to an already open file to examine.
- *
- *     Return: The size of the file. In the case of a file that is open in
- *             binary mode, this will be the file length in bytes.
- */
-DWORD ODFileSize(FILE *pfFile)
-{
-   DWORD dwOriginal;
-   DWORD dwFileSize;
-
-   ASSERT(pfFile != NULL);
-
-   dwOriginal = ftell(pfFile);
-   fseek(pfFile, 0L, SEEK_END);
-   dwFileSize = ftell(pfFile);
-   fseek(pfFile, dwOriginal, SEEK_SET);
-   return(dwFileSize);
-}
-
-
-/* ========================================================================= */
-/* DWORD math functions.                                                     */
-/* ========================================================================= */
-
-/* ----------------------------------------------------------------------------
- * ODDWordShiftLeft()
- *
- * Shifts a DWORD to the left by the specified number of bits.
- *
- * Parameters: dwValue    - Value to be shifted.
- *
- *             btDistance - Distance to shift dwValue by.
- *
- *     Return: Result of the shift operation.
- */
-DWORD ODDWordShiftLeft(DWORD dwValue, BYTE btDistance)
-{
-   WORD wUpper;
-   WORD wLower;
-
-   wLower = (WORD)dwValue;
-   wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
-
-   while(btDistance--)
-   {
-      wUpper <<= 1;
-      wUpper |= (wLower & 0x8000) >> 15;
-      wLower <<= 1;
-   }
-
-   dwValue = wLower;
-   *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
-
-   return(dwValue);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDWordShiftRight()
- *
- * Shifts a DWORD to the right by the specified number of bits.
- *
- * Parameters: dwValue    - Value to be shifted.
- *
- *             btDistance - Distance to shift dwValue by.
- *
- *     Return: Result of the shift operation.
- */
-DWORD ODDWordShiftRight(DWORD dwValue, BYTE btDistance)
-{
-   WORD wUpper;
-   WORD wLower;
-
-   wLower = (WORD)dwValue;
-   wUpper = *(WORD *)(((BYTE *)(&dwValue)) + 2);
-
-   while(btDistance--)
-   {
-      wLower >>= 1;
-      wLower |= (wUpper & 0x0001) << 15;
-      wUpper >>= 1;
-   }
-
-   dwValue=wLower;
-   *(WORD *)(((BYTE *)(&dwValue)) + 2) = wUpper;
-   return(dwValue);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDWordDivide()
- *
- * Divides one DWORD by another DWORD, calculating the quotient and remainder.
- *
- * Parameters: pdwQuotient   - Location where the quotient should be stored,
- *                             or NULL if quotient is not required.
- *
- *             pdwRemainder  - Location where remainder should be stored,
- *                             or NULL if remainder is not required.
- *
- *             dwDividend    - Dividend to be divided by divisor.
- *
- *             dwDivisor     - Divisor to divide dividend by.
- *
- *     Return: TRUE on success or FALSE on failure.
- */
-BOOL ODDWordDivide(DWORD *pdwQuotient, DWORD *pdwRemainder,
-   DWORD dwDividend, DWORD dwDivisor)
-{
-   INT nTimes = 0;
-   DWORD dwQuotient;
-   DWORD dwRemainder;
-
-   /* Check for divide by zero in debug versions. */
-   ASSERT(dwDivisor != 0);
-
-   /* Check that divisor is not zero. (An attempt to divide by zero will */
-   /* put this algorithm into an infinite loop, rather than triggering   */
-   /* a divide fault.)                                                   */
-   if(dwDivisor == 0L)
-   {
-      return(FALSE);
-   }
-
-   /* Initialize remainder to be entire dividend */
-   dwRemainder = dwDividend;
-
-   /* Initialize quotient to 0 */
-   dwQuotient = 0L;
-
-   /* Determine largest required multiple of divisor */
-   while(dwRemainder >=  dwDivisor)
-   {
-      dwDivisor = ODDWordShiftLeft(dwDivisor, 1);
-      ++nTimes;
-   }
-
-   /* Loop across for all multiples of divisor, beginning with the largest */
-   do
-   {
-      dwQuotient = ODDWordShiftLeft(dwQuotient, 1);
-
-      /* If current remainder is >= this multiple of the divisor */
-      if(dwRemainder >= dwDivisor)
-      {
-         /* Subtract the multiple of the divisor from the remainder */
-         dwRemainder -= dwDivisor;
-
-         /* The next bit of the quotient should be a 1 */
-         dwQuotient |= 1L;
-      }
-
-      /* Divide current multiple of divisor by two */
-      dwDivisor = ODDWordShiftRight(dwDivisor, 1);
-
-      /* Repeat for all multiples of the divisor */
-   } while(nTimes--);
-
-   /* If caller asked for quotient, then return it */
-   if(pdwQuotient != NULL)
-   {
-      *pdwQuotient = dwQuotient;
-   }
-
-   /* If caller asked for remainder, then return it */
-   if(pdwRemainder != NULL)
-   {
-      *pdwRemainder = dwRemainder;
-   }
-
-   return(TRUE);
-}
-
-
-/* ----------------------------------------------------------------------------
- * ODDWordDivide()
- *
- * Multiplies one DWORD by another, returning the product. Multiplication
- * is performed by using at most 32 additions.
- *
- * Parameters: dwMultiplicand - The multiplicand.
- *
- *             dwMultiplier   - The multiplier.
- *
- *     Return: Result of the multiplication.
- */
-DWORD ODDWordMultiply(DWORD dwMultiplicand, DWORD dwMultiplier)
-{
-   DWORD dwResult = 0;
-
-   /* Loop while multiplier is not zero */
-   while(dwMultiplier != 0)
-   {
-      /* If least significant bit of multiplier is set */
-      if(dwMultiplier & 0x00000001)
-      {
-         /* Add multiplicand to product */
-         dwResult += dwMultiplicand;
-      }
-
-      /* Shift multiplicand left one bit */
-      dwMultiplicand = ODDWordShiftLeft(dwMultiplicand, 1);
-
-      /* Shift multiplier right one bit */
-      dwMultiplier = ODDWordShiftRight(dwMultiplier, 1);
-   }
-
-   /* Return the final result to the caller. */
-   return(dwResult);
-}
diff --git a/src/odoors/ODUtil.h b/src/odoors/ODUtil.h
deleted file mode 100644
index da5423ef0b6d2f3af433c7f3f6826e5b95cb7ceb..0000000000000000000000000000000000000000
--- a/src/odoors/ODUtil.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODUtil.h
- *
- * Description: Contains prototypes and definitions for use by non-platform
- *              specific utility functions. These functions are implemented in
- *              odutil.c. Platform-specific utility functions are defined in
- *              odplat.h, and implemented in odplat.c.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Nov 01, 1994  6.00  BP   Created.
- *              Dec 31, 1994  6.00  BP   Added ODMakeFilename().
- *              Nov 13, 1995  6.00  BP   32-bit portability.
- *              Nov 23, 1995  6.00  BP   Added ODDWordDivide().
- *              Nov 23, 1995  6.00  BP   Added ODDStringHasTail().
- *              Nov 23, 1995  6.00  BP   Added ODFileSize().
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 06, 1996  6.10  BP   Added ODDWordMultiply().
- */
-
-#ifndef _INC_ODUTIL
-#define _INC_ODUTIL
-
-#include "ODGen.h"
-#include "ODTypes.h"
-#include "OpenDoor.h"
-
-/* General string manipulation functions. */
-void ODStringCopy(char *pszDest, CONST char *pszSource, INT nSizeofDest);
-char *ODStringCToPascal(char *psPascalString, BYTE btMaxPascalLength,
-   char *pszCString);
-char *ODStringPascalToC(char *pszCString, char *psPascalString,
-   BYTE btMaxLength);
-BOOL ODStringHasTail(char *pszFullString, char *pszTail);
-
-/* File-related functions. */
-tODResult ODMakeFilename(char *pszOut, CONST char *pszPath,
-   CONST char *pszFilename, INT nMaxOutSize);
-DWORD ODFileSize(FILE *pfFile);
-
-/* DWORD math functions. */
-DWORD ODDWordShiftLeft(DWORD dwValue, BYTE btDistance);
-DWORD ODDWordShiftRight(DWORD dwValue, BYTE btDistance);
-BOOL ODDWordDivide(DWORD *pdwQuotient, DWORD *pdwRemainder,
-   DWORD dwDividend, DWORD dwDivisor);
-DWORD ODDWordMultiply(DWORD dwMultiplicand, DWORD dwMultiplier);
-
-#endif /* !_INC_ODUTIL */
diff --git a/src/odoors/ODWCat.c b/src/odoors/ODWCat.c
deleted file mode 100644
index de79091204a171487cbe0f53f6a39b29a1c4908b..0000000000000000000000000000000000000000
--- a/src/odoors/ODWCat.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODWCat.c
- *
- * Description: Implements the Wildcat personality.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Jul 18, 1995  6.00  BP   Fix ODStatGetUserAge() bug.
- *              Nov 13, 1995  6.00  BP   32-bit portability.
- *              Nov 14, 1995  6.00  BP   Added include of odscrn.h.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 24, 1995  6.00  BP   Fixed black square at pos 25x80.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 03, 1996  6.00  BP   Display connect speed with %lu.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 19, 1996  6.10  BP   MSVC15 source-level compatibility.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <ctype.h>
-#include <stddef.h>
-#include <time.h>
-#include <stdio.h>
-
-#include "OpenDoor.h"
-#include "ODGen.h"
-#include "ODScrn.h"
-#include "ODCore.h"
-#include "ODStat.h"
-#include "ODKrnl.h"
-
-
-/* ----------------------------------------------------------------------------
- * pdef_wildcat()
- *
- * Personality function for the Wildcat BBS-like status line / function key
- * personality.
- *
- * Parameters: btOperation - Indicates personality operation to be performed.
- *
- *     Return: void
- */
-ODAPIDEF void ODCALL pdef_wildcat(BYTE btOperation)
-{
-   BYTE btInfoType = od_control.od_info_type;
-
-   switch(btOperation)
-   {
-      case PEROP_DISPLAY1:
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(1,24);
-         ODScrnDisplayString("                                    Baud:                                       ");
-         ODScrnSetCursorPos(1,25);
-         ODScrnDisplayString("Phone:                               Sec:                      Time Left:      ");
-         ODScrnPutText(80, 25, 80, 25, abtGreyBlock);
-
-         ODScrnSetAttribute(0x71);
-         ODScrnSetCursorPos(1,24);
-         sprintf(szStatusText, "(%s), ", od_control.user_name,
-            od_control.user_location);
-         ODScrnPrintf("%34.34s", szStatusText);
-         ODScrnSetCursorPos(43, 24);
-         ODScrnPrintf("%lu", od_control.od_connect_speed);
-
-         ODScrnSetCursorPos(8,25);
-         if(od_control.od_extended_info || btInfoType==SFDOORSDAT || btInfoType==DOORSYS_GAP || btInfoType==DOORSYS_WILDCAT)
-         {
-            ODScrnDisplayString(od_control.user_homephone);
-         }
-
-         if(btInfoType==RA1EXITINFO || btInfoType==RA2EXITINFO || btInfoType==DOORSYS_WILDCAT)
-         {
-            char szUserAge[7];
-            ODScrnSetCursorPos(28,25);
-            ODScrnSetAttribute(0x70);
-            ODScrnDisplayString("Age: ");
-            ODScrnSetAttribute(0x71);
-            ODStatGetUserAge(szUserAge);
-            ODScrnDisplayString(szUserAge);
-         }
-
-         ODScrnSetCursorPos(43,25);
-         ODScrnPrintf("%u",od_control.user_security);
-
-         if(btInfoType==RA1EXITINFO || btInfoType==RA2EXITINFO || btInfoType==DOORSYS_WILDCAT)
-         {
-            if(strlen(od_control.user_firstcall)==8)
-            {
-               ODScrnSetCursorPos(49,25);
-               ODScrnSetAttribute(0x70);
-               ODScrnDisplayString("Since: ");
-               ODScrnSetAttribute(0x71);
-               ODScrnDisplayChar(od_control.user_firstcall[0]);
-               ODScrnDisplayChar(od_control.user_firstcall[1]);
-               ODScrnDisplayChar('/');
-               ODScrnDisplayChar(od_control.user_firstcall[6]);
-               ODScrnDisplayChar(od_control.user_firstcall[7]);
-            }
-         }
-
-      case PEROP_UPDATE1:
-         ODScrnSetAttribute(0x71);
-         ODScrnSetCursorPos(74,25);
-         if(od_control.user_timelimit<=9)
-         {
-            ODScrnPrintf("   %d",od_control.user_timelimit);
-         }
-         else if(od_control.user_timelimit<=99)
-         {
-            ODScrnPrintf("  %d",od_control.user_timelimit);
-         }
-         else if(od_control.user_timelimit<=999)
-         {
-            ODScrnPrintf(" %d",od_control.user_timelimit);
-         }
-         else
-         {
-            ODScrnPrintf("%d",od_control.user_timelimit);
-         }
-
-         ODScrnSetAttribute(0x70);
-         ODScrnSetCursorPos(56,24);
-
-         if(od_control.od_okaytopage==TRUE)
-            ODScrnDisplayString("Page Bell ");
-         else
-            ODScrnDisplayString("          ");
-
-         if(od_control.od_user_keyboard_on)
-            ODScrnDisplayString("Kybd ");
-         else
-            ODScrnDisplayString("     ");
-
-         if(od_control.sysop_next)
-            ODScrnDisplayString("Local-Next");
-         else
-            ODScrnDisplayString("          ");
-         break;
-
-      case PEROP_INITIALIZE:
-         od_control.key_hangup=0x0000;
-         od_control.key_drop2bbs=0x4400;
-         od_control.key_dosshell=0x2000;
-         od_control.key_chat=0x4100;
-         od_control.key_sysopnext=0x3b00;
-         od_control.key_lockout=0x8100;
-         od_control.key_status[0]=0x0000;
-         od_control.key_status[1]=0x0000;
-         od_control.key_status[2]=0x0000;
-         od_control.key_status[3]=0x0000;
-         od_control.key_status[4]=0x0000;
-         od_control.key_status[5]=0x0000;
-         od_control.key_status[6]=0x0000;
-         od_control.key_status[7]=0x0000;
-         od_control.key_status[8]=0x0000;
-         od_control.key_keyboardoff=0x2500;
-         od_control.key_moretime=0x0000;
-         od_control.key_lesstime=0x0000;
-         od_control.od_page_statusline=-1;
-         ODStatAddKey(0x4200);         /* Key to end chat */
-         ODStatAddKey(0x4800);         /* Key to add five minutes */
-         ODStatAddKey(0x5000);         /* key to subtract five minutes */
-         ODStatAddKey(0x7800);         /* key to hangup */
-         ODStatAddKey(0x7900);         /* key to hangup */
-         ODStatAddKey(0x7a00);         /* key to hangup */
-         ODStatAddKey(0x7b00);         /* key to hangup */
-         ODStatAddKey(0x7c00);         /* key to hangup */
-         ODStatAddKey(0x7d00);         /* key to hangup */
-         ODStatAddKey(0x7e00);         /* key to hangup */
-         ODStatAddKey(0x7f00);         /* key to hangup */
-         ODStatAddKey(0x8000);         /* key to hangup */
-         ODStatAddKey(0x3f00);         /* key to toggle bell */
-         ODStatAddKey(0x3e00);         /* key to toggle bell */
-         break;
-
-      case PEROP_CUSTOMKEY:
-         switch((WORD)od_control.od_last_hot)
-         {
-            case 0x4200:
-               od_control.od_chat_active = FALSE;
-               break;
-
-            case 0x4800:
-               if(od_control.user_timelimit <= 1435)
-               {
-                  od_control.user_timelimit += 5;
-                  bForceStatusUpdate = TRUE;
-                  CALL_KERNEL_IF_NEEDED();
-               }
-               break;
-
-            case 0x5000:
-               od_control.user_timelimit -= 5;
-               bForceStatusUpdate = TRUE;
-               CALL_KERNEL_IF_NEEDED();
-               break;
-
-            case 0x7800:
-            case 0x7900:
-            case 0x7a00:
-            case 0x7b00:
-            case 0x7c00:
-            case 0x7d00:
-            case 0x7e00:
-            case 0x7f00:
-            case 0x8000:
-               od_exit(2,TRUE);
-               break;
-
-            case 0x3f00:
-            case 0x3e00:
-               if(od_control.od_okaytopage!=TRUE)
-               {
-                  od_control.od_okaytopage=TRUE;
-               }
-               else
-               {
-                  od_control.od_okaytopage=FALSE;
-               }
-               bForceStatusUpdate = TRUE;
-               CALL_KERNEL_IF_NEEDED();
-               break;
-
-            default:
-               return;
-         }
-         od_control.od_last_hot=0;
-         break;
-
-      case PEROP_DEINITIALIZE:
-         ODStatRemoveKey(0x4200);
-         ODStatRemoveKey(0x4800);
-         ODStatRemoveKey(0x5000);
-         ODStatRemoveKey(0x7800);
-         ODStatRemoveKey(0x7900);
-         ODStatRemoveKey(0x7a00);
-         ODStatRemoveKey(0x7b00);
-         ODStatRemoveKey(0x7c00);
-         ODStatRemoveKey(0x7d00);
-         ODStatRemoveKey(0x7e00);
-         ODStatRemoveKey(0x7f00);
-         ODStatRemoveKey(0x8000);
-         ODStatRemoveKey(0x3e00);
-         ODStatRemoveKey(0x3f00);
-         break;
-   }
-}
diff --git a/src/odoors/ODWin.c b/src/odoors/ODWin.c
deleted file mode 100644
index 923cff3458e2358e93af51d36b0ee3b22fb64a28..0000000000000000000000000000000000000000
--- a/src/odoors/ODWin.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: ODWin.c
- *
- * Description: Implements the od_window_...() functions for creating
- *              and removing text-mode windows.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Oct 13, 1994  6.00  BP   New file header format.
- *              Nov 01, 1994  6.00  BP   Include stdlib.h for malloc prototype.
- *              Dec 09, 1994  6.00  BP   Standardized coding style.
- *              Dec 12, 1994  6.00  BP   Set od_error on window remove failure.
- *              Aug 19, 1995  6.00  BP   32-bit portability.
- *              Nov 16, 1995  6.00  BP   Removed oddoor.h, added odcore.h.
- *              Dec 12, 1995  6.00  BP   Added entry, exit and kernel macros.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- */
-
-#define BUILDING_OPENDOORS
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "OpenDoor.h"
-#include "ODGen.h"
-#include "ODCore.h"
-#include "ODKrnl.h"
-
-
-/* ----------------------------------------------------------------------------
- * od_window_create()
- *
- * Creates a window on the screen, storing information on the original screen
- * contents "under" the window in order to restore the screen after the window
- * is removed. A window that is created with this function must be destroyed
- * by od_window_remove() in order to free up memory that is allocated by this
- * function.
- *
- * Parameters: nLeft        - 1-based column number of left edge of window.
- *
- *             nTop         - 1-based row number of top edge of window.
- *
- *             nRight       - 1-based column number of right edge of window.
- *
- *             nBottom      - 1-based row number of bottom edge of window.
- *
- *             pszTitle     - Pointer to a string containing title for window.
- *                            If this string is empty, no title is displayed.
- *
- *             btBoarderCol - Colour of window boarder.
- *
- *             btTitleCol   - Colour of window title.
- *
- *             btInsideCol  - Colour of rest of window.
- *
- *             nReserved    - Should always be 0 for this version.
- *
- *     Return: Pointer to window description buffer (which must later be
- *             passed to od_window_remove(), or NULL on failure.
- */
-ODAPIDEF void * ODCALL od_window_create(INT nLeft, INT nTop, INT nRight,
-   INT nBottom, char *pszTitle, BYTE btBorderCol, BYTE btTitleCol,
-   BYTE btInsideCol, INT nReserved)
-{
-   BYTE btLine;
-   BYTE btBetweenSize;
-   void *pBuffer;
-   BYTE btTitleSize;
-   BYTE btRemaining;
-
-   /* Log function entry if running in trace mode. */
-   TRACE(TRACE_API, "od_window_create()");
-
-   /* Ensure that OpenDoors has been initialized */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   nReserved &= 0x00;
-
-   btBetweenSize = (nRight - nLeft) - 1;
-
-   /* Setup od_box_chars appropriately. */
-   if(od_control.od_box_chars[BOX_BOTTOM]==0)
-   {
-      od_control.od_box_chars[BOX_BOTTOM] = od_control.od_box_chars[BOX_TOP];
-   }
-   if(od_control.od_box_chars[BOX_RIGHT]==0)
-   {
-      od_control.od_box_chars[BOX_RIGHT] = od_control.od_box_chars[BOX_LEFT];
-   }
-
-   /* Ensure that the current display mode can support the capabilities */
-   /* required to display and remove windows.                           */
-   if(!(od_control.user_ansi || od_control.user_avatar))
-   {
-      od_control.od_error = ERR_NOGRAPHICS;
-      OD_API_EXIT();
-      return(NULL);
-   }
-
-   /* Validate parameters. */
-   if(nLeft < 1 || nTop < 1 || nRight > 80 || nBottom > 25 || nRight-nLeft < 2
-      || nBottom-nTop < 2)
-   {
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(NULL);
-   }
-
-   /* Allocate a buffer large enough to hold all window information. */
-   if((pBuffer = malloc((nRight - nLeft + 1) * 2 + (nBottom - nTop + 1) * 160
-      + 4)) == NULL)
-   {
-      od_control.od_error = ERR_MEMORY;
-      OD_API_EXIT();
-      return(NULL);
-   }
-
-   /* Store current contents of screen where window will be drawn. */
-   if(!od_gettext(nLeft, nTop, nRight, nBottom, (char *)pBuffer+4))
-   {
-      free(pBuffer);
-
-      /* Note: od_control.od_error code has been set by od_gettext(). */
-
-      OD_API_EXIT();
-      return(NULL);
-   }
-
-   /* Store window information in buffer. */
-   ((char *)pBuffer)[0]=nLeft;
-   ((char *)pBuffer)[1]=nTop;
-   ((char *)pBuffer)[2]=nRight;
-   ((char *)pBuffer)[3]=nBottom;
-
-   /* Determine number of characters of title to display. */
-   if(pszTitle==NULL)
-   {
-      btTitleSize = 0;
-   }
-   else
-   {
-      if((btTitleSize = strlen(pszTitle)) > (btBetweenSize - 4))
-      {
-         btTitleSize = btBetweenSize - 4;
-      }
-   }
-
-   /* Move to position of window's top corner, prepare to begin drawing the */
-   /* window.                                                               */
-   od_set_cursor(nTop,nLeft);
-   od_set_attrib(btBorderCol);
-
-   /* Display corner character. */
-   od_putch(od_control.od_box_chars[BOX_UPPERLEFT]);
-
-   /* If there is no title, display top line all in one piece. */
-   if(btTitleSize == 0)
-   {
-      /* Display top line. */
-      od_repeat(od_control.od_box_chars[BOX_TOP],btBetweenSize);
-   }
-   else
-   {
-      /* If there is a title, display the top line with a title centered in */
-      /* it.                                                                */
-      od_repeat(od_control.od_box_chars[BOX_TOP],btRemaining =
-         ((btBetweenSize - btTitleSize - 2) / 2));
-      od_set_attrib(btTitleCol);
-      od_putch(' ');
-      od_disp(pszTitle,btTitleSize,TRUE);
-      od_putch(' ');
-      od_set_attrib(btBorderCol);
-      od_repeat(od_control.od_box_chars[BOX_TOP],
-         (BYTE)(btBetweenSize - btRemaining - btTitleSize - 2));
-   }
-
-   /* Display top right corner character. */
-   od_putch(od_control.od_box_chars[BOX_UPPERRIGHT]);
-
-   /* If AVATAR mode is available. */
-   if(od_control.user_avatar)
-   {
-      /* Display first left verticle line. */
-      od_set_cursor(nTop + 1, nLeft);
-      od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-      /* Fill in center of window with AVATAR clear area control sequence. */
-      od_emulate(22);
-      od_emulate(12);
-      od_emulate(btInsideCol);
-      od_emulate((BYTE)((nBottom - nTop) - 1));
-      od_emulate(btBetweenSize);
-
-      od_set_attrib(btBorderCol);
-      od_set_cursor(nTop + 1 , nRight);
-
-      /* Display first right verticle line. */
-      od_putch(od_control.od_box_chars[BOX_RIGHT]);
-
-      /* Display remaining verticle lines. */
-      for(btLine=nTop+2;btLine<nBottom;++btLine)
-      {
-         /* Move to line start and display left line character. */
-         od_set_cursor(btLine,nLeft);
-         od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-         /* Move to line start and display right line character. */
-         od_set_cursor(btLine,nRight);
-         od_putch(od_control.od_box_chars[BOX_RIGHT]);
-      }
-   }
-
-   /* If AVATAR mode is not available. */
-   else
-   {
-      /* Loop through middle lines of window. */
-      for(btLine=nTop+1;btLine<nBottom;++btLine)
-      {
-         /* Move to line start and display left line character. */
-         od_set_cursor(btLine,nLeft);
-         od_putch(od_control.od_box_chars[BOX_LEFT]);
-
-         /* Set window colour. */
-         od_set_attrib(btInsideCol);
-
-         /* display blank area between left and right vertical lines. */
-         od_repeat(' ',btBetweenSize);
-
-         /* Set border colour. */
-         od_set_attrib(btBorderCol);
-
-         /* Display right line. */
-         od_putch(od_control.od_box_chars[BOX_RIGHT]);
-      }
-   }
-
-   /* Display bottom border of window */
-   od_set_cursor(nBottom,nLeft);
-   od_putch(od_control.od_box_chars[BOX_LOWERLEFT]);
-   od_repeat(od_control.od_box_chars[BOX_BOTTOM],btBetweenSize);
-   od_putch(od_control.od_box_chars[BOX_LOWERRIGHT]);
-
-   /* Return a pointer to the window information buffer. */
-   OD_API_EXIT();
-   return(pBuffer);
-}
-
-
-/* ----------------------------------------------------------------------------
- * od_window_remove()
- *
- * Removes window from the screen, restoring the screen contents that where
- * in the window area when the window was first created.
- *
- * Parameters: pWinInfo - Pointer to buffer returned by od_window_create().
- *                        This buffer is deallocated before od_window_remove()
- *                        returns.
- *
- *     Return: TRUE on success, or FALSE on failure.
- */
-ODAPIDEF BOOL ODCALL od_window_remove(void *pWinInfo)
-{
-   /* Log function entry if running in trace mode */
-   TRACE(TRACE_API, "od_window_remove()");
-
-   /* Ensure that OpenDoors has been initialized */
-   if(!bODInitialized) od_init();
-
-   OD_API_ENTRY();
-
-   if(pWinInfo == NULL)
-   {
-      /* Set error code and return with failure. */
-      od_control.od_error = ERR_PARAMETER;
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   if(!od_puttext(((char *)pWinInfo)[0], ((char *)pWinInfo)[1], ((char *)pWinInfo)[2], ((char *)pWinInfo)[3], (char *)pWinInfo + 4))
-   {
-      /* Deallocate memory assigned to window information structure. */
-      free(pWinInfo);
-
-      /* Note: od_control.od_error code has been set by od_puttext(). */
-
-      /* Return with failure. */
-      OD_API_EXIT();
-      return(FALSE);
-   }
-
-   /* Deallocate memory assigned to window information structure. */
-   free(pWinInfo);
-
-   /* Return with success. */
-   OD_API_EXIT();
-   return(TRUE);
-}
diff --git a/src/odoors/ODoorW.lib b/src/odoors/ODoorW.lib
deleted file mode 100644
index 2c7182c2d7acef4ca219fdd1d700d1d4cccc5482..0000000000000000000000000000000000000000
Binary files a/src/odoors/ODoorW.lib and /dev/null differ
diff --git a/src/odoors/ODoors62.dll b/src/odoors/ODoors62.dll
deleted file mode 100644
index 74266f95d9dd92a8f6a3797036457101c4b36596..0000000000000000000000000000000000000000
Binary files a/src/odoors/ODoors62.dll and /dev/null differ
diff --git a/src/odoors/OPENDOOR.TXT b/src/odoors/OPENDOOR.TXT
deleted file mode 100644
index 3779bf67d942f5e37876629ed5575798f5a2f964..0000000000000000000000000000000000000000
--- a/src/odoors/OPENDOOR.TXT
+++ /dev/null
@@ -1,14805 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-    ����������                         ��������
-    ����������                         ���������
-    ���    ��� ������� ������� ������� ���   ��� ������� ������� ������ �������
-    ���    ��� ������� ������� ������� ���   ��� ������� ������� ������ �������
-    ���������� ��� ��� ������� ��� ��� ��������� ��� ��� ��� ��� ���    �������
-    ���������� ������� ������� ��� ��� ��������  ������� ������� ���    �������
-               ���
-               ���
-               ���                          Online Software Programming Toolkit
-    ���������������������������������������������������������������������������
-
-                                                            Programmer's Manual
-
-
-                                                                   Version 6.00
-
-
-                                                         DOS and Win32 Editions
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-          NOTE: Since you will likely want to refer to this manual while
-                working with OpenDoors, it is highly recommended that you take
-                the time to print it out. Simply type COPY OPENDOOR.TXT PRN
-                from your DOS prompt. With the exception of this title page,
-                this document contains only 7-bit ASCII characters.
-
-
-
-
-        (C) Copyright 1991 - 1996 by Brian Pirie. All Rights Reserved.
-
-                              TABLE OF CONTENTS
-
-
-CHAPTER 1 - INTRODUCTION TO OPENDOORS.......................................5
-    WELCOME! ...............................................................5
-    FEATURES OF THE OPENDOORS TOOLKIT ......................................6
-
-CHAPTER 2 - ABOUT THIS EVALUATION COPY AND ORDERING.........................9
-    THE EVALUATION COPY & BENEFITS OF REGISTERING ..........................9
-    HOW TO ORDER ...........................................................10
-    HOW TO ORDER BY MAIL ...................................................11
-    SENDING YOUR ORDER FEE IN THE MAIL .....................................12
-    ORDERING BY CREDIT CARD ................................................14
-    HOW YOU CAN RECEIVE YOUR ORDER .........................................15
-    ORDERING THE SOURCE CODE ...............................................17
-    OPENDOORS 6.00 ORDER FORM ..............................................18
-    OPENDOORS 6.00 FEEDBACK FORM ...........................................19
-    TERMS OF REGISTRATION AND SOURCE CODE USE ..............................20
-
-CHAPTER 3 - OPENDOORS TUTORIAL..............................................21
-    ABOUT THIS MANUAL ......................................................21
-    COMPILING A PROGRAM WITH OPENDOORS .....................................22
-    LINKING WITH OPENDOORS USING A DOS COMPILER ............................23
-    LINKING WITH OPENDOORS USING A WINDOWS COMPILER ........................24
-    RUNNING A DOOR PROGRAM WRITTEN WITH OPENDOORS ..........................26
-    RUNNING DOS-BASED DOOR PROGRAMS ........................................26
-    RUNNING WINDOWS 95/NT DOOR PROGRAMS ....................................26
-    BASICS OF DOOR PROGRAMMING WITH OPENDOORS ..............................29
-    TOUR OF A SAMPLE DOOR PROGRAM: "EX_VOTE" ...............................33
-    OTHER EXAMPLE PROGRAMS INCLUDED WITH OPENDOORS .........................38
-
-CHAPTER 4 - THE OPENDOORS API FUNCTIONS.....................................40
-    OVERVIEW ...............................................................40
-    TABLE OF MOST COMMONLY USED FUNCTIONS ..................................41
-    TABLE OF ALL FUNCTIONS .................................................42
-    OD_ADD_PERSONALITY() ...................................................47
-    OD_AUTODETECT() ........................................................48
-    OD_CHAT() ..............................................................50
-    OD_CARRIER() ...........................................................51
-    OD_CLEAR_KEYBUFFER() ...................................................53
-    OD_CLR_LINE() ..........................................................55
-    OD_CLR_SCR() ...........................................................57
-    OD_COLOR_CONFIG() ......................................................59
-    OD_DISP() ..............................................................60
-    OD_DISP_EMU() ..........................................................62
-    OD_DISP_STR() ..........................................................63
-    OD_DRAW_BOX() ..........................................................65
-    OD_EDIT_STR() ..........................................................68
-    OD_EXIT() ..............................................................79
-    OD_GET_ANSWER() ........................................................81
-    OD_GET_INPUT() .........................................................82
-    OD_GET_KEY() ...........................................................85
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 2
-
-    OD_GETTEXT() ...........................................................89
-    OD_HOTKEY_MENU() .......................................................90
-    OD_INIT() ..............................................................92
-    OD_INPUT_STR() .........................................................95
-    OD_KERNEL() ............................................................97
-    OD_LIST_FILES() ........................................................98
-    OD_LOG_WRITE() .........................................................100
-    OD_MULTILINE_EDIT() ....................................................101
-    OD_PAGE() ..............................................................104
-    OD_PARSE_CMD_LINE() ....................................................105
-    OD_POPUP_MENU() ........................................................107
-    OD_PRINTF() ............................................................110
-    OD_PUTCH() .............................................................115
-    OD_PUTTEXT() ...........................................................116
-    OD_REPEAT() ............................................................118
-    OD_RESTORE_SCREEN() ....................................................120
-    OD_SAVE_SCREEN() .......................................................121
-    OD_SCROLL() ............................................................123
-    OD_SEND_FILE() .........................................................124
-    OD_SET_ATTRIB() ........................................................128
-    OD_SET_COLOR() .........................................................131
-    OD_SET_CURSOR() ........................................................134
-    OD_SET_DTR() ...........................................................135
-    OD_SET_PERSONALITY() ...................................................136
-    OD_SET_STATUSLINE() ....................................................137
-    OD_SLEEP() .............................................................139
-    OD_SPAWN() .............................................................141
-    OD_SPAWNVPE() ..........................................................143
-    OD_WINDOW_CREATE() .....................................................145
-    OD_WINDOW_REMOVE() .....................................................147
-
-CHAPTER 5 - THE OPENDOORS CONTROL STRUCTURE.................................148
-    INTRODUCTION TO THE CONTROL STRUCTURE ..................................148
-    CONTROL STRUCTURE - DOOR INFO FILE STATS ...............................150
-    CONTROL STRUCTURE - SERIAL PORT SETTINGS ...............................153
-    CONTROL STRUCTURE - BBS AND CALLER INFORMATION .........................158
-    CONTROL STRUCTURE - DOOR SETTINGS ......................................182
-    CONTROL STRUCTURE - DIAGNOSTICS ........................................185
-    CONTROL STRUCTURE - OPENDOORS CUSTOMIZATION ............................187
-    CONTROL STRUCTURE - FUNCTION KEYS ......................................212
-    CONTROL STRUCTURE - COLOR CUSTOMIZATION ................................216
-    CONTROL STRUCTURE - TEXT CUSTOMIZATION .................................217
-
-CHAPTER 6 - SPECIAL TOPICS..................................................220
-    ADDITIONAL INFORMATION ON THE WIN32 VERSION ............................220
-    CONFIGURATION FILE SYSTEM ..............................................225
-    DEFINING CUSTOM DOOR INFORMATION FILE FORMATS ..........................230
-    MULTIPLE PERSONALITY SYSTEM ............................................233
-    LOG FILE SYSTEM ........................................................235
-    MAKING DOORS MULTI-NODE-AWARE ..........................................237
-
-CHAPTER 7 - TROUBLESHOOTING AND GETTING ASSISTANCE WITH OPENDOORS...........242
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 3
-
-    ABOUT THIS CHAPTER .....................................................242
-    TROUBLESHOOTING PROBLEMS ...............................................242
-    SOLUTIONS TO COMMON PROBLEMS ...........................................244
-    OPENDOORS SUPPORT ......................................................245
-    THE OPENDOORS SUPPORT BBS ..............................................245
-    THE OPENDOORS WORD WIDE WEB SITE .......................................246
-    THE OPENDOORS CONFERENCE ...............................................246
-    GETTING IN TOUCH WITH ME ...............................................247
-
-APPENDIX A - CONTENTS OF PACKAGE............................................249
-
-APPENDIX B - CHANGES FOR THIS VERSION.......................................250
-
-APPENDIX C - FUTURE VERSIONS................................................254
-
-APPENDIX D - SPECIAL THANKS.................................................255
-
-GLOSSARY....................................................................256
-
-INDEX.......................................................................267
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 4
-
-  11
- 111
-  11
-  11
-  11
-  11
- 1111
--------------------------------------------------------------------------------
-CHAPTER 1 - INTRODUCTION TO OPENDOORS
-
-
-
-
-WELCOME!
--------------------------------------------------------------------------------
-
-               Welcome to OpenDoors! OpenDoors is a POWERFUL and EASY TO USE
-               online software programming toolkit for C and C++. While
-               OpenDoors is most often used to create add-on "door" programs
-               that run under BBS systems, it can also be used for many other
-               online software applications. By using OpenDoors, you are
-               joining over 500 other programmers from around the world who
-               have used it since it was first released to the public in 1991.
-               Over the years, OpenDoors has grown from a simple BBS door
-               programming library to what is perhaps the most sophisticated,
-               widely used and supported package of its type.
-
-               What exactly is OpenDoors? OpenDoors provides a complete system
-               that allows you to quickly and easily write spectacular,
-               professional quality interactive online software. With
-               OpenDoors, you can write software such as BBS door programs just
-               as you would write any other program - without having to worry
-               about the many of the internal details of door programming.
-               OpenDoors looks after communicating through the modem, providing
-               ANSI/AVATAR/RIP terminal support and interfacing with a wide
-               variety of BBS packages through door information files (such as
-               DOOR.SYS, DORINFO1.DEF, etc.). OpenDoors also looks after status
-               lines and sysop function keys for DOS shells, chatting, hanging
-               up, and so on. In addition, OpenDoors carries out all the work
-               involved in keeping track of carrier detection, user timeouts
-               and much, much more. OpenDoors is also highly flexible, allowing
-               you to take as little or as much control of your program's
-               behavior as you wish.
-
-               This package includes both DOS and Win32 versions of OpenDoors.
-               This allows you to build a plain-DOS version of your program to
-               run under a variety of platforms (DOS, DesqView, Windows 3.x,
-               NT, 95 and OS/2), to build a Win32 version that takes special
-               advantage of Windows 95 / NT, or build both versions of your
-               program - the choice is yours. The DOS version of OpenDoors
-               performs its serial I/O using either a FOSSIL driver, or built-
-               in serial I/O capabilities, making the use of a FOSSIL driver
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 5
-
-               optional. The  Win32 version takes special advantage of 32-bit
-               programming, multithreading and the Windows GUI, and allows you
-               to access many services that are provided by Windows, such as
-               ODBC (for database access) and MAPI (for email and messaging).
-               Both the DOS and Win32 versions of OpenDoors can be run under
-               both DOS and Windows-based BBS packages. The DOS version of
-               OpenDoors can also be run under OS/2-based BBS packages.
-
-               The following section provides more detailed information on the
-               features and capabilities that OpenDoors provides.
-
-
-
-
-FEATURES OF THE OPENDOORS TOOLKIT
--------------------------------------------------------------------------------
-
-               You will find that OpenDoors provides a solid platform to build
-               BBS door programs and other online software on top of. You may
-               want to write simple utility door programs, on-line games or
-               sophisticated applications. Perhaps you are interested in
-               getting into the market of selling online software, or perhaps
-               you just wish to write some custom door programs for a
-               particular BBS system. With OpenDoors, you can accomplish all of
-               these things - and do it much more easily than ever before. Some
-               of the features that OpenDoors provides to :
-
-               - OpenDoors handles all the "dirty" work involved in writing
-                 BBS door programs. Since OpenDoors looks after all the door-
-                 related operations for you, you need do next to nothing
-                 different when writing door programs than you would when
-                 writing any other program. You simply call OpenDoor's simple
-                 functions to input, output and control door operation. In
-                 fact, many people have converted non-door programs to door
-                 programs in only a matter of minutes using OpenDoors. One of
-                 the most common comments I receive about OpenDoors is how
-                 easy it is to use.
-
-               -  OpenDoors allows you to write software that DIRECTLY support
-                 a wide variety of BBS systems, including RemoteAccess,
-                 QuickBBS, PC-Board, Maximus,  Opus, Wildcat!, WWIV, Spitfire,
-                 SuperBBS, Telegard, TriBBS, GAP, and others.
-
-               - As you would expect, OpenDoors flawlessly monitors the
-                 modem's carrier detect signal, to automatically recover when
-                 a user hangs up - without your having to do anything extra in
-                 your program. OpenDoors also monitors how much time the user
-                 has left in the door, and provides a fully adjustable
-                 inactivity timeout monitor.
-
-               - OpenDoors takes care of all the work involved in reading and
-                 writing BBS door information files, such as DORINFO1.DEF,
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 6
-
-                 EXITINFO.BBS, CHAIN.TXT, DOOR.SYS, etc.  If the particular
-                 information is available to OpenDoors, it will provide you
-                 with just about everything you could ever want to know about
-                 the user on-line, the system your door is running under, and
-                 so on. In addition to the many door information file formats
-                 supported by OpenDoors, you are also able to define your own
-                 custom formats.
-
-               - OpenDoors also does all the work involved in displaying and
-                 automatically updating the door's status line, with
-                 information available to the sysop such as user name,
-                 location, baud rate, time left, function keys,
-                 ANSI/AVATAR/RIP settings, and so on. Using OpenDoors, you can
-                 choose from a number of different "personalities". These
-                 personalities allows OpenDoors to mimic the status lines and
-                 sysop function keys used in various BBS packages. OpenDoors
-                 includes personalities that mimic RemoteAccess, PC-Board and
-                 Wildcat! OpenDoors also allows you to create your own
-                 personalities to mimic any other BBS system.
-
-               - OpenDoors automatically provides the sysop with all the
-                 standard function keys for adjusting user time, hanging up on
-                 or even locking out the user, and so on. OpenDoors also
-                 provides you with a chat mode, which is available to the
-                 sysop by pressing Alt-C. In addition, OpenDoors has full
-                 support for sysop shell to DOS, activated by the Alt-J key.
-
-               - What's more, OpenDoors is designed to be very easy to use.
-                 Even the most novice 'C' programmers are able to write
-                 professional-quality doors with OpenDoors. It takes care of
-                 just about every detail for you, yet still gives you the
-                 ability to completely control and customize every detail of
-                 your door's behavior. There are even people who begin door
-                 programming with OpenDoors, having never programmed in C in
-                 the past.
-
-               - OpenDoors supports both FOSSIL-based and built-in serial I/O
-                 capabilities. FOSSIL-based serial I/O can be used for maximum
-                 compatibility with various systems and serial ports,
-                 including multiple-port serial cards such as DigiBoard.
-                 OpenDoors can also operate without a FOSSIL driver, using
-                 it's own serial I/O capabilities. OpenDoor's built-in
-                 asynchronous communications supports baud rates of up to
-                 115,200 and non-standard serial port configurations.
-                 OpenDoors also has the ability to automatically detect which
-                 of the two serial I/O methods should be used on a particular
-                 system.
-
-               - OpenDoors also automatically detects when the BBS system is
-                 operating in local mode, and supports full local mode
-                 operations itself.
-
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 7
-
-               - Other OpenDoors functions include a built in sysop-page
-                 function that will ask the user why they wish to chat, and
-                 then proceed to page the sysop, just as any BBS package
-                 would. OpenDoors also provides screen clearing functions
-                 (which will detect whether the user has screen clearing
-                 turned on), and various ANSI/AVATAR/RIP control functions
-                 (which again detect if the user has graphics mode turned on).
-
-               - In addition to the basic display features of OpenDoors there
-                 are also a number of advanced screen control functions. These
-                 include functions to save and restore the entire screen,
-                 along with functions to save, restore or scroll portions of
-                 the screen. Other functions allow you to provide overlapping
-                 windows and pop-up menus with highlighted selection bars.
-
-               - OpenDoors provides a multi-line text editor that you can use
-                 to allow the user to enter or edit text files, email
-                 messages, or any other text that spans multiple lines. You
-                 can customize many of the editor's settings to suit your
-                 needs.
-
-               - OpenDoors has a number of special sub-systems that you may
-                 elect to include in your doors. Among these, is a log-file
-                 system that allows you to add log file support to your doors
-                 with only a single line of programming.
-
-               - Another valuable OpenDoors sub-system is the configuration
-                 file system. Again using only a single line of code, you can
-                 add configuration file support to your doors. OpenDoors
-                 configuration files permit the sysop using the door to
-                 customize the door's behavior to their own preferences.
-
-               - OpenDoors can also be fully customized in order that you may
-                 write door programs that use languages other than English.
-
-               - Among the ANSI/AVATAR/RIP features found in OpenDoors is the
-                 ability to send ANSI/AVATAR/RIP files from disk. This allows
-                 you to easily design program screens, and incorporate them
-                 into your doors.
-
-               - OpenDoors also comes with the source code for a number of
-                 example doors, which you can modify, or simply extract bits
-                 and pieces for use in your own doors. Plus, this manual
-                 contains many examples of C source code, to help you in
-                 writing nearly any door program you might wish to build.
-
-               - You may also elect to purchase the source code for OpenDoors,
-                 which will permit you to make modifications to any portion of
-                 OpenDoors, use any portions of the OpenDoors source code in
-                 other programs you write, or merely learn how communications-
-                 type programs are written.
-
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 8
-
-  2222
- 22  22
-     22
-    22
-   22
-  22
- 222222
--------------------------------------------------------------------------------
-CHAPTER 2 - ABOUT THIS EVALUATION COPY AND ORDERING
-
-
-
-
-THE EVALUATION COPY & BENEFITS OF REGISTERING
--------------------------------------------------------------------------------
-
-               OpenDoors is distributed and sold using the conventional
-               "shareware" approach. This complete package can be freely
-               distributed, both online (through BBS systems and the Internet)
-               and on CD-ROMs or other media. This gives you the chance to try
-               OpenDoors before you buy it. Unlike traditional commercial
-               software, you have the opportunity to see OpenDoors first-hand,
-               and determine whether it meets your needs without first paying
-               for it. However, before registering you are only permitted to
-               use it under the following conditions:
-
-               1.)You may only use this package for a one month period, and
-                  for evaluation purposes only.
-
-               2.) Programs written with this package may not be distributed.
-
-               Also, before registering, any program written with OpenDoors
-               will display a message to the user indicating that OpenDoors is
-               not registered. Of course, this message is removed once you have
-               registered.
-
-               If you decided to register OpenDoors, you will become the
-               licensed owner of a powerful tool for creating BBS door programs
-               and other online software. Registered (licensed) owners of
-               OpenDoors are entitled to:
-
-               1.)Virtually unlimited use of OpenDoors. You may write as many
-                  programs as you wish using OpenDoors, and do what you please
-                  with these programs. They may be freely distributed, or even
-                  sold. What's more, there are no additional royalty fees.
-                  Your one time purchase of OpenDoors entitles you to use it
-                  as you please.
-
-               2.)Your registration entitles you to use both the DOS and Win32
-                  versions of OpenDoors.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                            End of Page 9
-
-               3.)You will also be entitled to free upgrades to newer versions
-                  of OpenDoors. In addition to the great many features and the
-                  quality that this version of OpenDoors has to offer, I am
-                  currently working on a great many additions and enhancements
-                  for the next version. (See the end of this document for an
-                  outline of features currently "in the works".) Any programs
-                  you write using this version will also automatically take on
-                  many of these new features when you upgrade to the new
-                  version.
-
-
-               Perhaps the best news of all is the price of OpenDoors. Similar
-               packages sell for $50, $75, or even more. However, this version
-               of OpenDoors will only cost you $28 US Dollars, $34 Canadian
-               Dollars, or the equivalent in your country's currency! (Note
-               that this price will increase in future versions. By registering
-               now, you will save by being able to upgrade to all future
-               versions at no additional charge.)
-
-               Also, the source code for OpenDoors is now available to licensed
-               users for an additional $28US / $34CDN / equivalent. Ordering a
-               copy of the source code will allow you to customize OpenDoors
-               for your own use, making any changes or additions that you wish.
-               It also gives you the opportunity to see how OpenDoors works,
-               and to use any portions of the OpenDoors code in any other
-               programs you wish to write. If you think you might be interested
-               in ordering the OpenDoors source code, please be sure to read
-               the section entitled "Ordering The Source Code", located on page
-               20.
-
-
-
-HOW TO ORDER
--------------------------------------------------------------------------------
-
-               There are to ways of ordering and OpenDoors license
-               (registration):
-
-               -The most common way to order is by mailing the OpenDoors order
-                form along with a cheque, money order or cash to the address
-                on this order form.
-
-               - You may order using a major credit card. OpenDoors credit card
-                orders are handled by a third-party credit card order service,
-                named PsL.
-
-               The following sections provide more information on how to order
-               using each of these options.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 10
-
-HOW TO ORDER BY MAIL
--------------------------------------------------------------------------------
-
-               To order OpenDoors by mailing a cheque, money order or cash,
-               simply follow these three steps:
-
-               1.)  Fill out the registration form. Information on filling out
-                    the form is located on page 15.
-
-               2.)  Send the appropriate payment, $28US/$34CDN/equivalent for
-                    the registration or $56US/$68CDN/equivalent for both the
-                    registration and source code. If you wish more detailed
-                    instructions on sending the registration fee, see the
-                    section that begins page on 12. Included in that section is
-                    a list of equivalent prices for a number of other
-                    countries.
-
-               3.)  Send the above two items to me at:
-
-                              Brian Pirie
-                              117 Cedarock Drive
-                              Kanata ON  K2M 2H5
-                              Canada
-
-
-               Many people who register OpenDoors also order the source code
-               package. You may wish to consider the benefits of having the
-               OpenDoors source code - it allows you to learn how OpenDoors and
-               communications software is written, it allows you to modify and
-               customize OpenDoors to suit your own preferences, and it also
-               allows you to use portions of OpenDoors for other non-door
-               programming projects. If you think you might also be interested
-               in the OpenDoors source code, be sure to read the section on the
-               source code, which begins on page 20.
-
-               Also, you may wish to send the OpenDoors feedback form (located
-               on page 19), along with your registration. The feedback form
-               gives you a chance to tell me what you think of OpenDoors, and
-               what changes you would like to see in future versions. In fact,
-               the majority of suggestions made on these forms in the past have
-               already been implemented in the current version of OpenDoors.
-
-               If you have printed the OpenDoors manual, you can simply remove
-               and mail the forms on pages 18 and 19. If you have not already
-               printed a copy of the manual, and you have a printer, you can
-               quickly print these forms by printing the ORDER.FRM file
-               included in the OpenDoors distribution archive. (Type COPY
-               ORDER.FRM PRN from your DOS prompt.)
-
-NO PRINTER?    Alternatively, if you do not have a printer, simply send a hand-
-               written version of the order form.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 11
-
-               If you have any special instructions for me, or anything that
-               you would like to say when you register, feel free to write this
-               on the back of the registration form, or on a separate piece of
-               paper.
-
-               When filling out the OpenDoors registration form, be sure to
-               indicate how you would prefer to receive your OpenDoors
-               registration key and/or source code. The following options are
-               available:
-
-                         - Having me send the registration and/or source code
-                          by conventional mail
-                         - Internet E-Mail (the fastest option)
-                         - By Fax
-                         - Having me call to your BBS
-                         - You calling the OpenDoors support BBS
-                         - FidoNet "CrashMail"
-
-               Once you have decided which means you would prefer to receive
-               your order by, please read the detailed instructions on your
-               order method, below. Also, if you are ordering the source code,
-               please be sure to read the section on ordering the source code,
-               which begins on page 20.
-
-
-
-
-SENDING YOUR ORDER FEE IN THE MAIL
--------------------------------------------------------------------------------
-
-               The price of OpenDoors is 34 Canadian Dollars, 28 U.S. Dollars,
-               or equivalent for the registration. The source code costs an
-               additional 34 Canadian Dollars, 28 U.S. Dollars, or equivalent.
-               For your convenience, the equivalent value in a number of other
-               country's currencies, at the time of this writing, is as
-               follows:
-
-                       -----------------------------------------------
-                                                REGISTRATION
-                       REGISTRATION ONLY        AND SOURCE CODE
-                       -----------------------------------------------
-                       34 Canadian Dollars      68 Canadian Dollars
-                       28 US Dollars            56 US Dollars
-                       18 British Pounds        36 British Pounds
-                       150 French Francs        300 French Francs
-                       44 German Marks          88 German Marks
-                       50 Netherland Gilders    100 Netherland Gilders
-                       39 Australian Dollars    78 Australian Dollars
-                       -----------------------------------------------
-
-               If you are ordering by mail, this order fee may be paid using
-               any of the following methods:
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 12
-
-
-               -Cheque or Money Order in Canadian currency, drawn upon a
-                Canadian bank. In this case, your order fee will be either
-                $34CDN for just the registration, or $68CDN for both the
-                registration and source code.
-
-               -Cheque or Money Order in U.S. currency, drawn upon a U.S. bank.
-                In this case, your order fee will be either $28US for just the
-                registration, or $56US for both the registration and source
-                code.
-
-               -An International Money Order or International Bank Draft
-                (available from your bank, post office or companies such as
-                American Express), in Canadian currency. Depending on the
-                particular case, your order fee MAY be sent to me by the postal
-                service, and you will mail your order form by itself. You
-                should have the money order drawn in either $34CDN for just the
-                registration, or $68CDN for both the registration and source
-                code.
-
-               -A cheque drawn on any bank in the world, IN THAT COUNTRY'S
-                CURRENCY, equivalent to 34 Canadian dollars. For instance, a
-                cheque for the appropriate number of British Pounds, drawn on a
-                British bank, is perfectly acceptable. However, I am unable to
-                accept a cheque for $34 Canadian dollars, drawn on a British
-                Bank. UNFORTUNATELY, THE BANKS IN CANADA ARE CURRENTLY
-                UNWILLING TO ACCEPT EUROCHEQUES.
-
-               -Cash. Please note that it is not usually recommended that cash
-                be sent in the mail, and that I cannot be responsible for any
-                cash lost in the mail. Simply put, if you wish to order by
-                cash, it is your responsibility to get the cash to me. However,
-                if I do receive your order in the form of cash, it will be
-                perfectly acceptable to me. I would like to mention that many
-                people have already ordered OpenDoors by sending cash, and I
-                have yet to run across any case of cash being lost in the mail.
-                Nonetheless, if you wish to send cash, you may wish to consider
-                doing so by registered mail, for your added security.
-
-
-               If you are ordering OpenDoors from within Canada, you will most
-               likely choose the first option (a Canadian cheque or money
-               order). If you are ordering OpenDoors from within the United
-               States, you will most likely choose the second option (an
-               American cheque or money order). If you are ordering from
-               outside Canada and the U.S., it would be ideal if you could send
-               your fee by an international money order. However, it should be
-               noted that any of the above order methods will be acceptable
-               from any location. Also, it is quite possible that I may be able
-               to accept other means of sending your order fee. If you are
-               unsure about sending your order fee, please feel free to get in
-               touch with me by any of the means listed on page 247.
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 13
-
-ORDERING BY CREDIT CARD
--------------------------------------------------------------------------------
-
-               This information applies to CREDIT CARD ORDERS ONLY. Please read
-               this entire section before ordering OpenDoors by credit card.
-
-               In order to cover the additional costs of processing credit card
-               orders, an $8 shipping and handling fee applies to all OpenDoors
-               orders made through PsL. As such, the total prices you will pay
-               are:
-
-               - Just registration ($28 + $8 Handling) = $36 U.S.
-               - Registration and Source Code ($56 + $8 Handling) = $64 U.S.
-                 (All prices will be charged to your credit card in U.S.
-               Dollars.)
-
-               You can order OpenDoors with MC, Visa, Amex, or Discover from
-               Public (software) Library by calling 800-2424-PsL or 713-524-6394
-               or by FAX to 713-524-6398 or by CIS Email to 71355,470. You can
-               also order online through the World Wide Web. For more
-               information on how to do this, visit the OpenDoors Web site.
-               (Information on the OpenDoors web site is provided on page 246.)
-               You can also mail credit card orders to PsL at P.O.Box 35705,
-               Houston, TX 77235-5705. When ordering by phone, you must call
-               between 6:00am and 6:00pm CST on Monday to Thursday, or between
-               6:00am and 12:30pm on Fridays.
-
-               THE ABOVE NUMBERS ARE FOR CREDIT CARD ORDERS ONLY.
-               THE AUTHOR OF THIS PROGRAM CANNOT BE REACHED AT THESE NUMBERS.
-
-               Any questions about the status of the shipment of the order,
-               refunds, registration options, product details, technical
-               support, volume discounts, dealer pricing, site licenses, non-
-               credit card orders, etc., must be directed to:
-
-                              Brian Pirie
-                              117 Cedarock Drive
-                              Kanata ON  K2M 2H5
-                              Canada
-
-               To insure that you get the latest version, PsL will notify me the
-               day of your order and I will ship OpenDoors directly to you. I
-               will send OpenDoors by conventional mail unless I have previously
-               heard from you, asking me to send your order by some other means.
-
-               When ordering by credit card through PsL, please be sure to
-               indicate whether you wish to order just the OpenDoors
-               registration, or both the registration and source code. Also,
-               please be sure to include your credit card billing address.
-               Without this information, PsL will be unable to process your
-               order.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 14
-
-HOW YOU CAN RECEIVE YOUR ORDER
--------------------------------------------------------------------------------
-
-               For your convenience, I can send your OpenDoors registration key
-               and/or source code by any of the following methods. If you are
-               ordering OpenDoors by mail, simply check one of these options on
-               your order form. If you are ordering through the third-party
-               credit card service, I will automatically send your order by
-               Internet email or conventional mail unless I receive a message
-               from you before you order, asking me to send it by some other
-               means.
-
-
--------------------------------------------------------------------------------
-RECEIVING      If you wish to receive your OpenDoors registration key by
-ORDER BY       Internet E-Mail (including Internet E-Mail to a CompuServe
-INTERNET       account), fill out the order form and mail it along with your
-E-MAIL         payment as described below. Be sure to include your e-mail
-               address on your order form. Note that the source code cannot be
-               sent via Internet e-mail.
-
-
--------------------------------------------------------------------------------
-RECEIVING      In order to receive your OpenDoors registration key and/or
-ORDER          source code by conventional mail, simply fill out the order
-BY MAIL        form and mail it along with your payment as described below. I
-               will cover the cost of postage. If your address contains non-
-               Roman characters, also enclose a self-addressed envelope or
-               mailing label.
-
-
--------------------------------------------------------------------------------
-RECEIVING      If you wish to receive your OpenDoors registration key by
-ORDER BY       FAX, fill out the order form and mail it along with your payment
-FAX            as described below. Be sure to include your fax number on your
-               order form. Do to choose this method if you are ordering the
-               source code.
-
-
--------------------------------------------------------------------------------
-RECEIVING      You may choose to receive your OpenDoors registration and/or
-ORDER BY       source code by calling the OpenDoors BBS after your registration
-CALLING        form and order fee have been received here. If you are unable to
-OPENDOORS      receive your order by any other electronic means (such as a call
-BBS            to your BBS, or by electronic mail), this may be the quickest
-               way for you to receive your registration information and/or
-               source code. The obvious disadvantage with to option is the fact
-               that you will have to estimate when your order will arrive here
-               in order to receive it as quickly as possible. You may end up
-               calling the OpenDoors BBS more than once before your order has
-               arrived. After your order form has arrived, your registration
-               key and/or source code will be placed on hold for you, and you
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 15
-
-               will be able to receive it on your first call to the BBS. The
-               phone number of the BBS is:
-
-                         +1 (613) 599-5554
-
-
--------------------------------------------------------------------------------
-RECEIVING      In order to receive your OpenDoors registration key and/or
-ORDER BY       source code by a message and/or upload to your BBS, fill out
-CALL TO        the order form and mail it along with your payment as described
-YOUR BBS       below. Be sure to include the phone number, baud rate, and my
-               login and password for the BBS to which you would like me to
-               call. As always, I will cover any long distance costs. If, for
-               some reason, I am unable to connect to your BBS (not because it
-               is busy, but, for example, if your BBS is no longer online), I
-               will send your order by conventional mail instead.
-
-
--------------------------------------------------------------------------------
-RECEIVING      In order to receive your OpenDoors registration key and/or
-ORDER BY       source code by FidoNet CrashMail, simply fill out the order
-FIDONET        form and mail it along with your payment as described below.
-CRASHMAIL      Be sure to include the FidoNet node address to which you wish to
-               have your registration key and/or source code sent to (via
-               CrashMail). Again I will cover any long distance costs. If, for
-               some reason, I am unable to connect to your FidoNet system, I
-               will send your order by conventional mail instead.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 16
-
-ORDERING THE SOURCE CODE
------------------------------------------------------------------------------
-
-               Many people also choose to order the source code along with
-               their OpenDoors registration. Ordering the source code will
-               allow you to customize OpenDoors for your own use, use parts of
-               the OpenDoors source code in other programs, and learn more
-               about how OpenDoors works. If you have any ideas for changes
-               that you would like to see in OpenDoors, either large or small,
-               ordering the source code will allow you to makes these changes
-               yourself, creating your own customized version of OpenDoors. You
-               will be able to remove copyright notices, change the way certain
-               OpenDoors functions work, or add new capabilities to OpenDoors
-               in surprisingly little time. You will also be able to use any of
-               the OpenDoors source code, be it the DesqView-aware code,
-               EMS/disk swapping routines, configuration file system,
-               communications routines, or anything else, in any other programs
-               that you write. Also, ordering the OpenDoors source code will
-               allow you to learn more about how OpenDoors works, and how to
-               program communications software and BBS door programs.
-
-               When you order the OpenDoors source code, you will receive the
-               source code package. The source code package also includes a
-               short "Source Code Manual", with a description of how the
-               OpenDoors source code is organized, instructions on how to
-               recompile the source code, and more. If you choose to receive
-               the source code package electronically, you will receive it in
-               the form of a single .ZIP file. If you choose to receive the
-               source code package by mail, you will receive it on a 3-1/2"
-               diskette.
-
-REQUIREMENTS   Due to the wide variety of compilers that are available, and the
-               differences between them, I have been unable to test the
-               OpenDoors source code with every compiler. This means that you
-               may need to make some changes to the source code in order to
-               compile it with certain compilers.
-
-               In order to compile the DOS version of OpenDoors, you must be
-               using a compiler that supports inline assembly language
-               keywords. This includes all Borland compilers released since
-               1991, and many other compilers. The one notable exception is
-               Watcom's compiler, which does not support inline assembly
-               language at the time of this writing.
-
-               For your information, the DOS OpenDoors libraries included with
-               this package were compiled using Turbo C++ 1.0 Professional. The
-               Win32 libraries included with this package were compiled using
-               Microsoft Visual C++ 2.0. This means that you can be reasonably
-               certain that OpenDoors will compile with these compilers and any
-               more recent compilers by these companies without any changes.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 17
-
---------------------------------------------------------------------------
-                       OPENDOORS 6.00 ORDER FORM
---------------------------------------------------------------------------
-
- REGISTRATION NAME : _______________________________   (AS SHOULD APPEAR IN
-                                                        REGISTRATION)
-         YOUR NAME : _______________________________   (IF DIFFERENT)
-
-    POSTAL ADDRESS : ______________________________________________________
-
-                     ______________________________________________________
-
-                     ______________________________________________________
-
-  E-MAIL ADDRESSES : ____________________________________   (IF APPLICABLE)
-
-   ADDITIONAL INFO : ______________________________________________________
-                     (EG FAX/BBS PHONE NUMBER & BRIAN'S PASSWORD, IF NEEDED)
-
-I WISH TO RECEIVE MY ORDER BY:
-          ___                                ___
-         |   | - INTERNET E-MAIL (FASTEST)  |   | - I WILL CALL BRIAN'S BBS
-         |___|                              |___|
-          ___                                ___
-         |   | - CONVENTIONAL MAIL          |   | - CALL TO MY BBS
-         |___|                              |___|   (INCLUDE LOGIN INFO)
-          ___                                ___
-         |   | - FAX (INCLUDE FAX #)        |   | - FIDONET "CRASHMAIL"
-         |___|                              |___|
-
-                        ___
-I WOULD LIKE TO ORDER: |   | - BOTH REGISTRATION KEY AND SOURCE CODE
-                       |___|   ($56 US, $68 CANADIAN, OR EQUIVALENT FUNDS)
-                        ___
-                       |   | - JUST MY REGISTRATION KEY
-                       |___|   ($28 US, $34 CANADIAN, OR EQUIVALENT FUNDS)
-                        ___
-                       |   | - UPGRADE TO SOURCE CODE (ONLY IF ALREADY
-                       |___|   REGISTERED) ($28 US, $34 CANADIAN OR EQUIV.)
-
-
-I AGREE TO THE REGISTRATION TERMS,             ____________________________
-SET FORTH ON PAGE 20 OF THE MANUAL             (SIGNATURE)
-
-MAKE CHEQUES PAYABLE TO:   BRIAN PIRIE
-                           117 CEDAROCK DRIVE
-                           KANATA ON  K2M 2H5
-                           CANADA
-+-- OFFICIAL USE ONLY ----------------------------------------------------+
-|                                                                         |
-| S.N. : _____________  SENT : _________________________________________  |
-+-------------------------------------------------------------------------+
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 18
-
---------------------------------------------------------------------------
-                         OPENDOORS 6.00 FEEDBACK FORM
---------------------------------------------------------------------------
-
-YOUR NAME :  _______________________________
-
-
-WHICH OPENDOORS LIBRARY(S) DO YOU EXPECT TO USE:
-             ___
-            |   | - DOS VERSION, MEMORY MODELS: _________________________
-            |___|
-             ___
-            |   | - WINDOWS (WIN32) VERSION
-            |___|
-
-
-HOW DID YOU FIRST LEARN OF OPENDOORS?
-
-             ____________________________________________________________
-
-
-WHICH COMPILER(S) AND VERSION(S) ARE YOU USING?
-
-             ____________________________________________________________
-
-
-WHAT DO YOU LIKE MOST ABOUT OPENDOORS?
-
-             ____________________________________________________________
-
-             ____________________________________________________________
-
-
-WHAT CHANGES OR ADDITIONS WOULD YOU LIKE TO SEE IN FUTURE VERSIONS?
-
-             ____________________________________________________________
-
-             ____________________________________________________________
-
-
-DO YOU HAVE ANY ADDITIONAL COMMENTS?
-
-             ____________________________________________________________
-
-             ____________________________________________________________
-
-             ____________________________________________________________
-
-
------------------------------------------------------------------------------
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 19
-
-TERMS OF REGISTRATION AND SOURCE CODE USE
------------------------------------------------------------------------------
-
-               When you purchase an OpenDoors registration and/or source code
-               license, you are entitled to almost unlimited use of all
-               versions of OpenDoors. However, in order to protect my
-               investment of time and effort in developing OpenDoors, you must
-               also agree to the terms outlined below when licensing OpenDoors
-               and/or the source code. These terms are intended to be very
-               reasonable, and are in no way intended to limit your use of
-               OpenDoors. The primary intent of these terms is that you are not
-               permitted to disclose your OpenDoors registration information,
-               or the OpenDoors source code, to other individuals. The terms of
-               registration and source code use are as follows:
-
-               For the purpose of these terms, "OpenDoors" is defined to be the
-               library files, header files, example programs and programmer's
-               manual of all versions, past and present, for all languages and
-               platforms of the OpenDoors online software programming toolkit.
-               In the case of a source code license, OpenDoors also refers to
-               the source code that is used to build OpenDoors. Upon licensing
-               OpenDoors, the individual or organization named on the order
-               form (the licensee) is entitled to use of all versions of
-               OpenDoors, within the terms set forth below. Violation of these
-               terms will be considered copyright infringement, and grounds for
-               the termination of the registration agreement. The licensee is
-               entitled, at no additional cost, to use, distribute or sell the
-               executable (.EXE or .COM) files that are built from OpenDoors.
-               The licensee is also entitled to use, distribute or sell the
-               example programs, example configuration files and portions of
-               the manual. If licensing the source code, the licensee is also
-               entitled to distribute or sell any executable files that result
-               from using altered versions of the source code, or portions
-               thereof, provided that it is not possible for other programmers
-               to access the OpenDoors API functions through this executable
-               file. The licensee is NOT entitled to distribute the
-               registration key number that is provided by Brian Pirie, nor any
-               portions of the OpenDoors source code. For the purposes of these
-               terms, an organization is considered to be a company or non-
-               profit organization. If the licensee is an organization, the
-               registration key and source code may be shared among members of
-               the organization, under the condition that these individuals are
-               using the registration and/or source code only for official
-               activities of that organization. These terms in no way suggest
-               an agreement on the part of Brian Pirie to develop any future
-               versions of OpenDoors, or fix any bugs in current versions of
-               OpenDoors. OpenDoors is offered "as is", and no warrantees are
-               expressed or implied. In no event shall Brian Pirie be liable
-               for any loss of profit or any other damage, including but not
-               limited to special, incidental, consequential or other damages.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 20
-
-  3333
- 33  33
-     33
-   333
-     33
- 33  33
-  3333
--------------------------------------------------------------------------------
-CHAPTER 3 - OPENDOORS TUTORIAL
-
-
-
-
-ABOUT THIS MANUAL
--------------------------------------------------------------------------------
-
-               The OpenDoors programmer's manual is intended to serve as a
-               complete tutorial, guide and reference to writing programs with
-               OpenDoors. Chapter 1 of this manual, beginning on page 5,
-               provides an introduction and overview of the features of
-               OpenDoors. If you are unsure of what OpenDoors will do for you,
-               begin with Chapter 1. Chapter 2, beginning on page 9, provides
-               important information related to this evaluation copy of
-               OpenDoors, and how to register your copy. Chapter 3 serves as a
-               tutorial on OpenDoors and BBS door programming in general.
-               Chapter 4 provides a reference to the OpenDoors API functions
-               which you can use in your programs. Chapter 5 provides a
-               reference to the "OpenDoors control structure", which gives you
-               access to a wide array of information, and allows you to
-               customize OpenDoor's appearance and behavior. Chapter 6 provides
-               information on special OpenDoors features and advanced door
-               programming topics. Among the subjects discussed in chapter 6
-               are the Win32 version of OpenDoors, configuration files, multi-
-               node operation, RIP graphics, logfile support, defining custom
-               door information file formats, and more.
-
-               Chapter 7 (which begins on page 242) gives instructions on
-               troubleshooting programs written with OpenDoors, lists solutions
-               to common difficulties, and has information about the many
-               sources for OpenDoors support. If at any time you are having
-               difficulty with OpenDoors, be sure to refer to this chapter for
-               complete step-by-step instruction on tracing the source of your
-               problem, and for solutions to common difficulties with
-               OpenDoors. This chapter also directs you to some of the major
-               sources of support, including information on the OpenDoors email
-               conference, the OpenDoors support BBS, and how to get in touch
-               with me.
-
-               You will also find many useful tools in this manual, which will
-               no doubt come in useful while working with OpenDoors. Beginning
-               on page 2 is a basic table of contents, showing you how the
-               manual is organized, and helping you to locate general topics.
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 21
-
-               At the end of the manual, beginning on page 267, is an index to
-               help you locate more information on specific topics. The manual
-               also includes a glossary, on page 256, which will help you in
-               understanding new terms that you may come across while reading
-               the manual. At the end of the manual, you will also find several
-               useful sections, such as information on what is new in this
-               version, information on how to contact me, and information about
-               new OpenDoors features currently in the works.
-
-               You will likely want to print this manual, to make reading and
-               reference while programming easier. To print this manual, simply
-               type the following line from your DOS prompt. If you are worried
-               about the size of this manual, you might consider using a
-               utility that can print multiple pages of a text file on a single
-               sheet of paper. Printing two manual pages per side of paper
-               should certainly be legible, and even four-up would give you
-               text about the size of average newspaper text. Printing on both
-               sides, you should be able to fit the manual on about 34 sheets
-               of paper (269/8 < 34).
-
-
-
-
-COMPILING A PROGRAM WITH OPENDOORS
--------------------------------------------------------------------------------
-
-               The process of compiling a program written with OpenDoors is
-               very similar to that of compiling any other program. However,
-               there are two additional steps which you must be sure to
-               remember:
-
-               1.)  You must include the OPENDOOR.H header file.
-
-               2.)  You must link your program with the appropriate OpenDoors
-                    library file.
-
-
-               All programs written with OpenDoors, must "include" the
-               OPENDOOR.H header file. If you have placed the OPENDOOR.H header
-               file in the same directory as your program's source code, place
-               the following line at the beginning of your .C or .CPP file(s):
-
-                    #include "opendoor.h"
-
-               If you have placed the OPENDOOR.H header file in the same
-               directory as other standard header files (such as stdio.h),
-               place the following line at the beginning of your .C or .CPP
-               file(s):
-
-                    #include <opendoor.h>
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 22
-
-               In addition to including the OpenDoors header file in your
-               source code modules, you must also "link" the appropriate
-               OpenDoors library file with your program. The procedure for
-               doing this depends upon which compiler you are using. The
-               following sections describe how to link with the OpenDoors
-               libraries using various compilers.
-
-
-
-LINKING WITH OPENDOORS USING A DOS COMPILER
--------------------------------------------------------------------------------
-
-               This section describes how to link with the provided OpenDoors
-               library files under a variety of DOS compilers. If you are using
-               a compiler other than those described here, refer to your
-               compiler's manual for information on how to link with third-
-               party libraries.
-
-               If you are using Borland Turbo C 2.00 or earlier, you can cause
-               your compiler to link your program with the OpenDoors library by
-               creating a text file with a .PRJ extension. In this text file,
-               you should list the names of your program's .C modules, along
-               with the name of the appropriate OpenDoors library file, as
-               listed in the table at the end of this section. You should then
-               select this Project file from within the Turbo C IDE prior to
-               compiling your program.
-
-               If you are using Turbo C++ or Borland C++, you can set your
-               compiler to link your program with the OpenDoors library by
-               creating a project file from within the IDE. To do this, choose
-               the Open Project command from the Project menu, and enter the
-               name for your new project file in the Load Project dialog box.
-               Then add the names of your program's .C/.CPP modules, along with
-               the name of the appropriate OpenDoors library file, by pressing
-               [Insert] in the project window. When you return to Turbo C++ or
-               Borland C++ again, you can work with the same project file by
-               using the Open command from the Project menu.
-
-               If you are using any Microsoft C compiler, such as Quick C,
-               Microsoft C or Visual C++, you can set your compiler to link
-               your program with the OpenDoors library by creating a makefile.
-               You can create a new project file from within Quick C by using
-               the Set Program List option from the Make menu. You can do this
-               from within Visual C++ by using the New command from the Project
-               menu. You should add the names of your program's .C/.CPP source
-               files, along with the name of the appropriate OpenDoors library
-               file, to the newly create makefile.
-
-               There are several different DOS library files included with
-               OpenDoors, each one for use with a different memory model. The
-               following chart lists the library file names, along with their
-               corresponding memory model. It is important that you use the
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 23
-
-               library file which corresponds to the memory model you are
-               using. Whenever you change your compiler to use a different
-               memory model, it is important to rebuild all of your source
-               files (using the "Build All" or "Rebuild All" command) in
-               addition to changing the library that your program is being
-               linked with. If you are unfamiliar with the concept of memory
-               models, you should refer to your compiler's manuals. If you are
-               unsure as to what memory model your compiler is currently using,
-               check this setting in the compile options dialog box or command
-               line reference information.
-
-                 +------------------------------------------------+
-                 | Library     | Memory                           |
-                 | Filename    | Model                            |
-                 |-------------|----------------------------------|
-                 | ODOORS.LIB  | DOS small memory model library   |
-                 |             |                                  |
-                 | ODOORM.LIB  | DOS medium memory model library  |
-                 |             | (Available separately)           |
-                 |             |                                  |
-                 | ODOORC.LIB  | DOS compact memory model library |
-                 |             | (Available separately)           |
-                 |             |                                  |
-                 | ODOORL.LIB  | DOS large memory model library   |
-                 |             |                                  |
-                 | ODOORH.LIB  | DOS huge memory model library    |
-                 +------------------------------------------------+
-
-               To understand how to compile a program written with OpenDoors,
-               it is a good idea to try compiling one of the example programs,
-               such as ex_hello.c, that are included in the OpenDoors package.
-
-
-
-
-LINKING WITH OPENDOORS USING A WINDOWS COMPILER
--------------------------------------------------------------------------------
-
-               The Win32 version of OpenDoors resides in a DLL, ODOORS60.DLL.
-               In order to use OpenDoors from a Win32 program, you will
-               typically link to an import library (although it is also
-               possible to use load-time dynamic linking through the use of
-               LoadLibrary() and GetProcAddress()). The OpenDoors package
-               includes a COFF-format import library for use Microsoft
-               compilers, named ODOORW.LIB. If you are using a compiler that
-               uses OMF-format object files, such as a Borland compiler, you
-               will need to create your own version of the odoorw.lib import
-               library, by using the implib utility provided with your
-               compiler.
-
-               When compiling an OpenDoors program with a Windows compiler, be
-               sure that either the WIN32 or __WIN32__ constant is defined.
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 24
-
-               Microsoft and Borland compilers define one of these constants by
-               default. However, if you are using a compiler from another
-               company, you may need to explicitly configure your compiler to
-               define one of these preprocessor constants.
-
-               If you are using Microsoft Visual C++ 2.0 or later, you can
-               setup your compiler to link with the OpenDoors import library by
-               creating a makefile (choose File|New|Project) and adding both
-               your program's .C/.CPP source file(s) and the odoorw.lib import
-               library to the project. When prompted for the Project type,
-               choose "Application", not a "MFC AppWizard". If you are using
-               Visual C++ 2.0, then you must manually edit the .mak file using
-               a text editor. In this file, replace all occurrences of
-               "/SUBSYSTEM:windows" with "/SUBSYSTEM:windows,4.0". This
-               instructs the linker to create an executable file that is
-               targeted for Windows 95. If you do not do this, some of the
-               OpenDoors visual elements will not appear correctly. Later
-               versions of Microsoft's compiler default to using
-               "/SUBSYSTEM:windows,4.0", and so this step is no longer
-               necessary with those compilers.
-
-               If you are using Borland C++ 4.50 or later, you must create an
-               OpenDoors import library for ODOORS60.DLL before you can compile
-               your first OpenDoors program. To do this, go to the directory
-               where ODOORS60.DLL is located, move the original odoorw.lib to a
-               backup location, and issue the command:
-
-                    IMPLIB ODOORW.LIB ODOORS60.DLL
-
-               This will create a new import library (ODOORW.LIB) which you can
-               then use with your compiler. To compile an OpenDoors program
-               from the command line, issue the command:
-
-                    BCC32 -tW your_program.c ODOORW.LIB
-
-               To compile an OpenDoors program from within the IDE, create a
-               new project file, and add both your program's source file(s) and
-               the OpenDoors import library to that project. If you are
-               compiling from within the IDE, check the TargetExpert and be
-               sure that you are using the multithreaded version of the the
-               runtime libraries. By default, the Borland IDE compiles single-
-               threaded, which will not work with OpenDoors.
-
-               Additional information on the Win32 version of OpenDoors is
-               provided in chapter 6.
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 25
-
-RUNNING A DOOR PROGRAM WRITTEN WITH OPENDOORS
--------------------------------------------------------------------------------
-
-               This section provides information on how to run a BBS door
-               program that has been written with OpenDoors. If you are using
-               OpenDoors to write some other form of online software, the
-               information provided here will apply to different degrees,
-               depending on the nature of your program.
-
-               OpenDoors supports both local and remote modes. In the normal
-               mode of operation, remote mode, your program's output will be
-               displayed to both the local screen and the remote user's screen.
-               To run your program in remote mode, you will usually set it up
-               to run under some BBS package. However, for testing purposes, it
-               is often convenient to run your program in local mode.
-
-               There are several ways to start your program in local mode. The
-               first method is to place the example DORINFO1.DEF file in the
-               same directory as your program. If your program uses the
-               OpenDoors command line processing function, od_parse_cmd_line(),
-               then you can start your program in local mode by simply
-               specifying -local on your program's command line. For example,
-               you can try the example program include with OpenDoors by
-               issuing the command VOTEDOS -LOCAL (for the DOS version) or
-               VOTEWIN -LOCAL (for the Windows 95/NT version). OpenDoors will
-               also run in local mode if you set it up to run under a BBS
-               package, and log into the BBS in local mode. When the BBS runs
-               your door program, OpenDoors will automatically run in local
-               mode.
-
-               To run your program in remote mode, you will probably want to
-               run it under a BBS system. If you don't have a BBS package for
-               testing purposes, you might want to obtain a popular BBS package
-               such as Wildcat!, Maximus (which is free) or RemoteAccess.
-
-
-
-RUNNING DOS-BASED DOOR PROGRAMS
--------------------------------------------------------------------------------
-
-               DOS BBS packages typically run door programs using one of two
-               methods. Either the BBS package directly loads and executes the
-               program, or it exits to a DOS batch file, which in turn executes
-               the door program. In either case, the BBS package produces a
-               door information file, common called a "drop file", which
-               provides information to the door program such as the name of the
-               current user. OpenDoors automatically supports the common drop
-               file formats, including DORINFOx.DEF and DOOR.SYS.
-
-
-
-RUNNING WINDOWS 95/NT DOOR PROGRAMS
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 26
-
--------------------------------------------------------------------------------
-
-               This section provides information specific to running door
-               programs that are compiled with the Win32 version of OpenDoors.
-               Please feel free to include this information in your program's
-               manual.
-
-               Since the Win32 version of OpenDoors resides in a DLL,
-               ODOORS60.DLL, this file must be present on any system where your
-               program will be run. Although Windows 95/NT will find this file
-               if it is located in the same directory as your program's
-               executable file, it is a good idea to install this DLL into the
-               Windows system directory. This way, all programs using the Win32
-               version of OpenDoors can share the same copy of the DLL,
-               reducing the amount of disk space that is used.
-
-               The required setup for a Windows 95/NT door will depend upon
-               what BBS system it is being run under. If you the program is
-               being run under a native Windows 95/NT BBS system, then ideally
-               that BBS system will provide the ability to pass a live serial
-               port handle to the door program, on the program's command line.
-               Otherwise, you should run the door from a batch file, following
-               the instructions provided below for running the program under a
-               DOS-based BBS system. If the BBS system is able to pass a live
-               Window communications handle on the door's command line, and you
-               are using the OpenDoors standard command-line processing
-               function (od_parse_cmd_line()), then you can just setup the BBS
-               to run the program directly, using the command line:
-
-                    YourProgramName.exe -handle xxxxxxxxxx
-
-               where xxxxxxxxx is the serial port handle, in decimal format.
-               You do not need to use the start command, nor the DTRON utility,
-               and you do not have to change the COM<n>AutoAssign setting in
-               the system.ini file.
-
-               If you are running the Win32 door program under a DOS-based BBS
-               system, or a Windows-based BBS system that is unable to pass a
-               live serial port handle to the door program, then follow these
-               steps:
-
-               1.Add a line of the form "COM<n>AutoAssign=<x>" to the [386Enh]
-                 section of your system.ini file. Here, <n> specifies the
-                 serial port number that the BBS's modem is connected to, and
-                 <x> will usually be 0. For example, if your modem is
-                 connected to COM1, you would add a line such as
-                 "COM1AutoAssign=0" (sans quotes). You will then have to re-
-                 start your computer for this change to take effect. If you do
-                 not do this, the Windows-based door program will not be able
-                 to access the modem.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 27
-
-               2.Setup the BBS software to run the Windows-based door program
-                 just as you would any other door program. You will probably
-                 want to do this from a batch file. The command line that runs
-                 the Windows program should be of the form:
-
-                    start /w /m YourProgramName.exe [any command line
-                 parameters]
-
-                 This will cause the Windows-based door program to start in
-                 minimized mode, and cause the calling MS-DOS session to wait
-                 until the Windows program exits before continuing. If you do
-                 not wish the program to be started in minimized mode, remove
-                 the /m from the command line. If you attempt to start the
-                 door program by calling it directly, rather than using the
-                 "start /w" command, the BBS software will immediately start
-                 again, cause it to attempt to run simultaneously with the
-                 door program.
-
-               3.After running the start command, use DTRON.EXE or a similar
-                 utility to re-enable DTR detection by the modem. Normally,
-                 this command line will be of the form:
-
-                    dtron /port x /bps y
-
-                 Where x is the serial port number (0 for COM1, 1 for COM2,
-                 etc.) and y is the locked bps rate. For example, if your
-                 serial port is locked at 38400 bps and is connected to COM2,
-                 you would use:
-
-                    dtron /port 1 /bps 38400
-
-                 For full information on the DTRON utility, simply type the
-                 command line:
-
-                    dtron /help
-
-                 You may freely redistribute the DTRON utility that is
-                 included in this package with your program.
-
-               Additional information on the Win32 version of OpenDoors, and
-               further explanation of some of these steps, is provided in
-               chapter 6.
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 28
-
-BASICS OF DOOR PROGRAMMING WITH OPENDOORS
--------------------------------------------------------------------------------
-
-               This section provides a complete tutorial to the basics of
-               writing BBS door programs using OpenDoors. If you are using
-               OpenDoors to write other online software, much of this
-               information will still be relevant.
-
-               In addition to reading this section, I would encourage you to
-               look at the example programs included int the OpenDoors
-               packages. These programs, which are described beginning on page
-               38, will give you a much better idea of what an OpenDoors
-               program will look like. These programs can also serve as a great
-               starting point for writing your own programs using OpenDoors.
-
-               Probably the best means of introduction to door programming with
-               OpenDoors is by doing it yourself. As such, I strongly encourage
-               you to try compiling and running the simple introduction program
-               below. For instructions on compiling programs written with
-               OpenDoors, see page 22.
-
-               DOS version:
-
-                    #include "opendoor.h"
-
-                    main()
-                    {
-                       od_printf("Welcome to my first door program!\n\r");
-                       od_printf("Press a key to return to BBS!\n\r");
-                       od_get_key(TRUE);
-                       od_exit(0, FALSE);
-                    }
-
-               Win32 version:
-
-                    #include "opendoor.h"
-
-                    int WINAPI WinMain(HINSTANCE hInstance,
-                       HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int nCmdShow)
-                    {
-                       od_printf("Welcome to my first door program!\n\r");
-                       od_printf("Press a key to return to BBS!\n\r");
-                       od_get_key(TRUE);
-                       od_exit(0, FALSE);
-                    }
-
-               Keep in mind that even this simple program will automatically
-               have all of the door capabilities we have already mentioned.
-               Notice the line that reads #include "opendoor.h". All programs
-               written with OpenDoors must include the OPENDOOR.H header file
-               in order to compile correctly. The first two lines in the
-               main/WinMain function simply call the OpenDoors od_printf()
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 29
-
-               function. od_printf() is similar to the printf() function that C
-               programmers will already be familiar with. However, unlike
-               printf(), the od_printf() function sends the output to both the
-               modem and the local screen. Notice that the lines of text
-               displayed by the od_printf() function end with a "\n\r"
-               sequence, instead of the normal "\n". This is because the
-               terminal emulation software that is running on the remote user's
-               system usually requires both a carriage return and a line feed
-               to correctly begin a new line. The next line in our example
-               program is the OpenDoors single-key input function,
-               od_get_key(). The TRUE value causes OpenDoors to wait for a key
-               to be pressed (again, either from remote or local keyboard)
-               before returning. The last line of the main/WinMain function is
-               a call to od_exit(). Any program using OpenDoors should call
-               this function. For the time being, you can always use the (0,
-               FALSE) parameters.
-
-               Once again, you are encouraged to try compiling and running this
-               program, as described above. Congratulations, you have written
-               your first door program! Feel free to make any changes to this
-               program, and see what effects your changes have.
-
-               To simplify this example, separate versions of this program are
-               shown for the DOS and Win32 versions of OpenDoors. However, you
-               would typically write your program so that it could be compiled
-               using either the DOS or Win32 versions of OpenDoors, by
-               beginning the mainline function as follows:
-
-                    #ifdef ODPLAT_WIN32
-                    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE
-                    hPrevInstance,
-                       LPSTR lpszCmdLine, int nCmdShow)
-                    #else
-                    int main(int argc, char *argv[])
-                    #endif
-
-               In case you are not entirely familiar with the operation of door
-               programs, we will now provide an introduction to the internals
-               of a door's operation. Keep in mind that OpenDoors automatically
-               carries out most of these tasks for you. When any door program
-               starts up, one of the first things it must do is to read the
-               door information file(s) (sometimes called a "drop file") passed
-               to it by the BBS. When a user is on-line, and wishes to run a
-               door, they will most likely select a command from a menu. At
-               this point, the BBS system (such as RemoteAccess, Maximus, PC-
-               Board or whatever), will create a file of information about the
-               system, who is currently on-line, and so on. Various BBS
-               packages produce various styles of door information files.
-               OpenDoors automatically recognizes and reads a wide variety of
-               door information file formats. As a result, your doors will be
-               able to run on a almost any BBS system.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 30
-
-               Fortunately, OpenDoors takes care of all the work involved in
-               detecting and reading the door information file, and then
-               initializing and communicating with the serial port for you. In
-               order to carry out these tasks, along with setting up the status
-               line, and so on, OpenDoors provides a function called od_init().
-               If you do not explicitly call this function, the first call to
-               any other OpenDoors function (such as the first time your door
-               program outputs anything) will automatically cause the od_init()
-               function to be called. As a result, upon the first call to an
-               OpenDoors function, all of the initialization tasks for the door
-               will automatically be carried out. However, there may be times
-               when you will want your program to have access information about
-               the user who is on-line, or carry out other actions which
-               require od_init() to have been executed - prior to the point
-               where you call any other OpenDoors functions. In this case, you
-               will have to call od_init() yourself before you do any of these
-               things.
-
-               OpenDoors provides you with a C/C++ structure, by the name of
-               od_control, which allows you to access all the available
-               information about the user who is on-line, the system your door
-               is running on, and also allows you to adjust various OpenDoors
-               parameters. Depending on what BBS system your door is running
-               under, the actual information available from the od_control
-               structure will vary. For more information on the od_control
-               structure, see the section on the control structure, beginning
-               on page 148.
-
-               Once the door has initialized itself, it will then begin
-               communications with the user who is online. OpenDoors takes care
-               of all communications, through its various input and display
-               functions. When the door has finished, it will then write any
-               information that has changed back to the door information file
-               (if applicable), finish communicating with the modem, and return
-               to the BBS. In OpenDoors, these shut-down operations are
-               automatically performed you call the od_exit() function. This
-               function will terminate the door's activity, OPTIONALLY hang up
-               on the user (allowing you to provide either return to BBS or
-               logoff options for exiting), and then exit with the specified
-               errorlevel.
-
-               One other important OpenDoors function that you should be aware
-               of is the od_kernel() function. od_kernel() is the central
-               OpenDoors control function, and is responsible for much of
-               OpenDoor's updating of the status line, monitoring the carrier
-               detect and user timeout status, responding to sysop function
-               keys, and so on. The od_kernel() function is called
-               automatically by OpenDoors, within the other OpenDoors
-               functions. As a result, since most door programs will call some
-               OpenDoors function on a regular basis, you will most often have
-               no need to call the od_kernel() function yourself. However, if
-               your door is going to perform some action, such as updating data
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 31
-
-               files, during which it will not call any OpenDoors function for
-               more than a few seconds, you should then call the od_kernel()
-               function yourself. For more information on the od_kernel()
-               function, see page 97.
-
-               For more information on the functions available from OpenDoors,
-               or the control structure, see the corresponding sections in this
-               manual.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 32
-
-TOUR OF A SAMPLE DOOR PROGRAM: "EX_VOTE"
-------------------------------------------------------------------------------
-
-               One of the best ways to see how OpenDoors works, and the
-               potential that it has, is to look at the example programs
-               included in the OpenDoors package. A brief description of each
-               of these programs can be found on page 38. This section takes a
-               closer look at one of the example programs, EX_VOTE.C. Unlike
-               our simple example in the previous section, EX_VOTE.C is a much
-               more complicated program, taking advantage of many of the
-               advanced features of OpenDoors. Even if you do not understand
-               everything that EX_VOTE.C does, you should be able to make use
-               of various elements demonstrated here, in your own programs.
-
-               The OpenDoors package includes a two compiled versions of
-               EX_VOTE. VOTEDOS.EXE is a plain-DOS program which can run under
-               DOS, Windows or OS/2. VOTEWIN.EXE was compiled using the Win32
-               version of OpenDoors, and so it runs only on Windows 95/NT. The
-               OpenDoors package also contains a sample door information file,
-               DORINFO1.DEF. You can use this file to test any doors in local
-               mode. If you wish to manually create your own DORINFO1.DEF file,
-               you can do so very easily. The DORINFO1.DEF door information
-               file is a simple text file which lists a different piece of
-               information on each line, in the following format:
-
-               +----------------------------------------------------------+
-               | LINE NUMBER | DESCRIPTION            | EXAMPLE           |
-               +-------------+------------------------+-------------------|
-               |     1       | Name of the BBS        | MY OWN BBS        |
-               |     2       | Sysop's first name     | BRIAN             |
-               |     3       | Sysop's last name      | PIRIE             |
-               |     4       | Com Port modem is on   | COM0              |
-               |     5       | Baud rate, etc.        | 0 BAUD,N,8,1      |
-               |     6       | Unused                 | 0                 |
-               |     7       | User's first name      | JOHN              |
-               |     8       | User's last name       | PUBLIC            |
-               |     9       | Caller's location      | OTTAWA, ON        |
-               |     10      | ANSI mode (0=off, 1=on)| 1                 |
-               |     11      | User's security level  | 32000             |
-               |     12      | User's time left       | 60                |
-               +----------------------------------------------------------+
-
-
-               Feel free to make any changes you wish to EX_VOTE.C, and
-               recompile it. One of the most effective and enjoyable ways to
-               learn OpenDoors is by experimenting. If you are a registered
-               owner of OpenDoors, you may even distribute your own versions of
-               this door. Also, you may find that EX_VOTE.C serves as a good
-               framework for building your own door programs.
-
-               The EX_VOTE.C door behaves similarly to most other door
-               programs, and will have a fair bit in common with any other door
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 33
-
-               you write in OpenDoors. What you see in the output window is
-               identical to what a remote user will be seeing. If the user has
-               ANSI, AVATAR or RIP mode turned on, you will see the same colors
-               as they do, and if they have screen clearing turned on, your
-               screen will be cleared when theirs is. The status line at the
-               bottom of the window will list the name of the user currently
-               on-line (if you are using the sample DORINFO1.DEF file, the
-               user's name will be "The Sysop"), the user's location, and the
-               user's baud rate (0 if the door is operating in local mode). The
-               local display also shows how much time the user has left,
-               whether the user has paged the system operator for a chat, and
-               other information.
-
-               There are a number of special commands that are only available
-               to the system operator on the local keyboard. These commands
-               allow the system operator to hang up on the user, adjust the
-               amount of time the user may remain online, enter chat mode with
-               the user, enter a DOS shell (in the DOS version), and so on. In
-               the DOS version, help on these commands is available on the
-               status line by pressing the [F9] key. In the Windows version,
-               these commands are listed on the menu that appears at the top of
-               the window.
-
-               Now, let us take a closer look at the actual source code for the
-               EX_VOTE.C door. If you have not already printed out a copy of
-               this manual, and possibly the EX_VOTE.C file as well, it would
-               probably be a good idea to do so now.
-
-               Notice that near the top of the program, along with all the
-               standard header files, the OPENDOOR.H file is included. This
-               file must be included in all programs written under OpenDoors.
-               If you are placing the OPENDOOR.H file in the same directory as
-               the door you are compiling, simply include the line:
-
-                                    #include "opendoor.h"
-
-               in your program.
-
-               The main()/WinMain() function of the EX_VOTE.C program has a
-               for(;;) loop that repeatedly displays the main menu, obtains a
-               choice from the user and responds to the command, until the user
-               chooses to exit the program. Before the main menu is displayed,
-               the screen is cleared by calling od_clr_scr(). The od_clr_scr()
-               function will clear both the local and remote screens, but only
-               if the user has screen clearing enabled. Refer to page 57 for
-               information on how to force the screen to be cleared, regardless
-               of the user's screen clearing setting. The main menu is
-               displayed using the od_printf() function, one of the most common
-               OpenDoors functions you will use. Next, od_get_answer() is used
-               to obtain a menu choice from the user from the specified set of
-               keys. Next, a switch() statement is used to respond to the
-               user's command appropriately. If the user presses the P key to
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 34
-
-               page the system operator, od_page() is called. If the user
-               chooses to return to the BBS, od_exit() is called to terminate
-               OpenDoor's activities and return control to the BBS. The FALSE
-               parameter passed to od_exit() indicates that OpenDoors should
-               not disconnect (hangup) before exiting. If the user chooses to
-               log off, EX_VOTE.C first confirms this action with the user, and
-               then calls od_exit() with the TRUE parameter. The numerical
-               parameter passed to od_exit() sets the errorlevel that OpenDoors
-               will exit with.
-
-               In its ChooseQuestion() function, EX_VOTE.C uses the OpenDoors
-               function od_get_key(). This function is similar to the
-               od_get_answer() function that we have already seen. However,
-               unlike od_get_answer() which will wait until the user presses
-               some key from the list of possibilities you provide,
-               od_get_key() will allow the user to press any key. od_get_key()
-               accepts a single parameter. If this parameter is TRUE,
-               od_get_key() will wait for the user to press a key before
-               returning. If this parameter is FALSE, od_get_key() will return
-               immediately with a value of 0 if there are no keys waiting in
-               the inbound buffer, and returning the next key if there are
-               characters waiting.
-
-               In a number of places, EX_VOTE.C also uses the od_input_str()
-               function. Unlike od_get_key() and od_get_answer() which return a
-               single character, od_input_str() allows the user to input and
-               edit a string of many characters. You will only receive the
-               string entered by the user after they press the enter key.
-               od_input_str() accepts four parameters: the string where the
-               user's input should be stored, the maximum number of characters
-               to input, the minimum character value to accept and the maximum
-               character value to accept.
-
-               Another new feature of OpenDoors that is used by EX_VOTE.C is
-               the OpenDoors control structure, od_control. This global
-               structure is documented in chapter 5 of this manual. The
-               OpenDoors control structure allows you to access a wide variety
-               of information about the user who is currently online, the BBS
-               system your program is running on, and also allows you to
-               control various OpenDoors settings. For example, EX_VOTE.C
-               compares the current user name (od_control.od_user_name) with
-               the name of the system operator (od_control.od_sysop_name) to
-               determine whether it is the system operator who using the
-               program.
-
-               EX_VOTE.C uses two data files, the first of which contains a
-               record for every user, and the second of which contains a record
-               for every question. EX_VOTE.C accesses these data files in a
-               controlled manner in order to permit the program to be running
-               simultaneously on multiple lines on a multi-node BBS system.
-               When EX_VOTE.C needs to update a data file, it opens it for
-               exclusive access, so that only one node can access the file at
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 35
-
-               any given time. Since the data file could have been changed by
-               another node since the time that EX_VOTE.C last read the file,
-               it always reads a record, makes changes to it and then re-writes
-               the record while it has the file open for exclusive access. It
-               then closes the file as soon as possible after opening the file,
-               in order to permit other nodes to once again access the file.
-               Because EX_VOTE.C keeps track of which questions each user has
-               voted on, along with the questions and results of voting on each
-               question, its data file format is more complex than many door
-               programs (although not as complex as others).
-
-               EX_VOTE.C also uses color. One of the easiest ways to use
-               different colors in an OpenDoors program is to use the
-               OpenDoor's print color-setting extensions. You can change the
-               color of text display at any point in an od_printf() format
-               string using by enclosing the name of new display color in back
-               quote characters (`, not '). For example:
-
-                    od_printf("`red`This is in red `green`This is green\n\r");
-
-               Would cause the words "This is in red" to be displayed in red,
-               and the words "This is in green" to be displayed in green.
-
-               EX_VOTE.C also takes advantage of a number of OpenDoors
-               capabilities that you can optionally choose to include in your
-               door programs. You will notice that there are a number of new
-               lines at the beginning of the main() function, all of which
-               change settings in the OpenDoors control structure. The line:
-
-                    od_control.od_config_file = INCLUDE_CONFIG_FILE;
-
-               causes the OpenDoors configuration file system to be included in
-               your program. Using this system, OpenDoors automatically reads a
-               configuration file that can be used by the system operator to
-               change various program settings. Refer to the included door.cfg
-               file for an example OpenDoors configuration file. In addition to
-               the configuration file settings automatically supported by the
-               configuration file system, you can also add your own
-               configuration file settings. To do this, you simply supply
-               OpenDoors with a callback function that it will call whenever it
-               encounters an unrecognized keyword in the configuration file.
-               The line:
-
-                    od_control.od_config_function = CustomConfigFunction;
-
-               Causes OpenDoors to call the function CustomConfigFunction() in
-               EX_VOTE.C for this purpose. You will notice that the
-               CustomConfigFunction() receives two parameters - the first is
-               the unrecognized keyword, and the second is any parameters that
-               follow the keyword in the configuration file. EX_VOTE.C checks
-               for two special configuration file lines - one to set whether or
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 36
-
-               not users can add questions, and one to set whether or not users
-               can view the results of a question before voting on it.
-
-               The next line in the main() function,
-
-                    od_control.od_mps = INCLUDE_MPS;
-
-               causes the OpenDoors "Multiple Personality System" to be
-               included in program. This allows the sysop to choose from a
-               number of status line / sysop function key "personalities" that
-               mimic a number of different BBS systems, using the Personality
-               setting in the configuration file.
-
-
-               The line:
-
-                    od_control.od_logfile = INCLUDE_LOGFILE;
-
-               causes the OpenDoors log file system to be included in the
-               program. The OpenDoors log file system automatically records the
-               date and time of program startup, exit and other major actions
-               in the specified file. EX_VOTE.C also writes its own log file
-               entries by calling the od_log_write() function.
-
-               EX_VOTE.C also provides the ability for the sysop to provide
-               their own ASCII/ANSI/AVATAR/RIP files to be displayed in place
-               of the normal main menu. EX_VOTE.C uses the od_hotkey_menu()
-               function to display a VOTE.ASC/.ANS/.AVT/.RIP file for the main
-               menu, if such a file exists. If the file is not available, the
-               normal EX_VOTE.C menu is used instead. The od_hotkey_menu()
-               function will automatically select the appropriate file
-               (.ASC/.ANS/.AVT/.RIP) for the current display mode, and the user
-               is able to make a menu choice at any time. If a menu choice is
-               made before the menu is entirely displayed, the function will
-               stop displaying the menu and return immediately.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 37
-
-OTHER EXAMPLE PROGRAMS INCLUDED WITH OPENDOORS
-------------------------------------------------------------------------------
-
-               In addition to the EX_VOTE.C program, which is discussed in
-               detail in the previous section, a number of other example
-               programs are included with OpenDoors. These programs help to
-               demonstrate what is possible with OpenDoors. They can also serve
-               as excellent tools to help you learn OpenDoors. In addition, you
-               are free to include any portions of any of these example
-               programs in your own programs. Below is a summary of each of
-               these example programs:
-
-
--------------------------------------------------------------------------------
-EX_HELLO.C     This an example of a very simple door program that displays a
-               short message and prompts for the user to press a key. After the
-               user presses a key, the door exits and control is returned to
-               the main BBS software. Despite the fact that it only consists of
-               a few lines of code, EX_HELLO remains a fully functional door
-               program. For information on compiling an OpenDoors door program,
-               see the section that begins on page 22.
-
-
--------------------------------------------------------------------------------
-EX_CHAT.C      This program is an example of a multi-window full-screen chat
-               door written with OpenDoors. EX_CHAT demonstrates the ease of
-               using sophisticated ANSI / AVATAR / RIP terminal features within
-               OpenDoors programs. For instructions on how to compile this
-               program, see the section that begins on page 22.
-
-               This program create two windows on the screen, separated by a
-               bar with user name / sysop name information. This program
-               permits communication between the local sysop and remote user by
-               displaying the text typed by the user in one window, and the
-               text typed by the sysop in the other window. When either
-               person's typing reaches the bottom of the window, the contents
-               of the window is scrolled up to provide more room for typing.
-               Words are also wrapped when either typist reaches the end of a
-               line. The advantage of a split-screen chat program is that it
-               permits both sysop and user to type at the same time without
-               difficulty. The chat function automatically invokes OpenDoor's
-               internal chat mode if ANSI, AVATAR or RIP modes are not
-               available. The display colors, window sizes and locations, and
-               distance to scroll a window's contents are configurable by
-               setting the appropriate variables, below. When the Sysop invokes
-               a DOS shell, a pop-up window is displayed to indicate to the
-               user that the door program has been suspended.
-
-               The chat feature of this program can also be easily integrated
-               into other doors you write, and may be used to replace the
-               existing OpenDoors line-oriented chat system.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 38
-
-
--------------------------------------------------------------------------------
-EX_MUSIC.C     This example door demonstrates how to play "ANSI" music and
-               sound effects in an OpenDoors door. Included in this program is
-               a function to send "ANSI" music to the remote system, and a
-               function to text the remote system's ability to play "ANSI"
-               music. You may use both of these functions in your own doors, if
-               you wish to add music or sound effect capabilities. This program
-               can be compiled by following the instructions that begin on page
-               22.
-
-
--------------------------------------------------------------------------------
-EX_SKI.C       This is a simple but addictive online game that is written using
-               OpenDoors. In this action game, the player must control a skier
-               through a downhill slalom course. The user may turn the skier
-               left or right, and the game ends as soon as the player skis
-               outside the marked course. The game begins at an easy level, but
-               quickly becomes more and more difficult as the course to be
-               navigated becomes more and more narrow. The game maintains a
-               list of players with high scores, and this list may be viewed
-               from the main menu.
-
-
--------------------------------------------------------------------------------
-EX_VOTE.C      The EX_VOTE.C file contain the source code for the Vote example
-               door, as is described beginning on page 38. The Vote example
-               door allows users to vote on up to 200 different "polls", view
-               the results of voting on each question, and optionally add their
-               own questions for other users to answer.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 39
-
-    444
-   4444
-  44 44
- 44444444
-     44
-     44
-     44
--------------------------------------------------------------------------------
-CHAPTER 4 - THE OPENDOORS API FUNCTIONS
-
-
-
-
-OVERVIEW
-------------------------------------------------------------------------------
-
-               OpenDoors provides a wide set of features that you can take
-               advantage of in your program. You control these features and
-               access OpenDoors from your program using two facilities - the
-               OpenDoors API functions, and the OpenDoors control structure. In
-               general, the API functions are used to actually accomplish a
-               task, such as displaying something to the user, or retrieving
-               input from the user. The OpenDoors control structure, on the
-               other hand, is used to alter OpenDoors settings or retrieve
-               specific information.
-
-               Any program written with OpenDoors makes use of the OpenDoors
-               API functions for all of its door-related input and output. In
-               addition to the common input and output tasks, the OpenDoors API
-               functions provide access to many special capabilities, such as
-               displaying ASCII/ANSI/AVATAR/RIP files, providing pop-up windows
-               and menus, and much more. Much of the information about the user
-               who is online, information about the system your door is running
-               on, and settings which customize OpenDoor's behavior are
-               controlled through the OpenDoors control structure. The control
-               structure is described in the section beginning on page 148.
-
-               This chapter is divided into the following sections:
-
-                    i.)   TABLE OF MOST COMMONLY USED FUNCTIONS (Page 41)
-                   ii.)  TABLE OF ALL OPENDOORS FUNCTIONS (Page 42)
-                  iii.) DETAILED INFORMATION ON EACH FUNCTION (Pages 47 - 147)
-
-               The two tables list the names of the OpenDoors functions, along
-               with a brief description of the task performed by each function,
-               and the page number on which the detailed description of that
-               function can be found. The first table lists only the most
-               commonly used OpenDoors functions, to allow you to quickly find
-               the function you are most likely looking for. The second table
-               lists all of the OpenDoors functions, grouped according to
-               general categories of functionality.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 40
-
-               The section containing detailed information lists all of the
-               functions in alphabetical order, with the information about each
-               function beginning on a new page. This section includes a brief
-               description of each function's purpose, a detailed description
-               of how to use the function, the function call format, a list of
-               related functions, and in many cases example source code showing
-               you a typical use of the function.
-
-
-
-
-TABLE OF MOST COMMONLY USED FUNCTIONS
-------------------------------------------------------------------------------
-
-               od_printf()         Displays text, with the ability to change
-                                   display color. (page 110)
-
-               od_clr_scr()        Clears the screen. (Page 57)
-
-               od_input_str()      Inputs a string of one or more characters
-                                   from the user. (Page 95)
-
-               od_get_answer()     Inputs a single key from a list of possible
-                                   choices ignoring upper/lower case. (Page 81)
-
-               od_get_key()        Inputs any single key from the user.
-                                   (Page 82)
-
-               od_set_cursor()     Positions the cursor in ANSI/AVATAR/RIP
-                                   modes. (Page 134)
-
-               od_hotkey_menu()    Displays an ASCII/ANSI/AVATAR/RIP file, with
-                                   the option of watching for a keypress from
-                                   the user. (Page 90)
-
-               od_popup_menu()     Displays a popup menu in ANSI/AVATAR/RIP
-                                   modes. (Page 105)
-
-               od_window_create()  Creates a popup window in ANSI/AVATAR/RIP
-                                   modes. (Page 145)
-
-               od_window_remove()  Removes a popup window in, restoring screen
-                                   contents "underneath" window. (Page 147)
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 41
-
-TABLE OF ALL FUNCTIONS
--------------------------------------------------------------------------------
-OUTPUT         TEXT DISPLAY FUNCTIONS
-FUNCTIONS      ----------------------
-               od_disp_str()            Displays a normal, NULL-terminated
-                                        string. (page 63)
-
-               od_disp()                Sends the specified number of
-                                        characters to the modem, with or
-                                        without local echo. (page 60)
-
-               od_printf()              Performs formatted output, as the
-                                        printf() function does. Also allows
-                                        imbedded codes to change display color.
-                                        (page 110)
-
-               od_putch()               Displays a single character. (page 115)
-
-               od_disp_emu()            Displays a string, interpreting
-                                        imbedded ANSI/AVATAR terminal emulation
-                                        codes. (page 62)
-
-               od_repeat()              Displays the same character any number
-                                        of times, using AVATAR optimization, if
-                                        possible. (page 118)
-
-               COLOR AND CURSOR CONTROL
-               ------------------------
-               od_set_color()           Sets current color to specified
-                                        foreground and background settings.
-                                        (page 131)
-
-               od_set_attrib()          Sets current color to specified IBM-PC
-                                        display attribute. (page 128)
-
-               od_set_cursor()          Sets the position of the cursor, if
-                                        ANSI/AVATAR/RIP mode is enabled. (page
-                                        134)
-
-               SCREEN MANIPULATION
-               -------------------
-               od_clr_scr()             Clears the screen, if user has screen
-                                        clearing enabled. (page 57)
-
-               od_save_screen()         Stores the current contents of the
-                                        screen, to be later redisplayed using
-                                        od_restore_screen(). Works in all
-                                        display modes. (page 121)
-
-               od_restore_screen()      Restores the contents of the screen, as
-                                        previously stored using
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 42
-
-                                        od_save_screen(). Works in all display
-                                        modes. (page 120)
-
-               BLOCK MANIPULATION
-               ------------------
-               od_clr_line()            Clears the remainder of current line.
-                                        (page 55)
-
-               od_gettext()             Stores any area of the screen, to later
-                                        be displayed by od_puttext(). Requires
-                                        ANSI/AVATAR/RIP graphics mode. (page
-                                        89)
-
-               od_puttext()             Displays text with color information,
-                                        as previously stored using
-                                        od_gettext(). Requires ANSI/AVATAR/RIP
-                                        graphics mode. (page 116)
-
-               od_scroll()              Scrolls a portion of the screen in
-                                        ANSI/AVATAR/RIP graphics modes. (page
-                                        123)
-
-               POPUP WINDOWS AND MENUS
-               -----------------------
-               od_draw_box()            Draws a box on the screen in
-                                        ANSI/AVATAR/RIP graphics mode. (page
-                                        65)
-
-               od_window_create()       Displays a popup window, storing the
-                                        screen contents "under" the window.
-                                        Requires ANSI/AVATAR/RIP graphics mode.
-                                        (page 145)
-
-               od_window_remove()       Removes a popup window displayed with
-                                        od_window_create(), restoring the
-                                        original screen contents "under" the
-                                        window. Requires ANSI/AVATAR/RIP
-                                        graphics mode. (page 147)
-
-               od_popup_menu()          Displays a menu in a popup window,
-                                        allowing the user to choose menu items
-                                        either by pressing a "hot" key, or
-                                        moving a highlighted selection bar.
-                                        After menu selection, the menu may be
-                                        removed, restoring the original screen
-                                        contents "under" the window. Requires
-                                        ANSI/AVATAR/RIP graphics mode. (page
-                                        105)
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 43
-
-               FILE DISPLAY FUNCTIONS
-               ----------------------
-               od_send_file()           Displays an ASCII/ANSI/AVATAR/RIP file
-                                        (for instance, an .ANS file created by
-                                        a program such as "TheDraw" (page 124)
-
-               od_hotkey_menu()         Displays an ASCII/ANSI/AVATAR/RIP menu
-                                        file, with hotkeys active. (page 90)
-
-               od_list_files()          Lists the files available for download
-                                        in an area, using a FILES.BBS file.
-                                        (page 98)
-
-
--------------------------------------------------------------------------------
-INPUT          od_get_answer()          Inputs a single key from the keyboard,
-FUNCTIONS                               allowing only particular responses.
-                                        (page 81)
-
-               od_get_input()           A more flexible version of
-                                        od_get_key(), that also supports
-                                        extended keys such as arrow keys,
-                                        insert, etc. (page 82)
-
-               od_get_key()             Inputs a single key from the keyboard,
-                                        optionally waiting if a key is not
-                                        available. (page 82)
-
-               od_input_str()           Inputs a string of specified length,
-                                        from the keyboard. (page 95)
-
-               od_edit_str()            Formatted string editing function,
-                                        requiring ANSI/AVATAR/RIP graphics.
-                                        (page 68)
-
-               od_multiline_edit()      Provides a text editor that allows the
-                                        user to enter or edit text that spans
-                                        multiple lines, such as email messages
-                                        or text files. (page 101)
-
-               od_clear_keybuffer()     Removes any waiting keys from the
-                                        keyboard input queue. (page 53)
-
-
--------------------------------------------------------------------------------
-COMMON         od_page()                Allows the user to page the sysop.
-DOOR                                    (page 101)
-ACTIVITY
-FUNCTIONS      od_spawn()                    OpenDoors "quick" spawn function.
-                                        Executes an external program (eg. file
-                                        compressor, external protocol, etc.) on
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 44
-
-                                        a separate screen, restoring the
-                                        OpenDoors screen afterwards. (page 139)
-
-               od_spawnvpe()            OpenDoors full-featured spawn function.
-                                        Executes an external program on a
-                                        separate screen, searching the path for
-                                        the program, allowing you to specify an
-                                        environment to pass to the child
-                                        process, and returning the errorlevel
-                                        returned by the child process. (page
-                                        143)
-
-               od_log_write()           Adds an entry to the end of the log
-                                        file. (page 100)
-
-               od_parse_cmd_line()      Handle standard command line options.
-                                        (page 105)
-
-
--------------------------------------------------------------------------------
-SPECIAL        od_init()                Begins door operation by setting up
-CONTROL                                 the OpenDoors control structure,
-FUNCTIONS                               setting up the local screen,
-                                        initializing the serial port (if
-                                        applicable), and reading the door
-                                        information file. (page 92)
-
-               od_color_config()        Transfers a color configuration line to
-                                        a color attribute value. (page 59)
-
-               od_add_personality()     Adds a custom status line/control key
-                                        personality to OpenDoors. (page 47)
-
-               od_set_statusline()      Temporarily alters the setting of the
-                                        current OpenDoors status line. (page
-                                        137)
-
-               od_autodetect()          Automatically determines the remote
-                                        terminal software's graphical
-                                        capabilities. (page 48)
-
-               od_kernel()              The central OpenDoors control function,
-                                        which should be executed every few
-                                        seconds. (page 97)
-
-               od_exit()                Ends door operations, closing the
-                                        serial port driver, re-writing the door
-                                        information file, and optionally
-                                        returning control to the BBS. (page 79)
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 45
-
-               od_carrier()             Allows detection of carrier signal in
-                                        programs that have disabled OpenDoors
-                                        internal checking. (page 51)
-
-               od_set_dtr()             Controls the DTR signal to the modem.
-                                        Can be used to manually disconnect a
-                                        remote user, in order to perform
-                                        activities such as call back
-                                        verification. (page 135)
-
-               od_chat()                Forces OpenDoors to enter chat mode,
-                                        even if sysop did not press the "chat"
-                                        key. (page 50)
-
-               od_sleep()               Suspends program execution, yielding
-                                        control to other tasks in a
-                                        multitasking environment. (page 139)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 46
-
-OD_ADD_PERSONALITY()
--------------------------------------------------------------------------------
-
-PURPOSE        Installs a custom status line / sysop function key personality
-               into OpenDoors.
-
-
-FORMAT         BOOL od_add_personality(char *pszName, BYTE btOutputTop,
-                   BYTE btOutputBottom, OD_PERSONALITY_PROC *pfPerFunc);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    If used, this function should be called before any other
-               OpenDoors API functions. This function installs a new
-               personality into OpenDoors. The first parameter specifies the
-               string that will be used to identify the personality. This is
-               the string that the user will be able to supply in the
-               configuration file to select this personality, and is also the
-               string that can be passed to od_set_personality() to manually
-               switch to this personality. The second and third parameters
-               specify the 1-based to and bottom line numbers of the output
-               window to be used with this personality. For instance, a top
-               value of 1 and bottom value of 23 would cause all door output to
-               be displayed on the first 23 lines of the screen, leaving the
-               bottom two lines for use by the personality's status line. The
-               last parameter is a pointer to the personality function, which
-               OpenDoors will call to perform various operations with that
-               involve the personality. For more information on personalities
-               and the OpenDoors Multiple Personality System, see the section
-               which begins on page 233.
-
-               This function only has an effect under the DOS version of
-               OpenDoors.
-
-SEE ALSO       od_set_personality(), od_set_statusline()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 47
-
-OD_AUTODETECT()
--------------------------------------------------------------------------------
-
-PURPOSE        Attempts to automatically determine the terminal capabilities of
-               the remote system.
-
-
-FORMAT         void od_autodetect(int nFlags);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function can be used to determine whether or not the remote
-               terminal supports ANSI and/or RIP (Remote Imaging Protocol)
-               graphics modes. This information is usually supplied to the door
-               by the BBS software, through the door information file. For this
-               reason, most door programs do not need to make used of this
-               function. However, if your door will be running under any BBS
-               software that does not report the ANSI or RIP capabilities of
-               the remote system, you may wish to use this function.
-               od_autodetect() will set either of the following OpenDoors
-               control structure variables to TRUE if the corresponding
-               graphics mode is detected:
-
-                    od_control.user_ansi     - TRUE if ANSI mode is available
-                    od_control.user_rip      - TRUE if RIP mode is available
-
-               However, if either of these variables have previously been set
-               to TRUE (either explicitly by your program, or due to the
-               corresponding modes being enabled in the door information file),
-               and od_autodetect() does not detect the corresponding graphics
-               mode, they will not be set to FALSE. Not all terminal software
-               that supports ANSI or RIP graphics mode will necessarily have
-               the ability to report their graphics mode capabilities to the
-               door. For this reason, failure to detect either of these modes
-               does not necessarily indicate that they are not available.
-               However, if these modes are detected by od_autodetect(), it is
-               safe to assume that the remote system does support the detected
-               mode.
-
-               The nFlags parameter is reserved for future use, and should
-               always be set to DETECT_NORMAL.
-
-               This function cannot auto-detect AVATAR mode, because there is
-               no standard means of determining whether a remote system
-               supports AVATAR mode.
-
-
-EXAMPLE        Below is an example of using od_autodetect() in determining the
-               remote terminal's graphics capabilities. Since not all terminal
-               software supports auto-detection, this example will also prompt
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 48
-
-               the user to determine their software's capabilities if
-               od_autodetect() fails to detect ANSI mode. This code assumes
-               that if the terminal software supports the autodetection of ANSI
-               mode, that it will also support the autodetection of RIP mode.
-               OpenDoors assumes that ANSI mode is always available in
-               conjunction with RIP mode.
-
-                    /* Call the automatic terminal detection function */
-                    od_autodetect();
-
-                    /* If ANSI mode was not detected, ask the user about
-                    if(!od_control.user_ansi)
-                    {
-                       /* Prompt the user for ANSI capabilities */
-                       od_clr_scr();
-                       od_printf("Does your system support ANSI graphics?");
-                       od_printf(" (Y/N)");
-
-                       /* If the user chooses [Y]es */
-                       if(od_get_answer("YN") == 'Y')
-                       {
-                          /* Turn on ANSI mode */
-                          od_control.user_ansi = TRUE;
-
-                          /* Since ANSI mode is present, RIP mode may also */
-                          /* be available. Prompt the user for RIP. */
-                          od_printf("\r\n\n");
-                          od_printf("Does your system support RIP graphics?");
-                          od_printf(" (Y/N)");
-
-                          /* If the user chooses [Y]es */
-                          if(od_get_answer("YN") == 'Y')
-                             /* Turn on RIP mode */
-                             od_control.user_rip = TRUE;
-
-                          /* Since ANSI mode is present, AVATAR mode may  */
-                          /* also be available. Prompt the user for AVATAR. */
-                          od_printf("\r\n\n");
-                          od_printf("Does your system support AVATAR ");
-                          od_printf("graphics? (Y/N)");
-
-                          /* If the user chooses [Y]es */
-                          if(od_get_answer("YN") == 'Y')
-                             /* Turn on AVATAR mode */
-                             od_control.user_avatar = TRUE;
-                       }
-
-                       od_printf("\r\n\n");
-                    }
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 49
-
-OD_CHAT()
--------------------------------------------------------------------------------
-
-PURPOSE        Manually invokes sysop chat mode.
-
-
-FORMAT         void od_chat(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    Normally, the OpenDoors sysop chat mode will only be invoked
-               when the sysop explicitly requests it using the sysop chat key.
-               However, there may be some cases where you wish to manually
-               invoke the sysop chat mode. One example is when you are
-               replacing the OpenDoors built-in chat mode with your own, but
-               still wish to use the OpenDoors chat mode under some
-               circumstances. For instance, you may wish to use your own split-
-               screen chat routine if ANSI, AVATAR or RIP graphics mode is
-               available, and use the OpenDoors line-oriented chat mode if only
-               ASCII mode is available.
-
-
-SEE ALSO       od_page()
-
-
-EXAMPLE        For an example of using the od_chat() function, see the
-               ex_chat.c example door, which is described on page 38.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 50
-
-OD_CARRIER()
--------------------------------------------------------------------------------
-
-PURPOSE        To determine the status of the carrier detect signal, in
-               programs where OpenDoors' internal carrier detection has been
-               disabled.
-
-
-FORMAT         BOOL od_carrier(void);
-
-
-RETURNS        TRUE if a carrier is present, or
-               FALSE if no carrier is present, or in local mode.
-
-
-DESCRIPTION    Usually, you will not have any use for the od_carrier()
-               function, as OpenDoors automatically monitor's the carrier
-               detect signal, and will correctly recover if the carrier detect
-               signal is lost while the door is operating in remote mode.
-               However, in some programs, you may wish to disable OpenDoors'
-               internal carrier detection routines, using the
-               od_control.od_disable variable. Two such cases in which you
-               might want to do this, are a call-back verification door, which
-               disconnects the user and attempts to call them back, or in a
-               terminal program, which is in fact not a door at all (and as
-               such you would not want to have OpenDoors exit when the carrier
-               detect signal is lost). In cases like these, you will then be
-               able to use the od_carrier() function in order to determine the
-               state of the carrier detect signal.
-
-               This function will return a Boolean value (for more information
-               on Boolean values, see the Glossary which begins on page 256),
-               of either TRUE or FALSE. If a carrier detect signal is present
-               when the function is called, it will return TRUE, and if no
-               carrier detect signal is detected, it will return FALSE. Since
-               there is no remote connection, and thus no carrier when
-               OpenDoors is operating in local mode, this function will always
-               return a value of FALSE in local mode.
-
-
-SEE ALSO       od_set_dtr()
-
-
-EXAMPLE        As an example of the use of this function, let us consider a
-               call back verification door, which hangs up on the user, and
-               then calls the user back at their entered phone number, in order
-               to verify the correctness of that number. This program would
-               probably contain a function that is responsible for
-               disconnecting the user, waiting for the connection to be broken,
-               and then phoning the user. At some point in this function,
-               likely just prior to the point where the function hangs up on
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 51
-
-               the user, you would disable OpenDoors' internal carrier
-               detection, using the line:
-
-                    od_control.od_disable |= DIS_CARRIERDETECT;
-
-               You would then want to have a piece of code which would simply
-               wait up to a given amount of time for the carrier signal to
-               drop. If this occurs, you would continue to place the call, and
-               if it does not occur, you would probably try your hangup
-               procedure one or two more times. In this example, the function
-               will return with a value of FALSE if the carrier signal does not
-               drop, and will return a value of TRUE if it does.
-
-                    char hangup(void)
-                    {
-                       clock_t timer;
-                       char to_return = FALSE;
-
-                       od_set_dtr(FALSE);                    /* Hangup modem */
-
-                                                        /* Wait up to 30secs */
-                       timer = clock() + CLOCKS_PER_SEC * 30;
-                       while(timer >= clock())
-                       {    /* If carrier has been lost, return with success */
-                          if(!od_carrier())
-                          {
-                             to_return = TRUE;
-                             break;
-                          }
-                       }
-
-                       od_set_dtr(TRUE);             /* Re-enable DTR signal */
-                       return(to_return);
-                    }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 52
-
-OD_CLEAR_KEYBUFFER()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to clear the input keyboard buffer
-
-
-FORMAT         void od_clear_keybuffer(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    OpenDoors maintains its own keyboard input buffer, in order to
-               permit the user to "type ahead" - to send input to the door
-               prior to the time when it is ready to process those key presses.
-               For example, the user could begin to type a command while a menu
-               is still being displayed, and when your door reaches the point
-               of inputting the menu command, the characters already typed by
-               the user will already be waiting for the OpenDoors input
-               functions. Note that the keyboard input buffer will include both
-               the keys hit by the user on-line, and the non-function keys (ie,
-               Alt-C will not appear in the OpenDoors keyboard buffer), hit by
-               the sysop. This allows both the user on-line and the sysop to
-               control the door at any time. If the sysop wishes to temporarily
-               prevent the user from having any control over the door, the
-               sysop may use the Alt-K (user-keyboard off) key. The key strokes
-               placed in the OpenDoors type-ahead buffer will be retrieved by
-               the od_get_key() and od_input_str() functions. The keyboard
-               buffer can contain a maximum of 64 user keystrokes in this
-               version of OpenDoors, after which any additional keystrokes will
-               simply be discarded by OpenDoors.
-
-               There are times, however, when you will want to erase any keys
-               that have been hit by the user, to prevent them from typing
-               ahead. For example, if your door has been busy doing some
-               processing for a few moments, they user may have been pressing
-               keys on their keyboard - perhaps in the hope that doing so will
-               speed things up. These keys will be waiting in the type-ahead
-               buffer, and if one of the keys the user entered was a valid
-               response to the next prompt in your door, the user may find that
-               they have accidentally made a choice they did not wish to. A
-               well designed door will simply erase the contents of the type-
-               ahead buffer after any long period of internal processing, etc.
-               Keep in mind that too much use of the od_clear_keybuffer()
-               function can be just as undesirable as not using it all, as
-               there are times when the presence of the keyboard buffer can
-               prove to be very useful for the user of a door.
-
-               To erase the contents of the type-ahead buffer, you simply call
-               the od_clear_keybuffer() function. This function takes no
-               parameters, and does not return any value.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 53
-
-
-
-SEE ALSO       od_get_key(), od_input_str(), od_edit_str()
-
-
-EXAMPLE        For one example of the use of the od_clear_keybuffer() function,
-               see the example program EX_VOTE.C, which is described beginning
-               on page 38. Below is another example of using this function. In
-               this case, we present a simple function, wait_for_return(),
-               which simply pauses for the user to press their [Enter]/[Return]
-               key. The function begins by displaying a prompt asking for the
-               [Enter] or [Return] key to be pressed. The function then clears
-               the keyboard input buffer, and waits until the user presses the
-               carriage return key, using the od_get_key() function. Note also
-               that this function will only continue if the user has pressed
-               the correct key. This is a good idea in all door programs, as it
-               allows your door to distinguish between a character pressed by
-               the user, and a "line noise" character.
-
-                    void wait_for_return(void)
-                    {                                      /* Display prompt */
-                       od_disp_str("Please Press [Enter] to continue...\n\r");
-                       od_clear_keybuffer();        /* Clear keyboard buffer */
-                       while(od_get_key(TRUE) != 13);  /* Wait for Enter key */
-                    }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 54
-
-OD_CLR_LINE()
--------------------------------------------------------------------------------
-
-PURPOSE        Clears the rest of the current display line
-
-
-FORMAT         void od_clr_line(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function clears the line that the cursor is on, from the
-               cursor position to the end of the line. After the rest of the
-               line is cleared, the cursor is automatically returned to the
-               position it was at prior to issuing the command. Hence, if the
-               display line the cursor was located on looked as follows, with
-               the underscore (_) character representing the cursor position:
-
-                        This is a_line of text!
-
-               With the cursor between the words "a" and "line", after the
-               od_clr_line command is issued, the line would appear as follows:
-
-                        This is a_
-
-               With the cursor directly following the word "a". Note that this
-               function places a space character at the cursor location, and
-               every location up to the end of the line.
-
-               When the door is running in plain ASCII mode, this command will
-               simply clear the rest of the line by manually sending a series
-               of space and backspace characters. When ANSI, AVATAR or RIP
-               modes are active, the corresponding ANSI/AVATAR control sequence
-               will be sent in order to accomplish the line clear. Since the
-               graphics mode sequences are much shorter than the sequence that
-               would be required to clear the line manually, the use of this
-               function will cause your door's graphics to display much more
-               quickly when ANSI, AVATAR or RIP modes are active. Also note
-               that in ANSI, AVATAR or RIP graphics modes, the line will be
-               cleared with the currently selected color attribute. Thus, if
-               you wanted to place a blue background on a particular line, you
-               would use the od_set_color() (or od_set_attrib()) function, then
-               use the od_set_cursor() function to locate the cursor at the
-               beginning of the desired line, followed by the od_clr_line()
-               function. Just such a procedure is demonstrated in the example,
-               below.
-
-
-SEE ALSO       od_clr_scr(), od_set_cursor()
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 55
-
-EXAMPLE        Below, is an example of a function that clears an entire line
-               with a specified color. Since this function performs operations
-               that require ANSI, AVATAR or RIP graphics mode, it should only
-               be used in a case where these modes are known to be available.
-               For example, this function would be useful in a full-screen
-               editor or viewer, or when performing ANSI animations. The
-               function accepts three parameters: the line to be cleared (where
-               1 is the first line, 2 the second, and so on), the foreground
-               color of this line, and the background color of this line.
-
-               This function differs from the od_clr_line() function itself in
-               several important manners. First of all, this function clears
-               the entire line, whereas the od_clr_line() function can be used
-               to clear only the remaining characters of the line, after any
-               particular location. Also, as mentioned before, this function
-               selects a color to clear the line to, and moves the cursor to
-               the line which is to be cleared - neither of which is done by
-               the od_clr_line() function.
-
-
-               void clear_line(char line_number,char foreground,char
-               background)
-               {
-                  od_set_cursor(line_number,1);      /* move to correct line */
-                  od_set_color(foreground,background);          /* set color */
-                  od_clr_line();                        /* clear entire line */
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 56
-
-OD_CLR_SCR()
-------------------------------------------------------------------------------
-
-PURPOSE        The OpenDoors clear screen function
-
-
-FORMAT         void od_clr_scr(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    The od_clr_scr() function can be used to clear the output
-               screen. (ie, the user's screen and local screen with the
-               exception of the status line are cleared.) This function will
-               only clear the screen if screen clearing is enabled. If your
-               program will be running under BBS systems that do not pass the
-               user's screen clearing setting to the door, you may wish to
-               determine yourself whether or not the user's system supports
-               screen clearing codes, during the first time the user uses the
-               door. You will then be able to store this setting in a data
-               file. The example below demonstrates how to detect whether or
-               not the user's system supports screen clearing.
-
-               You should note that the ability for the user's terminal to
-               support screen clearing codes is independent of the user's ANSI
-               / AVATAR / RIP graphics mode settings.
-
-               For more information on the user's screen clearing setting,
-               please refer to the user_attrib variable in the OpenDoors
-               Control Structure chapter of this manual. If you wish to force a
-               screen clear, regardless of the user's screen clearing setting,
-               simply use the function call:
-
-                         od_disp_emu("\xc", TRUE);
-
-
-SEE ALSO       od_clr_line()
-
-
-EXAMPLE        Below is an example of a function which determines whether or
-               not the user's system supports screen clearing. This function
-               will return a value of TRUE if screen clearing is supported, and
-               will return a value of FALSE if screen clearing is not
-               supported:
-
-               int user_supports_screen_clearing(void)
-               {
-                  char answer;
-                                             /* display instructions to user */
-                  od_disp_str("In order for this door to function\n\r");
-                  od_disp_str("correctly, we must know whether or not\n\r");
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 57
-
-                  od_disp_str("your system supports screen clearing.\n\r");
-                  od_disp_str("In a moment, we will attempt to clear\n\r");
-                  od_disp_str(
-                     "your screen in order to test your system's\n\r");
-                  od_disp_str("capabilities.\n\r\n\r");
-
-                  od_disp_str("Please press [Enter]/[Return] when you\n\r");
-                  od_disp_str("are ready to perform this test.\n\r");
-                  while(od_get_key(TRUE)!=13);      /* wait for [Return] key */
-
-                  od_clr_scr();                   /* attempt to clear screen */
-                                         /* ask user if their screen cleared */
-                  od_disp_str("Did your screen just clear? (Y/N)\n\r");
-                  for(;;)           /* loop until user chooses [Y]es or [N]o */
-                  {
-                     answer=od_get_key(TRUE);           /* Get user's answer */
-                     if(answer=='y' || answer=='Y') return(TRUE);
-                     if(answer=='n' || answer=='N') return(FALSE);
-                  }
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 58
-
-OD_COLOR_CONFIG()
--------------------------------------------------------------------------------
-
-PURPOSE        Parses a color configuration line from the configuration file,
-               generating a color attribute value.
-
-
-FORMAT         BYTE od_color_config(char *pszColorDesc);
-
-
-RETURNS        Color attribute value
-
-
-DESCRIPTION    This function will be of use if you are using the configuration
-               file system of OpenDoors, and wish to allow the sysop to specify
-               text colors to be used in your door. While OpenDoors
-               automatically recognizes color configuration settings for things
-               such as sysop chat mode and FILES.BBS listings, you may wish to
-               add additional color configuration options. In this case, you
-               could call the od_color_config() function from your custom line
-               function. For more information on the custom line function, see
-               the section on the OpenDoors configuration file system, which
-               begins on page 224.
-
-               To use this function, simply pass the configuration file line
-               you wish to have parsed to the function in it's single
-               parameter. The function will then return a color attribute value
-               in the same format that is used but the od_set_attrib()
-               function. Colors are specified using a string of the format:
-
-                    {Flashing} {Bright} [foreground] on [background]
-
-               Where "Flashing" is an optional keyword indicating that the text
-               should be flashing. "Bright" is an optional keyword indicating
-               that the foreground color should be bright. Foreground is the
-               name of a foreground color, and background is the name of a
-               background color. Case (upper or lower) is not significant.
-
-               The color keywords are language configurable, using the array
-               od_control.od_color_names.
-
-
-EXAMPLE        See the example accompanying in the section on the OpenDoors
-               configuration file system, which begins on page 224.
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 59
-
-OD_DISP()
-------------------------------------------------------------------------------
-
-PURPOSE        Sends a buffer of text with optional local echo
-
-
-FORMAT         void od_disp(char *pachBuffer, INT nSize, BOOL bLocalEcho);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function allows you to send a buffer of text of any
-               specified length, with the option of enabling or disabling local
-               echo. You will probably have little use for this function -
-               instead you will most likely display strings using either the
-               od_disp_str() or od_printf() functions, depending on whether or
-               not you wish to use printf()'s formatting options. For a
-               breakdown of the uses of the various OpenDoors display
-               functions, see the description of the od_disp_str() function, on
-               page 63.
-
-               There are two cases when this function will come in useful:
-
-                    1.)If you wish to display a buffer of characters of known
-                       length, which may contain null (ASCII 0) characters.
-                       Since this character is used by the C language to
-                       indicate the end of a string, the other two string
-                       display functions (od_disp_str() and od_printf()) will
-                       not send this character to the remote system.
-
-                    2.)If you wish to send text to the remote system without
-                       having it displayed on the local screen, or if you wish
-                       to send strings to the modem when it is in command
-                       mode, without having these characters displayed on the
-                       local screen.
-
-               The od_disp() function is called with three parameters. The
-               first parameter, pachBuffer, is a pointer to a buffer of
-               characters you wish to have displayed. The second parameter,
-               nSize, is simply the number of characters in the buffer to be
-               displayed. If the third parameter, bLocalEcho, is set to TRUE,
-               then all characters sent to the modem will also be displayed on
-               the local screen. If the third parameter is set to FALSE, then
-               the buffer will be sent to the modem without being echoed to the
-               sysop's screen.
-
-
-SEE ALSO       od_disp_str(), od_printf(), od_putch(), od_repeat(),
-               od_disp_emu()
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 60
-
-EXAMPLES       The following are a few examples of the use of the od_disp()
-               function:
-
-               In order to display a single character, contained in the
-               variable "character", without echo to the local screen:
-
-                    od_disp(&character,1,FALSE);
-
-
-               In order to send a command to the modem (only if you know that
-               the modem is in command mode), with the command contained in the
-               null-terminated string "string":
-
-                    od_disp(string,strlen(string),FALSE);
-
-
-               In order to send exactly 5 characters from the buffer "buffer",
-               WITH echo to the local screen:
-
-                    od_disp(buffer,5,TRUE);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 61
-
-OD_DISP_EMU()
--------------------------------------------------------------------------------
-
-PURPOSE        Displays a string with ANSI/AVATAR terminal emulation
-
-
-FORMAT         void od_disp_emu(char *pszToDisplay, BOOL bRemoteEcho);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    The od_disp_emu() function allows you to display your own ANSI /
-               AVATAR graphics sequences. This function passes the characters
-               you wish to display to the OpenDoors terminal emulator, which is
-               fully documented in the description of the od_send_file()
-               function, on page 124. This function can be used to send these
-               control sequences to the user's terminal, and also have them
-               displayed on the local screen as they will appear to the user.
-
-               The string passed to od_disp_emu() contains any stream of text
-               to display, and may include both normal text and terminal
-               emulation control sequences. If the bRemoteEcho parameter is set
-               to TRUE, the string passed to od_disp_emu() will be sent to the
-               remote terminal in addition to being displayed locally. If this
-               parameter is set to FALSE, the string will only be displayed
-               locally.
-
-               Note that if you wish to display an entire file containing
-               ANSI/AVATAR/RIP graphics sequences (perhaps as your program's
-               menu or title screen), you can use the od_send_file() function.
-
-
-SEE ALSO       od_send_file(), od_disp(), od_disp_str() od_printf().
-
-               For a breakdown of the uses of the various OpenDoors display
-               functions, see the od_disp_str() function, on page 63.
-
-
-EXAMPLE        For an example of the use of the od_disp_emu() function, see the
-               SpaceRight() and MoveLeft() functions included in the example
-               program ex_ski.c.
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 62
-
-OD_DISP_STR()
--------------------------------------------------------------------------------
-
-PURPOSE        Displays a string to the screen (remote and local)
-
-
-FORMAT         od_disp_str(char *pszToDisplay);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    The two functions most often used for displaying strings within
-               a door are the od_disp_str() and od_printf() functions. The
-               od_printf() function allows for formatted output, whereas the
-               od_disp_str function simply displays the actual contents of the
-               string passed to it. If you wish to display a single character,
-               use the od_putch() function. If you wish to send a string or
-               buffer to the modem without local echo, use the od_disp()
-               function. If you wish to send a sequence of the same character
-               to the modem, the od_repeat() function will use graphics control
-               codes, if available to display the sequence much faster than
-               simply sending the same character in repetition. Also, if you
-               wish to send ANSI, AVATAR or RIP graphics control codes, and
-               have them emulated on the local screen, use the od_disp_emu()
-               function.
-
-               The od_disp_str() function displays the contents of the null-
-               terminated string pointed to by *string. Display is sent to both
-               the local screen and modem (presuming the door is not running in
-               local mode).
-
-               An important thing to keep in mind when using the od_disp_str()
-               function, is that you should use "/n/r" instead of simply "/n"
-               for a new line. This is due to the fact that terminal programs
-               usually require a carriage-return line-feed sequence (/n/r),
-               instead of just a line-feed (/n). For example, instead of using:
-
-                              od_disp_str("Hello world!\n");
-
-               You should use:
-
-                              od_disp_str("Hello world!\n\r");
-
-               To change the cursor color or location of output with the
-               od_disp_str() function, refer to the od_set_cursor() and the
-               od_set_attrib() functions.
-
-
-SEE ALSO       od_disp(), od_printf(), od_putch(), od_repeat(), od_disp_emu()
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 63
-
-EXAMPLES       Below are a few examples of various uses of the od_disp_str()
-               function:
-
-               Displaying three string constants on separate lines:
-
-                         od_disp_str("This is an example\n\r");
-                         od_disp_str("of the OpenDoors\n\r");
-                         od_disp_str("od_disp_str() function\n\r");
-
-
-               Displaying three string constants on the same line:
-
-                         od_disp_str("Another ");
-                         od_disp_str("od_disp_str() ");
-                         od_disp_str("example\n\r");
-
-
-               Displaying a string variable:
-
-                         char string[80];
-
-                         strcpy(string,"This is a string!\n\r");
-                         od_disp_str(string);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 64
-
-OD_DRAW_BOX()
--------------------------------------------------------------------------------
-
-PURPOSE        Draws a box on the screen in ANSI, AVATAR or RIP graphics modes.
-
-
-FORMAT         BOOL od_draw_box(BYTE btLeft, BYTE btTop, BYTE btRight, BYTE
-                  btBottom);
-
-
-RETURNS        TRUE on success, FALSE on failure
-
-
-DESCRIPTION    This function is for use in ANSI, AVATAR or RIP graphics modes.
-               This function will draw a box in the current display attribute,
-               at the specified location on the screen. The boarder of the box
-               is made up of the characters specified in the od_control.
-               od_box_chars[] array. If AVATAR graphics mode is available, this
-               function uses AVATAR control codes to display the box in less
-               than 1/10 the length of time required to display the box in ANSI
-               mode.
-
-               The first two parameters of this function, btLeft and btTop,
-               specify the coordinates of the top, left-hand corner of the box
-               to be draw. The third and fourth parameters, btRight and
-               btBottom, specify the coordinates of the bottom, left-hand
-               corner of the box. Like the values passed to the od_set_cursor()
-               function, these coordinates are relative to the upper left-hand
-               corner of the screen, with the position (1,1) being this corner.
-
-               As mentioned above, this function will display the window in the
-               current text color. Thus, before calling this function, you
-               should use either the od_set_color() or the od_set_attrib()
-               function to specify the color in which you would like to have
-               the window displayed.
-
-               Normally, the boarder of the window will be displayed using the
-               IBM extended ASCII characters which produce a single line
-               boarder. However, you may wish to have the boarder displayed
-               using different characters. In this case, the characters used to
-               display the boarder can be specified by the od_control.
-               od_box_chars variable, described in the OpenDoors control
-               structure section of this manual.
-
-SEE ALSO       od_set_color(), od_set_attrib(), od_clr_scr(), od_edit_str(),
-               od_set_cursor()
-
-
-EXAMPLE        As an example of the use of the od_draw_box() function in
-               conjunction with the od_edit_str() function, we show a portion
-               of a program which displays a window, and allows the user to
-               input the name of a file they would like to upload, a
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 65
-
-               description of the file, and whether they want it to be a
-               private upload. The user is able to move among fields using the
-               tab key, and select a "continue" button when they are finished.
-               The function returns TRUE if the user selects continue, and
-               FALSE if the user presses [ESCape].
-
-                                                  // Main "dialog box" function
-               int get_information(char *filename, char *description,
-                                    char *private)
-               {
-                  char current_field=1;             // Currently selected field
-                  int choice;                                  // User's choice
-
-                  od_set_color(L_WHITE,D_BLUE);               // Display window
-                  od_draw_box(10,5,70,13);
-
-                  od_set_cursor(5,25);                  // Display window title
-                  od_set_color(L_GREEN,D_BLUE);
-                  od_disp_str(" ENTER FILENAME INFORMATION ");
-
-                  od_set_color(L_CYAN,D_BLUE);     // Display fields and titles
-                  od_set_cursor(6,15);
-                  od_disp_str("FILENAME : ");
-                  od_repeat(176,13);
-                  od_set_cursor(7,12);
-                  od_disp_str("DESCRIPTION : ");
-                  od_repeat(176,43);
-                  od_set_cursor(8,16);
-                  od_disp_str("PRIVATE : ");
-                  od_repeat(176,2);
-                  draw_button();
-
-                  filename[0]='\0';    // Blank out contents of input variables
-                  description[0]='\0';
-                  private[0]='\0';
-
-                  for(;;)                               // Main dialog box loop
-                  {
-                     if(current_field==4)             // If field is the button
-                     {
-                        od_set_color(L_GREEN,D_BLUE);       // Highlight button
-                        draw_button();
-
-                        do  // Loop until user presses [TAB], [ENTER], or [ESC]
-                        {
-                           choice=od_get_key(TRUE);
-                        } while(choice!=9 && choice!=13 && choice!=27);
-
-                        od_set_color(L_CYAN,D_BLUE);     // Un-highlight button
-                        draw_button();
-
-                        if(choice==13) return(TRUE);  // If [ENTER] was pressed
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 66
-
-                        if(choice==27) return(FALSE);   // If [ESC] was pressed
-                        current_field=1;        // Otherwise, [TAB] was pressed
-                     }
-
-                    switch(current_field)        // According to selected field
-                     {                       // Input from the appropriate line
-                        case 1:
-                           choice=od_edit_str(filename,"FFFFFFFFFFFF",6,26,
-                                              0x1b,0x1a,176,
-                                              EDIT_FLAG_EDIT_STRING|
-                                              EDIT_FLAG_ALLOW_CANCEL|
-                                              EDIT_FLAG_FIELD_MODE|
-                                              EDIT_FLAG_KEEP_BLANK);
-                           break;
-                        case 2:
-                           choice=od_edit_str(description,
-                                              "*******************",
-                                              7,26,0x1b,0x1a,176,
-                                              EDIT_FLAG_EDIT_STRING|
-                                              EDIT_FLAG_ALLOW_CANCEL|
-                                              EDIT_FLAG_FIELD_MODE|
-                                              EDIT_FLAG_KEEP_BLANK);
-
-                           break;
-                        case 3:
-                           choice=od_edit_str(private,"Y",8,26,
-                                              0x1b,0x1a,176,
-                                              EDIT_FLAG_EDIT_STRING|
-                                              EDIT_FLAG_ALLOW_CANCEL|
-                                              EDIT_FLAG_FIELD_MODE);
-                     }
-                                                    // If user pressed [ESCape]
-                     if(choice==EDIT_RETURN_CANCEL) return(FALSE);
-                                      // If user choice to go to previous field
-                     if(choice==EDIT_RETURN_PREVIOUS)
-                     {
-                        if(current_field==1)               // If at first field
-                           current_field=4;                 // Go to last field
-                        else                           // If not at first field
-                           --current_field;             // Go to previous field
-                     }
-                     else                           // If user chose next field
-                        ++current_field;                    // Go to next field
-                  }
-               }
-
-               void draw_button(void)         // Function to display the button
-               {
-                  od_draw_box(12,10,23,12);              // Draw box for button
-                  od_set_cursor(11,14);
-                  od_disp_str("Continue");            // Display text in button
-               }
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 67
-
-OD_EDIT_STR()
--------------------------------------------------------------------------------
-
-PURPOSE        Allows you to perform formatted input with full line editing
-               features, etc., in ANSI/AVATAR/RIP graphics mode.
-
-
-FORMAT         WORD od_edit_str(char *pszInput, char *pszFormat, INT nRow,
-                  INT nColumn, BYTE btNormalColor, BYTE btHighlightColor,
-                  char chBlank, WORD nFlags);
-
-
-RETURNS        This function will return one of the following values:
-
-               EDIT_RETURN_ERROR        Indicates that an error has occurred,
-                                        and the edit function was unable to
-                                        run. This will occur if there is an
-                                        error in one of the parameters, or if
-                                        ANSI/AVATAR/RIP graphics is not
-                                        available
-
-               EDIT_RETURN_CANCEL       Indicates that the user pressed the
-                                        cancel key [ESC], and that the string
-                                        was left unaltered.
-
-               EDIT_RETURN_ACCEPT       Indicates that the user pressed the
-                                        accept key [Enter], or that the auto-
-                                        enter feature was activated.
-
-               EDIT_RETURN_PREVIOUS     Indicates that the user wishes to move
-                                        to the previous field, by pressing [UP
-                                        ARROW], [SHIFT]-[TAB], etc.
-
-               EDIT_RETURN_NEXT         Indicates that the user wishes to move
-                                        to the next field, by pressing [DOWN
-                                        ARROW], [TAB], etc.
-
-
-DESCRIPTION    To perform string input within OpenDoors, one of two functions
-               can be used, od_input_str() and od_edit_str(). The first
-               function, od_input_str(), allows simple line input and editing,
-               and can be used in ASCII, ANSI, AVATAR and RIP modes. The second
-               function, od_edit_str(), allows many formatted input options,
-               advanced line editing, and other features, but requires the use
-               of ANSI, AVATAR or RIP terminal modes.
-
-               As mentioned above, the od_edit_str() function allows for
-               advanced line editing, such as inputting and deleting text from
-               the middle of the string (whereas the od_input_str() function
-               only allows editing from the end of the string, such as
-               backspacing to erase a mistake). The edit functions available
-               from the od_edit_str() are listed below. Note that some of these
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 68
-
-               functions may or may not be available, depending upon the
-               capabilities of the user's terminal program. While there is no
-               single standard used for the transmission of special edit keys
-               such as the arrow keys, the od_edit_str() function makes as much
-               effort as possible to make all of the edit features available to
-               most terminal programs. Many of the edit functions can be
-               accesses using either [CONTROL]-key combinations or special keys
-               such as the arrow keys, delete key, and so on. OpenDoors will
-               recognize most of these special control keys when sent as either
-               an ANSI control sequence (which is sent by most terminal
-               programs), or as a DoorWay style scan code / ASCII code sequence
-               (which is also available from many terminal programs, but is not
-               usually required). The od_edit_str() edit functions are as
-               follows. Note that all edit functions are always available from
-               the local keyboard.
-
-               HOME - Moves the cursor to the beginning of the line being
-                         edited. Press the [HOME] key, either in DoorWay mode
-                         or from the local keyboard.
-
-               END - Moves the cursor to the end of the line being edited.
-                         Press the [END] key, either in DoorWay mode or from
-                         the local keyboard.
-
-               DELETE CHARACTER - Deletes the character under the cursor. Press
-                         [DELete] on the local keyboard, in DoorWay mode, and
-                         under many terminal programs without DoorWay mode.
-                         Alternatively, press [CONTROL]-[G].
-
-               BACKSPACE - Deletes the character left of the cursor. Press
-                         [BACKSPACE] or [CONTROL]-[H].
-
-               TOGGLE INSERT MODE - Switches the od_edit_str() function between
-                         insert mode and overwrite mode. Press [INSert], either
-                         in DoorWay mode, or from the local keyboard.
-                         Alternatively, press [CONTROL]-[V].
-
-               CURSOR LEFT - Moves the cursor left one character. Press [LEFT
-                         ARROW] on the local keyboard, in DoorWay mode, and
-                         under many terminal programs without DoorWay mode.
-                         Alternatively, press [CONTROL]-[S].
-
-               CURSOR RIGHT - Moves the cursor right one character. Press
-                         [RIGHT ARROW] on the local keyboard, in DoorWay mode,
-                         and under many terminal programs without DoorWay mode.
-                         Alternatively, press [CONTROL]-[D].
-
-               ERASE ENTIRE LINE - Press [CONTROL]-[Y].
-
-               ACCEPT INPUT - Press the [ENTER] / [RETURN] line to accept the
-                         input. Alternatively, press [CONTROL]-[Z]. Note that
-                         this key will only work when the current input is
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 69
-
-                         "valid" (ie, it conforms to the format string, which
-                         is described below)
-
-               CANCEL INPUT - Only available if specifically enabled on the
-                         od_edit_str() command line. Press [ESCape].
-
-               NEXT FIELD - If enabled, allows the user to move to the next
-                         field in a dialog box / form. Press [DOWN ARROW] in
-                         DoorWay mode and under many terminal programs without
-                         DoorWay mode. Alternatively, press [TAB]. Note that
-                         the [DOWN ARROW] key is NOT usually available from the
-                         local keyboard, as it is usually used to adjust the
-                         user's remaining time.
-
-               PREVIOUS FIELD - If enabled, allows the user to move to the
-                         previous field in a dialog box / form. Press [UP
-                         ARROW] in DoorWay mode and under many terminal
-                         programs without DoorWay mode. Alternatively, press
-                         [SHIFT]-[TAB] on the local keyboard or in DoorWay
-                         mode. Again, note that the [UP ARROW] key is NOT
-                         usually available from the local keyboard, as it is
-                         usually used to adjust the user's remaining time.
-
-
-               Let us now look at the parameters which the od_edit_str()
-               function accepts. The first parameter, pszInput, is a pointer to
-               the string where the user's input should be stored. It is
-               important that this string be long enough to accommodate the
-               longest input your format string will permit, including the '\0'
-               C string terminator (ie, the string should be one character
-               greater than the length of the format string, not including the
-               format string's ' and " characters).
-
-               The second parameter, pszFormat, is a pointer to a string which
-               specifies the format and maximum length of the input the
-               od_edit_str() function should accept. Using the format string,
-               not only do you specify the length of the input field, but you
-               can also force the user's input into certain formats. For
-               example, if you wished to input a North American style phone
-               number, you could use a format string of "###-###-####". Then
-               regardless of whether the user typed any dash character or not,
-               their input would be converted, as they type, to the format of
-               the phone number 613-599-5554. You could also specify a format
-               string such of "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM", which would
-               permit the user to enter a name of up to 30 characters. Note
-               that since the cursor can be moved to the position immediately
-               following the last character, a the input field for a 30
-               character string will occupy 31 columns on the screen. The
-               od_edit_str() function would then automatically capitalize the
-               name, so that the first character of each word is capitalized,
-               and the remain characters of the word is in lower case. Even if
-               the user were to move the cursor to the middle of the string
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 70
-
-               they had entered, and add or delete a space (and thus either
-               make one work two or two words one), od_edit_str() would re-
-               format the string to reflect the change. The valid characters
-               for the format sting, along with their meanings, are listed
-               below. Note that the format string is NOT case sensitive (except
-               for literal strings delimited by the '' or "" characters), and
-               space characters can be added at any point to increase
-               legibility.
-
-               #    Indicates that numeric characters from '0' to '9' are valid
-                    for this position
-
-               %    Indicates that numeric characters from '0' to '9', and the
-                    space character (' ') are valid for this position.
-
-               9    Indicates that numeric characters from '0' to '9', along
-                    with '.', '-' and '+' are valid for this position. This
-                    format style is intended for floating-point numeric input.
-
-               ?    Indicates that any character is valid for this position.
-
-               *    Indicates that any printable character, from ASCII 32 to
-                    ASCII 127, is valid for this position.
-
-               A    Indicates that alphabetical characters 'A' to 'Z', 'a' to
-                    'z' and space (' ') are valid for this position.
-
-               C    Indicates that city name characters are valid for this
-                    position. As with the 'M' format character, words are
-                    automatically capitalized so that the first letter is in
-                    upper case, and all subsequent letters are in lower case.
-                    In addition to permitting alphabetical characters and the
-                    space (' ') character, the ',' and '.' characters are also
-                    accepted in this position.
-
-               D    Indicates that date characters '0' to '9', '-' and '/' are
-                    valid for this position.
-
-               F    Indicates that MS-DOS filename characters are valid for
-                    this position.
-
-               H    Indicates that hexidecimal character '0' to '9', 'A' to 'F'
-                    and 'a' to 'f' are valid for this position.
-
-               L    Indicates that only lower case alphabetical characters 'a'
-                    to 'z', and the space (' ') character is valid for this
-                    position. However, if the user attempts to enter an upper
-                    case alphabetical character in this position, it will
-                    automatically be converted to the lower case equivalent.
-
-               M    Indicates that name characters are valid for this position.
-                    These characters are the alphabetical characters 'A' to
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 71
-
-                    'Z', 'a' to 'z', and the space character (' '). A
-                    character's case is converted such that the first character
-                    of a word is in upper case, and all other letters are in
-                    lower case.
-
-               T    Indicates that telephone number character '0' to '9', '(',
-                    ')', '-' and ' ' are valid for this position.
-
-               U    Indicates that only upper case alphabetical characters 'A'
-                    to 'Z', and the space (' ') character is valid for this
-                    position. However, if the user attempts to enter a lower
-                    case alphabetical character in this position, it will
-                    automatically be converted to the upper case equivalent.
-
-               W    Indicates that MS-DOS filename characters are permitted in
-                    this position, including the '*' and '?' wildcard
-                    characters.
-
-               X    Indicates that alphanumeric characters 'A' to 'Z', 'a' to
-                    'z', '0' to '9' and ' ' are valid for this position.
-
-               Y    Indicates that yes/no characters 'Y', 'N', 'y', 'n' are
-                    valid for this position. The characters are automatically
-                    converted to upper case.
-
-               '/"  Single or double quotes can be used to specify sequences of
-                    characters that should appear at the same location in the
-                    input string (referred to elsewhere as "literal strings").
-                    When the user is entering the string, these characters are
-                    automatically supplied, and the user is not required to
-                    type them. Literal strings must begin and end with the same
-                    quote character. Remember that the double quote (")
-                    character must be imbedded in C strings by preceding the
-                    quote character with a \ (backslash) character.
-
-               The third and fourth parameters, nRow and nColumn specify the
-               location on the screen where the first (left most) character of
-               the input field should be located. These parameters are
-               identical to the nRow and nColumn parameters passed to the
-               od_set_cursor() function. In other words, nRow specifies the
-               line number on the screen, where 1 is the first line, and
-               nColumn specifies the column across the screen, where 1 is the
-               first column.
-
-               The fifth and sixth parameters, btNormalColor and
-               btHighlightColor, allow you to specify the color of the input
-               field. The fifth parameter, btNormalColor, specifies the color
-               of the input field when input is not taking place and the sixth
-               parameter, btHighlightColor, specifies the color of the field
-               while input is taking place. Thus, if you had several input
-               fields on the screen at one time, you would be able to make is
-               easier for the user to identify the currently active field by
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 72
-
-               having the field currently accepting input highlighted in a
-               color distinct from the other fields. When the od_edit_str()
-               function begins, it will change the current color of the field
-               from the normal color to the highlighted color. Then, when the
-               od_edit_str() function exits, it will change the current color
-               of the field back to its normal color. If you do not wish to
-               have the field highlighted, you can set both of these parameters
-               to the same value, and disable field re-drawing by using the
-               eighth parameter, flags.
-
-               The seventh parameter accepted by the od_edit_str() function,
-               chBlank, will serve one of two purposes. Normally, this
-               parameter will specify a background character to display in the
-               unfilled portion at the end of the input field. This can be set
-               to a character, such as the ASCII 177 grey block character, to
-               produce a visual background to the field. Doing this will show
-               the user visually how long the field is, and how many character
-               they will be permitted to type into the field. Normally, this
-               field will be displayed during input, and removed when the
-               od_edit_str() function exits. However, you may cause the
-               background to remain in place using the eighth parameter, flags.
-               If you do not wish to have this "background" visual field
-               effect, simply set the character parameter to a space (ASCII
-               32). In password input mode, this parameter will instead specify
-               the character to display in place of characters typed by the
-               user. In this case, the background display character defaults to
-               the space (ASCII 32) character.
-
-               The eighth, and last, parameter accepted by the od_edit_str()
-               function is the nFlags parameter. This parameter is a bit-mapped
-               flags variable which allows you to control special features of
-               the od_edit_str() function. More than one of these settings may
-               be specified by listing a chain of the values, separated by the
-               bitwise-or (|) operator. If you do not wish to turn on any of
-               these modes, simply pass the EDIT_FLAG_NORMAL value as the flags
-               parameter.
-
-               EDIT_FLAG_NORMAL - Default setting, use this value of none of
-                         the other flags below are active.
-
-               EDIT_FLAG_NO_REDRAW - When set, prevents the od_edit_str()
-                         function from re-drawing the input string and field
-                         when it starts up and exits. If you set this flag, the
-                         normal color and highlight color should contain the
-                         same value. If background character (the character
-                         parameter) is not a space (ASCII 32) character, you
-                         must draw the field background prior to calling
-                         od_edit_str(). Also, if you are calling od_edit_str()
-                         with the EDIT_FLAG_EDIT_STRING flag set, you must
-                         display the existing string in the field prior to
-                         calling od_edit_str().
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 73
-
-               EDIT_FLAG_FIELD_MODE - Setting this flag specifies that
-                         od_edit_str() should operate in field input mode. In
-                         field input mode, the user may finish entering their
-                         input by pressing the previous field or next field
-                         button (arrow keys, tab keys, etc.), as described
-                         above. If the user chooses to finish and accept their
-                         input by pressing one of these keys, the od_edit_str()
-                         return value will reflect which choice they made. This
-                         will allow you to make it possible for the user to
-                         move between a number of input fields in a form /
-                         dialog box, as demonstrated in the example
-                         accompanying the od_draw_box() function.
-
-               EDIT_FLAG_EDIT_STRING - Setting this flag specifies that
-                         od_edit_str() should edit a pre-existing string,
-                         instead of starting with a blank string. In this case,
-                         the input_string parameter MUST point to an
-                         initialized string. This string may either contain
-                         some text, or be empty, but od_edit_str() will expect
-                         to find a string terminator ('\0') character, and will
-                         begin editing the contents of the string prior to that
-                         character. If you do not set the EDIT_FLAG_EDIT_STRING
-                         flag, the previous contents of the input_string
-                         parameter is not significant, as od_edit_str() will
-                         automatically start with a blank string.
-
-               EDIT_FLAG_STRICT_INPUT - Setting this flag causes the
-                         od_edit_str() function to operate in "strict" input
-                         mode, which may be desirable if your input format
-                         contains more than one type of input. Normally, if you
-                         were inputting such a string, the user would be able
-                         to move to the middle of the string, and insert any
-                         text. Doing so would cause the rest of the input line
-                         to shift right. However, in cases where your format
-                         string specifies different types of character to be
-                         permitted in different positions, this can cause the
-                         input to be changed so that it no longer conforms to
-                         the format string. In this case, the user's input will
-                         no longer be valid, and the user will not be able to
-                         exit the function by pressing [ENTER] (although
-                         [ESCAPE] will still be available, if you activated it)
-                         until they change their input. However, when strict
-                         input mode is turned on, od_edit_str() will restrict
-                         the ways in which the user is permitted to edit the
-                         string, to prevent just such a case from occurring.
-
-               EDIT_FLAG_PASSWORD_MODE - Setting this flag causes the
-                         od_edit_str() function to operate in "password" mode.
-                         In password mode, the characters typed by the user
-                         will be hidden, displayed instead as the blank
-                         character specified in the "character" parameter.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 74
-
-               EDIT_FLAG_ALLOW_CANCEL - When this flag is set, the user will be
-                         able to cancel their current input and abort the
-                         editing process by pressing their [ESCAPE] key. When
-                         they do so, any changes they have made to the input
-                         field will be canceled, and replaced by the original
-                         contents of the string. The od_edit_str() function
-                         will then exit, indicating that the user has canceled
-                         their input.
-
-               EDIT_FLAG_FILL_STRING - When set, this flag will force the user
-                         to enter a string that fills the entire length of the
-                         format string. Normally, the user will be able to
-                         enter a string of any length up to the maximum length
-                         specified by the format string. However in some cases,
-                         such as when inputting a date, you will want to have
-                         the input field filled. (Otherwise, the user would be
-                         able to enter only the first part of the date.)
-
-               EDIT_FLAG_AUTO_ENTER - When set, this flag will cause the
-                         od_edit_str() function to automatically simulate
-                         pressing of the [ENTER] key when the string is filled.
-                         This can be used to cause the od_edit_str() function
-                         to finish inputting as soon as a valid string is
-                         entered, instead of having to wait for the user to
-                         press [ENTER] / [RETURN].
-
-               EDIT_FLAG_AUTO_DELETE - When set, along with the
-                         EDIT_FLAG_EDIT_STRING flag, this flag will activate
-                         the auto-delete feature of the od_edit_str() function.
-                         When auto-delete is active, if the first key pressed
-                         by the user is not an edit control key, the existing
-                         text will automatically be deleted, and a totally new
-                         string accepted from the user. This could be useful
-                         when you are allowing the user to go back to edit a
-                         previous input. If the user wishes to only change part
-                         of the old string, they can move the cursor to the
-                         location where they wish to make the change, and
-                         perform their editing. However, if the user wishes to
-                         completely replace the old string with a new one, they
-                         can simply begin to type, and the old string will
-                         automatically be deleted, and the new string accepted.
-
-               EDIT_FLAG_KEEP_BLANK - Normally, OpenDoors will only display the
-                         input field background (as passed in the "character"
-                         parameter) while the user is editing the string, and
-                         will remove it when the od_edit_str() function exits.
-                         However, you may wish to continue having this field
-                         displayed after input has taken place, and the
-                         od_edit_str() function has exited. In this case,
-                         setting this flag will cause the background characters
-                         to remain visible after input has finished.
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 75
-
-               EDIT_FLAG_PERMALITERAL - When the format string contains literal
-                         characters (such as forcing a ':' character to be
-                         added to a time input by using the format string
-                         "##':'##':'##"), the od_edit_str() function can
-                         operate in one of two modes. In the default mode, the
-                         literal characters will only be displayed when they
-                         have been automatically added to the string. For
-                         instance, if you were inputting the current time using
-                         the above format string, this mode would result in the
-                         input field initially being blank. When the user types
-                         the first digit of the time, that number would appear.
-                         When the user types the second digit of the time, that
-                         number will appear, and then the colon character will
-                         automatically be added by OpenDoors. However, you can
-                         also set the od_edit_str() function to operate in
-                         "PermaLiteral" mode, by setting this flag. When the
-                         EDIT_FLAG_PERMALITERAL flag is set, the input field
-                         will initially contain the literal characters (ie, the
-                         colons in our example), with the cursor still located
-                         at the leftmost position in the input field. In this
-                         mode, the literal character become a permanent part of
-                         the input field, and can not be moved or deleted by
-                         the user - instead the cursor simply skips over the
-                         literal character's position.
-
-               EDIT_FLAG_LEAVE_BLANK - This flag applies to the special case
-                         where the first character or characters of the format
-                         string are literals. By default, the od_edit_str()
-                         function will always return a string containing at
-                         least these first literal characters. However, you can
-                         alter this behaviors by setting this flag. When set,
-                         if no non-literal characters have been entered in the
-                         string, od_edit_str() will return an empty string.
-
-               EDIT_FLAG_SHOW_SIZE - Normally, od_edit() adds an extra blank to
-                         the end of the input field, to give the cursor a space
-                         to move into when the field is full. However, you may
-                         prefer to have the input field be shown as exactly the
-                         maximum size of input that is permitted. Setting
-                         EDIT_FLAG_SHOW_SIZE does just this. In this case, the
-                         cursor will be positioned immediately past the end of
-                         the input field when the maximum number of characters
-                         have been entered.
-
-
-SEE ALSO       od_input_str(), od_get_char(), od_clear_keybuffer()
-
-
-EXAMPLE        Below are several examples of typical uses of the od_edit_str()
-               function. For the sake of simplicity, all of these examples
-               perform their input beginning at the top, left hand corner of
-               the screen, and store the user's input in the string variable
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 76
-
-               named "string". For an example of the user of the od_edit_str()
-               function in a dialog-box / form entry application, see the
-               example accompanying the od_draw_box() function.
-
-               To input a name with a maximum of 25 characters, having the
-               first letter of each word automatically capitalized:
-
-                        od_edit_str(string, "MMMMMMMMMMMMMMMMMMMMMMMMM", 1, 1,
-                                    0x03, 0x21, 176, EDIT_FLAG_NORMAL);
-
-               To input a North American style phone number, requiring that all
-               digits be filled, and running in "strict input" mode:
-
-                        od_edit_str(string, "###'-'###'-'####",
-                                    1, 1, 0x03, 0x21, 176,
-                                    EDIT_FLAG_FILL_STRING|
-                                    EDIT_FLAG_STRICT_INPUT);
-
-               To allow the user to edit a previously entered 20 character
-               string, with auto-delete mode on. Any characters will be
-               permitted in the string. Remember that when the
-               EDIT_FLAG_EDIT_STRING flag is set, the string must be
-               initialized prior to calling the od_edit_str() function.
-
-                        od_edit_str(string, "????????????????????",
-                                    1, 1, 0x03, 0x21, 176,
-                                    EDIT_FLAG_EDIT_STRING|
-                                    EDIT_FLAG_AUTO_DELETE);
-
-
-               To input a password of up to 16 characters from the user. Here,
-               the password will only be permitted to contain upper case
-               characters, and the od_edit_str() password mode is used, with a
-               small block displayed in place of any characters typed:
-
-                         od_edit_str(string, "UUUUUUUUUUUUUUUU",
-                                     1, 1, 0x03, 0x21, 254,
-                                     EDIT_FLAG_PASSWORD_MODE);
-
-               To input a two-digit number from the user, requiring that both
-               digits be filled, and automatically accepting the input after
-               the two digits have been entered (not requiring the user to
-               press [ENTER]):
-
-                        od_edit_str(string, "##", 1, 1, 0x03, 0x21, 176,
-                                    EDIT_FLAG_FILL_STRING|
-                                    EDIT_FLAG_AUTO_ENTER);
-
-               To input a filename to download, as a field in a dialog box.
-               Here, the filename will be permitted to contain valid filename
-               characters, and the od_input_str() function will operate in
-               field mode, with the cancel [ESCape] key enabled. Also, string
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 77
-
-               edit mode will be enabled, allowing the user to edit a
-               previously entered line, and the EDIT_FLAG_KEEP_BLANK flag will
-               be set, causing the field background to remain displayed after
-               the user exits. This time, however, auto-delete mode will not be
-               used. Note that this combination of parameters expects that the
-               field and it's contents will have already been displayed, prior
-               to calling the od_edit_str() function.
-
-                        od_edit_str(string, "WWWWWWWWWWWW",
-                                    1, 1, 0x03, 0x21, 176,
-                                    EDIT_FLAG_EDIT_STRING|
-                                    EDIT_FLAG_FIELD_MODE|
-                                    EDIT_FLAG_ALLOW_CANCEL|
-                                    EDIT_FLAG_KEEP_BLANK);
-
-               To input a string without the field background and line
-               redrawing before and after input takes place:
-
-                        od_edit_str(string, "******************************",
-                                    1, 1, 0x07, 0x07, ' ',
-                                    EDIT_FLAG_NO_REDRAW);
-
-               To input a date, using PermaLiteral mode. Here, the month is
-               entered by a three digit short form ("JAN", "FEB", etc.), and
-               the literal characters such as the '-' and the "19" are a
-               permanent part of the input field:
-
-                        od_edit_str(string,"UUU'-'##'-19'##",
-                                    1, 1, 0x03, 0x21, 176,
-                                    EDIT_FLAG_PERMALITERAL|
-                                    EDIT_FLAG_FILL_STRING);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 78
-
-OD_EXIT()
--------------------------------------------------------------------------------
-
-PURPOSE        The OpenDoors program termination function
-
-
-FORMAT         void od_exit(INT nErrorLevel, BOOL bTermCall);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    You MUST USE THIS FUNCTION when you want your program to exit.
-               This function will close the serial port, re-write changed
-               information to the door information (drop), call your end-of-
-               program function (if any), and then exit with the errorlevel
-               specified in the first parameter.
-
-               Also, if the second parameter, bTermCall, is set to TRUE,
-               od_exit() will also log the user off (for options such as
-               logging off within the door - as shown in the example below).
-               This is accomplished by lowering the DTR line to the modem,
-               causing the modem to hangup. When control is returned to the
-               BBS, it will then detect that the user is no longer online, and
-               will carry out its own logoff processing.
-
-               If you wish for your program to always perform any activities
-               prior to exiting, such as updating or closing data files, you
-               should set a function to be executed from within the od_exit()
-               function. This is accomplished by using the od_control.
-               od_before_exit variable, as described in the section on the
-               OpenDoors control structure in chapter 5. Use of this variable
-               will allow your program to always carry out these activates,
-               even if OpenDoors decides to call the od_exit() function itself,
-               such as when a user hangs up on the door.
-
-               Note that in special cases, you may use the
-               od_control.od_disable variable to prevent the od_exit() function
-               from re-writing the door information file. Also, you may use the
-               od_control.od_noexit variable to shutdown door operations
-               without actually exiting your program. Both of these variables
-               are described in chapter 5.
-
-
-SEE ALSO       od_init()
-
-
-EXAMPLE        The example below demonstrates a function which a door could
-               execute when the user chooses to exit the door. This function
-               will ask the user whether they wish to exit the door and return
-               to the BBS, simply logoff of the BBS, or continue using the
-               door. The example function will then call od_exit() if the user
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 79
-
-               wishes to exit the door, or return control to the function which
-               called it, if the user does not wish to exit:
-
-               void goodbye(void)
-               {
-                  char pressed;
-                                                  /* Display choices to user */
-                  od_disp_str("You have chosen to exit this door.\n\r");
-                  od_disp_str("Do you wish to:\n\r");
-                  od_disp_str("      [R]eturn to the BBS\n\r");
-                  od_disp_str("      [L]ogoff of the BBS\n\r");
-                  od_disp_str("      [C]ontinue using the door\n\r");
-
-                  for(;;)              /* loop until user makes valid choice */
-                  {
-                     pressed=od_get_key(TRUE);          /* Get key from user */
-
-                               /* If user selects R, exit without hanging up */
-                     if(pressed=='R' || pressed=='r') od_exit(40,FALSE);
-
-                                  /* If user selects L, hangup and then exit */
-                     if(pressed=='L' || pressed=='l') od_exit(41,TRUE);
-
-                     /* If user selects C, return and allow door to continue */
-                     if(pressed=='C' || pressed=='c') return;
-                  }
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 80
-
-OD_GET_ANSWER()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to allow the user to respond to a prompt using only
-               certain keys.
-
-
-FORMAT         char od_get_answer(char *pszOptions);
-
-
-RETURNS        Character that user entered
-
-
-DESCRIPTION    This function can be used to get a response from the user, when
-               only particular responses should be accepted. The parameter to
-               the od_get_answer() function is simply a string listing the
-               valid responses. The function will wait until the user selects
-               one of the valid responses, and then return that response. The
-               function is case insensitive, and will return the character in
-               the same case that was supplied to it in the string.
-
-
-SEE ALSO       od_get_key(), od_hotkey_menu()
-
-
-EXAMPLES       od_get_answer("YN");
-                    - If the user presses 'y', will return 'Y'.
-
-               od_get_answer("yn");
-                    - If the user presses 'y', will return 'y'.
-
-               od_get_answer("ABC 123\n\rZ");
-                    - Valid responses will be: [A], [B], [C], [SPACE],
-                      [1], [2], [3], [ENTER], [Z]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 81
-
-OD_GET_INPUT()
--------------------------------------------------------------------------------
-
-PURPOSE        This function allows a single input event (e.g. keystroke) to be
-               retrieved, optionally translating extended key sequences such as
-               arrow keys and the insert key.
-
-
-FORMAT         BOOL od_get_input(tODInputEvent *pInputEvent,
-                  tODMilliSec TimeToWait, WORD wFlags);
-
-
-RETURNS        TRUE on success, FALSE if no input event was retrieved.
-
-
-DESCRIPTION    Like od_get_key(), od_get_input() can be used to retrieve a
-               single key of input from the user. However, od_get_input() has
-               been designed to be easily extended in future versions of
-               OpenDoors. The information retrieved by this new function is
-               placed in a structure, which contains information on whether the
-               input event was generated by the remote user or the local
-               console, and what type of input event it was. This function also
-               has built-in the ability to recognize and translate the multiple-
-               character sequences that are generated when the user presses
-               extended keys such as arrow keys, insert, delete, etc.
-
-               The first parameter points to a tODInputEvent structure, which is
-               defined as follows:
-
-                    typedef struct
-                    {
-                       tODInputEventType EventType;
-                       BOOL bFromRemote;
-                       char chKeyPress;
-                    } tODInputEvent;
-
-               When od_get_input() successfully retrieves an input event, this
-               structure is filled with information about the input. The
-               EventType member can be either EVENT_CHARACTER (indicating a
-               single character keystroke) or EVENT_EXTENDED_KEY (indicating an
-               extended key, such as an arrow key). In the case of
-               EVENT_CHARACTER, chKeyPress is set to the character that was
-               received. In the case of EVENT_EXTENDED_KEY, chKeyPress is set to
-               one of the following values:
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 82
-
-               +------------------+---------------+-------------------------+
-               | chKeyPress Value | Meaning       | Control Key Alternative |
-               +------------------+---------------+-------------------------+
-               | OD_KEY_F1        | [F1]          | None                    |
-               | OD_KEY_F2        | [F2]          | None                    |
-               | OD_KEY_F3        | [F3]          | None                    |
-               | OD_KEY_F4        | [F4]          | None                    |
-               | OD_KEY_F5        | [F5]          | None                    |
-               | OD_KEY_F6        | [F6]          | None                    |
-               | OD_KEY_F7        | [F7]          | None                    |
-               | OD_KEY_F8        | [F8]          | None                    |
-               | OD_KEY_F9        | [F9]          | None                    |
-               | OD_KEY_F10       | [F10]         | None                    |
-               | OD_KEY_UP        | [UP ARROW]    | [CTRL]-[E]              |
-               | OD_KEY_DOWN      | [DOWN ARROW]  | [CTRL]-[X]              |
-               | OD_KEY_LEFT      | [LEFT ARROW]  | [CTRL]-[S]              |
-               | OD_KEY_RIGHT     | [RIGHT ARROW] | [CTRL]-[D]              |
-               | OD_KEY_INSERT    | [INSERT]      | [CTRL]-[V]              |
-               | OD_KEY_DELETE    | [DELETE]      | [CTRL]-[G]              |
-               | OD_KEY_HOME      | [HOME]        | None                    |
-               | OD_KEY_END       | [END]         | None                    |
-               | OD_KEY_PGUP      | [PAGE UP]     | None                    |
-               | OD_KEY_PGDN      | [PAGE DOWN]   | None                    |
-               | OD_KEY_SHIFTTAB  | [SHIFT]-[TAB] | None                    |
-               +------------------+---------------+-------------------------+
-
-               The bFromRemote member of the tODInputEvent structure will be set
-               to TRUE if the input event originated from the remote system, or
-               FALSE if the event originated from the local system.
-
-               The second parameter, TimeToWait specifies how long the function
-               should wait for input before returning, in milliseconds. A value
-               of 0 causes the function to return immediately if no input is
-               waiting in OpenDoor's internal input buffer. The is equivalent to
-               a value of FALSE being passed to the od_get_key() function. A
-               value of OD_NO_TIMEOUT causes this function to wait and only
-               return after the next input event has been received. This is
-               equivalent to a value of TRUE being passed to the od_get_key()
-               function. An other value specifies the maximum number of
-               milliseconds that od_get_input() should wait for input. If input
-               is received before this time elapses, od_get_key() will return
-               immediately with a value of TRUE, and the tODInputEvent structure
-               will be fill accordingly. If no input is received before this
-               time elapses, od_get_key() will return FALSE. The number of
-               milliseconds to wait is rounded to the nearest 55 milliseconds in
-               the DOS version of OpenDoors.
-
-               The third parameter allows you to specify flags to further
-               control the behavior of od_get_input(). Normally, this parameter
-               will be set to GETIN_NORMAL. However, you can disable all
-               translation of extended keystrokes by setting this value to
-               GETIN_RAW. In this mode, od_get_input() works just like
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 83
-
-               od_get_key(), returning every individual character received from
-               the remote system.
-
-               Since extended keys are not directly supported by all terminal
-               programs, od_get_input() provides alternatives for some of the
-               extended keys, in the form of control-key combinations. The
-               control key combinations recognized by od_get_input() are listed
-               in the table above. However, these control key alternatives can
-               be ignored by setting the GETIN_RAWCTRL flag.
-
-               The od_get_input() function is used internally by
-               od_popup_menu(), od_edit_str() and od_multiline_edit().
-
-
-SEE ALSO       od_get_key(), od_clear_keybuffer()
-
-
-EXAMPLE        The following example shows the structure of how od_get_input()
-               might be used in your program:
-
-                    tODInputEvent InputEvent;
-                    od_get_input(&InputEvent, OD_NO_TIMEOUT, GETIN_NORMAL);
-                    if(InputEvent.EventType == EVENT_EXTENDED_KEY)
-                    {
-                       switch(InputEvent.chKeyPress)
-                       {
-                          case OD_KEY_UP:
-                             /* The up arrow key has been pressed. */
-                             break;
-                          case OD_KEY_DOWN:
-                             /* The down arrow key has been pressed. */
-                             break;
-                       }
-                    }
-                    else if(InputEvent.EventType == EVENT_CHARACTER)
-                    {
-                       /* A single character key has been pressed, and is  */
-                       /* stored in InputEvent.chKeyPress.                 */
-                    }
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 84
-
-OD_GET_KEY()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to input a key from the user
-
-
-FORMAT         char od_get_key(BOOL bWait);
-
-
-RETURNS        The next key waiting from the keyboard, or 0 if none.
-
-
-DESCRIPTION    This function retrieves the next key waiting in the OpenDoors
-               keyboard buffer (see the description of the od_clear_keybuffer()
-               function, on page 53, for more information on the OpenDoors
-               keyboard buffer). The od_get_key() function allows your door to
-               retrieve both those keystrokes pressed by the user, and the
-               keystrokes pressed on the sysop keyboard (other than the sysop
-               function keys), in the sequence they were pressed. Since input
-               is accepted from both sources, it is possible for the sysop, as
-               well as the remote user, to make selections and control the
-               door.
-
-               Door input with OpenDoors can be accomplished with this
-               function, with the od_input_str() function or with the
-               od_edit_str() function. The od_input_str() and od_edit_str()
-               functions is used to input an entire sequence of characters from
-               the user (a string), and requires the user to press the [Enter]
-               key when they are finished typing their input. On the other
-               hand, the od_get_key() function is used to input a single
-               keystroke (one character) from the user, and allows the user to
-               make choices without having to press the enter key.
-
-               The od_get_key() function accepts a single parameter, which
-               determines whether or not it should wait for the user to press a
-               key, if they have not already done so. If you pass a FALSE value
-               to od_get_key(), then the function will not wait for a key to be
-               pressed at the keyboard, but instead return a 0 if there are no
-               keys waiting in the buffer. If you pass a TRUE value to
-               od_get_key(), then this function will instead wait for a key to
-               be pressed. Also, while waiting for the user to press a key, the
-               od_get_key() function will give up the processor to other
-               waiting programs, if you door is running under DesqView.
-
-               If you are waiting for the user to make a choice from a menu or
-               list of options, you will most likely pass a TRUE to the
-               od_get_key() function, indicating that you wish for it to wait
-               until a key is pressed. However, if you wish to continue other
-               processing if no key is yet available from the keyboard, you
-               should pass a FALSE to the od_get_key() function. For example,
-               if you are displaying a screen of text, and wish to allow the
-               user to pause or abort the display, you would simply call the
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 85
-
-               od_get_key() function every few moments, passing it a value of
-               FALSE. You would then be able to check if any control keys have
-               been pressed, and if not, continue displaying text.
-
-               The od_get_key() function returns the ASCII value representing
-               the keystroke that was made. If you are waiting for the user to
-               make a particular choice, perhaps from a menu, you will most
-               likely store the value returned by od_get_key() in a variable of
-               type char. For example:
-
-                      char key;
-                      ...
-                      key=od_get_key(TRUE);
-
-               You would then be able to determine which key the user pressed
-               by testing the value of key, either by comparing it's numerical
-               ASCII value, or by comparing it to a character constant. If you
-               are testing for a non-character key, such as [ESCape], [Tab] or
-               [Return], you may wish to use the ASCII value of that key. For
-               example, if you wished to take some action in the case that the
-               user presses the [Enter]/[Return] key, who's ASCII value is 13,
-               you could do:
-
-                      key=od_get_key(TRUE);        /* Get keypress from user */
-                      if(key==13)             /* If key was [Enter]/[Return] */
-                      {
-                         ...                      /* Whatever you want to do */
-                      }
-
-               If you wish, instead, to respond to the user pressing a
-               character key (perhaps as a choice from a menu), you can do so
-               by using character constants, such as 'c', '6', or 'F'. Also,
-               when testing for an alphabetical character, you will probably
-               want to check for the user pressing either the upper or lower-
-               case version of the letter. For example, if you wished to have
-               the user press the [Y] key to continue, you could test for
-               either an upper or lower-case Y as follows:
-
-                       key=od_get_key(TRUE);       /* Get keypress from user */
-                       if(key=='y' || key=='Y')        /* If key was [y]/[Y] */
-                       {
-                          ...                     /* Whatever you want to do */
-                       }
-
-
-
-
-
-The charts on the following page lists the decimal value and corresponding
-keystroke(s) of each of the ASCII values from 0 to 127.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 86
-
-ASCII  KEYSTROKE                       |  ASCII   KEYSTROKE
------  ------------------------------  |  -----   ----------------------
-  0    [Control]-[@]                   |   15     [Control]-[O]
-  1    [Control]-[A]                   |   16     [Control]-[P]
-  2    [Control]-[B]                   |   17     [Control]-[Q]
-  3    [Control]-[C]                   |   18     [Control]-[R]
-  4    [Control]-[D]                   |   19     [Control]-[S]
-  5    [Control]-[E]                   |   20     [Control]-[T]
-  6    [Control]-[F]                   |   21     [Control]-[U]
-  7    [Control]-[G]                   |   22     [Control]-[V]
-  8    [Control]-[H]/[Backspace]       |   23     [Control]-[W]
-  9    [Control]-[I]/[Tab]             |   24     [Control]-[X]
- 10    [Control]-[J]                   |   25     [Control]-[Y]
- 11    [Control]-[K]                   |   26     [Control]-[Z]
- 12    [Control]-[L]                   |   27     [ESCape]
- 13    [Control]-[M]/[Enter]/[Return]  |   32     [SpaceBar]
- 14    [Control]-[N]                   |
-
-
-
-ASCII  KEYSTROKE | ASCII  KEYSTROKE | ASCII  KEYSTROKE | ASCII  KEYSTROKE
------  --------- | -----  --------- | -----  --------- | -----  ---------
- 33       '!'    |  57       '9'    |  80       'P'    |  104      'h'
- 34       '"'    |  58       ':'    |  81       'Q'    |  105      'i'
- 35       '#'    |  59       ';'    |  82       'R'    |  106      'j'
- 36       '$'    |  60       '<'    |  83       'S'    |  107      'k'
- 37       '%'    |  61       '='    |  84       'T'    |  108      'l'
- 38       '&'    |  62       '>'    |  85       'U'    |  109      'm'
- 39    '\''  (') |  63       '?'    |  86       'V'    |  110      'n'
- 40       '('    |  64       '@'    |  87       'W'    |  111      'o'
- 41       ')'    |  65       'A'    |  88       'X'    |  112      'p'
- 42       '*'    |  66       'B'    |  89       'Y'    |  113      'q'
- 43       '+'    |  67       'C'    |  90       'Z'    |  114      'r'
- 44       ','    |  68       'D'    |  91       '['    |  115      's'
- 45       '-'    |  69       'E'    |  92    '\\'  (\) |  116      't'
- 46       '.'    |  70       'F'    |  93       ']'    |  117      'u'
- 47       '/'    |  71       'G'    |  94       '^'    |  118      'v'
- 48       '0'    |  72       'H'    |  95       '_'    |  119      'w'
- 49       '1'    |  73       'I'    |  96       '`'    |  120      'x'
- 50       '2'    |  74       'J'    |  98       'b'    |  121      'y'
- 51       '3'    |  75       'K'    |  99       'c'    |  122      'z'
- 52       '4'    |  76       'L'    |  100      'd'    |  123      '{'
- 53       '5'    |  77       'M'    |  101      'e'    |  124      '|'
- 54       '6'    |  78       'N'    |  102      'f'    |  125      '}'
- 55       '7'    |  79       'O'    |  103      'g'    |  126      '~'
- 56       '8'    |                  |                  |  127    [DELete]
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 87
-
-
-
-
-
-SEE ALSO       od_get_input(), od_input_str(), od_edit_str(),
-               od_clear_keybuffer()
-
-
-EXAMPLE        For examples of the use of the od_get_key() function, see the
-               examples in the description portion, above, and the examples for
-               the od_exit() and od_clear_keybuffer() functions. For further
-               examples of this function, see the example program EX_VOTE.C,
-               described in the section beginning on page 38.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 88
-
-OD_GETTEXT()
--------------------------------------------------------------------------------
-
-PURPOSE        Stores a rectangular region of the screen in an array, to later
-               be redrawn using od_puttext(). Requires ANSI, AVATAR or RIP
-               modes.
-
-
-FORMAT         BOOL od_gettext(INT nLeft, INT nTop, INT nRight, INT nBottom,
-                  void *pBlock);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    This function stores the contents (both text and color
-               information) of the rectangular portion of the screen denoted by
-               the variables nLeft, nTop, nRight and nBottom into the buffer
-               pointed to by pBlock. The saved portion of the screen may then
-               be restored using od_puttext(). The buffer must be large enough
-               to store two bytes for every character in the specified
-               rectangle. In other words, the required size of the buffer, in
-               bytes, is:
-
-                           length * width * 2
-
-               The parameters nLeft and nRight are column numbers from 1 to 80,
-               and the parameters nTop and nBottom are row numbers between 1
-               and 23.
-
-               This function has no effect on the current text color or cursor
-               position. ANSI, AVATAR or RIP mode is required for this
-               function. If you wish to save and restore the entire screen, you
-               may use the od_save_screen() and od_restore_screen() functions,
-               which can be used in all display modes.
-
-               If this function fails for any reason, a value of FALSE is
-               returned, and the od_control.od_error variable is set to
-               indicate the reason for the failure. For more information on the
-               od_control.od_error variable, see page 185.
-
-
-SEE ALSO       od_puttext(), od_save_screen(), od_restore_screen(),
-               od_scroll(), od_window_create(), od_window_remove()
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 89
-
-OD_HOTKEY_MENU()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to display a menu file with hotkeys
-
-
-FORMAT         char od_hotkey_menu(char *pszFileName, char *pszHotKeys, BOOL
-               bWait);
-
-
-RETURNS        Key pressed in response to menu, or '\0' if none.
-
-
-DESCRIPTION    This function can be used to display a menu from an ASCII, ANSI,
-               AVATAR or RIP file, allowing the user to select an option at any
-               time while the menu is being displayed. The od_hotkey_menu()
-               function is quite similar to the od_send_file() function, and
-               you should probably familiarize yourself with that function if
-               you are going to use od_hotkey_menu(). Like od_send_file(),
-               od_hotkey_menu() will display the file specified by pszFileName,
-               using the appropriate terminal emulation. If no extension is
-               provided for the filename, OpenDoors will automatically search
-               for matching files ending in .ASC, .ANS and .AVT extensions.
-               OpenDoors will the select the appropriate file to display, based
-               on the available files and available terminal emulation.
-
-               The second parameter, pszHotKeys, is a string specifying the
-               valid responses to the menu, in the same format as the string
-               passed to the od_get_answer() function. If any of the characters
-               listed in this string are pressed, either uppercase or lowercase
-               versions, OpenDoors will immediately stop displaying the menu,
-               and return with the value of the key pressed. The case (upper or
-               lower) returned will always be identical to the case used in the
-               hotkeys string. You can include the [ENTER] key as a valid hot
-               key by including the \n character in the hotkey string.
-
-               The third parameter passed to od_hotkey_menu(), bWait, specifies
-               whether OpenDoors should wait after displaying the menu for the
-               user to make a valid selection from the menu (TRUE), or if it
-               should exit immediately (FALSE). Normally, you will want to use
-               the TRUE value when calling this function. This will allow you
-               to use a single function call that will display the menu and
-               always return the user's selection. If you wish to gain control
-               as soon as OpenDoors has displayed the menu, you may specify
-               FALSE for this parameter. In this case, if the user does not
-               press any of the valid hot keys while the menu is being sent,
-               the function will return the character '\0'.
-
-
-SEE ALSO       od_send_file(), od_get_answer()
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 90
-
-EXAMPLE        As an example of the use of the od_hotkey_menu() function,
-               consider the following code fragment:
-
-
-                    for(;;)                             /* Main program loop */
-                    {                  /* Display menu and get user's choice */
-                         char choice=od_hotkey_menu("MAINMENU","123Q",TRUE");
-
-                         switch(choice)    /* Perform the appropriate action */
-                         {
-                              case '1':
-                                   od_printf("You selected one.\n\r");
-                                   break;
-
-                              case '2':
-                                   od_printf("You selected two.\n\r");
-                                   break;
-
-                              case '3':
-                                   od_printf("You selected three.\n\r");
-                                   break;
-
-                              case 'Q':
-                                   od_exit(FALSE,10);
-                         }
-                    }
-
-               This is an example of the main menu loop of a simple door that
-               uses the od_hotkey_menu() function. The program will continue
-               executing the for(;;) loop until the user chooses to exit the
-               door. On each iteration of the loop, the od_hotkey_menu()
-               function is called, to display the door's menu from the file
-               MAINMENU.A??. The appropriate .ASC/.ANS/.AVT file will be chosen
-               and displayed as the menu. The possible choices that may be made
-               from the menu are specified by the string "123Q". Thus, whenever
-               the user presses one of the keys [1], [2], [3] or [Q], the
-               od_hotkey_menu() function will return immediately with the value
-               of the key pressed. If the menu is still being displayed at the
-               time when the key was pressed, menu display will cease at that
-               moment. The program then executes a case statement, to respond
-               to the user's key appropriately. If the user presses [1], [2] or
-               [3] this door will output a simple message to the screen. If the
-               user presses the [Q] key, the door will pass control back to the
-               BBS.
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 91
-
-OD_INIT()
--------------------------------------------------------------------------------
-
-PURPOSE        To initialize OpenDoors activities
-
-
-FORMAT         void od_init(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function initializes OpenDoors. This function must be
-               called manually if you wish to access data about the user, etc.,
-               before you call any other OpenDoors functions. However, if you
-               do not explicitly call the od_init() function, it will be called
-               automatically on the first call to most other OpenDoors
-               functions. The only functions that should be called before
-               od_init() are od_add_personality() and od_parse_cmd_line(). The
-               od_init() function reads information from the door information
-               file, initializes communications with the modem, displays the
-               status line, and sets up OpenDoors' internal data structures.
-               For more information on what data is and is not available before
-               od_init() has been called, please refer to the chapter on the
-               OpenDoors control structure, which begins on page 148.
-
-               The od_init() function will read the door information file which
-               is located in the directory specified by the variable
-               od_control.info_path. If this variable has not been set prior to
-               calling the od_init() function, OpenDoors will expect to find
-               the door information file in the current directory. Thus, if you
-               wish your door to be able to be run in a directory other than
-               the BBS system directory, it would be a good idea to allow the
-               sysop using your door to specify the location of the door
-               information file. For an example of setting the
-               od_control.info_path variable, please see the example program
-               located on page 150.
-
-               Also note that you can prevent the od_init() function from
-               carrying out some of it's normal activities, such as attempting
-               to read a door information file, by the use of the
-               od_control.od_disable variable, as described in the section on
-               the OpenDoors control structure, which begins on page 148.
-
-
-SEE ALSO       od_exit()
-
-
-EXAMPLE        At times, you may wish to write a door program which will
-               require a maintenance utility to be run on a regular basis. For
-               example, a game door may have to have its system files updated
-               on a daily basis, by having a utility program run in a system
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 92
-
-               event each day at midnight. One way of accomplishing this would
-               be to have your door package include two .EXE files, one being
-               the actual door program, and the other being a utility program.
-               However, another option would be to have both the door and
-               maintenance functions to be accessible from a single .EXE file,
-               in order to simplify use of the door for the sysop. In this
-               case, you would want to test the command line to determine
-               whether your program should run in door mode or maintenance
-               mode. You would then only execute the od_init() function, along
-               with the rest of your door code, if you program were running in
-               "door mode".
-
-               The program below demonstrates one method of doing just this. In
-               this case, the program would include two functions, door(),
-               which would carry out all of the door-related activities, and
-               maint(), which would carry out all of the maintenance-related
-               activities. In this simple example, if the command line includes
-               a "-M" or "/M", the program will run in maintenance mode,
-               otherwise it will run in door mode. Also, if it is running in
-               door mode, the program will take the first command-line
-               parameter, if any, as a path to the location of the door
-               information file.
-
-
-               #include "opendoor.h"
-
-               void door(void);
-               void maint(void);
-
-
-               int main(int argc, char *argv[])
-               {
-                  int counter;
-
-                           /* Check any command line parameters for /M or -M */
-                  for(counter=1;counter<argc;++counter)
-                  {
-                     if((argv[counter])[1]=='m' || (argv[counter])[1]=='M')
-                     {
-                        maint();               /* Then carry out maintenance */
-                        exit(20);                                /* And exit */
-                     }
-                  }
-                          /* If there was no -M or /M, then run in door mode */
-
-                  /* If there are any command-line parameters take the first */
-                                 /* as the path to the door information file */
-                  if(argc>1) strncpy(od_control.info_path,argv[1],59);
-
-                  od_init();                  /* call the od_init() function */
-                  door();             /* Run the door portion of the program */
-                  od_exit(30,FALSE);                    /* Shutdown the door */
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 93
-
-               }
-
-
-               void maint(void)
-               {
-                  ...               /* Carry out maintenance activities here */
-               }
-
-
-               void door(void)
-               {
-                  ...                      /* Carry out door activities here */
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 94
-
-OD_INPUT_STR()
--------------------------------------------------------------------------------
-
-PURPOSE        Inputs a string from the user
-
-
-FORMAT         void od_input_str(char *pszInput, INT nMaxLength,
-                  unsigned char chMin, unsigned char chMax);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    To perform string input within OpenDoors, one of two functions
-               can be used, od_input_str() and od_edit_str(). The first
-               function, od_input_str(), allows simple line input and editing,
-               and can be used in ASCII, ANSI, AVATAR and RIP modes. The second
-               function, od_edit_str(), allows many formatted input options,
-               advanced line editing, and other features, but requires the use
-               of ANSI, AVATAR or RIP graphics modes.
-
-               The od_input_str() function allows you to input a string from
-               the user. The string will be permitted to have up to the number
-               of characters specified by the max_len parameter, and all
-               characters must be between the values of the min_char and
-               max_char parameters. This function will wait until the user
-               presses the [Enter] key to finish inputting the string.
-
-               The first parameter passed to this function should be a pointer
-               to the string where the user's input should be stored. So, if
-               you wanted to store a string of up to 30 characters inputted by
-               the user, you might define this string as follows:
-
-                         char input_string[31];
-
-               Notice here than the string must be long enough to hold the
-               thirty characters which can be entered by the user, along with
-               the additional "null" character which is used to indicate the
-               end of a string in C. Hence, the length of the string should
-               always be at least one greater than the total number of
-               characters the user is permitted to enter, passed in the
-               nMaxLength parameter.
-
-               The second parameter passed to the od_input_str() function
-               should be an integer value indicating the maximum number of
-               characters which can be input by the user. For example, if this
-               parameter had a value of 10, the user would be able to enter a
-               string containing any number of characters up to and including
-               10 characters. If this parameter had a value of 1, the user
-               would only be able to enter a single character. However, the
-               user would be able to backspace, change the character, and press
-               [Enter] when they were satisfied with their entry. Note that
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 95
-
-               even if you only ask the od_input_str() function to input a
-               single character, it will still expect a STRING to be passed to
-               it, and will return a string with either zero or one character,
-               followed by a null (string terminator) character.
-
-               The third and fourth parameters passed to this function allow
-               you to control what characters the user will be permitted to
-               enter as part of the string. For example, you could set the
-               minimum character to the '0' character and the maximum character
-               to the '9' character, permitting the user to only enter numeric
-               characters. On the other hand, you could permit the user to
-               enter all ASCII characters in the range from 32 to 127. The
-               od_input_str() function will permit characters in the range
-               beginning with the character passed as minchar, up to and
-               including the character passed as maxchar.
-
-
-SEE ALSO       od_edit_str(), od_get_key(), od_clear_keybuffer()
-
-
-EXAMPLE        Below are a number of examples of the use of the od_input_str()
-               function in various applications:
-
-                 - To input a two character number (only digits from 0-9):
-
-                        od_input_str(string, 2, '0', '9');
-
-                 - To input a 35 character name (characters from Space to
-                   ASCII 127):
-
-                        od_input_str(string, 35, 32, 127);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 96
-
-OD_KERNEL()
--------------------------------------------------------------------------------
-
-PURPOSE        The OpenDoors Central Control function.
-
-
-FORMAT         void od_kernel(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    In the DOS version of OpenDoors, the od_kernel() function is
-               responsible for many vital OpenDoors tasks, such as monitoring
-               the carrier detect signal, monitoring the amount of time that
-               the user has remaining, updating the status line, responding to
-               sysop hotkeys, and reading characters which are received from
-               the modem. The od_kernel() function is automatically called on a
-               frequent basis by the other OpenDoors functions, so most often
-               you will not need to be concerned with this function. However,
-               in order that OpenDoors can carry out the activities mentioned
-               above with a quick response, it is important that od_kernel(),
-               or some other OpenDoors function be called at least once every
-               second. Thus, if your program will be carrying out some
-               processing, in which it will not be calling any OpenDoors
-               functions for more than a second or so, you should call the
-               od_kernel() function yourself. The example below demonstrates
-               one method of doing just this.
-
-               Note that if for some reason or other, it is not possible for
-               your program to call the od_kernel() function, or any other
-               OpenDoors functions for a period of several seconds, this will
-               not cause your door to crash or fail in any way. The only
-               problem will be that OpenDoors will not be able to respond to
-               any action, such as the sysop pressing a function key, or the
-               user dropping carrier, until such time as you next call
-               od_kernel(), or some OpenDoors function. Hence, use of the
-               od_kernel() function will improve the quality and response time
-               of your program, but calling it or some OpenDoors function on a
-               regular basis is not absolutely vital.
-
-               This function has no effect in the Win32 version of OpenDoors.
-
-
-SEE ALSO       od_sleep()
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 97
-
-OD_LIST_FILES()
--------------------------------------------------------------------------------
-
-PURPOSE        Lists files in a particular file area (using FILES.BBS)
-
-
-FORMAT         BOOL od_list_files(char *pszFileSpec);
-
-
-RETURNS        TRUE if successful, FALSE if unsuccessful
-
-
-DESCRIPTION    This function allows you to display a list of files available
-               for download from a particular file area, as any BBS system
-               would. The file names and descriptions are taken from the
-               FILES.BBS located in the directory pointed to by pszFileSpec.
-               Thus, to list the files available for download in
-               C:\BBS\FILES\UPLOADS, simply:
-
-                      od_list_files("C:\\BBS\\FILES\\UPLOADS");
-
-               OpenDoors uses a third-generation FILES.BBS format, that is
-               compatible with other FILES.BBS formats, but adds some
-               additional features. Each line in the FILES.BBS file lists a
-               filename, along with it's description. Thus, a typical FILES.BBS
-               file might look as follows:
-
-                        PKZ110.EXE    PKZip file compressor, version 1.10
-                        ODOORS60.ZIP  The newest version of OpenDoors
-                        REC*.ZIP      A Record file
-                        C:\BBS\*.*    All BBS files.
-
-               When displayed, OpenDoors will list the size of each file found
-               in the FILES.BBS file beside it's name, if the file is found. If
-               the file does not exist, then a "[OFFLINE]" string is displayed
-               in the file size column. Title lines may also be added to the
-               FILES.BBS, by indenting them one or more columns. Thus, you
-               could have something like:
-
-                           NEWEST UPLOADS
-                           ~~~~~~~~~~~~~~
-                        PKZ110.EXE    PKZip file compressor, version 1.10
-                        ODOORS60.ZIP  The newest version of OpenDoors
-                        REC*.ZIP      A Record file
-                        C:\BBS\*.*    All BBS files.
-
-               In addition to this standard FILES.BBS format, OpenDoors will
-               also permit wildcards to be used in FILES.BBS filenames (ie
-               FNEWS???.*), or full directory paths to allow files from several
-               different directories to be included in the same files area.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 98
-
-               You may alter the colors used to display the various portions of
-               the files list using the od_control variables:
-                         od_control.od_list_title_col
-                         od_control.od_list_name_col
-                         od_control.od_list_size_col
-                         od_control.od_list_comment_col
-                         od_control.od_list_offline_col
-
-               which are documented in the OpenDoors control structure section
-               on this manual, which begins on page 148.
-
-
-SEE ALSO       od_send_file()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 99
-
-OD_LOG_WRITE()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to write an entry to the log file
-
-
-FORMAT         BOOL od_log_write(char *pszMessage);
-
-
-RETURNS        TRUE on success, or FALSE on failure
-
-
-DESCRIPTION    This function can be used to write entries to the log file. If
-               the logfile has not already been opened when you call this
-               function for the first time, OpenDoors will automatically open
-               the log file at that time.
-
-               To create an entry in the log file, simply call the
-               od_log_write() function, passing to it the string of the text
-               you wish to write. You should not include any control characters
-               in this string, simply the text that should appear on the line.
-               OpenDoors will automatically format the log file, adding the
-               time information and other control characters. It is recommended
-               that the length of the string passed to od_log_write() not
-               exceed 67 characters, in order that logfile lines will all be
-               less than 80 characters in length.
-
-               Log file entries do not usually contain periods or other
-               punctuation at the end of the line. Also, log file entries are
-               usually written in the present tense. The first character of the
-               entry is usually upper-case, with all other entries in lower
-               case. Also, since excessive numbers or lengths of log file
-               entries can quickly use a lot of disk space, it is best to think
-               carefully about what events should be recorded in the log file.
-               It is also a good idea to minimize the number of words used in
-               the entry, without being too cryptic. As an example, "User
-               entering options menu" should be used instead of "user entered
-               the options menu."
-
-
-SEE ALSO       Page 224.
-
-
-EXAMPLE        Calling the od_log_write() function is as simple as follows:
-
-                    od_log_write("Awarding user with 5 minutes more time");
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 100
-
-OD_MULTILINE_EDIT()
--------------------------------------------------------------------------------
-
-PURPOSE        Provides a multiple line text editor which can be used for
-               entering editing any text that spans more than one line, such as
-               messages or text files.
-
-
-FORMAT         INT od_multiline_edit(char *pszBufferToEdit, UINT unBufferSize,
-                  tODEditOptions *pEditOptions);
-
-
-RETURNS        OD_MULTIEDIT_SUCCESS on success, or OD_MULTIEDIT_ERROR on
-               failure
-
-
-DESCRIPTION    This function provides a text editor with optional word wrap
-               capabilities. This editor can be used for entering or editing
-               text files, messages or other information that spans multiple
-               lines. The editor can be configured to operate in full-screen
-               mode, or to occupy any smaller area of the screen that you
-               specify. It provides the navigation (home / end / page up / arrow
-               keys) features and editing features (insert / overwrite mode,
-               Ctrl-Y to delete a line, etc.) that you would expect.
-
-               The od_multiline_edit() function is designed to be both easy to
-               use and very flexible. To that end, the function only takes three
-               parameters. The first two parameters are required, and the third
-               parameter is an optional options structure. The first parameter,
-               pszBufferToEdit, is a pointer to the buffer of text to edit. This
-               buffer must always be a '\0'-terminated string. This buffer must
-               be initialized before calling od_multiline_edit(). The second
-               parameter, unBufferSize, indicates the size of the buffer that is
-               passed in pszBufferToEdit. Note that this should be the total
-               amount of space that is available in the buffer for text entered
-               by the user, not the length of data that is actually initially in
-               the buffer. If you do not wish to customize any of the
-               od_multiline_edit() options, then you may simply set the third
-               parameter to 0. Hence, a simple example of how to use
-               od_multiline_edit() is:
-
-                    char szMyEditBuffer[4000] = "";
-                    od_multiline_edit(szMyEditBuffer, sizeof(szMyEditBuffer),
-                    NULL);
-
-               If you wish to customize od_multiline_edit(), you should pass a
-               pointer to a tODEditOptions structure as the third parameter. You
-               should initialize this entire structure to zeros before
-               attempting to use it. You can then set any values of this
-               structure which you wish to change from their default. Any values
-               that are left at 0 will automatically revert to their defaults.
-               For example, if you wanted to specify a text format other than
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 101
-
-               the default, you could create, initialize and pass in a
-               tODEditOptions structure as follows:
-
-                    char szMyEditBuffer[4000] = "";
-                    tODEditOptions MyEditOptions;
-                    memset(&MyEditOptions, 0, sizeof(MyEditOptions));
-                    MyEditOptions.TextFormat = FORMAT_LINE_BREAKS;
-                    od_multiline_edit(szMyEditBuffer, sizeof(szMyEditBuffer),
-                         &MyEditOptions);
-
-               The definition of the tODEditOptions structure is as follows:
-
-                    typedef struct
-                    {
-                       INT nAreaLeft;
-                       INT nAreaTop;
-                       INT nAreaRight;
-                       INT nAreaBottom;
-                       tODEditTextFormat TextFormat;
-                       tODEditMenuResult (*pfMenuCallback)(void *pUnused);
-                       void * (*pfBufferRealloc)(void *pOriginalBuffer,
-                          UINT unNewSize);
-                       DWORD dwEditFlags;
-                       char *pszFinalBuffer;
-                       UINT unFinalBufferSize;
-                    } tODEditOptions;
-
-               nAreaLeft, nAreaTop, nAreaRight, nAreaBottom allows you to
-               specify the portion of the screen that the text editor should
-               use. This defaults to 1, 1 - 80, 23.
-
-               TextFormat allows you to specify what format the text should be
-               stored in the buffer using. The default is
-               FORMAT_PARAGRAPH_BREAKS, which specifies that a line break only
-               appears at the end of each paragraph, and that the contents of a
-               paragraph are word wrapped. FORMAT_LINE_BREAKS specifies that a
-               line break appears at the end of each line of text on the screen,
-               and that newly entered text is word wrapped. FORMAT_NO_WORDWRAP
-               is equivalent to FORMAT_LINE_BREAKS, except that newly entered
-               text is not word wrapped. Instead, lines may be arbitrarily long.
-               For each of these text formats, od_multiline_edit() automatically
-               decides whether line breaks should take the form of a carriage
-               return ('\r'), line feed ('\n'), or some combination of these,
-               based on what it sees in the buffer that you supply. If no line
-               breaks are found in the buffer, then the default is to use just a
-               line feed ('\n') character. FORMAT_FTSC_MESSAGE specifies a FTSC-
-               compliant message, such as is used in a *.MSG message file. Among
-               other things, this specifies that carriage returns ('\r') end
-               paragraphs, and that line feeds ('\n') should be ignored.
-
-               pfMenuCallback allows you to provide a callback function that
-               will be called when the user presses the escape (or control-Z)
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 102
-
-               key. This allows you to provide a menu that can be accessed from
-               within the text editor. This function should return
-               EDIT_MENU_DO_NOTHING if the editor should continue normally, or
-               EDIT_MENU_EXIT_EDITOR if the od_multiline_edit() should return.
-               If no menu callback function is provided, then
-               od_multiline_edit() always returns when the escape or control-z
-               key is pressed.
-
-               pfBufferRealloc allows you to provide a function which will
-               attempt to reallocate a larger buffer if the user enters more
-               text than will fit in the originally supplied buffer. You should
-               only do this if you have dynamically allocated the buffer that
-               you initially passed into od_multiline_edit(). If you allocated
-               the buffer using malloc() or calloc(), then pfBufferRealloc can
-               be set to point to the realloc() function. If you allocated the
-               buffer using the C++ new operator, then you must write a your own
-               reallocation function which obeys the same semantics as the C
-               realloc() function. If no buffer reallocation function is
-               provided, then od_multiline_edit() will never allow the user to
-               enter more text than will fit in the buffer that you initially
-               supply. If you are using the buffer reallocation option, you can
-               obtain a pointer to the final buffer, and the size of the final
-               buffer, from the pszFinalBuffer and unFinalBufferSize members.
-
-
-SEE ALSO       od_input_str(), od_edit_str(), od_get_input()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 103
-
-OD_PAGE()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to allow user to page the sysop
-
-
-FORMAT         void od_page(void);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function can be called to allow the user to page the sysop.
-               This function will ask the user why they wish to chat with the
-               sysop, and then page the sysop. The sysop will then be free to
-               break into chat at any time. Sysop paging will also be aborted
-               by the user, simply by pressing [Enter] when asked for a reason
-               for chat. When the user pages the sysop, the [Wants-Chat]
-               indicator will begin to flash on the main status line, and the
-               status line will switch to show the user's reason for wanting to
-               chat. Also, the user's total number of pages will be
-               incremented.
-
-               Depending upon the setting of the od_control.od_okaytopage
-               variable, this function will also optionally check sysop paging
-               hours, and only allow the user to page the sysop during valid
-               paging hours. For information on the variables containing the
-               user's total number of pages, the user's want-chat status, valid
-               sysop paging hours, and the od_control.od_okaytopage variable,
-               see the section on the OpenDoors control structure, which begins
-               on page 148.
-
-
-EXAMPLE        For an example of the use of the od_page() function, see the
-               EX_VOTE.C example program, which is described beginning on page
-               38.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 104
-
-OD_PARSE_CMD_LINE()
--------------------------------------------------------------------------------
-
-PURPOSE        Handles standard command line options.
-
-
-FORMAT         Under DOS Version:
-               void od_parse_cmd_line(INT nArgCount, char *papszArguments[]);
-
-               Under Win32 Version:
-               void od_parse_cmd_line(LPSTR pszCmdLine);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This is the only OpenDoors function that uses a different
-               calling format in the DOS and Win32 versions of OpenDoors. The
-               reason for this is that od_parse_cmd_line() always allows you to
-               pass command line parameters in the same format that the
-               operating system passes them to you. Under the DOS version of
-               OpenDoors, you should pass the argc and argv values that were
-               passed to your main function as the two parameters to
-               od_parse_cmd_line(). Under the Win32 version of OpenDoors, you
-               should pass the pszCmdLine values that were passed to your
-               WinMain() function as the one parameter to od_parse_cmd_line().
-
-               The od_parse_cmd_line() function should be called before your
-               first call to any other OpenDoors function, with the possible
-               exception of the od_add_personality() function.
-
-               It is recommended that any program which uses OpenDoors call
-               od_parse_cmd_line() as part of its startup procedure. This
-               allows your program to automatically handle many common command
-               line options that will make it easier to setup and run your
-               program. Among the helpful command line options processed by
-               od_parse_cmd_line() are options to set serial port information
-               (including information on non-standard serial port setups),
-               specify the location of configuration and drop files, force the
-               program to run in silent mode (without no local display), pass
-               in user information, and the ability to start the program in
-               local mode without a drop file. For a complete list of the
-               options supported by od_parse_cmd_line(), run the example Vote
-               door that is included in the OpenDoors packages, specifying -
-               help on the command line.
-
-               If you wish to process your own command line parameters in
-               addition to those supported by OpenDoors, simply check the
-               command-line for your own parameters after calling
-               od_parse_cmd_line(). You can do this in the same way that you
-               would handle command line options if you weren't using
-               od_parse_cmd_line(). The od_parse_cmd_line() function does not
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 105
-
-               generate an error message if it encounters unrecognized command
-               line options. You can supply your own text to display when the
-               user chooses the /Help option by setting
-               od_control.od_cmd_line_help to point to your own string. Separate
-               lines in your string with the \n character, and align text using
-               the \t character.
-
-
-SEE ALSO       od_init()
-
-
-EXAMPLE        The following example shows how a program that uses
-               od_parse_cmd_line() should be structured in order to compile
-               under either DOS or Win32 versions of OpenDoors:
-
-               #include "opendoor.h"
-
-               /* main() or WinMain() function - Program begins here. */
-               #ifdef ODPLAT_WIN32
-               int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-                  LPSTR lpszCmdLine, int nCmdShow)
-               #else
-               int main(int argc, char *argv[])
-               #endif
-               {
-               #ifdef ODPLAT_WIN32
-               #endif
-
-                  /* Set program's name for use by OpenDoors. */
-               #ifdef ODPLAT_WIN32
-                  /* In Windows, pass in nCmdShow value to OpenDoors. */
-                  od_control.od_cmd_show = nCmdShow;
-
-                  /* Call od_parse_cmd_line. */
-                  od_parse_cmd_line(lpszCmdLine);
-               #else
-                  od_parse_cmd_line(argc, argv);
-               #endif
-
-
-                  /* Start the rest of your program here. */
-
-
-               }
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 106
-
-OD_POPUP_MENU()
--------------------------------------------------------------------------------
-
-PURPOSE        Creates a popup menu which allows the user to make a selection
-               by pressing a single key, or selecting the item with a highlight
-               bar. After the user has made a selection, the menu may be
-               removed from the screen, restoring the original screen contents
-               "beneath" the window.
-
-
-FORMAT         INT od_popup_menu(char *pszTitle, char *pszText, INT nLeft,
-                  INT nTop, INT nLevel, WORD uFlags);
-
-
-RETURNS        POPUP_ERROR    On error (od_control.od_error is set to
-                              indicate type of error).
-               POPUP_ESCAPE   If user exited menu by pressing [ESCape].
-               POPUP_LEFT     If user exited menu by pressing the left arrow
-                              key.
-               POPUP_RIGHT    If user exited menu by pressing the right arrow
-                              key.
-
-               Or, a postive integer indicating the menu item that was chosen
-               if a selection was made.
-
-
-DESCRIPTION    od_popup_menu() creates a popup window with a menu of choices,
-               for use in ANSI/AVATAR/RIP modes. The user is able to choose an
-               item from the menu by moving the highlighted selection bar with
-               the arrow keys, or by pressing a key associated with a
-               particular menu item. The contents of the menu are defined by
-               the string pointed to by the pszText parameter. This menu
-               definition string contains each menu option, separated by a '|'
-               (pipe) character. Keys associated with each menu entry can be
-               defined by proceeding the letter with a '^' (carat) character.
-               For example, the string:
-
-                    "^Save|^Load|E^xit"
-
-               would produce a menu with three options: Save, Load and Exit.
-               The user would be able to select the Save option by pressing the
-               [S] key, the Load option by pressing the [L] key, and the Exit
-               option by pressing the [X] key. Furthermore, the characters
-               corresponding to each menu item would be displayed in a
-               highlighted color.
-
-               Menus displayed with od_popup_menu() may optionally have a
-               title, as specified by the pszTitle parameter. If this parameter
-               is set to NULL, no title will be displayed. If this parameter is
-               not NULL, the specified string will be displayed as a title on
-               the window.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 107
-
-               The nLeft and nTop parameters specify the left and top locations
-               of the menu window, were 1, 1 is the upper right corner of the
-               screen. The bottom and right corners of the menu are
-               automatically determined by the size and number of menu entries
-               in the menu definition string.
-
-               The nLevel parameter specifies the menu level, an integer from 0
-               to 10. Unless you are using the MENU_KEEP flag, this parameter
-               can always be 0.
-
-               The uFlags parameter specifies one or more of the following
-               options, joined by the bitwise-OR operator (|).
-
-                    MENU_NORMAL         Has no effect.
-                    MENU_ALLOW_CANCEL   Allow user to exit menu with [ESCape].
-                    MENU_PULLDOWN       Allow exit with arrow keys.
-                    MENU_KEEP           Leave menu active on selection.
-                    MENU_DESTROY        Remove a currently active menu.
-
-               If you are not using any of the other flags, you can use
-               MENU_NORMAL as a place-holder for this parameter. If you specify
-               MENU_ALLOW_CANCEL, the user will be able to exit the menu
-               without making a selection by pressing the [ESCape] key. If the
-               user presses [ESCape], od_popup_menu() returns POPUP_ESCAPE.
-
-               You can use the MENU_PULLDOWN option with od_popup_menu() to
-               implement a set of pulldown menus. In this case, if the user
-               presses the left arrow key or right arrow key while the menu is
-               being displayed, od_popup_menu() returns with POPUP_LEFT or
-               POPUP_RIGHT, allowing you to display a different menu.
-
-               Normally, od_popup_menu() will remove the menu from the screen
-               as soon as the user makes a selection. However, there may be
-               some cases when you want the menu to continue to be visible
-               after the user makes a selection. For example, you may want some
-               menu options to lead to further sub-menus, or you may wish to
-               display a popup window, and return to this menu after the user
-               has exited from the popup window. If the MENU_KEEP flag is
-               specified, the menu will remain active (on-screen) after the
-               user makes a selection. However, the menu will still be
-               destroyed if the user cancels out of the menu (this will only
-               happen if you have specified MENU_ALLOW_CANCEL), or if the user
-               moves to another menu by pressing the left or right arrow keys
-               (this will only happen if you have specified MENU_PULLDOWN). If
-               MENU_KEEP has been specified, and the user makes a selection,
-               you must eventually either return to the menu, or destroy it by
-               calling MENU_DESTROY. If you want to return to the menu, simply
-               call od_popup_menu() again with the same level value that was
-               used to originally create the menu. The user will now be able to
-               make another selection from the menu, and od_popup_menu() will
-               once again return that selection to you. If you want to destroy
-               the menu, simply call od_popup_menu() with the MENU_DESTROY flag
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 108
-
-               set, and the same level value that was used to create the
-               original menu. If you wish to create another popup menu while
-               the first one is still active, simply call od_popup_menu()
-               again, this time with a different level value. The colors used
-               by the od_popup_menu() function are set by the following
-               OpenDoors control structure settings:
-
-                    char od_control.od_menu_title_col;
-                    char od_control.od_menu_border_col;
-                    char od_control.od_menu_text_col;
-                    char od_control.od_menu_key_col;
-                    char od_control.od_menu_highlight_col;
-                    char od_control.od_menu_highkey_col;
-
-
-SEE ALSO       od_window_create(), od_window_remove(), od_draw_box(),
-               od_hotkey_menu()
-
-
-EXAMPLE        The following example shows the use of multiple-level menus:
-
-               #include <stdlib.h>
-               #include "opendoor.h"
-               main()
-               {
-                  for(;;)
-                  {
-                     switch(od_popup_menu("Main Menu",
-                        "^Files|^Electronic Mail|^News|E^xit",
-                        20, 5, 0, MENU_NORMAL | MENU_KEEP))
-                     {
-                        case 1:
-                           od_popup_menu("Files Menu",
-                              "^Search For Files|^Download|^Upload",
-                              30, 7, 2, MENU_NORMAL | MENU_ALLOW_CANCEL);
-                           break;
-                        case 2:
-                           od_popup_menu("EMail Menu",
-                              "Get ^New Mail|^Send Mail|Send ^Fax",
-                              30, 8, 1, MENU_NORMAL | MENU_ALLOW_CANCEL);
-                           break;
-                        case 3:
-                           od_popup_menu("News Menu",
-                              "Choose News^Group|^Read News|^Post News",
-                              30, 9, 1, MENU_NORMAL | MENU_ALLOW_CANCEL);
-                           break;
-                        case 4:
-                           od_popup_menu(NULL, NULL, 0, 0, 0, MENU_DESTROY);
-                           return(0);
-                     }
-                  }
-               }
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 109
-
-OD_PRINTF()
--------------------------------------------------------------------------------
-
-PURPOSE        Performs formatted output (remote & local), with the ability to
-               change display colors.
-
-
-FORMAT         void od_printf(char * pszFormat,...);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This is one of two OpenDoors function which allows you to
-               display a string of characters, the other being the
-               od_disp_str() function. For a complete comparison of the various
-               OpenDoors display function, see the description of the
-               od_disp_str() function, on page 63. Like the od_disp_str()
-               function, the od_printf() function will display its output both
-               on the local screen, and on the remote user's screen (if the
-               door is not operating in local mode). However, the od_printf()
-               function also allows for formatted output, just as the printf()
-               function does. In addition to providing all of the features of
-               the normal C printf() function, the od_printf() function allows
-               you to include codes to change the color of the display of text.
-               This unique feature allows you to display multi-colored text,
-               without having to use chains of alternating od_disp_str() and
-               od_set_color() calls.
-
-               As with the printf() function, the od_printf() function accepts
-               one or more parameters, the first parameter being the format
-               string to be displayed, and the additional parameters being data
-               to be displayed within the string. The OpenDoors od_printf()
-               function recognizes all of the control characters and options
-               recognized by the normal printf() function. For example, to
-               display the amount of time that a user has left online, the
-               following line would be a valid use of the od_printf() function:
-
-                    od_printf("Time Left:%d\n\r", od_control.user_timelimit);
-
-               Note that a full discussion of the printf() function is beyond
-               the scope of this manual. For more information on using
-               printf(), please see your Turbo C(++) / Borland C++ manuals.
-
-               In addition to the normal control sequences, such as "%s", "%d",
-               or "%12.12s", the od_printf() function also allows you to
-               include special color-setting codes within the format string.
-               These color code sequences BEGIN and END with a delimiter
-               character, which is used to indicate that the sequence is a
-               color setting. Consider, for example, the following line of
-               code, which displays text in various colors:
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 110
-
-                       od_printf("`blue`Blue `green`Green `red`Red  \n\r");
-
-               In this case (assuming of course that a color monitor is being
-               used) the word "Blue" will be displayed in the color blue, the
-               word "Green" will be displayed in the color green, and the word
-               "Red" will be displayed in the color red. In this case, the
-               sequence `blue` sets the display color to dark blue on black.
-               Here, the back-quote (`) is the delimiter character which
-               indicates the beginning and end of the color sequence. Be sure
-               not to confuse the back-quote character (`) with the normal
-               forward quote ('). THIS IS THE MOST COMMON DIFFICULTY
-               EXPERIENCED WITH THE OD_PRINTF() FUNCTION. The text between the
-               back-quote characters indicates the color that should be set.
-               This text can include the name of the foreground color, the name
-               of the background color, the "bright" keyword and the "flashing"
-               keyword. The first color mentioned is taken to be the foreground
-               color, and the second the background color. Case is not
-               sensitive, additional words can be included for legibility.
-               Thus:
-
-                         `bright white cyan`
-
-               is equivalent to:
-
-                         `Bright white on a cyan background`.
-
-               The "bright" keyword indicates that the foreground color should
-               be displayed in high intensity, and the "flashing" keyword
-               indicates that the text should be flashing. If no background is
-               specified, the background color defaults to black. If no
-               foreground or background colors are specified, the color
-               defaults to white on black.
-
-               The od_printf() function will automatically determine whether
-               the user has ANSI, AVATAR or RIP graphics enabled, and will send
-               the appropriate color codes to change the color of displayed
-               text. If the user does not have either ANSI or AVATAR graphics
-               modes turned on, then the od_printf() function will not send any
-               color codes. Thus, a door program using color codes would work
-               just as well when ANSI/AVATAR/RIP graphics are not available,
-               except that all text will appear in the same color.
-
-               You may prefer to set colors by using the od_set_color() or
-               od_set_attrib() functions, instead of using these cryptic color
-               codes imbedded in od_printf() functions. In some cases, however,
-               it will be much more advantageous to place the color codes
-               within your od_printf() strings. As a case in point, consider
-               the single od_printf() statement in the example, above. To
-               accomplish the same result using the od_disp_str() and
-               od_set_color() functions, you would have to use the following
-               SIX function calls:
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 111
-
-                       od_set_color(D_BLUE,D_BLACK);
-                       od_disp_str("Blue ");
-                       od_set_color(D_GREEN,D_BLACK);
-                       od_disp_str("Green ");
-                       od_set_color(D_RED,D_BLACK);
-                       od_disp_str("Red  \n\r");
-
-               While this method MAY be easier understand, it certainly
-               requires many more line of code to accomplish. However, either
-               method will work, and the choice is up to you as to which method
-               you prefer. Keep in mind, however, that if the color to be set
-               is stored in a variable, instead of always being the same color,
-               you must use either the od_set_color() or od_set_attrib()
-               function to set the display color.
-
-               While the back-quote (`) character is normally used to delimit a
-               color sequence in the od_printf() function, you may wish to be
-               able to print a back-quote character using the od_printf()
-               function. In this case, you may configure OpenDoors to use a
-               different character to represent color code sequences. To do
-               this, simply use the od_control.od_color_delimiter variable,
-               which is described in the OpenDoors control structure section,
-               beginning on page 148. For example, if you wished to use the
-               tilde (~) character instead of the back-quote character to
-               change colors, simply place the following line within your
-               program, at some point after having called od_init() or some
-               OpenDoors function:
-
-                       od_control.od_color_delimiter='~';
-
-               Also, you may disable the color code interpretation within the
-               od_printf() function altogether, by setting the
-               od_control.od_color_delimiter variable to 0.
-
-               Note that the od_printf() function interprets the color codes
-               AFTER parsing the other control sequences, such as "%d" or "%s".
-               Thus, if you used the command:
-
-                       od_printf("%s",string);
-
-               Any color codes contained in the string "string" would also be
-               interpreted. If you did not wish to have any color code
-               characters which might be contained in the string "string"
-               treated as such, you could again disable od_printf()'s color
-               code interpretation, by setting the od_control.od_color_char
-               variable to 0.
-
-               Note that the string to be displayed by od_printf() should not
-               exceed 511 characters in size, including the size of color
-               sequences and expanded % fields.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 112
-
-SEE ALSO       od_disp_str(), od_disp(), od_putch(), od_repeat(), od_disp_emu()
-
-
-EXAMPLE        Below is a simple example of a user statistics door program,
-               which displays various pieces of information to the user, by
-               using the od_printf() function. Notice the use of color code
-               sequences in order to display the titles in a different color
-               from the information fields. Note that since the information
-               available to this door will depend on the BBS system under which
-               it is running, not all of the information displayed by this door
-               will be available under all BBS systems. For a description of
-               what information is available under what BBS systems, see the
-               OpenDoors control structure portion of this manual, which begins
-               on page 148.
-
-
-#include "opendoor.h"
-
-int main(int argc,char *argv[])
-   {
-   od_init();                                     /* Begin OpenDoors program */
-
-   od_printf("`bright white` YOUR STATISTICS\n\r");         /* Display title */
-   od_printf("---------------\n\r\n\r");
-
-                                                       /* Display statistics */
-   od_printf("`red`NAME :             `blue`%s\n\r",od_control.user_logintime);
-   od_printf("`red`LOCATION :         `blue`%s\n\r",od_control.user_location);
-   od_printf("`red`PHONE NUMBER :     `blue`%s\n\r",od_control.user_homephone);
-   od_printf("`red`LAST CALL :        `blue`%s\n\r",od_control.user_lastdate);
-   od_printf("`red`NUMBER OF CALLS :  `blue`%u\n\r",od_control.user_numcalls);
-   od_printf("`red`NUMBER OF PAGES :  `blue`%u\n\r",od_control.user_numpages);
-   od_printf("`red`REMAINING TIME :   `blue`%d\n\r",od_control.user_timelimit);
-   od_printf("`red`# OF DOWNLOADS :   `blue`%u\n\r",od_control.user_downloads);
-   od_printf("`red`# OF UPLOADS :     `blue`%u\n\r",od_control.user_uploads);
-   od_printf("`red`KBYTES DL TODAY :  `blue`%u\n\r",od_control.user_todayk);
-
-                                                /* Ask user to press [Enter] */
-   od_printf("`bright green on green`Press [Enter] to return to BBS...\n\r");
-
-   while(od_get_key(TRUE)!=13);            /* Wait for user to press [Enter] */
-
-   od_exit(20,FALSE);                                       /* Return to BBS */
-   }
-
-
-HELPFUL        This section demonstrates use of the od_printf() color
-HINT           sequences imbedded directly in the printf() format string, such
-               as:
-
-                         od_printf("Hello `bright green` there!");
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 113
-
-               However, there are also other ways that you can take advantage
-               of this feature. For example, the C programming language
-               concatenates string constants that are separated only by white
-               space or carriage returns. For instance,
-
-                         "Hello " "`bright green`" " there!"
-
-               is equivalent to:
-
-                         "Hello `bright green` there!"
-
-               For this reason, you can create macros for common color
-               sequences in your program, such as:
-
-                         #define HIGHLIGHT "`bright green`"
-
-               You can then use such constants when calling the od_printf()
-               function, as follows:
-
-                         od_printf("Hello " HIGHLIGHT " there!");
-
-               You may find this method of setting the display color to be
-               easier to read, and more easily configurable than including the
-               color sequence directly in the format string. Below another use
-               of the color sequences is describe, which allows the colors used
-               by od_printf() not be "hard-wired".
-
-
-               Since color control sequences are evaluated by od_printf() after
-               it evaluates all format sequences (such as "%d"). For this
-               reason, it is possible to change the display color using a
-               string variable, instead of using a fixed color in the string.
-               For example, if you program had the variable:
-
-                         char highlight[40];
-
-               which was set at some point to be equal to:
-
-                         "`bright green`"
-
-               you would be able to use od_printf() as follows:
-
-                         od_printf("Hello %s there!", highlight);
-
-               The display color would then be changed at the location where
-               the "%s" appears in the od_printf() format string. The advantage
-               of using this method to change display colors is that unlike
-               other methods, the value of the highlight variable can be
-               changed. This could be used, for example, to allow the sysop to
-               configure the colors they wish your door to use. You would only
-               need to change the value of the highlight variable in order to
-               change the color set by od_printf().
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 114
-
-OD_PUTCH()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to display a single character.
-
-
-FORMAT         void od_putch(int chToDisplay);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function performs a similar function to the other OpenDoors
-               display functions. For information on the uses of the various
-               OpenDoors display functions, see the description of the
-               od_disp_str() function, on page 63. This function is most
-               similar to the od_disp() and od_disp_str() functions, except
-               that it only displays a single character at a time.
-
-               This function will display the character passed to it at the
-               cursor position in the output window, and then advance the
-               cursor to the next display position. If OpenDoors is not
-               operating in local mode, the character will also be sent to the
-               modem, and thus displayed on the user's screen in the same
-               manner that it is displayed on the local screen. If ANSI, AVATAR
-               or RIP graphics mode is activated the character will be
-               displayed in the current color.
-
-
-SEE ALSO       od_disp_str(), od_disp(), od_printf(), od_repeat(),
-               od_disp_emu()
-
-
-EXAMPLE        Below is an example of the use of the od_putch() function. This
-               example is a function which you could use in place of the
-               od_get_key() function. This function inputs a single character
-               from the keyboard, just as the od_get_key() function does.
-               However, if the character entered is a printable character, the
-               function will also echo the character to the local screen, using
-               the od_putch() function.
-
-               char get_key_with_echo(int wait)
-               {
-                  char pressed=od_get_key(wait);        /* Get key from user */
-
-                  if(pressed>=32 && pressed<=126)     /* If key is printable */
-                  {
-                     od_putch(pressed);             /* Display the character */
-                  }
-
-                  return(pressed);             /* Return key pressed by user */
-               }
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 115
-
-OD_PUTTEXT()
--------------------------------------------------------------------------------
-
-PURPOSE        Displays a rectangular region of text and color information, as
-               previously stored using od_gettext()
-
-
-FORMAT         BOOL od_puttext(INT nLeft, INT nTop, INT nRight, INT nBottom,
-                  void *pBlock);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    This function "pastes" a rectangular block of text and color
-               information that has been previously retrieved using
-               od_gettext(). The block is placed at the screen location
-               indicated by the variables nLeft, nTop, nRight and nBottom,
-               where nLeft and nRight are column numbers from 1 - 80, and nTop
-               and nBottom are row numbers from 1 - 23. The length and width of
-               the rectangle specified by nLeft, nTop, nRight and nBottom must
-               be the same as the length and width of the rectangle passed to
-               od_gettext() when storing the block of text.
-
-               This function attempts to display the pasted block as quickly as
-               possible, only transmitting information on portions of the block
-               that are different than the original screen contents. When this
-               function returns, it leaves the cursor at its original position,
-               and the display color at its original setting. This function
-               requires ANSI or AVATAR mode.
-
-               The control structure variable od_control.od_full_put may be set
-               to TRUE to force od_puttext() to always send all characters in
-               the block to be displayed, instead of only displaying the
-               portions of the block that differ from the original screen
-               contents. If you wish to save and restore the entire screen, you
-               can use od_save_screen() and od_restore_screen(), which work in
-               all display modes.
-
-               You may also use the od_puttext() to display a rectangular block
-               of text that you generate manually, instead of retrieving using
-               od_gettext(). To do this, you pass an array which contains the
-               text and color information for the rectangular area to be
-               painted, in the pBlock parameter. The array passed to
-               od_puttext() contains a two-byte sequence of information for
-               each character in the rectangle. The first byte contains the
-               ASCII code of the character to be displayed. The second byte
-               contains the color attribute value of the character, in the same
-               format as used by the od_set_attrib() function (described on
-               page 128). These two byte sequences are stored in the order in
-               which English is written; the array begins with the two byte
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 116
-
-               sequences for all of the characters on the first line, from left
-               to right, followed by the characters for the second line, and so
-               on. The length of each line must be exactly equal to the width
-               of the rectangular region to be painted.
-
-
-SEE ALSO       od_gettext(), od_save_screen(), od_restore_screen(),
-               od_scroll(), od_window_create(), od_window_remove()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 117
-
-OD_REPEAT()
--------------------------------------------------------------------------------
-
-PURPOSE        Repeatedly display the specified character any number of times,
-               using special graphics codes for greater speed, if possible.
-
-
-FORMAT         void od_repeat(char chValue, BYTE btTimes);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This display function will repeatedly display the character
-               chValue, btTimes times. For a complete breakdown of the various
-               OpenDoors display functions, see the description of the
-               od_disp_str() function, located on page 63.
-
-               The advantage of using this function to display a series of
-               identical characters is that this function will use special
-               graphics-mode control sequences to display the repeated
-               character very efficiently, if the required graphics mode is
-               available. For example, in AVATAR mode, this function can
-               display an entire line of one character, by sending a control
-               sequence to the modem that is only three characters long. If
-               graphics mode is not turned on, then the od_disp_str() function
-               will simply send the specified character the appropriate number
-               of times. As with the other display functions, the output of
-               this function is sent to both the local and remote screens.
-
-
-SEE ALSO       od_putch(), od_disp_str(), od_disp(), od_printf(), od_disp_emu()
-
-
-EXAMPLE        The example function below demonstrates the use of the
-               od_repeat() function in drawing a window (a square box) on the
-               screen. This function is essentially a simplified version of the
-               od_draw_box() function, which is described on page 65. Unlike
-               this function, the od_draw_box() function allows the
-               customization of the characters used to draw the box's boarder,
-               and if possible uses additional AVATAR graphics codes to display
-               the window even faster than this function does. Thus, the
-               function below is really provided for demonstration purposes
-               only.
-
-               This function accepts four parameters, which indicate the
-               location of the upper left and lower right corners of the window
-               to be displayed. The function then displays the window with the
-               current color attribute settings. Since this function uses the
-               od_repeat() function, if AVATAR graphics are available, it can
-               display the entire window in a fraction of a second, even if it
-               is displaying a window the size of the entire screen at slow
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 118
-
-               baud rates. Note that this window display function requires that
-               the user has ANSI, AVATAR or RIP graphics mode enabled.
-
-               void draw_window(char left, char top, char right, char bottom)
-               {
-                  char line_counter;   /* Number of current line being drawn */
-                  char between_size=(right-left)-1;      /* X size of window */
-
-                  od_set_cursor(top,left);             /* move to top corner */
-                  od_putch(218);                 /* display corner character */
-                  od_repeat(196,between_size);           /* display top line */
-                  od_putch(191);                 /* display corner character */
-                                      /* loop through middle lines of window */
-                  for(line_counter=top+1;line_counter<bottom;++line_counter)
-                  {
-                     od_set_cursor(line_counter,left); /* move to line start */
-                     od_putch(179);                /* display left line char */
-                     od_repeat(' ',between_size);      /* display blank area */
-                     od_putch(179);               /* display right line char */
-                  }
-
-                  od_set_cursor(bottom,left);       /* move to bottom corner */
-                  od_putch(192);                 /* display corner character */
-                  od_repeat(196,between_size);        /* display bottom line */
-                  od_putch(217);                 /* display corner character */
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 119
-
-OD_RESTORE_SCREEN()
--------------------------------------------------------------------------------
-
-PURPOSE        Restores the screen contents as previous saved using the
-               od_save_screen() function. This function can be used in any
-               display mode.
-
-
-FORMAT         BOOL od_restore_screen(void *pBuffer);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    This function restores the entire contents of the screen, along
-               with the current cursor position and display color, which was
-               previously stored using the od_save_screen() function. Unlike
-               the od_get_text() and od_put_text() functions, the
-               od_save_screen() and od_restore_screen() functions will work in
-               all display modes (ASCII, ANSI, AVATAR and RIP).
-
-               The pBuffer parameter must point to the buffer previously passed
-               to od_save_screen(). Note that the od_save_screen() and
-               od_restore_screen() functions save the stored information in
-               different formats than the od_getttext() and od_puttext()
-               functions. For this reason, you cannot save the screen contents
-               with od_gettext() and restore them with od_restore_screen(), or
-               visa-versa.
-
-               If this function fails for any reason, a value of FALSE is
-               returned, and the od_control.od_error variable is set to
-               indicate the reason for the failure. For more information on the
-               od_control.od_error variable, see page 185.
-
-
-SEE ALSO       od_save_screen(), od_gettext(), od_puttext(), od_clr_scr()
-
-
-EXAMPLE        For an example of how to use the od_restore_screen() function,
-               see the example which accompanies the od_save_screen() function,
-               on page 121.
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 120
-
-OD_SAVE_SCREEN()
--------------------------------------------------------------------------------
-
-PURPOSE        Saves the contents of the screen, to later be restored using
-               od_restore_screen(). Can be used in any display mode.
-
-
-FORMAT         BOOL od_save_screen(void *pBuffer);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    This function saves the entire contents of the screen, along
-               with the current cursor position and display color, to be later
-               restored using the od_restore_screen() function. Unlike the
-               od_get_text() and od_put_text() functions, the od_save_screen()
-               and od_restore_screen() functions will work in all display modes
-               (ASCII, ANSI, AVATAR and RIP).
-
-               The pBuffer parameter should point to a buffer where the current
-               screen information is to be stored. This buffer must be at least
-               4004 bytes in size.
-
-               Note that the od_save_screen() and od_restore_screen() functions
-               save the stored screen information in different formats than the
-               od_getttext() and od_puttext() functions. For this reason, you
-               cannot save the screen contents with od_save_screen() and
-               restore them with od_puttext(), or visa-versa.
-
-               Also, note that when used in RIP graphics mode, this function
-               only saves and restores textual information, and not bit-mapped
-               graphical information.
-
-               If this function fails for any reason, a value of FALSE is
-               returned, and the od_control.od_error variable is set to
-               indicate the reason for the failure. For more information on the
-               od_control.od_error variable, see page 185.
-
-
-SEE ALSO       od_restore_screen(), od_gettext(), od_puttext(), od_clr_scr()
-
-
-EXAMPLE        One case where you might wish to save and restore the contents
-               of the screen is when sysop chat mode is activated. This can be
-               accomplished by using the od_control.od_cbefore_chat and
-               od_control.od_cafter_chat variables. The following example
-               causes the screen contents to be saved and the entire screen
-               cleared, prior to entering sysop chat mode when the sysop
-               presses the "chat key". When the sysop ends chat mode, the
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 121
-
-               user's original screen is restored, and the user will be able to
-               continue working in the door as though nothing had happened.
-
-               Code to perform screen saving and restoring:
-
-                    /* Function prototypes */
-                    void before_chat_function(void);
-                    void after_chat_function(void);
-
-                    /* Buffer to hold contents of screen prior to chat */
-                    char before_chat_buffer[4004];
-                    /* Variable to store whether screen save was successful */
-                    char before_chat_saved = FALSE;
-
-                    /* Function which is called prior to entering chat mode */
-                    void before_chat_function(void)
-                       {
-                       /* Store current screen contents */
-                       before_chat_saved = od_save_screen(before_chat_buffer);
-
-                       /* Present a blank screen for chat mode */
-                       od_clr_scr();
-                       }
-
-                    /* Function which is called after exiting chat mode */
-                    void after_chat_function(void)
-                       {
-                       /* If screen was successfully saved prior to chat */
-                       if(before_chat_saved)
-                          {
-                          /* Restore original screen contents */
-                          od_restore_screen(before_chat_buffer);
-                          }
-                       }
-
-               Code included in main() function to enable screen saving and
-               restoring code:
-
-                    od_control.od_cbefore_chat = before_chat_function;
-                    od_control.od_cafter_chat = after_chat_function;
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 122
-
-OD_SCROLL()
--------------------------------------------------------------------------------
-
-PURPOSE        Scrolls any rectangular area of the screen a specified number of
-               lines upwards or downwards. Requires ANSI/AVATAR/RIP graphics
-               mode to be active.
-
-
-FORMAT         BOOL od_scroll(INT nLeft, INT nTop, INT nRight, INT nBottom,
-                  INT nDistance, WORD nFlags);
-
-
-RETURNS        TRUE on success
-               FALSE on FAILURE
-
-
-DESCRIPTION    This function scrolls a rectangular area of the screen described
-               by the parameters nLeft, nTop, nRight and nBottom. The
-               parameters nLeft and nRight are column numbers from 1 - 80, and
-               the parameters nTop and nBottom are row numbers from 1 - 23.
-
-               The parameter nDistance indicates the direction and number of
-               lines to scroll the text in the specified area. Positive values
-               denote moving the text upwards, and negative values denote
-               moving the text downwards.
-
-               The new lines created by scrolling text will appear in the
-               current color. When this function returns, it leaves the cursor
-               at its original position, and the display color at its original
-               setting. This function requires ANSI or AVATAR modes. If ANSI
-               mode is active, this function is equivalent to calling
-               od_gettext(), od_puttext(), and then sending addition codes to
-               the modem clear the newly created lines. In ANSI mode, scrolling
-               can be accomplished more quickly if the area to be scrolled is
-               equal in width to the entire screen. This is because the
-               clearing of newly created lines is done by sending a simple
-               control sequence, instead of a line of space characters. If
-               AVATAR mode is active, scrolling of the window is accomplished
-               by sending a single 6-byte control sequence.
-
-               The last parameter to od_scroll(), nFlags, should normally be
-               set to SCROLL_NORMAL. However, if you set nFlags to
-               SCROLL_NO_CLEAR, the newly created lines at the top or bottom of
-               the screen are not cleared if it would take longer to do so.
-
-
-SEE ALSO       od_gettext(), od_puttext(), od_window_create(),
-               od_window_remove()
-
-
-EXAMPLE        For an example of a program which uses the od_scroll() function,
-               see the ex_chat.c example program, described on page 38.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 123
-
-OD_SEND_FILE()
--------------------------------------------------------------------------------
-
-PURPOSE        Sends an ASCII/ANSI/AVATAR/RIP file from disk, using terminal
-               emulation.
-
-
-FORMAT         BOOL od_send_file(char *pszFileName);
-
-
-RETURNS        TRUE if the file was successfully sent
-               FALSE if OpenDoors was unable to send the file
-
-
-DESCRIPTION:   This powerful function will display any ASCII, ANSI, AVATAR or
-               RIP file. The od_send_file() function can be used to display
-               existing BBS text files, such as a "logoff screen", before your
-               door hangs up on the user. You can also make use of the
-               od_send_file() function to build many of your door screens as
-               external files. This will allow you to easily create these
-               screens in an ANSI editor program, such as "TheDraw". It will
-               could also optionally allow sysops to customize your door for
-               use on their own BBS.
-
-               The od_send_file() function is called with the full path and
-               filename of the file you wish to have displayed. Thus, if you
-               wished to send the ANSI file MAINMENU.SCR, you would simply
-               call:
-
-                            od_send_file("MAINMENU.SCR");
-
-               In many cases, instead of having just one file that you want
-               displayed in particular, you will have several different files,
-               and will want a different one displayed according to the user's
-               graphics mode. For example, you might have the four files,
-               MAINMENU.ASC, MAINMENU.ANS, MAINMENU.AVT and MAINMENU.RIP; the
-               .ASC file containing no special control codes, the .ANS file
-               containing ANSI control codes, the .AVT file containing AVATAR
-               control codes, and the .RIP file containing RIP graphics control
-               codes. In this case, you can have the od_send_file() function
-               automatically select the appropriate file according to the
-               user's current display mode, by omitting the extension
-               altogether. Thus, a call to:
-
-                            od_send_file("MAINMENU");
-
-               would cause OpenDoors to automatically send the appropriate
-               file, according to the user's graphics mode settings. When the
-               od_send_file() function is used in this "automatic mode" (where
-               you do not specify a filename extension), it will look for one
-               of the four filename extensions listed below.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 124
-
-               +----------------------------------------------------------+
-               | Extension| File type                                     |
-               +----------+-----------------------------------------------|
-               |   .ASC   | Does not require any graphics mode to display |
-               |   .ANS   | Requires ANSI graphics mode to display        |
-               |   .AVT   | Requires AVATAR graphics mode to display      |
-               |   .RIP   | Requires RIP graphics mode to be displayed    |
-               +----------------------------------------------------------+
-
-
-               If the user has RIP graphics enabled, od_send_file() will first
-               search for the .RIP file. If no file exists with the specified
-               filename and a .RIP extension, od_send_file() will then search
-               for .AVT, then .ANS, and if not found .ASC. If the user has only
-               ANSI graphics enabled, od_send_file() will attempt first to
-               display the .ANS file, and if not found will search for .ASC. In
-               the case that the user is using plain-ASCII mode, this function
-               will attempt only to display the .ASC file.
-
-               When displaying a .RIP file to the remote system, OpenDoors will
-               attempt to locate and display a corresponding .AVT/.ANS/.ASC
-               file on the local system. If no such file can be found, a window
-               will be displayed, indicating the name of the .RIP file that is
-               being sent to the remote system. When a .RIP file is being
-               displayed, page pausing is disabled.
-
-               When displaying .AVT/.ANS/.ASC files, od_send_file() will send
-               any ANSI or AVATAR codes in the file directly to the remote
-               terminal, and interpret them to display on the local screen
-               (regardless of the actual filename extension). This
-               interpretation is accomplished by OpenDoor's built in terminal
-               emulator. The terminal emulator fully supports all ANSI and
-               AVATAR level 0 and level 0+ control codes. The terminal emulator
-               will also translate Remote Access/QuickBBS style control codes,
-               if enabled by setting od_control.od_no_ra_codes to FALSE. The
-               control codes supported by OpenDoors are listed in the chart on
-               the following pages. When these control codes are inserted into
-               the file, OpenDoors will replace them with various pieces of
-               user or system information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 125
-
-                 +-----------------------------------------------------+
-                 | CONTROL | ASCII |                                   |
-                 |  CODE   | VALUE | DESCRIPTION                       |
-                 +---------+-------+-----------------------------------|
-                 |   ^FA   | 06,65 | Displays the user's full name     |
-                 |   ^FB   | 06,66 | Location the user is calling from |
-                 |   ^FC   | 06,67 | Displays the user's password      |
-                 |   ^FD   | 06,68 | Business/data phone number        |
-                 |   ^FE   | 06,69 | Home/voice phone number           |
-                 |   ^FF   | 06,70 | Date of the user's last call      |
-                 |   ^FG   | 06,71 | Time of day of the last call      |
-                 |   ^FH   | 06,72 | The user's `A' flags settings     |
-                 |   ^FI   | 06,73 | The user's `B' flags settings     |
-                 |   ^FJ   | 06,74 | The user's `C' flags settings     |
-                 |   ^FK   | 06,75 | The user's `D' flags settings     |
-                 |   ^FL   | 06,76 | User's remaining netmail credit   |
-                 |   ^FM   | 06,77 | Number of messages posted by user |
-                 |   ^FN   | 06,78 | Last read message number by user  |
-                 |   ^FO   | 06,79 | Displays security level of user   |
-                 |   ^FP   | 06,80 | Number of times user has called   |
-                 |   ^FQ   | 06,81 | Total # of uploads by user        |
-                 |   ^FR   | 06,82 | Total KBytes uploaded by user     |
-                 |   ^FS   | 06,83 | Total # of downloads by user      |
-                 |   ^FT   | 06,84 | Total Kbytes downloaded by user   |
-                 |   ^FU   | 06,85 | # of minute user has used today   |
-                 |   ^FV   | 06,86 | User's screen length setting      |
-                 |   ^FW   | 06,87 | User's first name only            |
-                 |   ^FX   | 06,88 | User's ANSI setting               |
-                 |   ^FY   | 06,89 | User's "continue?" prompt setting |
-                 |   ^FZ   | 06,90 | Does user have screen clearing on |
-                 |   ^F0   | 06,48 | User's Full-screen editor setting |
-                 |   ^F1   | 06,49 | User's Quiet mode setting         |
-                 |   ^F2   | 06,50 | User's hot-keys setting           |
-                 |   ^F3   | 06,51 | Displays the user's alias         |
-                 |   ^F4   | 06,52 | The date of the User's first call |
-                 |   ^F5   | 06,53 | The user's date of birth          |
-                 |   ^F6   | 06,54 | User's subscription expiry date   |
-                 |   ^F7   | 06,55 | Number of days until expiry       |
-                 |   ^F8   | 06,56 | User's AVATAR setting             |
-                 |   ^F9   | 06,57 | The user's upload:download ratio  |
-                 |   ^F:   | 06,58 | User's Upload K:download K ratio  |
-                 +-----------------------------------------------------+
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 126
-
-                 +-----------------------------------------------------+
-                 | CONTROL | ASCII |                                   |
-                 |  CODE   | VALUE | DESCRIPTION                       |
-                 +---------+-------+-----------------------------------|
-                 |   ^F;   | 06,59 | Full-screen message reader        |
-                 |   ^KA   | 11,65 | Total # of calls BBS has received |
-                 |   ^KB   | 11,66 | Name of the last caller to BBS    |
-                 |   ^KC   | 11,67 | Total # of active messages on BBS |
-                 |   ^KD   | 11,68 | Displays # of the first message   |
-                 |   ^KE   | 11,69 | Displays # of the last message    |
-                 |   ^KF   | 11,70 | # of times user has paged sysop   |
-                 |   ^KG   | 11,71 | Full name of the current weekday  |
-                 |   ^KH   | 11,72 | Displays total number of users    |
-                 |   ^KI   | 11,73 | Displays the current time         |
-                 |   ^KJ   | 11,74 | Displays the current date         |
-                 |   ^KK   | 11,75 | Minutes the user has been online  |
-                 |   ^KL   | 11,76 | Seconds the user has been online  |
-                 |   ^KM   | 11,77 | Minutes the user has used today   |
-                 |   ^KN   | 11,78 | Seconds the user has used today   |
-                 |   ^KO   | 11,79 | Minutes remaining for user today  |
-                 |   ^KP   | 11,80 | Seconds remaining for user today  |
-                 |   ^KQ   | 11,81 | The user's daily time limit       |
-                 |   ^KR   | 11,82 | Displays the current baud rate    |
-                 |   ^KS   | 11,83 | The current weekday in short-form |
-                 |   ^KT   | 11,84 | The user's daily download limit   |
-                 |   ^KU   | 11,85 | # of minutes until the next event |
-                 |   ^KV   | 11,86 | Time of the next system event     |
-                 |   ^KW   | 11,87 | # of node user is currently on    |
-                 |   ^KX   | 11,88 | Disconnects the user              |
-                 +-----------------------------------------------------+
-
-
-SEE ALSO       od_disp_emu(), od_list_files(), od_hotkey_menu()
-
-
-EXAMPLE        For an example of the use of the od_send_file() function in
-               displaying a custom door menu, see the EX_VOTE.C example
-               program, which is described beginning on page 38.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 127
-
-OD_SET_ATTRIB()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to change the text color in ANSI or AVATAR mode, using
-               a single IBM-PC color attribute value.
-
-
-FORMAT         void od_set_attrib(INT nColor);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    od_set_attrib() is one of two functions which change the color
-               of the currently displayed text. This function allows you to set
-               the text color using a single IBM-PC style color attribute. On
-               the other hand, the od_set_color() function allows you to set
-               the display color by specifying a foreground and background text
-               color. Generally speaking, which of these two functions you use
-               will be only a matter of personal preference. You will, however,
-               most likely find it more convenient to use the od_set_color()
-               function for changing display color. However the od_set_attrib()
-               offers the advantage of allowing you to manipulate the color to
-               be displayed as a single value, instead of two separate values.
-               This could be convenient, for example, when displaying text in a
-               user configured color. Using a single byte to represent the
-               color will likely be easier than using two. An alternative
-               method of setting the color of displayed text is to include the
-               color codes within a string displayed by the od_printf()
-               function. The benefits of doing this, along with instructions on
-               how to do this, are described in the section on the od_printf()
-               function, which begins on page 110.
-
-               This function will only have an effect if the user has ANSI,
-               AVATAR or RIP modes enabled. As a result, you can use this
-               function within your door program, and have your text
-               automatically displayed in multiple colors if graphics mode is
-               available, and displayed without colors if graphics mode is not
-               available.
-
-               Note that the color to be set is passed to this function as an
-               IBM-style screen attribute. Hence, you can set the color of text
-               to be displayed by a single hexidecimal value, encoded as
-               follows:
-
-                              +------------- Background color
-                              |
-                            0x7f
-                               |
-                               +------------ Foreground color
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 128
-
-               Where the left digit (most significant nibble) of the
-               hexidecimal number represents the background color, and the
-               right digit (least significant nibble) represents the foreground
-               color. Each of the possible colors, along with their
-               corresponding hexidecimal values, are listed in the charts,
-               below.
-
-               +-----------------------+  +--------------------------+
-               |   Foreground colors   |  |   Background  | Flashing |
-               +-----------------------|  +---------------+----------|
-               |  0  | Black           |  |  0  | Black   |   Off    |
-               |  1  | Blue            |  |  1  | Blue    |   Off    |
-               |  2  | Green           |  |  2  | Green   |   Off    |
-               |  3  | Cyan            |  |  3  | Cyan    |   Off    |
-               |  4  | Red             |  |  4  | Red     |   Off    |
-               |  5  | Magenta         |  |  5  | Magenta |   Off    |
-               |  6  | Brown           |  |  6  | Brown   |   Off    |
-               |  7  | White (grey)    |  |  7  | White   |   Off    |
-               |  8  | Bright Black    |  |  8  | Black   |    On    |
-               |  9  | Bright Blue     |  |  9  | Blue    |    On    |
-               |  a  | Bright Green    |  |  a  | Green   |    On    |
-               |  b  | Bright Cyan     |  |  b  | Cyan    |    On    |
-               |  c  | Bright Red      |  |  c  | Red     |    On    |
-               |  d  | Bright Magenta  |  |  d  | Magenta |    On    |
-               |  e  | Yellow          |  |  e  | Brown   |    On    |
-               |  f  | White (bright)  |  |  f  | White   |    On    |
-               +-----------------------+  +--------------------------+
-
-
-SEE ALSO       od_set_color(), od_disp_emu(), od_clr_scr(), od_clr_line(),
-               od_set_cursor()
-
-
-EXAMPLE        At times, you may wish to allow the user to select the color of
-               text they wish to have displayed, perhaps to configure your door
-               for the ideal colors to be displayed on their system. To
-               demonstrate the use of the od_set_attrib() function, we show
-               another function, which shows the user all 256 possible colors
-               that can be displayed, and allows the user to choose which color
-               they prefer. The function will then return the color attribute
-               value of the user's chosen color.
-
-               unsigned char choose_color(void)
-               {
-                  register unsigned char counter;   /* for displaying colors */
-                  char string[4];                    /* string input by user */
-
-                  od_set_attrib(0x07);                      /* display title */
-                  od_disp_str("Available colors:\n\r\n\r");
-
-                  for(counter=0;counter<=255;)    /* loop through all colors */
-                  {
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 129
-
-                     od_set_attrib(counter);        /* set appropriate color */
-                     od_printf("%03.3u",counter);  /* display color's number */
-                     if(((++counter)%16)==0)    /* after every 16 colors ... */
-                     {
-                        od_set_attrib(0x07);  /* ... reset display color ... */
-                        od_disp_str("\n\r");     /* ... and start a new line */
-                     }
-                  }
-
-                  od_set_attrib(0x07);         /* Allow user to choose color */
-                  od_disp_str("Which color do you prefer : ");
-                  od_input_str(string,3,'0','9');
-                  return(atoi(string));               /* Return chosen color */
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 130
-
-OD_SET_COLOR()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to change the current display color in ANSI, AVATAR or
-               RIP modes, using foreground and background color values.
-
-
-FORMAT         void od_set_color(INT nForeground, INT nBackground);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    od_set_color() is one of two functions which change the color of
-               the currently displayed text. This function allows you to set
-               the text color using separate foreground an background text
-               colors, whereas od_set_attrib() allows you to set the text color
-               using a single IBM-PC style color attribute. Generally speaking,
-               which of these two functions you use is only a matter of
-               personal preference. An alternative method of setting the color
-               of displayed text is to include the color codes within a string
-               displayed by the od_printf() function. The benefits of doing
-               this, along with instructions on how to do this, are described
-               in the section on the od_printf() function, which begins on page
-               110.
-
-               This function will only have an effect if the user has ANSI,
-               AVATAR or RIP mode turned on. As a result, you can use this
-               function within your door program, and have your text
-               automatically displayed in multiple colors if graphics mode is
-               available, and displayed without colors if graphics mode is not
-               available.
-
-               The od_set_color() function accepts two parameters, the first
-               parameter being the foreground color to be used in displaying
-               text, and the second parameter being the background color to be
-               used in displaying text. For example,
-
-                               od_set_color(L_WHITE,D_BLACK);
-
-               would set the current color to Light White on Dark Black. The
-               foreground and background text colors can be any one of the
-               color values listed on the following page.
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 131
-
-
-
-               +-------------------+-----------+
-               | Foreground Color  | Value     |
-               +-------------------+-----------+
-               | Dark Black        | D_BLACK   |
-               | Dark Blue         | D_BLUE    |
-               | Dark Green        | D_GREEN   |
-               | Dark Cyan         | D_CYAN    |
-               | Dark Red          | D_RED     |
-               | Dark Magenta      | D_MAGENTA |
-               | Dark Brown        | D_BROWN   |
-               | Grey (Dark White) | D_GREY    |
-               | Light Black (Grey)| L_BLACK   |
-               | Light Blue        | L_BLUE    |
-               | Light Green       | L_GREEN   |
-               | Light Cyan        | L_CYAN    |
-               | Light Red         | L_RED     |
-               | Light Magenta     | L_MAGENTA |
-               | Yellow            | L_YELLOW  |
-               | White             | L_WHITE   |
-               +-------------------+-----------+
-
-
-               +-------------------+-----------+
-               | Background Color  | Value     |
-               +-------------------+-----------+
-               | Black             | D_BLACK   |
-               | Blue              | D_BLUE    |
-               | Green             | D_GREEN   |
-               | Cyan              | D_CYAN    |
-               | Red               | D_RED     |
-               | Magenta           | D_MAGENTA |
-               | Brown             | D_BROWN   |
-               | Grey              | D_GREY    |
-               | Blinking Black    | B_BLACK   |
-               | Blinking Blue     | B_BLUE    |
-               | Blinking Green    | B_GREEN   |
-               | Blinking Cyan     | B_CYAN    |
-               | Blinking Red      | B_RED     |
-               | Blinking Magenta  | B_MAGENTA |
-               | Blinking Brown    | B_BROWN   |
-               | Blinking Grey     | B_WHITE   |
-               +-------------------+-----------+
-
-
-SEE ALSO       od_set_attrib(), od_disp_emu(), od_clr_scr(), od_clr_line(),
-               od_set_cursor()
-
-EXAMPLE        As an example of using the od_set_color() function to set the
-               color of displayed text, we show a pair of two functions. These
-               functions will allow a program to set the foreground OR
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 132
-
-               background color of text, without setting the other. In
-               contrast, the od_set_color() function sets both the foreground
-               and background color at the same time. These function presume
-               that they are the only functions used within the door to set the
-               color of displayed text, and that the original text color prior
-               to calling either of these functions is dark white on black.
-               These function must also have access to the two global variables
-               "current_foreground" and "current_background", as defined below.
-
-
-               void set_foreground(char foreground);
-               void set_background(char background);
-               unsigned char current_foreground=D_BLACK;
-               unsigned char current_background=D_GREY;
-
-               void set_foreground(char foreground)
-               {                                       /* set new text color */
-                  od_set_color(foreground, current_background);
-                  current_foreground=foreground;      /* save new foreground */
-               }
-
-               void set_background(char background)
-               {                                       /* set new text color */
-                  od_set_color(current_foreground, background);
-                  current_background=background;      /* save new background */
-               }
-
-
-               Using these functions, you would then be able to set just the
-               foreground text color by a function call like:
-
-                         set_foreground(L_YELLOW);
-
-               Or set just the background text color by a function call like:
-
-                         set_background(D_GREY);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 133
-
-OD_SET_CURSOR()
--------------------------------------------------------------------------------
-
-PURPOSE        Function to reposition the text cursor in ANSI, AVATAR or RIP
-               mode
-
-
-FORMAT         void od_set_cursor(INT nRow, INT nColumn);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    This function repositions the cursor to the specified row and
-               column on the screen. nRow can have a value of 1 to 23, and
-               nColumn can have a value of 1 to 80. ANSI, AVATAR or RIP mode
-               must be active.
-
-
-SEE ALSO       od_disp_emu(), od_clr_scr(), od_clr_line(), od_set_color(),
-               od_set_attrib()
-
-
-EXAMPLE        Below is a simple example that demonstrates the use of the
-               od_set_cursor() function. Note that this example detects whether
-               or not graphics mode is available, and if it is not, will carry
-               out the same task without the use of od_set_cursor().
-
-                            od_init();         /* Initialize door operations */
-                            od_clr_scr();                /* Clear the screen */
-                            if(od_control.user_ansi || od_control.user_avatar)
-                            {               /* If graphics mode is available */
-                               od_set_cursor(1,1);           /* Display demo */
-                               od_disp_str("Top, Left Corner");
-
-                               od_set_cursor(1,70);
-                               od_disp_str("Top, Right Corner");
-
-                               od_set_cursor(15,1);
-                               od_disp_str("Fifteenth line\n\r");
-                            }
-                            else        /* If graphics mode is not available */
-                            {                                /* Display demo */
-                               od_disp_str("Top, Left Corner");
-                               od_repeat(' ', 54);
-                               od_disp_str("Top, Right Corner\n\r");
-                               od_disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n");
-                               od_disp_str("Fifteenth line\n\r");
-                            }
-                            od_get_key(TRUE);  /* Wait for user to press key */
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 134
-
-OD_SET_DTR()
--------------------------------------------------------------------------------
-
-PURPOSE        Controls the DTR (Data Terminal Ready) signal to the modem. Used
-               primarily to cause the modem to "hang up".
-
-
-FORMAT         void od_set_dtr(BOOL bHigh);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    In certain circumstances (such as call back verification doors),
-               you may wish to "hang up" the modem without exiting your door
-               program. This can be accomplished with most modems by
-               controlling the DTR (Data Terminal Ready) signal to the modem.
-               Passing a FALSE value to od_set_dtr() causes the DTR signal to
-               be set low, and passing a TRUE value causes the DTR signal to be
-               set high. Normally, OpenDoors maintains the DTR signal in its
-               high state. Since most (but not all) modems are configured to
-               disconnect from the remote modem when the DTR signal is set low,
-               calling od_set_dtr(FALSE) can be used to hangup the modem. When
-               hanging up by this method, you should be sure to set the DTR
-               signal high again, after the carrier detect signal has
-               disappeared. For more information on determining the state of
-               the carrier detect signal, see the od_carrier() function, which
-               is described on page 51. Note that not all modems will
-               disconnect from the remote user in response to your lowering the
-               DTR signal. If your software may be used with such modems, you
-               may wish to also provide the option of disconnecting the modem
-               by sending a "hang up" command sequence to the modem.
-
-               Since OpenDoors normally monitors the carrier detect signal, and
-               exits when this signal disappears, you will have to disable
-               OpenDoor's carrier detection if you wish your program to
-               continue executing after hanging up the modem. OpenDoor's
-               automatic carrier detection can be disabled using the
-               od_control.od_disable OpenDoors control structure variable, as
-               follows:
-
-                    od_control.od_disable |= DIS_CARRIERDETECT;
-
-SEE ALSO       od_carrier(), od_exit()
-
-
-EXAMPLE        For an example of using the od_set_dtr() function to "hang up"
-               the modem, see the example that accompanies the od_carrier()
-               function, which is described on page 52.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 135
-
-OD_SET_PERSONALITY()
--------------------------------------------------------------------------------
-
-PURPOSE        Sets the current status line / sysop function key personality to
-               be used.
-
-
-FORMAT         BOOL od_set_personality(char *pszName);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    This function changes the current status line / sysop function
-               key personality. The pszName parameter should contain the string
-               which uniquely identifies the personality to be set. This
-               function may only be used by OpenDoors programs which include
-               the OpenDoors "Multiple Personality System". To enable use of
-               the MPS, include the following line before your first call to
-               any OpenDoors function:
-
-                         od_control.od_mps=INCLUDE_MPS;
-
-               OpenDoors includes a number of built-in personalities.
-               Additional personalities may be added using the
-               od_add_personality() function, which is described on page 47.
-               The following personalities are included with this version of
-               OpenDoors:
-
-                    Name                Description
-                    -----------------------------------------------------------
-                    Standard            OpenDoors style, similar to RA 1.11
-                    PCBoard             Similar to PC-Board
-                    RemoteAccess        Similar to RemoteAccess 2.x
-                    Wildcat             Similar to Wildcat!
-
-               Personality names are not case sensitive. For more information
-               on the OpenDoors Multiple Personality System, see the section
-               which begins on page 233.
-
-               This function returns TRUE on success, or FALSE on failure. In
-               the case of a failure, the od_control.od_error variable is set
-               to indicate the nature of the failure. For more information on
-               the od_control.od_error variables, see page 185.
-
-
-SEE ALSO       od_add_personality(), od_set_statusline()
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 136
-
-OD_SET_STATUSLINE()
--------------------------------------------------------------------------------
-
-PURPOSE        To set the currently displayed status line.
-
-
-FORMAT         void od_set_statusline(INT nSetting);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    If you have the OpenDoors status line enabled within your door
-               program (as is the default), the sysop will be able to control
-               the setting of the status line using the F1 - F10 keys on the
-               keyboard. These function keys are as follows:
-
-                         [F1] -  Display basic door and user information
-                         [F2] -  Display phone numbers and important dates
-                         [F3] -  Display security flags and up/download info
-                         [F4] -  Display system information and current time
-                         [F5] -  Display message info and user's settings
-                         [F6] -  Display chat reason and sysop's comment
-                         [F9] -  Display help information for sysop
-                         [F10] - Turn off the status line
-
-               Using the od_set_statusline() function, you can manually set
-               which of these status line settings is currently selected. The
-               od_set_statusline() accepts a single parameter, which should be
-               one of the values listed below, which indicates which status
-               line you would like to have selected:
-
-               +---------------+---------------+------------------------------+
-               |               | Corresponding |                              |
-               | Value         | Function Key  | Meaning                      |
-               +---------------+---------------+------------------------------+
-               | STATUS_NORMAL | [F1]          | Basic door and user info     |
-               | STATUS_NONE   | [F10]         | Turn off status line         |
-               | STATUS_HELP   | [F9]          | Displays help for the sysop  |
-               | STATUS_USER1  | [F2]          | Phone Numbers and dates      |
-               | STATUS_USER2  | [F3]          | Security flags & up/downloads|
-               | STATUS_USER3  | [F5]          | Message info & user settings |
-               | STATUS_USER4  | [F6]          | Chat reason and sysop comment|
-               | STATUS_SYSTEM | [F4]          | System info & current time   |
-               +---------------+---------------+------------------------------+
-               (Note that these keys may be customized using variables in the
-                OpenDoors control structure.)
-
-               Keep in mind that the od_set_statusline() function only
-               temporarily changes the current status line setting, and that
-               the sysop will still be able to change the status line to any of
-               the other settings using the function keys. For instance, if you
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 137
-
-               wished to allow the sysop to normally see all 25 lines of text
-               displayed by your door, but at the same time to still allow the
-               sysop to turn on the status line at any time, you could place
-               the line
-
-                         od_set_statusline(STATUS_NONE);
-
-               at the beginning of your program. Similarly, when the user pages
-               the sysop, OpenDoors itself calls
-
-                         od_set_statusline(STATUS_USER4);
-
-               in order to display the status line which shows the user's
-               reason for chat, while still allowing the sysop to switch back
-               to any of the other status lines.
-
-               If you wish to permanently turn off the OpenDoor's status line,
-               without allowing the sysop to be able to turn it back on using
-               the sysop function keys, simply set the
-               "od_control.od_status_on" variable to FALSE. This variable is
-               described in the OpenDoors control structure section of this
-               manual, which begins on page 148.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 138
-
-OD_SLEEP()
--------------------------------------------------------------------------------
-
-PURPOSE        Suspends program execution, yielding control to other tasks in a
-               multitasking environment.
-
-
-FORMAT         void od_sleep(tODMilliSec Milliseconds);
-
-
-RETURNS        N/A
-
-
-DESCRIPTION    od_sleep() suspends execution of your program for the specified
-               number of milliseconds. Note that under the DOS version of
-               OpenDoors, this value is rounded to the nearest 55 milliseconds.
-               While the program's execution is suspended, od_sleep() yields
-               control of the processor to other tasks in a multitasking
-               environment.
-
-               Calling od_sleep() with a sleep time of 0 causes control to be
-               yielded to other waiting processes without imposing a minimum
-               sleep time. If no other processes are waiting to execute, the
-               function returns immediately. OpenDoors automatically calls
-               od_sleep(0) itself in most of the situations where there is a
-               need to do so. However, there may be circumstances under which
-               od_sleep(0) can be used to improve performance. In particular,
-               od_sleep(0) can be used to improve the performance of other
-               applications that are also running at the same time as yours. By
-               calling od_sleep(0), you are essentially telling the operating
-               system that your program doesn't currently need all of the
-               processing time that has been allocated to it. While appropriate
-               use of od_sleep(0) can improve overall system performance,
-               overusing od_sleep(0) can dramatically degrade the performance
-               of your own program. The only way to determine the optimal use
-               of od_sleep(0)  is by trial and error.
-
-               The most common situation where you might want to use
-               od_sleep(0) is when your program cannot do anything useful until
-               you receive input from the user, but for some reason you cannot
-               call od_get_key(TRUE). Rather than sitting in a tight loop,
-               repeatedly checking where the user has pressed a key yet, it is
-               better to call od_sleep(0) to let other tasks run for a while
-               before checking again. OpenDoors calls od_sleep(0) itself under
-               any of the following circumstances:
-
-                    - When transmitting characters, if the outbound serial
-                      buffer is full, OpenDoors yields while waiting for some
-                      of the characters in the buffer to be sent.
-                    - During od_get_key(), if called with the wait parameter
-                      set to TRUE.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 139
-
-                    - While waiting for input, during the execution of any of
-                      the following input functions: od_get_answer(),
-                      od_hotkey_menu() (after menu has been displayed),
-                      od_popup_menu(), od_edit_str(), od_input_str().
-                    - While pausing at the end of a screen during
-                      od_send_file(), od_list_files(), od_hotkey_menu().
-                    - During chat mode.
-
-
-SEE ALSO       od_kernel()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 140
-
-OD_SPAWN()
--------------------------------------------------------------------------------
-
-PURPOSE        To facilitate easy execution of child tasks from doors.
-
-
-FORMAT         BOOL od_spawn(char *pszCommandLine);
-
-
-RETURNS        TRUE on success,
-               FALSE on failure
-
-
-DESCRIPTION    This function allows you to easily run other programs from
-               within your door programs, such as external file transfer
-               utilities, compression utilities, and so on.
-
-               This function will attempt to swap OpenDoors and your entire
-               door to expanded memory or disk. OpenDoors swapping can be
-               controlled by the OpenDoors control structure variables,
-               od_swapping_disable, od_swapping_ems and od_swap_path. The
-               od_spawn...() functions first attempt to swap OpenDoors to EMS
-               memory. If enough EMS 3.2 or later memory is available, it will
-               be used. If not, OpenDoors will swap to a disk file in the
-               directory specified by the od_control.od_swap_path variable.
-
-               Unlike the other Turbo C(++) / Borland C++ library functions
-               such as system() or spawnf(), this function will automatically
-               store the door screen prior to executing the sub-program, and
-               will restore the screen upon return. This function will also
-               store the current drive and directory settings prior to
-               executing the program, and restore them after the program has
-               returned.
-
-               Normally, the user's time will continue to be decreased during
-               the execution of the od_spawn() function. However, you can
-               freeze the user's time during the spawn process by using the
-               OpenDoors control structure variable od_spawn_freeze_time.
-
-
-SEE ALSO       od_spawnvpe()
-
-
-EXAMPLE        Below are a few examples of various uses of the od_spawn()
-               function:
-
-               To run the command processor from within your door program, to
-               allow the sysop access to the DOS shell, simply use the
-               following line of code:
-
-                              od_spawn(getenv("COMSPEC"));
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 141
-
-               The following function is an example of using the od_spawn()
-               function to call DSZ, allowing the user to download a file. You
-               pass the name of the file that you wish to send to the user.
-               This function will then ask the user what transfer protocol they
-               would like to use, generate the appropriate DSZ command line,
-               and then transmit the file to the user. Note that in order to
-               use a door which implements this function, the external file
-               transfer program "DSZ" must be available in the current search
-               path. As an alternative, you may want to allow the sysop to
-               specify the location of the DSZ file from within a configuration
-               program. If you wish to receive a file (allow the user to
-               upload), instead of sending one, simply change the "s" in the
-               command line to a "r".
-
-               char download(char *filename)
-               {
-                  char commandline[80];/* string containing DSZ command line */
-                  char protocol;   /* character representing chosen protocol */
-
-                                                    /* display protocol menu */
-                  od_printf("Select File Transfer Protocol:\n\r");
-                  od_printf("   [X] XModem\n\r");
-                  od_printf("   [Y] YModem\n\r");
-                  od_printf("   [Z] ZModem\n\r");
-                  od_printf("or press [A] to abort transfer\n\r");
-
-                  do            /* loop until valid protocol has been chosen */
-                  {
-                     protocol=od_get_key();                       /* get key */
-                                              /* abort if [A] key is pressed */
-                     if(protocol=='a' || protocol=='A') return(FALSE);
-                  } while(protocol!='x' && protocol!='y' && protocol!='z' &&
-                          protocol!='X' && protocol!='Y' && protocol!='Z');
-
-                  od_printf("Begin receiving file now or press [CTRL]-[X] to
-                             abort\n\r");
-                                                /* generate DSZ command line */
-                  sprintf(commandline,"dsz port %d s%c %s",
-                          od_control.port+1,
-                          protocol,
-                          filename);
-
-                  return(od_spawn(commandline));             /* spawn to DSZ */
-               }
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 142
-
-
-OD_SPAWNVPE()
--------------------------------------------------------------------------------
-
-PURPOSE        To facilitate easy execution of child tasks from doors. Allows
-               specification of child's environment, returns errorlevel
-               returned by child task, and searches path for the executable
-               file.
-
-
-FORMAT         INT16 od_spawnvpe(INT16 nModeFlag, char *pszPath,
-                  char *papszArg[], char *papszEnv[]);
-
-
-RETURNS        -1 on failure
-               errorlevel returned by child process on success
-
-
-DESCRIPTION    This function behaves very similarly to the od_spawn() function.
-               Thus, to save space in the manual, I will not recapitulate what
-               is already said in the description of the od_spawn() function.
-               Instead, this description concentrates on the additional
-               features available through the od_spawnvpe() function. If you
-               are not already familiar with the od_spawn() function, take a
-               moment now to review the description of that function.
-
-               The od_spawn() function (the OpenDoors "quick-spawn" function)
-               is designed to be quick and easy to use, but does not have all
-               of the features available in the od_spawnvpe() function. In
-               addition to the features of the od_spawn() function, the
-               od_spawnvpe() function also provides the following features:
-
-                         - od_spawnvpe() will search the "path" for the file
-                           to be executed.
-
-                         - od_spawnvpe() allows you to pass an altered
-                           environment to the child process.
-
-                         - od_spawnvpe() returns the errorlevel returned by
-                           the child process.
-
-               The parameters passed to the od_spawnvpe() function are
-               identical to those passed to the C spawnvpe() function. The
-               first parameter should usually the be P_WAIT flag. The second
-               parameter is the name of the child program to execute. If a full
-               path to the child program is not specified, and the child
-               program does not exist in the current directory, OpenDoors will
-               search the directories listed by the PATH environment variable.
-               Also, if the .EXE or .COM extension is not provide, OpenDoors
-               will look first for a .COM file, and if not found, for a .EXE
-               file. The third parameter is an array of arguments to pass to
-               the child process, or NULL if no arguments are to be passed. The
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 143
-
-               fourth parameter is the environment to be passed to the child
-               process, or NULL if the a copy of the current environment should
-               be used.
-
-
-SEE ALSO       od_spawn()
-
-
-EXAMPLE        For an example of the use of the od_spawn...() functions, see
-               the example accompanying the od_spawn() function. As a specific
-               example of the od_spawnvpe function, consider the following code
-               which executes the "TEST.EXE" program.
-
-                         od_spawnvpe(P_WAIT,"TEST.EXE",NULL,NULL);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 144
-
-OD_WINDOW_CREATE()
--------------------------------------------------------------------------------
-
-PURPOSE        Creates a popup window of the specified size and color, storing
-               the contents of the screen "under" the window. The window can
-               later be removed from the screen, restoring the original
-               contents of the screen "under" the window, using the
-               od_window_remove() function. Requires ANSI, AVATAR or RIP mode.
-
-
-FORMAT         void *od_window_create(INT nLeft, INT nTop, INT nRight, INT
-               nBottom,
-                    char *pszTitle, BYTE btBorderCol, BYTE btTitleCol,
-                    BYTE btInsideCol, INT nReserved);
-
-
-RETURNS        Pointer to newly allocated window structure on success
-               NULL on failure
-
-
-DESCRIPTION    This function creates a pop-up window on the remote and local
-               screens. The contents of the screen beneath the window are
-               stored, to allow the window to later be removed from the screen
-               using the od_window_remove() function. The window is drawn using
-               the boarder characters defined in the already existing
-               od_control.od_box_chars[] array. The boarder is displayed using
-               the color attribute specified in btBorderCol. The working area
-               of the window is created in the color specified in btInsideCol.
-               A title may optionally be displayed on the window by specifying
-               a string in pszTitle. This title will be displayed in the color
-               specified by btTitleCol. If you do not wish a title to be
-               displayed, pass an empty string or NULL pointer in pszTitle. On
-               success, od_window_create() will return a pointer to a buffer
-               which was allocated to store information on the window and the
-               contents of the screen "under" the window. This pointer should
-               at some point be passed in a call to od_window_remove().
-
-               This function requires ANSI, AVATAR or RIP graphics mode. If
-               AVATAR mode is active, this function will take advantage of
-               special AVATAR control sequences to display the window much
-               faster than is possible in ANSI mode. In ANSI mode, window
-               display will be slightly faster if btBorderCol and btTitleCol
-               are equal. Note that the nReserved parameter of this function is
-               not currently used. To preserve compatibility with future
-               versions of OpenDoors, this parameter should always be set to 0.
-               Currently, the size of the buffer allocated to store the window
-               information will be (length*width*2) + 4 bytes in size.
-
-               If od_window_create() fails for any reason, a value of NULL is
-               returned, and the od_control.od_error variable is set to
-               indicate the reason for the failure. For more information on the
-               od_control.od_error variable, see page 185.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 145
-
-
-
-SEE ALSO       od_window_remove(), od_draw_box(), od_gettext(), od_puttext(),
-               od_save_screen(), od_restore_screen(), od_scroll()
-
-
-EXAMPLE        For an example of the use of the od_window_create() function,
-               see the included ex_chat.c example program.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 146
-
-OD_WINDOW_REMOVE()
--------------------------------------------------------------------------------
-
-PURPOSE        Removes a window previously created using od_window_create(),
-               restoring the original screen background.
-
-
-FORMAT         BOOL od_window_remove(void *pWinInfo);
-
-
-RETURNS        TRUE on success
-               FALSE on failure
-
-
-DESCRIPTION    The od_window_remove() function removes a window from the screen
-               which was previously created by od_window_create(), and
-               deallocates the memory which was allocated to store the window
-               information. The contents of the screen beneath the window is
-               restored to appear as it did prior to the call to
-               od_window_create(). pWinInfo must point to the value returned by
-               od_window_create().
-
-               Note that overlapping windows must be removed in the reverse
-               order from which they were created for proper display results.
-               The last window to be created must be the first window to be
-               removed.
-
-               If od_window_remove() fails for any reason, a value of FALSE is
-               returned, and the od_control.od_error variable is set to
-               indicate the reason for the failure. For more information on the
-               od_control.od_error variable, see page 185.
-
-
-SEE ALSO       od_window_create(), od_draw_box(), od_gettext(), od_puttext(),
-               od_save_screen(), od_restore_screen(), od_scroll()
-
-
-EXAMPLE        For an example of the use of the od_window_remove() function,
-               see the included ex_chat.c example program.
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 147
-
- 555555
- 55
- 55
- 55555
-     55
-     55
- 55555
--------------------------------------------------------------------------------
-CHAPTER 5 - THE OPENDOORS CONTROL STRUCTURE
-
-
-
-
-INTRODUCTION TO THE CONTROL STRUCTURE
--------------------------------------------------------------------------------
-
-               The OpenDoors "Control Structure" is used by OpenDoors in order
-               to provide you with a wide range of information about the system
-               on which you door is running, and the user who is currently
-               using the door, along with providing you a means by which to
-               customize much of OpenDoor's behavior. Using the OpenDoors
-               control structure, you can access or alter information about the
-               user who is online, information about the system on which your
-               door is running, and information about OpenDoors itself. You can
-               also use the control structure to customize all of the text
-               displayed by OpenDoors, the function keys to which it responds,
-               and many other aspects of OpenDoor's behavior.
-
-               The OpenDoors control structure is quite simply a normal C
-               "struct", named od_control, and is defined in the OPENDOOR.H
-               file. This "struct" contains many different variables, which
-               provide you access to the information provided by the control
-               structure. Hence, to access the contents of a control structure
-               variable, for example the variable "system_name" which contains
-               the name of the BBS the door is running under, you would use:
-
-                                  od_control.system_name
-
-               The following section of this chapter contains a complete
-               reference to all of the variables which make up the OpenDoors
-               control structure. This reference includes the name, type and
-               complete description of the use of each variable. The reference
-               is divided into the following categories of variables, with the
-               reference to the variables in each section beginning on the
-               listed page.
-
-                         Door Information File Statistics..................150
-                         Modem Settings....................................153
-                         BBS and Caller Information........................158
-                         Door Settings.....................................182
-                         OpenDoors Behavior Customization..................187
-                         Function Keys Customization.......................212
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 148
-
-                         Color Customization...............................237
-                         Text Customization................................217
-
-               Within each section, variables are listed alphabetically by
-               name.
-
-               Also, in order to make use of some of the variables in the
-               OpenDoors control structure, it is important to understand the
-               concepts of Boolean (TRUE/FALSE), and bit-mapped flag variables.
-               If you are not familiar with these two terms, they are described
-               in detail in the glossary, located towards the end of this
-               manual.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 149
-
-CONTROL STRUCTURE - DOOR INFO FILE STATS
--------------------------------------------------------------------------------
-
-               The following OpenDoors control structure variables provide your
-               program with information concerning the door information file
-               from which OpenDoors obtained the BBS and caller information
-               that is found elsewhere in the control structure. The following
-               control structure items are listed in this section:
-
-               info_path                Sets the location and, optionally, the
-                                        name of the door information file
-
-               od_info_type             Type of door information file that was
-                                        found
-
-               od_node                  Node number the door is running under
-
-               user_timeofcreation      The time at which the door information
-                                        file was created
-
-
-
-
--------------------------------------------------------------------------------
-info_path      char od_control.info_path[60];
-
-               If used, this variable should be set prior to calling od_init()
-               or any other OpenDoors function. This variable allows you to
-               control where OpenDoors will look for the door information (drop
-               file). By default, OpenDoors searches for the door information
-               file in the current directory. If this variable is set to the
-               name of some other directory, OpenDoors will first search for
-               any door information files in that directory. If you only wish
-               OpenDoors to look for a particular type of door information file
-               (for instance, you want OpenDoors to only read a DORINFO1.DEF,
-               and ignore any DOOR.SYS file), you can specify the full path and
-               filename of the file you wish OpenDoors to use.
-
-               It is usually a good idea to design your door to allow the
-               system operator to set the location of the door information
-               file. This will allow the sysop to place your door in its own
-               directory, and will facilitate the use of your door on multi-
-               line BBS systems. If you are using the OpenDoors configuration
-               file system, then the system operator can set the door
-               information file location and/or name using the BBSDir keyword.
-               However, you may also wish to allow the location of the door
-               information file to be set on the command line. The following
-               example illustrates a method of reading and setting the location
-               of the door information file from the door's command line:
-
-               #include "opendoor.h"
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 150
-
-               main(int argc, char *argv[])
-                  {
-                  if(argc>1) strncpy(od_control.info_path,argv[1],59);
-
-                  od_disp_str("This is a sample OpenDoors door.\n\r");
-                  od_disp_str("Press any key to continue...\n\r");
-                  od_get_key(TRUE);
-                  od_exit(20);
-                  }
-
-
-
--------------------------------------------------------------------------------
-od_info_type   char od_control.od_info_type;
-
-               This variable indicates the type of information file from which
-               OpenDoors has obtained the BBS and caller information that is
-               found elsewhere in the OpenDoors control structure. This
-               variable will have one of the following values, indicating that
-               the door information file was of the corresponding type:
-
-                     +----------------+----------------------------+
-                     |  od_info_type  | Door Information File Type |
-                     |      Value     |                            |
-                     +----------------+----------------------------+
-                     | DORINFO1       | DORINFO?.DEF               |
-                     | EXITINFO       | EXITINFO.BBS (Normal)      |
-                     | RA1EXITINFO    | EXITINFO.BBS (Extended)    |
-                     | RA2EXITINFO    | EXITINFO.BBS (RA 2.x)      |
-                     | QBBS275EXITINFO| EXITINFO.BBS (QuickBBS)    |
-                     | CHAINTXT       | CHAIN.TXT                  |
-                     | SFDOORSDAT     | SFDOORS.DAT                |
-                     | CALLINFO       | CALLINFO.BBS               |
-                     | DOORSYS_GAP    | DOOR.SYS (GAP/PC-Board)    |
-                     | DOORSYS_DRWY   | DOOR.SYS (Doorway style)   |
-                     | DOORSYS_WILDCAT| DOOR.SYS (WildCat standard)|
-                     | CUSTOM         | Custom door information    |
-                     |                | file, defined in config    |
-                     |                | file.                      |
-                     | NO_DOOR_FILE   | No drop file was found.    |
-                     +----------------+----------------------------+
-
-               The value of this variable is only valid AFTER od_init() or some
-               OpenDoors function has been called.
-
-               Note that this variable should be treated as a read-only
-               variable, and should not normally be altered by your program.
-               Altering this variable may cause OpenDoors to re-write a
-               different type of door information file upon exiting, than was
-               read upon startup.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 151
-
-
--------------------------------------------------------------------------------
-od_node        char od_control.od_node;
-
-               This variable indicates the node number that the door is running
-               under. If this information is supplied by the BBS in the door
-               information file, the node number will be automatically by
-               OpenDoors. Specifically, the node number can be determined
-               automatically from systems that produce an SFDOORS.DAT, PC-
-               Board/GAP style DOOR.SYS or Wildcat style DOOR.SYS door
-               information file. If this information is not supplied in the
-               door information file, but is provided by the sysop in the
-               door's configuration file, OpenDoors will use the value found
-               there. Alternatively, you can set this variable manually.
-
-               On systems that produce a DORINFO?.DEF file, OpenDoors will use
-               this variable to determine which DORINFO?.DEF file to search
-               for. For instance, if od_control.od_node is set to 3, OpenDoors
-               will first search for a DORINFO3.DEF file. If this file is not
-               found, OpenDoors will then default to the DORINFO1.DEF filename.
-
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_timeofcreation[6];
-_timeof
-creation       This variable contains the time of day at which the door
-               information file was created. This variable is available only
-               when the door is running under a system that produces an
-               EXITINFO.BBS file. To determine what type of door information
-               file your door is running under, see the od_control.od_info_type
-               variable, below.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 152
-
-CONTROL STRUCTURE - SERIAL PORT SETTINGS
--------------------------------------------------------------------------------
-
-               The following OpenDoors control structure items store the
-               communications settings that OpenDoors uses to communicate with
-               the modem. These values are normally set upon the first call to
-               an OpenDoors function, during the od_init() procedure. However,
-               you may need to manual set this variables if:
-
-                    - you wish to allow greater configurability of your door
-                    - you are reading the door information file yourself
-                    - you are using the OpenDoors to write a non-door
-                     program
-
-               Some of these variables are always used by OpenDoors, while
-               others are only relevant if OpenDoor's built-in serial
-               communications code is being used instead of a FOSSIL driver.
-               Those that are only used when no FOSSIL driver is present are
-               denoted by an [*] in the list below.
-
-               The control structure variables controlling OpenDoor's serial
-               port settings are as follows:
-
-               od_control.baud            Serial Port BPS rate
-
-               od_control.od_connect_sppedThe modem connection BPS rate
-
-               od_control.od_com_address  Serial Port address [*]
-
-                " " .od_com_fifo_trigger  16550A FIFO trigger size
-
-                " " .od_com_flow_control  Type of flow control to use.
-
-               od_control.od_com_irq      Serial Port IRQ number [*}
-
-               od_control.od_com_method   Is FOSSIL or built-in serial I/O
-                                          being used
-
-               od_control.od_com_no_fifo  Disables use of 16550A FIFOs [*]
-
-               od_control.od_com_rx_buf   Size of receive buffer [*]
-
-               od_control.od_com_tx_buf   Size of transmit buffer [*]
-
-               od_control.od_no_fossil    Prevents OpenDoors from using a
-                                          FOSSIL driver, even if one is
-                                          available.
-
-               od_control.od_open_handle  Allows a live serial port handle to
-                                          be passed to OpenDoors.
-
-               od_control.port            Serial port number, 0 based.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 153
-
-
-
-
--------------------------------------------------------------------------------
-baud           unsigned long od_control.baud;
-
-               This variable contains the BPS rate at which the computer is
-               communicating with the modem, not to be confused with the BPS
-               rate at which the local modem is communicating with the remote
-               modem.
-
-               A value of 0 indicates that the program is operating in local
-               mode.
-
-               If a FOSSIL driver is being used for serial I/O, this value is
-               ignored if it does not correspond to one of the baud rates that
-               an application can directly set a FOSSIL driver to. The BPS
-               rates recognized by FOSSIL drivers are: 300, 600, 1200, 2400,
-               4800, 9600, 19200, 38400. If any other BPS rate is to be used,
-               the FOSSIL driver must be locked at that BPS from the FOSSIL
-               driver command-line. When locked, FOSSIL drivers ignore any
-               attempt by an application to change the BPS rate of the locked
-               port. For this reason, the od_control.baud setting has no effect
-               on the FOSSIL driver if it is locked.
-
-
-
--------------------------------------------------------------------------------
-od_com_        int od_control.od_com_address;
-address
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the serial port address can be set from the FOSSIL driver
-               command line).
-
-               This variable may optionally be set to specify the base address
-               of the serial port to be used. For ports COM1: through COM4:,
-               OpenDoors can normally determine the serial port address
-               automatically. However, for other serial ports, the port address
-               must be specified using this variable. If you are not specifying
-               a serial port address with this variable, do not change it's
-               default value of 0.
-
-
-
--------------------------------------------------------------------------------
-od_com_        char od_control.od_com_fifo_trigger;
-fifo_trigger
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the IRQ line can be set from the FOSSIL driver command
-               line).
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 154
-
-
-               This variable sets the number of bytes that will be placed in
-               the 16550A UART FIFO buffers before an interrupt is triggered,
-               if the 16550A UART FIFOs are used. Valid values are 1, 4, 8 and
-               14.
-
-
-
--------------------------------------------------------------------------------
-od_com_        unsigned char od_control.od_com_flow_control;
-flow_control
-               This variable sets the type of serial I/O flow control to use.
-               By default, this variable is set to COM_DEFAULT_FLOW, which
-               specifies the default mode of flow control. Most often, this
-               will be RTS/CTS flow control. A value of COM_RTSCTS_FLOW
-               explicitly enables RTS/CTS flow control. A value of COM_NO_FLOW
-               disables all flow control. If you are going to change the value
-               of this variable, it should be set prior to your first call to
-               any OpenDoors function.
-
-
-
--------------------------------------------------------------------------------
-od_com_        unsigned char od_control.od_com_irq;
-irq
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the IRQ line can be set from the FOSSIL driver command
-               line).
-
-               This variable may optionally be set to specify the IRQ line to
-               be used for the serial port. By default, OpenDoors uses the
-               normal IRQ 4 line for ports COM1: and COM3:, and IRQ 3 for ports
-               COM2: and COM4:. To override this default, the IRQ line can be
-               set using this variable. If you are not specifying an IRQ line
-               with this variable, do not change it's default value of 0.
-
-
-
--------------------------------------------------------------------------------
-od_com_        char od_control.od_com_method;
-method
-               This read-only variable reports the method that OpenDoors is
-               using for serial I/O. This variable is set during od_init() or
-               the first call to an OpenDoors function. This variable can be
-               one of the following values:
-
-               COM_FOSSIL          - Indicates that a FOSSIL driver is being
-               used
-               COM_INTERNAL   - Indicates that OpenDoor's internal serial I/O
-                                code is being used.
-               COM_WIN32      - Indicates that the Win32 communication system
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 155
-
-                                is being used.
-
-
-
--------------------------------------------------------------------------------
-od_com_        char od_control.od_com_no_fifo;
-no_fifo
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the receive buffer size can be set from the FOSSIL driver
-               command line).
-
-               Normally, OpenDoors will use a 16550A FIFO buffer if a 16550A
-               UART is installed. You can disable the use of the 16550A FIFO
-               buffer by setting this variable to TRUE.
-
-
-
--------------------------------------------------------------------------------
-od_com_        unsigned int od_control.od_com_rx_buf;
-rx_buf
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the receive buffer size can be set from the FOSSIL driver
-               command line).
-
-               This variable allows you to set the size of OpenDoor's serial
-               I/O receive buffer. If you do not set this buffer size, a
-               default value of 256 characters is used. Normally, this buffer
-               size is more than large enough for door programs. However, if
-               you find that inbound characters are lost before they can be
-               processed by your program, you may wish to increase the size of
-               this buffer.
-
-               This variable should only be changed before your first call to
-               od_init() or any other OpenDoors function.
-
-
-
--------------------------------------------------------------------------------
-od_com_        unsigned int od_control.od_com_tx_buf;
-tx_buf
-               This variable is only used when OpenDoors is NOT performing
-               serial I/O using a FOSSIL driver. (When a FOSSIL driver is being
-               used, the receive buffer size can be set from the FOSSIL driver
-               command line).
-
-               This variable allows you to set the size of OpenDoor's serial
-               I/O transmit buffer. If you do not set this buffer size, a
-               default value of 1024 characters is used.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 156
-
-               This variable should only be changed before your first call to
-               od_init() or any other OpenDoors function.
-
-
-
--------------------------------------------------------------------------------
-od_connect_    DWORD od_control.od_connect_speed;
-speed
-               This variable contains the best guess at the current modem
-               connection speed. This information is currently only accurate if
-               a DOOR.SYS file is being used. In other situations, it will
-               always be set to be equal to od_control.baud.
-
-
-
--------------------------------------------------------------------------------
-od_open_       DWORD od_control.od_open_handle;
-handle
-               Under platforms where this is supported (currently only the
-               Win32 version of OpenDoors), this variable can be used to pass a
-               live serial port handle to OpenDoors, which OpenDoors will use.
-               OpenDoors will not close this handle when it exits. If this
-               value is set to 0, OpenDoors will open and close the serial port
-               itself.
-
-
-
--------------------------------------------------------------------------------
-port           char od_control.port;
-
-               This variable contains the serial port number that the modem is
-               connected. This number is 0 based, so that a value of 0
-               corresponds to COM1:, a value of 1 corresponds to COM2:, and so
-               on. This value will normally be set by the od_init() function,
-               when the door information file is read, and should not be
-               changed after modem initialization has been carried out by the
-               od_init() function.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 157
-
-CONTROL STRUCTURE - BBS AND CALLER INFORMATION
--------------------------------------------------------------------------------
-
-               As we have already described, there are two types of variables
-               in the OpenDoors control structure. Some of the variables are
-               simply used to allow you to customize OpenDoor's various
-               features, such as altering colors, prompts, timeouts, etc. Other
-               variables in the OpenDoors control structure serve to provide
-               you with information about the user who is online and the BBS
-               system your door is running under. This section deals with those
-               variables that provide you with information about the BBS and
-               the user.
-
-               The information in these variables is read from the door
-               information file, a small file created by the BBS specifically
-               for the purpose of communicating with door programs. Depending
-               on what BBS system your door is running under, the type of door
-               information file will vary. Since different door information
-               files do not all provide the same pieces of information, some
-               variables in this section will only be available when your door
-               is running under particular BBS systems.  Other variables will
-               be available with many or all BBS systems. In the description of
-               each variable in this section, we indicate under which door
-               information files the particular variable will be . So, if you
-               wish to access a variable that is only under certain door
-               information files, your program should test whether or not the
-               required information is available under the particular door
-               information file that was found. In order to determine which
-               door information file your door is running under, you should use
-               the od_control.od_info_type variable. This variable is described
-               in the section which begins on page 150. If you test the value
-               of the od_control.od_info_type variable, and find that the
-               required information is not available, you may wish to simply
-               use some sort of default value for the variable, or
-               alternatively, not allow your door to run under certain BBS
-               systems. Another possibility, if the required information is not
-               available, is imply to obtain this information from the user
-               yourself. For example, if you wished to know the length of the
-               user's screen, when this information is not available from the
-               door information file, you could simply prompt the user for
-               their screen length the first time they use your door. This
-               information could then be stored in your door's data files for
-               future reference.
-
-               As an example of testing what door information file your door is
-               running under, consider the case where you wanted to display the
-               user's birthday. The example below will display the user's
-               birthday if it is known, and otherwise, print the string
-               "unknown".
-
-                         if(od_control.od_info_type == RA1EXITINFO
-                            od_control.od_info_type == RA2EXITINFO)
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 158
-
-                         {
-                            od_disp_str(od_control.user_birthday);
-                         }
-                         else
-                         {
-                            od_disp_str("Unknown");
-                         }
-
-               The chart below lists the door information file formats that
-               OpenDoors recognizes, along with example BBS systems that
-               produce these files and a reference letter for each type. Thus,
-               an OpenDoors door can run DIRECTLY under ANY BBS SYSTEM that
-               produces one of these files formats, and under ANY OTHER BBS
-               system when used in conjunction with a door information file
-               conversion utility.
-
-+--------------------------+----------------------------------------+
-| FILE FORMAT              | EXAMPLE BBS SYSTEMS                    |
-+--------------------------+----------------------------------------+
-| CHAIN.TXT                | WWIV                                   |
-+--------------------------+----------------------------------------+
-| DORINFO1.DEF             | RBBS-PC                                |
-+--------------------------+----------------------------------------+
-| DORINFO1.DEF             | QuickBBS                               |
-|      &                   | Remote Access (versions 0.01-0.04)     |
-| EXITINFO.BBS (Std. Ver.) |                                        |
-+--------------------------+----------------------------------------+
-| DOOR.SYS (DoorWay Style) | Remote Access                          |
-+--------------------------+----------------------------------------+
-| DOOR.SYS (PCB/GAP Style) | PC-Board                               |
-|                          | GAP                                    |
-+--------------------------+----------------------------------------+
-| DOOR.SYS (WildCat Style) | Wildcat 3.00 and above                 |
-|                          | Telegard                               |
-+--------------------------+----------------------------------------+
-| SFDOORS.DAT              | Spitfire                               |
-|                          | TriBBS                                 |
-+--------------------------+----------------------------------------+
-| CALLINFO.BBS             | WildCat 2.xx                           |
-+--------------------------+----------------------------------------+
-| DORINFO1.DEF             | Remote Access (versions 1.00 and later)|
-|      &                   |                                        |
-| EXITINFO.BBS (Ext. Ver.) |                                        |
-+--------------------------+----------------------------------------+
-
-
-
-               The chart on the following page lists all of the OpenDoors
-               control structure variables in this section, along with a brief
-               description of their use. The variables are then described in
-               detail, below.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 159
-
-+-----------------------+-----------------------------------------------+
-| VARIABLE NAME         | VARIABLE CONTENTS                             |
-+-----------------------+-----------------------------------------------+
-| EMSI INFORMATION      | Information on current IEMSI session          |
-| event_status          | The status of the next system event           |
-| event_starttime       | The start time of the next system event       |
-| event_errorlevel      | The errorlevel of the next system event       |
-| event_days            | The days of the week to execute the event     |
-| event_force           | Whether the next system event is forced       |
-| event_last_run        | When the next system event was last run       |
-| sysop_name            | The name of the BBS's sysop                   |
-| system_calls          | Total number of calls BBS has received        |
-| system_last_caller    | The name of the last caller to the BBS        |
-| system_last_handle    | The handle (alias) of the last caller         |
-| system_name           | The name of the BBS                           |
-| TIMELOG VARIABLES     | The times at which the BBS has been most busy |
-| user_ansi             | Whether the user has ANSI graphics mode on    |
-| user_attribute        | User attribute bit-mapped flags               |
-| user_attrib2          | Second set of user attribute bit-mapped flags |
-| user_attrib3          | Third set of user attribute flags             |
-| user_avatar           | Whether the user has AVATAR graphics mode on  |
-| user_birthday         | The date the user was born                    |
-| user_callsign         | The user's amateur radio call sign            |
-| user_combinedrecord   | The user's combined message areas settings    |
-| user_comment          | Sysop's comment about the user                |
-| user_credit           | Amount of NetMail credit the user has         |
-| user_dataphone        | The user's data phone number                  |
-| user_date_format      | Format user wishes to have dates displayed in |
-| user_deducted_time    | Total time that has been subtracted from user |
-| user_downk            | Total Kilobytes downloaded by the user        |
-| user_downlimit        | User's daily download limit                   |
-| user_downloads        | Total number of files downloaded by the user  |
-| user_echomailentered  | Whether or not the user has entered EchoMail  |
-| user_error_free       | Whether or not connection is error-free       |
-| user_file_area        | The user's current file area                  |
-| user_firstcall        | Date of the user's first call to the BBS      |
-| user_flags            | User's sysop-defined flag settings            |
-| user_forward_to       | Name to forward user's mail to                |
-| user_group            | User's group number                           |
-| user_handle           | User's alias                                  |
-| user_homephone        | User's home telephone number                  |
-| user_language         | User's language setting                       |
-| user_last_pwdchange   | Total calls since last password change        |
-| user_lastdate         | Date of the user's last call                  |
-| user_lastread         | Highest message number read by user           |
-| user_lasttime         | Time of the user's last call                  |
-| user_location         | Name of the city where the user lives         |
-| user_logindate        | Date on which the current call began          |
-+-----------------------+-----------------------------------------------+
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 160
-
-
-
-
-+-----------------------+-----------------------------------------------+
-| VARIABLE NAME         | VARIABLE CONTENTS                             |
-+-----------------------+-----------------------------------------------+
-| user_loginsec         | User's security at the beginning of this call |
-| user_logintime        | Time at which the current call began          |
-| user_logonpassword    | User's password at the beginning of this call |
-| user_menustack        | Contents of the user's current menu stack     |
-| user_menustackpointer | Pointer to the top of the menu stack          |
-| user_messages         | Total number of messages written by the user  |
-| user_msg_area         | The user's current message area               |
-| user_name             | The user's name                               |
-| user_net_credit       | The user's remaining netmail credit           |
-| user_netmailentered   | Whether or not the user has entered NetMail   |
-| user_num              | The user's record number in the user file     |
-| user_numcalls         | Number of calls the user has made to the BBS  |
-| user_numpages         | Number of times the user has paged the sysop  |
-| user_password         | The user's current password                   |
-| user_pending          | The value of unsent NetMail written by user   |
-| user_reasonforchat    | The reason the user wishes to chat with sysop |
-| user_rip_ver          | RIP protocol version being used               |
-| user_screen_length    | The length of the user's screen               |
-| user_screenwidth      | The width of the user's screen                |
-| user_security         | The user's security access level              |
-| user_sex              | The user's gender                             |
-| user_subdate          | The date the user's subscription expires      |
-| user_timelimit        | The user's daily time limit                   |
-| user_todayk           | Kilobytes downloaded by the user today        |
-| user_upk              | Total Kilobytes uploaded by the user          |
-| user_uploads          | Total number of files uploaded by the user    |
-| user_wantchat         | Whether or not the user wishes to chat        |
-| user_xi_record        | The user's record in the USERSXI.BBS file     |
-+-----------------------+-----------------------------------------------+
-
-
-
-
--------------------------------------------------------------------------------
-EMSI           char od_control.ra_emsi_session;
-INFORMATION    char od_control.ra_emsi_crtdef[41];
-               char od_control.ra_emsi_protocols[41];
-               char od_control.ra_emsi_capabilities[41];
-               char od_control.ra_emsi_requests[41];
-               char od_control.ra_emsi_software[41];
-               char od_control.ra_hold_attr1;
-               char od_control.ra_hold_attr2;
-               char od_control.ra_hold_len;
-
-               These variables provide your door with information pertaining to
-               an interactive EMSI session that has been established. Note that
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 161
-
-               these variables are only available under systems that produce an
-               RA 1.00 and later style extended EXITINFO.BBS door information
-               file.
-
-               If an IEMSI session has been established, the Boolean variable
-               od_control.ra_emsi_session will be TRUE, and if no session has
-               not been established, this variable will be FALSE.
-
-               A full discussion of the IEMSI protocol is beyond the scope of
-               this manual. Specifications for the IEMSI protocol are available
-               from the OpenDoors support BBS.
-
-
-
--------------------------------------------------------------------------------
-event_days     unsigned char od_control.event_days;
-
-               This variable is a bit-mapped flag of the days of the week on
-               which the next system event is run. The bit-map bits are as
-               follows:
-
-                       +-----+------+-----------+
-                       | BIT | MASK | MEANING   |
-                       +-----+------+-----------+
-                       |  0  | 0x01 | Sunday    |
-                       |  1  | 0x02 | Monday    |
-                       |  2  | 0x04 | Tuesday   |
-                       |  3  | 0x08 | Wednesday |
-                       |  4  | 0x10 | Thursday  |
-                       |  5  | 0x20 | Friday    |
-                       |  6  | 0x40 | Saturday  |
-                       |  7  | 0x80 | All Days  |
-                       +-----+------+-----------+
-
-               For more information on bit-mapped flags, see the glossary item
-               entitled "BIT-MAPPED FLAGS".
-
-               This variable is only available under systems that produce an
-               EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-event_         unsigned char od_control.event_errorlevel;
-errorlevel
-               This variable contains the ErrorLevel associated with the next
-               system event. This variable is only available under systems that
-               produce an EXITINFO.BBS door information file.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 162
-
--------------------------------------------------------------------------------
-event          char od_control.event_force;
-_force
-               This variable indicates whether the next system event should be
-               forced to run at a particular time. If this variable contains a
-               value of TRUE, then the user should be forced off-line in order
-               to accommodate the event, and if this variable is false, then
-               the event can wait until after the user logs off normally. This
-               variable is only available under systems that produce an
-               EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-event          char od_control.event_last_run[9];
-_last_run
-               This variable contains a string representing the date on which
-               the next system event was last run, and is in the same format as
-               the user_lastdate variable. This variable is only available
-               under systems that produce an EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-event          char od_control.event_starttime[6];
-_starttime
-               This variable contains a string representing the time at which
-               the next system event is scheduled to start, in the same format
-               as the user_lasttime variable. This variable is only available
-               under systems that produce an EXITINFO.BBS or Wildcat style
-               DOOR.SYS door information file.
-
-
-
--------------------------------------------------------------------------------
-event          unsigned char od_control.event_status;
-_status
-               This variable represents the status of the next system event,
-               and will be equal to the value
-
-                            ES_ENABLED
-
-               if and only if the other event information contained in the
-               control structure is valid. This variable is only available
-               under systems that produce an EXITINFO.BBS file.
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 163
-
--------------------------------------------------------------------------------
-sysop_name     char od_control.sysop_name[40];
-
-               The od_control.sysop_name variable contains the name of the
-               sysop of the BBS under which your door is running. This variable
-               is available under any BBS system that produces a DORINFO?.DEF
-               (including RA & QBBS which process both DORINFO1.DEF and
-               EXITINFO.BBS files), or Wildcat style DOOR.SYS file.
-
-
-
--------------------------------------------------------------------------------
-system_calls   long od_control.system_calls;
-
-               This variable contains the total number of calls that have been
-               placed to the BBS, and is available under any BBS which produces
-               an EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-system_last    char od_control.system_last_caller[36];
-_caller
-               This string contains the name of the previous caller to the BBS,
-               on any line, and is available under EXITINFO.BBS.
-
-
-
--------------------------------------------------------------------------------
-system_last    char od_control.system_last_handle[36];
-_handle
-               This string contains the handle (alias) of the previous caller
-               to the BBS, on any line, and is available under EXITINFO.BBS.
-
-
-
--------------------------------------------------------------------------------
-system_name    char od_control.system_name[40];
-
-               The od_control.system_name variable contains the name of the BBS
-               under which your door is running. This variable is available
-               under any BBS system that produces a DORINFO?.DEF (including RA
-               & QBBS which process both DORINFO1.DEF and EXITINFO.BBS files).
-
-
-
--------------------------------------------------------------------------------
-TIMELOG        char od_control.timelog_start_date[9];
-VARIABLES
-               This string contains the date of the beginning of the time
-               period for which the time log is recorded. This variable is
-               available under any system that produces an EXITINFO.BBS file.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 164
-
-
-
-               int od_control.timelog_busyperhour[24];
-
-               This variable is an array of 24 elements, with each element
-               indicating the total number of times the BBS was in use during
-               each of the 24 hours of the day. Element 0 corresponds to the
-               time period of 0:00-1:00, element 1 corresponds to the time
-               period of 1:00-2:00, and so on. In order to determine the
-               frequency of system use during any hour as a percentage, simply
-               calculate the total of all 24 entries in the array, and divide
-               any given entry by the total, in order to come up with an
-               average. This variable is available under any system that
-               produces an EXITINFO.BBS file.
-
-
-               int od_control.timelog_busyperday[7];
-
-               This variable is an array of 7 elements, with each element
-               indicating the total number of times the BBS was in use during
-               each of the 7 days of the week. Here, elements 0 corresponds to
-               Sunday, element 1 to Monday, and so on. In order to calculate
-               the frequency of system use during any day of the week, use the
-               same method as for calculating the frequency of calls during
-               each hour, as described above. This is only available under
-               systems that produces an EXITINFO.BBS file. Note that at least
-               some, if not all, versions of RemoteAccess do not maintain this
-               variable correctly, and thus even with the presence of an
-               EXITINFO.BBS file, this array may contain all zero entries.
-
-
-
--------------------------------------------------------------------------------
-user_ansi      char od_control.user_ansi;
-
-               This variable contains a Boolean value, indicating whether or
-               not the user has ANSI mode turned on. If ANSI graphics mode is
-               enabled, this variable will contain a value of TRUE, and if ANSI
-               graphics mode is disabled, this variable will contain a value of
-               FALSE. Many of the OpenDoors functions test the setting of this
-               variable in order to determine whether or not they should send
-               ANSI-graphics control characters. Also, if this variable
-               contains a TRUE value, OpenDoors will display an "[ANSI]"
-               indicator on the status line.
-
-               You may change the value of this variable at any time after the
-               first call to od_init() or any other OpenDoors functions.
-               Depending upon what BBS system your door is running under,
-               changes to this variable may or may not result in changes to the
-               user's ANSI setting upon return to the BBS.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 165
-
-               This variable is available under all door information file
-               formats.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned char od_control.user_attribute;
-attribute
-               This variable is a bitmap of eight flags, each of which
-               represent individual pieces of information pertaining to the
-               user that is currently online. These flags are as follows:
-
-                       +-----+------+-----------------------+
-                       | BIT | MASK | DESCRIPTION           |
-                       +-----+------+-----------------------+
-                       |  0  | 0x01 | Is the user deleted   |
-                       |  1  | 0x02 | Is screen clearing on |
-                       |  2  | 0x04 | Is "more" prompt on   |
-                       |  3  | 0x08 | Is ANSI mode on       |
-                       |  4  | 0x10 | User no-kill setting  |
-                       |  5  | 0x20 | Transfer-priority     |
-                       |  6  | 0x40 | Full screen editor    |
-                       |  7  | 0x80 | Quiet mode            |
-                       +-----+------+-----------------------+
-
-               For more information on using and setting bit-mapped flags,
-               please see the entry entitled "BITMAPED FLAGS" in the glossary
-               of this manual.
-
-               Note that this variable is only available under systems that
-               produce and EXITINFO.BBS format door information file.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned char od_control.user_attrib2;
-attrib2
-               See the user_attrib variable for more information. This variable
-               is like the user_attrib variable, except that it contains
-               different information. The bit-mapped flags for the
-               od_control.user_attrib2 variable are as follows:
-
-                       +-----+------+-----------------------+
-                       | BIT | MASK | DESCRIPTION           |
-                       +-----+------+-----------------------+
-                       |  0  | 0x01 | User hot-keys setting |
-                       |  1  | 0x02 | Is AVATAR graphics on |
-                       |  2  | 0x04 | Full screen reader    |
-                       |  3  | 0x08 | Hidden from userlist  |
-                       +-----+------+-----------------------+
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 166
-
-               Note that this variable is only available under systems that
-               produce an EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned char od_control.user_attrib3;
-attrib3
-               This variable contains user attribute flags when a RA 2.50 or
-               later EXITINFO.BBS file is used.
-
-
-
--------------------------------------------------------------------------------
-user_avatar    char od_control.user_avatar;
-
-               This variable is a Boolean value indicating whether or not
-               AVATAR graphics mode is on. If AVATAR graphics is available,
-               then many of the OpenDoors functions will make use of AVATAR
-               graphics codes for greater display speed. If AVATAR graphics
-               mode is on, a [AVT] indicator will appear on the status line. If
-               your door is running under a system which produces an RA 1.00+
-               style extended EXITINFO.BBS door information file, the
-               user_avatar variable is set automatically. If the extended
-               EXITINFO.BBS file is not available, this value will default to
-               FALSE. In this case, you may wish to ask the user whether or not
-               they wish to use AVATAR graphics, and thus set this variable
-               yourself.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_birthday[9];
-_birthday
-               This variable is a string, in the same format as the
-               od_control.user_lastcall variable, which stores the date of the
-               user's birthday, if it is available. This variable is only
-               available under systems that produce an RA 1.00 and later style
-               extended EXITINFO.BBS or Wildcat style DOOR.SYS file.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_callsign[12];
-_callsign
-               This variable is a string which contains the user's amateur
-               radio call sign, if any. This variable is only available under
-               systems that produce a CHAIN.TXT file.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 167
-
--------------------------------------------------------------------------------
-user_combined  unsigned char od_control.user_combinedrecord[25];
-record
-               This variable is an array of bit-mapped flags, with each flag
-               corresponding to an individual message area. In this case, the
-               first bit of od_control.ra_combinedrecord[0] corresponds to the
-               first message area, the second bit to the second message area,
-               and so on. If any given bit-flag is turned on, then the user has
-               corresponding message area enabled for combined access, and if
-               the bit is turned off, the user does not have the area enabled
-               for combined access. A detailed description of the combined
-               message access is beyond the scope of this manual. This variable
-               is only available under systems that produce an RA 1.00 or later
-               style extended EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_comment   char od_control.user_comment[81];
-
-               This variable is a string which contains the sysop's comment
-               about the user that is currently online. This comment may be
-               displayed on the OpenDoors status line, if this variable is
-               available. This variable is available under systems that produce
-               an RA 1.00 and later style extended EXITINFO.BBS or Wildcat
-               style DOOR.SYS file.
-
-
-
--------------------------------------------------------------------------------
-user_credit    unsigned int od_control.user_credit;
-
-               This variable contains the total amount of NetMail credit that
-               the caller has left. Changes to this variable will be by the BBS
-               when your door exits and control is returned to the BBS. This
-               variable is only available under systems that produce an
-               EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_          char od_control.user_dataphone[13];
-dataphone
-               This string contains the user's data or business phone number,
-               if available. This value is only available under system that
-               produce EXITINFO.BBS, PC-Board/GAP style DOOR.SYS and WildCat
-               DOOR.SYS format door information files.
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 168
-
--------------------------------------------------------------------------------
-user           int od_control.user_deducted_time;
-_deducted
-_time          This variable contains a signed integer value, which indicates
-               the total amount of time that has been deducted from the user
-               during this call. This variable is only available under systems
-               that produce an RA 1.00 and later style extended EXITINFO.BBS
-               door information file.
-
-
-
--------------------------------------------------------------------------------
-user_downk     unsigned int od_control.user_downk;
-
-               This variable contains the total kilobytes of files that the
-               current user has downloaded from the BBS, and is available under
-               systems that produce EXITINFO.BBS, Wildcat style DOOR.SYS or
-               SFDOORS.DAT format door information files.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_downlimit;
-_downlimit
-               This variable contains the total number of kilobytes that the
-               caller is permitted to download during this call. If your door
-               allows files do be downloaded, you will probably want to compare
-               the value of this variable to the size of any file to be
-               transferred and the total kilobytes already downloaded, as
-               stored in the od_control.user_todayk variable. This variable is
-               only available under systems that produce an EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_downloads;
-_downloads
-               This variable contains the total number of files that the
-               current user has downloaded from the BBS, and is available under
-               systems that produce EXITINFO.BBS, PC-Board/GAP style DOOR.SYS,
-               WildCat style DOOR.SYS or SFDOORS.DAT format door information
-               files.
-
-
-
--------------------------------------------------------------------------------
-user_echo      char od_control.user_echomailentered;
-mailentered
-               This variable is a Boolean value, indicating whether or not the
-               user has entered new EchoMail during this call. If this variable
-               has a value of TRUE, then EchoMail has been entered, and if it
-               has a value of FALSE, then EchoMail has not been entered. This
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 169
-
-               variable will contain a valid value only after od_init() or some
-               OpenDoors function has been called. Any changes made to this
-               variable will be reflected within the BBS software when control
-               is returned to the BBS. This variable is accessible only under
-               systems which produce an EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_error          char od_control.user_error_free;
-_free
-               This variable contains a Boolean value indicating whether or not
-               the user is connected to the BBS via an error free connection
-               (eg. a V.42/MNP or similar modem protocol). This variable is
-               only available under systems that produce an SFDOORS.DAT,
-               Wildcat style DOOR.SYS or RA 1.00 or later style extended
-               EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_first     char od_control.user_firstcall[9];
-call
-               This variable is a string which contains the date of the user's
-               first call, in the same format as the od_control. user_lastcall
-               variable. This variable is only available under systems which
-               produce an RA 1.00 and later style extended EXITINFO.BBS door
-               information file.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned char od_control.user_flags[4];
-flags
-               The od_control.user_flags variable is an array of four sysop
-               defined bit-mapped flags, which represent some sort of
-               information about the user. od_control.user_flags[0] stores
-               flags A1 - A8 in bits 0 through 7, respectively. Likewise,
-               od_control.user_flags[1] stores flags B1 - B8, and so on. This
-               variable is only available under systems that produce
-               EXITINFO.BBS format door information files.
-
-
-
--------------------------------------------------------------------------------
-user_handle    char od_control.user_handle[36];
-
-               This variable contains the user's alias or handle name, if any.
-               If the user does not have and alias or handle, this variable
-               will be blank. This variable is only available under systems
-               that produce a CHAIN.TXT, RA 1.00 and later extended
-               EXITINFO.BBS or Wildcat style DOOR.SYS door information file.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 170
-
-
-
-
--------------------------------------------------------------------------------
-user_          char od_control.user_homephone[13];
-homephone
-               This string contains the user's home or data phone number, if
-               available. This value is only available under system that
-               produce one of the following door information files:
-               EXITINFO.BBS, PC-Board/GAP style DOOR.SYS, WildCat style
-               DOOR.SYS or SFDOORS.DAT.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned char od_control.user_last_pwdchange;
-_last
-_pwdchange     This variable contains the number of calls that the user has
-               made since they last changed their password. This variable is
-               only available under EXITINFO.BBS files.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_lastdate[9];
-_lastdate
-               This variable is a string containing the date of the user's last
-               call to the BBS, and should always be of the format:
-
-                                  "MM-DD-YY"
-
-               Where MM is two digits representing the number of the month of
-               the user's call, with 1 being January, 2 being February, and so
-               on. DD should be two digits representing the day of the month of
-               the user's last call, beginning with 1, and MM should be the
-               last two digits of the year of the user's last call.
-
-               This variable is only available under systems that produce one
-               of the following door information files: CHAIN.TXT,
-               EXITINFO.BBS, PC-Board/GAP style DOOR.SYS or WildCat style
-               DOOR.SYS files.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned int od_control.user_lastread;
-lastread
-               This variable contains the number of the highest message number
-               that the user has read, and is only available under EXITINFO.BBS
-               format door information files.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 171
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_lasttime[6];
-_lasttime
-               This variable contains a string representing the time of the
-               user's last call to the BBS, and should always be of the format:
-
-                                  "HH:MM"
-
-               Where HH is two digits representing the 24-hour format hour of
-               the user's last call, and MM is two digits representing the
-               minute of the user's last call. Thus, the following strings
-               would be valid entries for this string:
-
-                    "00:01"    (12:01 am)
-                    "03:47"    (3:47 am)
-                    "18:20"    (6:20 pm)
-
-               This variable is only available under systems that produce an
-               EXITINFO.BBS or Wildcat style DOOR.SYS format door information
-               file.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_location[26];
-_location
-               This string contains the name of the location from which the
-               current user is calling from. This will usually be the name of
-               the city, region (province, state, etc.) and sometimes country
-               where the user lives. The contents of this variable are
-               displayed on the OpenDoors status line. The value of this
-               variable is valid after od_init() or any other OpenDoors
-               function has been called. Also, you may change the value of this
-               variable if you wish. However, not that these changes may not
-               immediately be reflected in the status line, and may or may not
-               cause the setting to be changed after the user returns to the
-               BBS. This variable is available under systems that produce one
-               of the following door information files: DORINFO?.DEF,
-               EXITINFO.BBS, PC-Board/GAP style DOOR.SYS, WildCat style
-               DOOR.SYS SFDOORS.DAT and CALLINFO.BBS, but is not available
-               under CHAIN.TXT or DoorWay style DOOR.SYS files.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.caller_logindate[9];
-_logindate
-               This variable contains a string representing the date on which
-               the current call to the BBS began. This variable is in the same
-               format as the od_control.user_lastdate variable, described
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 172
-
-               below. This variable is only available under systems which
-               produce an EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-user           long od_control.user_loginsec;
-_loginsec
-               This variable contains the user's security at login, and can be
-               used to detect changes by the sysop or other programs during the
-               course of the call, by comparing it's value with the
-               od_control.user_security variable. This variable is only
-               available under systems which produce an EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_logintime[6];
-_logintime
-               This variable contains a string representing the time of day at
-               which the current call to the BBS began. This variable is in the
-               same format as the od_control.user_lasttime variable, which is
-               also described below. This variable is available under systems
-               which produce an EXITINFO.BBS, a Wildcat style DOOR.SYS, or an
-               SFDOORS.DAT file.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_logonpassword[16];
-_logon
-password       This variable is a string which contains the user's password
-               at the time at which the current call to the BBS began. This
-               variable can be used to detect changes by the sysop or other
-               programs to the user's password, which have taken place during
-               the course of the call. In order to detect such changes, simply
-               compare the contents of this string with the contents of the
-               od_control.user_password variable. This variable is only
-               available under systems which produce an EXITINFO.BBS format
-               door information file.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_menustack[50][9];
-_menustack
-               This variable is an array of 50 strings, containing the stack of
-               BBS menus that have been executed, and is used to record the
-               current position of the user within the BBS's menu system. Each
-               string contains just the base portion of the filename of the
-               menu, without the extension. The od_control.ra_menustackpointer
-               variable points to the top of the menu stack. However, a
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 173
-
-               complete discussion of the menu stack is beyond the scope of
-               this manual. This variable is only available under systems that
-               produce an RA 1.00 and later style extended EXITINFO.BBS door
-               information file.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned char od_control.user_menustackpointer;
-_menustack
-pointer        This variable points to the top of the current menu stack. For
-               more information on the menu stack, please refer to the
-               od_control.ra_menustack variable, above. This variable is only
-               available under systems that produce an RA 1.00 and later style
-               extended EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_messages;
-_messages
-               This variable contains a value representing the total number of
-               messages that have been written by the user, and is available
-               under EXITINFO.BBS or Wildcat style DOOR.SYS format door
-               information files.
-
-
-
--------------------------------------------------------------------------------
-user_name      char od_control.user_name[36];
-
-               This string contains the name of the user that is currently on-
-               line, and is used by OpenDoors to display the current user name
-               on the status line, and will most likely be used by your door
-               for differentiating among different users. In most cases, you
-               should probably not change the value of this variable, as a
-               user's name does not usually change, and doing so could results
-               in problems when returning to some BBS systems. For an example
-               of using this variable, see the EX_VOTE.C example program. This
-               variable is available under all BBS systems.
-
-
-
--------------------------------------------------------------------------------
-user_net_      unsigned int od_control.user_net_credit;
-credit
-               This variable contains the amount of NetMail credit that the
-               current user has to his or her name. This variable is only
-               available under systems that produce an EXITINFO.BBS file.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 174
-
-               Note that if you wish to change the value of the user's
-               remaining NetMail credit, you should use the od_control.
-               user_credit variable, instead of this variable.
-
-
-
--------------------------------------------------------------------------------
-user_net       char od_control.user_netmailentered;
-mailentered
-               This variable is a Boolean value, indicating whether or not the
-               user has entered new NetMail or GroupMail during this call. If
-               this variable has a value of TRUE, then NetMail/GroupMail has
-               been entered, and if it has a value of FALSE, then
-               NetMail/GroupMail has not been entered. This variable will
-               contain a valid value only after od_init() or some OpenDoors
-               function has been called. Any changes made to this variable will
-               be reflected within the BBS software when control is returned to
-               the BBS. This variable is accessible only under systems which
-               produce an EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_num       unsigned int od_control.user_num;
-
-               This variable contains the number of the user's record in the
-               user database file, where 0 is the first record. This can be
-               useful for changing user settings that are not re-read by the
-               BBS, such as the user's phone number or security level which
-               might be altered by a call back verification door. However, the
-               value of this variable itself should not be altered.
-
-               This variable is available under systems which produce any of
-               the following door information file formats: CHAIN.TXT, PC-
-               Board/GAP style DOOR.SYS, Wildcat style DOOR.SYS SFDOORS.DAT and
-               EXITINFO.BBS.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned int od_control.user_numcalls;
-numcalls
-               This variable contains the total number of calls that the
-               current user has placed to the BBS, and is available under
-               systems that produce EXITINFO.BBS or PC-Board/GAP and Wildcat
-               style DOOR.SYS door information files.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 175
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_numpages;
-_numpages
-               The value of this variable contains the total number of times
-               that the user has paged the sysop, and can be used to limit the
-               number of times that the user is permitted to page the sysop.
-               OpenDoors increments this variable every time that the user
-               pages the sysop, via the od_page() function. This variable is
-               used with all types of door information files. However, this
-               variable will only reflect the value within the BBS if an
-               EXITINFO.BBS file is produced. Otherwise, the variable will only
-               contain the number of times that the user has paged within the
-               door, but not the total number of times the user has paged.
-               Under EXITINFO.BBS systems, changes to the value of this
-               variable will be reflected within the BBS upon return by the
-               DOOR.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_password[16];
-_password
-               This variable contains the user's password for accessing the
-               BBS. OpenDoors does not use this value itself. This variable
-               will contain a valid value only after od_init() or some
-               OpenDoors function has been called. You may change the value of
-               this variable. Note, however, that changes in this variable may
-               or may not cause the setting to be changed when control returns
-               to the BBS - this will depend upon the particular BBS system
-               your door is running under. This variable is only available
-               under systems that produce one of the following door information
-               files: EXITINFO.BBS, PC-Board/GAP and Wildcat style DOOR.SYS,
-               SFDOORS.DAT, and CALLINFO.BBS.
-
-
-
--------------------------------------------------------------------------------
-user_pending   unsigned int od_control.user_pending;
-
-               This variable represents the total value of NetMail that has
-               been written by the current user, but not yet exported from the
-               message base. This variable is only available under systems that
-               produce an EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user_reason    char od_control.user_reasonforchat[78];
-forchat
-               This variable is a string, containing the reason for which the
-               user wishes to chat with the sysop, as they entered at the time
-               of paging the sysop. This variable will contain an empty string
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 176
-
-               if the user has not paged the sysop, or if the reason the user
-               wishes to chat is unknown. See also the od_control.user_wantchat
-               variable. This variable is available under all BBS systems,
-               regardless of what style of door information file they produce.
-               However, this variable will not be passed between the door and
-               BBS, and thus the user's reason for chat within the door will
-               not necessarily correspond to their reason for chat outside the
-               door.
-
-
-
--------------------------------------------------------------------------------
-user_rip       char user_rip;
-
-               This variable is set to TRUE if the user has RIP (Remote Imaging
-               Protocol) graphics enabled, and FALSE if they do not. This
-               setting can be determined from the door information (drop) file
-               in many cases. In other cases, you can automatically determine
-               whether or not the user's system supports RIP graphics using the
-               od_autodetect() function (see page 48).
-
-
-
--------------------------------------------------------------------------------
-user_rip_ver   BYTE user_rip_ver;
-
-               This variable contains the version of the RIP protocol that is
-               in use. This variable is only available under a RemoteAccess
-               2.50 EXITINFO.BBS file.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_screen_length;
-_screen
-_length        This value of this variable represents the total number of
-               lines that can be displayed on the user's screen at once, and is
-               usually either 24 or 25. You may wish to make use of this
-               variable to allow your door to pause the display of long pieces
-               of text after every screen length, in order to allow the user to
-               read this information before it passes off of their screen. In
-               this case, you would simply maintain a counter of the total
-               number of lines displayed, and when this value reaches one less
-               than the length of the user screen, display a prompt asking the
-               user to whether or not they wish to continue.
-
-               This variable is set to the user's setting within the BBS under
-               systems that produce any of the following door information file
-               formats: CHAIN.TXT, EXITINFO.BBS, PC-Board/GAP and Wildcat style
-               DOOR.SYS and CALLINFO.BBS files.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 177
-
-               This variable is used by the OpenDoors function,
-               od_list_files(). If this variable contains a valid value,
-               OpenDoors will pause the listing of files after every screen,
-               and give the user the option of continuing, aborting, or
-               disabling the "Continue?" prompt for the rest of the file
-               listing. Thus, if you are using the od_list_files() under a
-               system that does not produce one of the door information files
-               listed above, you may wish to obtain the user's screen length
-               from the user themselves. If the screen length is not available
-               from the particular type of door information file that is found,
-               and you do not set this value yourself, this variable will
-               default to 23. If you are going to set the value of this
-               variable yourself, you should do so after having called
-               od_init() or some OpenDoors function.
-
-
-
--------------------------------------------------------------------------------
-user_          unsigned char od_control.user_screenwidth;
-screenwidth
-               This variable contains a value representing the width of the
-               user's screen, and will most often be equal to 80. This variable
-               is only available under systems that produce a CHAIN.TXT or RA
-               1.00 and later style extended EXITINFO.BBS door information
-               file.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_security;
-_security
-               This variable contains a numerical value representing the user's
-               security access level on the BBS. You may wish to use this value
-               to determine whether or not the current user of your door should
-               have access to certain sysop-only functions. In this case, you
-               may wish to have a configuration file used by your door, in
-               which the sysop may define the minimum security level for sysop
-               access. You would then be able to compare this configuration
-               setting to the security level stored in this variable, in order
-               to determine whether or not sysop function should be available.
-               An alternative method, used by the EX_VOTE.C sample door, of
-               determining whether or not the current user is the sysop is to
-               compare the user's name with the value of the
-               od_control.sysop_name variable. This method has the advantage of
-               not requiring a configuration program, but the disadvantage that
-               the door will not function correctly under all BBS systems, as
-               the od_control.sysop_name variable is not available under all
-               BBS systems.
-
-               The od_control.user_security variable is available under BBS
-               systems that produce any of the following door information file
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 178
-
-               formats: CHAIN.TXT, EXITINFO.BBS, PC-Board/GAP and Wildcat style
-               DOOR.SYS, SFDOORS.DAT or CALLINFO.BBS.
-
-
-
--------------------------------------------------------------------------------
-user_sex       char od_control.user_sex;
-
-               This variable contains a single character representing the
-               gender of the user that is currently online. This variable will
-               contain an upper-case 'F' if the user is female, and an upper-
-               case 'M' if the user is male. This variable is available under
-               systems that produce a CHAIN.TXT or RA 2.x style EXITINFO.BBS
-               file.
-
-
-
--------------------------------------------------------------------------------
-user_subdate   char od_control.user_subdate[9];
-
-               This variable is a string, in the same format as the
-               od_control.user_lastdate variable, which stores the date of
-               expiry of the user's subscription to the BBS. This variable is
-               only available under systems which produce a PC-Board/GAP and
-               Wildcat style DOOR.SYS or RA 1.00 and later style extended
-               EXITINFO.BBS door information file.
-
-
-
--------------------------------------------------------------------------------
-user           int od_control.user_timelimit;
-_timelimit
-               This variable contains the amount of time, in minutes, that the
-               user has left in the door. Note that this value may or may not
-               be equal to the total amount of time that the user has left on
-               the BBS, depending upon whether the BBS or a third-party door
-               manager program only allows a limited amount of time in this
-               door. This variable contains a valid value after od_init() or
-               some OpenDoors function has been called. OpenDoors uses this
-               variable to keep track of how much time the user has left in the
-               door, and will automatically warn the user when nearly all of
-               his or her time has been used up. OpenDoors will also force the
-               user out of the door when their time in the door has expired.
-               OpenDoors automatically subtracts one minute from this variable
-               every minute that OpenDoors is active, unless chat mode has been
-               activated (in which case the user's time will freeze), and also
-               adjusts the value of this variable when the sysop uses the time
-               adjustment function keys. Hence, you will not normally have any
-               need to alter the value of this variable yourself. However,
-               there may be some cases in which you wish to subtract a penalty
-               or add a bonus to the user's time, such as in a "timebank" door
-               or a door game that permits the user to "gamble time".
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 179
-
-
-               Depending on which BBS system your door is running under, the
-               value of this variable may or may not effect the user's time
-               left upon return to the BBS. The BBS system will either reset
-               the user's time to the value re-written to the door information
-               file (this variable), or will always subtract the amount of time
-               spent in the door from the user's remaining time.
-
-               This variable is available under all door information file
-               formats.
-
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_todayk;
-_todayk
-               This variable contains the total kilobytes of files that the
-               current user has downloaded from the BBS during the current day,
-               and is available under systems that produce EXITINFO.BBS, PC-
-               Board/GAP and Wildcat style DOOR.SYS, or SFDOORS.DAT format door
-               information files.
-
-
-
--------------------------------------------------------------------------------
-user_upk       unsigned int od_control.user_upk;
-
-               This variable contains the total kilobytes of files that the
-               current user has uploaded to the BBS, and is available under
-               systems that produce EXITINFO.BBS, Wildcat style DOOR.SYS or
-               SFDOORS.DAT files.
-
-
-
--------------------------------------------------------------------------------
-user_uploads   unsigned int od_control.user_uploads;
-
-               This variable contains the total number of files that the
-               current user has uploaded to the BBS, and is available under
-               systems that produce EXITINFO.BBS, PC-Board/GAP and Wildcat
-               style DOOR.SYS, or SFDOORS.DAT format door information files.
-
-
-
--------------------------------------------------------------------------------
-user           char od_control.user_wantchat;
-_wantchat
-               This variable is a Boolean value which indicates whether or not
-               the user wishes to chat with the sysop (ie, the user has paged
-               the sysop, but has yet to receive a chat with the sysop). This
-               variable is used under all door information file formats.
-               However, changes to this variable are only reflected on the BBS
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 180
-
-               when the door is running under a system that produces an
-               EXITINFO.BBS door information file.
-
-               This variable is automatically turned on (ie., set to TRUE),
-               when the user begins to page the sysop for chat, within the
-               od_page() function, and is automatically turned off (ie., set to
-               FALSE), when the sysop breaks in for chat via the chat function
-               key. Also, setting this variable to TRUE will turn on the
-               flashing want-chat indicator on the OpenDoors status line.
-
-
--------------------------------------------------------------------------------
-user           unsigned int od_control.user_xi_record;
-_xi_record
-               This variable contains the number of the user's record in the
-               USERXI.BBS file, if any. This variable is only available under
-               system that produce a Remote Access 1.00 and later style
-               extended door information file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 181
-
-CONTROL STRUCTURE - DOOR SETTINGS
--------------------------------------------------------------------------------
-
-               This section deals with those variables in the OpenDoors control
-               structure which reflect the current door settings. These
-               variables are as follows:
-
-               od_cur_attrib            The current display attribute, or -1 if
-                                        unknown.
-
-               od_okaytopage            Controls whether the user is currently
-                                        permitted to page the sysop.
-
-               od_pageendmin            End of valid paging hours.
-
-               od_pagestartmin          Start of valid paging hours.
-
-               od_silent_mode           Turns off local user interface.
-
-               od_user_keyboard_on      Controls whether OpenDoors will
-                                        currently accept input from the remote
-                                        user's keyboard.
-
-               od_update_status_now     Forces immediate update of the status
-                                        line.
-
-               sysop_next               Indicates whether or not the sysop has
-                                        reserved use of the system after the
-                                        current calls.
-
-
-
--------------------------------------------------------------------------------
-od_cur         int od_control.od_cur_attrib;
-_attrib
-               This read-only values stores the current display color
-               attribute, or the value -1 if the current display color is
-               unknown (such as when the door first begins execution).
-
-
-
--------------------------------------------------------------------------------
-od             char od_control.od_okaytopage;
-_okaytopage
-               This variable allows you to control whether or not the user is
-               currently permitted to page the sysop via the od_page()
-               function. A value of PAGE_ENABLE indicates that paging is
-               currently permitted, regardless of the sysop page hours setting.
-               A value of PAGE_DISABLE indicates that paging is not current
-               permitted. A value of PAGE_USE_HOURS indicates that the
-               od_page() function should check the values of the
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 182
-
-               od_pagestartmin and od_pageendmin variables in order to
-               determine whether or not paging should be permitted.
-               The od_okaytopage variable should only be set after you call
-               od_init() or some other OpenDoors function. The default value is
-               PAGE_USE_HOURS. For more information on the od_page() function
-               itself, see page 101.
-
-
-
--------------------------------------------------------------------------------
-od             unsigned int od_control.od_pageendmin;
-_pageendmin
-               This variable can be used to set the beginning of valid sysop
-               paging hours within the od_page() function. If the
-               od_control.od_okaytopage variable (which is described above) is
-               set to MAYBE, then OpenDoors will check the value of this
-               variable prior to paging the sysop via the od_page() function.
-               This variable should contain the time at which the valid sysop
-               paging hours end, represented as the a number of minutes since
-               midnight. For more information on the od_page() function itself,
-               see page 101.
-
-
-
--------------------------------------------------------------------------------
-od             unsigned int od_control.od_pagestartmin;
-_pagestartmin
-               This variable can be used to set the beginning of valid sysop
-               paging hours within the od_page() function. If the
-               od_control.od_okaytopage variable (which is described above) is
-               set to MAYBE, then OpenDoors will check the value of this
-               variable prior to paging the sysop via the od_page() function.
-               This variable should contain the time at which the valid sysop
-               paging hours begin, represented as the a number of minutes since
-               midnight. For more information on the od_page() function itself,
-               see page 101.
-
-
-
--------------------------------------------------------------------------------
-od_silent      BOOL od_control.od_silent_mode;
-_mode
-               If this variable is set to TRUE prior to the first call to any
-               OpenDoors function, OpenDoors will operate in silent mode, where
-               the local display and sysop commands are not used. Silent mode
-               is automatically disabled if the program is running in local
-               mode.
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 183
-
--------------------------------------------------------------------------------
-od_update      char od_control.od_update_status_now;
-_status_now
-               Setting this variable to TRUE forces OpenDoors to update the
-               status line during the next od_kernel() execution. When the
-               status line is updated, this variable is reset to its default
-               value of FALSE.
-
-
-
--------------------------------------------------------------------------------
-od_user        char od_control.od_user_keyboard_on;
-_keyboard_on
-               This variable is a Boolean value, indicating whether OpenDoors
-               will currently accept input from a remote user. OpenDoors
-               provides a function key (usually [ALT]-[K], unless you have
-               changed the default), which will allow the sysop to temporarily
-               prevent the user from having any control over the door. When the
-               sysop activates this feature, a flashing [Keyboard-Off]
-               indicator will appear on the status line, and this variable will
-               be set to FALSE. When the sysop presses the [ALT]-[K]
-               combination a second time, to toggle the user's keyboard back
-               on, the flashing indicator will disappear, and this variable
-               will be set back to TRUE.
-
-
-
--------------------------------------------------------------------------------
-sysop_next     char od_control.sysop_next;
-
-               This variable is a Boolean value, indicating whether or not the
-               "sysop next" feature has been activated. The "sysop next"
-               feature, which reserves the system for the sysop after the call
-               has ended, can be toggled on and off within OpenDoors by use of
-               a function key (Alt-N by default). Also, when the "sysop next"
-               feature has been activated, an indicator will appear on the
-               OpenDoors status line. This variable is only available under
-               systems that produce an SFDOORS.DAT or RA 1.00 and later style
-               extended EXITINFO.BBS door information file. For more
-               information on testing the type of door information file
-               available, please see page 158.
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 184
-
-CONTROL STRUCTURE - DIAGNOSTICS
--------------------------------------------------------------------------------
-
-               To help in diagnosing problems in your OpenDoors programs,
-               OpenDoors stores information on the most recent error which
-               occurred. When any of the OpenDoors functions return an "error"
-               or "failure" state, the reason for this failure is recorded.
-
-               The following OpenDoors control structure variable provides
-               diagnostics information:
-
-               od_error                 Stores a "reason code" for the last
-                                        failed OpenDoors API function call.
-
-
-
-
--------------------------------------------------------------------------------
-od_error       int od_control.od_error;
-
-               When any of the OpenDoors API functions return an "error" or
-               "failure" state (usually denoted by either of the values FALSE
-               or NULL), the reason for the failure is recorded in this
-               variable. Since successful function calls do not alter the value
-               of the od_control.od_error variable, you must be careful not
-               only to check the value of the od_control.od_error variable, but
-               also to check the OpenDoors function return codes, in order to
-               determine which function failed.
-
-               This variable will always store the reason for the most recent
-               function call failure, or ERR_NONE if no functions have failed.
-               od_error may take on any of the following values:
-
-                    ERR_NONE            Indicates that no error has occurred
-                                        yet.
-
-                    ERR_MEMORY          Function was unable to allocate
-                                        required memory. This usually indicates
-                                        that there is not enough available
-                                        memory. This failure may also be due to
-                                        memory corruption caused by your
-                                        program inadvertently overwriting heap
-                                        structures. If your program has been
-                                        compiled in either the small or the
-                                        medium memory model, try recompiling it
-                                        in the compact, large, or huge memory
-                                        models. If your program is already
-                                        compiled in the compact, large, or huge
-                                        memory models, try making more system
-                                        memory available to your program.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 185
-
-                    ERR_NOGRAPHICS      This setting indicates that the
-                                        function called requires ANSI, AVATAR
-                                        or RIP graphics mode, but none of these
-                                        modes are active.
-
-                    ERR_PARAMETER       An invalid parameter was passed to an
-                                        OpenDoors functions. Check the
-                                        function's description in chapter four,
-                                        to determine the required values for
-                                        each function parameter.
-
-                    ERR_FILEOPEN        OpenDoors was unable to open a file.
-                                        This can be due to the specified
-                                        filename not existing, due to the file
-                                        being locked for exclusive access by
-                                        another process, or due to a hardware
-                                        failure.
-
-                    ERR_FILEREAD        OpenDoors was able to open the
-                                        specified file, but unable to read the
-                                        required data from the file. This error
-                                        may be due to an invalid file format,
-                                        due to a portion of the file being
-                                        locked by another process, or due to a
-                                        hardware failure.
-
-                    ERR_LIMIT           An internal function limit has been
-                                        exceeded. Refer to the function's
-                                        description in chapter four for
-                                        information on the function's
-                                        limitations.
-
-                    ERR_NOREMOTE        Indicates that a function has been
-                                        called which is not valid in local
-                                        mode, such as od_carrier() or
-                                        od_set_dtr().
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 186
-
-CONTROL STRUCTURE - OPENDOORS CUSTOMIZATION
--------------------------------------------------------------------------------
-
-               The OpenDoors control structure provides many variables which
-               allow you to customize OpenDoor's behavior and appearance. These
-               customization variables fit into one of the following
-               categories:
-
-                         General Behavior Customization Variables
-                         Sysop Function Keys Customization Variables
-                         Color Customization Variables
-                         Language-Specific Prompts Customization Variables
-
-               This section deals with those variables that fit into the first
-               category, "General Behavior Customization Variables". The other
-               categories are dealt with in the following sections of this
-               chapter.
-
-               Below is a brief overview of the variables grouped into this
-               section of the OpenDoors control structure. Following the
-               overview is a detailed description of each of these variables.
-
-
-               od_app_icon              Program icon for Win32 version.
-
-               od_box_chars             Array of characters used by the
-                                        od_draw_box() function.
-
-               od_before_exit           Function to call prior to exiting.
-
-               od_cafter_chat           Function to call after sysop chat.
-
-               od_cafter_shell          Function to call after DOS shell.
-
-               od_cbefore_chat          Function to call prior to sysop chat.
-
-               od_cbefore_shell         Function to call prior to DOS shell.
-
-               od_cfg_lines             Sets the configuration file's custom
-                                        door information file line keywords.
-
-               od_cfg_text              Sets the built-in configuration file
-                                        keywords that OpenDoors will recognize.
-
-               od_chat_active           Controls whether or not sysop chat mode
-                                        is active.
-
-               od_clear_on_exit         Controls whether the screen is cleared
-                                        upon door exit.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 187
-
-               od_color_delimiter       Indicates what character should delimit
-                                        imbedded color codes for the
-                                        od_printf() function.
-
-               od_color_names           Strings which OpenDoors recognizes as
-                                        the names of various text colors.
-
-               od_config_file           Used to enable or disable the OpenDoors
-                                        configuration file system.
-
-               od_config_filename       Sets the filename that will be read by
-                                        the configuration file system.
-
-               od_config_function       The callback function that OpenDoors
-                                        will call to allow your program to
-                                        process custom configuration file
-                                        entries.
-
-               od_default_personality   Sets the default personality to be used
-                                        with the OpenDoors Multiple Personality
-                                        System, and also sets the personality
-                                        to use when the MPS is not active.
-
-               od_default_rip_win       Whether OpenDoors should use the
-                                        default 43-line RIP window for ANSI
-                                        text (TRUE), or a 23-line window
-                                        (FALSE).
-
-               od_disable               Disable OpenDoors activities such as
-                                        reading door information file and
-                                        monitoring carrier detect / remaining
-                                        time.
-
-               od_disable_dtr           Specifies the string that will be sent
-                                        to the modem to prevent the modem from
-                                        hanging up when DTR is lowered.
-
-               od_emu_simluate_modem    Simulates modem display speed for
-                                        emulation functions such as
-                                        od_send_file(), od_disp_emu() and
-                                        od_hotkey_menu().
-
-               od_errorlevel            Sets the errorlevel OpenDoors exits
-                                        with under various conditions.
-
-               od_force_local           Forces door to operate in local mode,
-                                        ignoring any door information file and
-                                        using default user settings.
-
-               od_help_callback         Allows you to provide a help menu item
-                                        under the Win32 version of OpenDoors
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 188
-
-               od_in_buf_size           Sets size of OpenDoor's internal
-                                        local/remote inbound buffer.
-
-               od_inactive_warning      Number of seconds before hanging up
-                                        that OpenDoors displays the inactivity
-                                        timeout warning.
-
-               od_inactivity            Controls user inactivity timeout.
-
-               od_ker_exec              Is called whenever od_kernel()
-                                        executes.
-
-               od_last_input            Indicates whether the last input came
-                                        from the remote user (==0) or the local
-                                        sysop (==1).
-
-               od_list_pause            Controls whether or not the user may
-                                        pause display within the
-                                        od_list_files() and od_send_file()
-                                        functions by using the [P] key.
-
-               od_list_stop             Controls whether or not the user may
-                                        terminate display within the
-                                        od_list_files() and od_send_file()
-                                        functions using [S], [CTRL]-[K], etc.
-
-               od_logfile               Enables or disables the OpenDoors log
-                                        file system.
-
-               od_logfile_disable       Prevents the logfile from being opened,
-                                        even if the logfile is enabled by
-                                        od_logfile.
-
-               od_logfile_messages      Array of message strings that OpenDoors
-                                        will use when writing log file entries.
-
-               od_logfile_name          Contains the filename and possibly path
-                                        of the logfile.
-
-               od_maxtime               Indicates the maximum length of time
-                                        any user is permitted to use the door.
-
-               od_maxtime_deduction     Indicates the amount of time that has
-                                        temporarily been taken away from the
-                                        user's remaining time, as a result of
-                                        the maximum door time setting.
-
-               od_mps                   Enables or disables the OpenDoors
-                                        Multiple Personality System.
-
-               od_no_file_func          Called when no door information file
-                                        can be read.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 189
-
-
-               od_no_ra_codes           Disables translation of RA/QBBS control
-                                        codes.
-
-               od_nocopyright           Prevents OpenDoors from displaying it's
-                                        name and version number when a door
-                                        program begins execution.
-
-               od_noexit                Prevents OpenDoors from exiting when
-                                        the od_exit() function is called.
-
-               od_page_len              Controls length of the sysop page beep.
-
-               od_page_pausing          Enables or disables page pausing in
-                                        od_send_file(), od_hotkey_menu() and
-                                        od_list_files() functions.
-
-               od_page_startmin         Indicates the time of day at which
-                                        sysop paging is first enabled.
-
-               od_page_statusline       Which status line (if any) is activated
-                                        when the user pages the sysop.
-
-               od_page_endmin           Indicates the time of day at which
-                                        sysop paging is disabled.
-
-               od_prog_name             Stores the name of your program.
-
-               od_prog_version          Stores the version number of your
-                                        program.
-
-               od_prog_copyright        Place your copyright information here.
-
-               od_reg_key               Stores the registration key that you
-                                        receive when purchasing OpenDoors.
-
-               od_reg_name              Stores your name or your companies name
-                                        when you have purchased an OpenDoors
-                                        license (registration).
-
-               od_spawn_freeze_time     Indicates whether the user's time
-                                        remaining continues to be decreased
-                                        during the execution of the
-                                        od_spawn...() functions (FALSE), or if
-                                        the timer should be "frozen" (TRUE).
-
-               od_swapping_disable      Disables swapping during DOS shell and
-                                        od_spawn...() functions.
-
-               od_swapping_noems        Prevents swapping form being done to
-                                        EMS expanded memory.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 190
-
-               od_swapping_path         Location where disk swap file should be
-                                        created.
-
-               od_status_on             Controls whether the status line sub-
-                                        system is active.
-
-               od_time_msg_func         Called instead of displaying time limit
-                                        warning messages.
-
-
-
-
--------------------------------------------------------------------------------
-od_app         HICON od_control.od_app_icon;
-_icon
-               Normally, the Win32 version of OpenDoors displays its own icon
-               on the application title bar, on the Windows taskbar, and in the
-               help|about dialog box. You can supply your own icon by setting
-               this variable to point to the handle of the icon, as returned by
-               LoadIcon();
-
-
-
--------------------------------------------------------------------------------
-od_box         char od_control.od_box_chars[8];
-_chars
-               This variable allows you to specify which character the
-               od_draw_box() function uses in drawing the boarder of a window.
-               The elements of this array are as follows:
-
-               od_box_chars[BOX_UPPERLEFT]  - Upper left corner of box
-               od_box_chars[BOX_TOP]        - Top horizontal line
-               od_box_chars[BOX_UPPERRIGHT] - Upper right corner of box
-               od_box_chars[BOX_LEFT]       - Left Vertical line
-               od_box_chars[BOX_LOWERLEFT]  - Lower left corner of box
-               od_box_chars[BOX_LOWERRIGHT] - Lower right corner of box
-               od_box_chars[BOX_BOTTOM]     - Bottom horizontal line
-               od_box_chars[BOX_RIGHT]      - Right horizontal line
-
-
-
--------------------------------------------------------------------------------
-od_before      void (*od_control.od_before_exit)();
-_exit
-               This variable contains a pointer to a function which OpenDoors
-               should call prior to exiting, or NULL if you do not wish to have
-               any function called at exit time. For an example of the use of
-               this variable, see the description of the EX_VOTE.C example
-               program, which begins on page 38.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 191
-
--------------------------------------------------------------------------------
-od_cafter      void (*od_control.od_cafter_chat)();
-_chat
-               The function pointed to by this variable will be called after
-               sysop chat mode has ended. This may be useful for allowing you
-               to save the user's screen contents prior to chat, and restoring
-               the afterwards. If this variable contains its default value of
-               NULL, no function will be called. To alter the string of text
-               which is displayed after sysop chat, see the
-               od_control.od_after_chat variable, which is described in the
-               section on the prompts customization portion of the control
-               structure.
-
-
-
--------------------------------------------------------------------------------
-od_cafter      void (*od_control.od_cafter_shell)();
-_shell
-               The function pointed to by this variable will be called after
-               the sysop has returned from a DOS shell. If this variable
-               contains its default value of NULL, no function will be called.
-               To alter the string of text which is displayed after a DOS
-               shell, see the od_control.od_after_shell variable, which is
-               described in the section on the prompts customization portion of
-               the control structure.
-
-
-
--------------------------------------------------------------------------------
-od_cbefore     void (*od_control.od_cbefore_chat)();
-_chat
-               The function pointed to by this variable will be called prior to
-               entering sysop chat mode. This may be useful for allowing you to
-               save the user's screen contents prior to chat, and restoring the
-               afterwards. If this variable contains its default value of NULL,
-               no function will be called. To alter the string of text which is
-               displayed prior to sysop chat, see the od_control.od_before_chat
-               variable, which is described in the section on the prompts
-               customization portion of the control structure. To replace the
-               OpenDoors sysop chat facility with your own, simply activate
-               your chat mode when this function is called. Your chat mode
-               facility should remain active until OpenDoors sets the
-               od_control.od_chat_active variable to FALSE. If you wish to
-               terminate chat mode prior to this variable being set to FALSE,
-               you should set this variable to FALSE yourself if you do not
-               wish OpenDoors to activate its own chat mode.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 192
-
--------------------------------------------------------------------------------
-od_cbefore     void (*od_control.od_cbefore_shell)();
-_shell
-               The function pointed to by this variable will be called prior to
-               executing a sysop DOS shell. If this variable contains its
-               default value of NULL, no function will be called. To alter the
-               string of text which is displayed before a DOS shell, see the
-               od_control.od_before_shell variable, which is described in the
-               section on the prompts customization portion of the control
-               structure.
-
-
-
--------------------------------------------------------------------------------
-od_cfg_lines   char od_control.cfg_lines[25][33];
-
-               This array contains the strings for the keywords that represent
-               various lines in the definition of a custom door information
-               file. Each keyword must be 32 character or less in length. These
-               keywords are not case sensitive. See page 230 for more
-               information on defining custom door information (drop) file
-               formats. The default values for this array are as follows:
-
-                    [0]  "Ignore"
-                    [1]  "ComPort"
-                    [2]  "FossilPort"
-                    [3]  "ModemBPS"
-                    [4]  "LocalMode"
-                    [5]  "UserName"
-                    [6]  "UserFirstName"
-                    [7]  "UserLastName"
-                    [8]  "Alias"
-                    [9]  "HoursLeft"
-                    [10] "MinutesLeft"
-                    [11] "SecondsLeft"
-                    [12] "ANSI"
-                    [13] "AVATAR"
-                    [14] "PagePausing"
-                    [15] "ScreenLength"
-                    [16] "ScreenClearing"
-                    [17] "Security"
-                    [18] "City"
-                    [19] "Node"
-                    [20] "SysopName"
-                    [21] "SysopFirstName"
-                    [22] "SysopLastName"
-                    [23] "SystemName"
-                    [24] "RIP"
-
-               If you wish to change any of these variable, you must do so
-               before calling any OpenDoors functions.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 193
-
-
-
--------------------------------------------------------------------------------
-od_cfg_text    char od_control.od_cfg_text[47][33];
-
-               This array of strings contains the built-in configuration file
-               keywords that are recognized by OpenDoors. These keywords may be
-               up to 32 characters in size, and are not case sensitive. If you
-               wish to change any of these settings, you must do so before
-               calling any OpenDoors functions. The default values for this
-               array are as follows:
-
-                    [0]  "Node"
-                    [1]  "BBSDir"
-                    [2]  "DoorDir"
-                    [3]  "LogFileName"
-                    [4]  "DisableLogging"
-                    [5]  "SundayPagingHours"
-                    [6]  "MondayPagingHours"
-                    [7]  "TuesdayPagingHours"
-                    [8]  "WednesdayPagingHours"
-                    [9]  "ThursdayPagingHours"
-                    [10] "FridayPagingHours"
-                    [11] "SaturdayPagingHours"
-                    [12] "MaximumDoorTime"
-                    [13] "SysopName"
-                    [14] "SystemName"
-                    [15] "SwappingDisable"
-                    [16] "SwappingDir"
-                    [17] "SwappingNoEMS"
-                    [18] "LockedBPS"
-                    [19] "SerialPort"
-                    [20] "CustomFileName"
-                    [21] "CustomFileLine"
-                    [22] "InactivityTimeout"
-                    [23] "PageDuration"
-                    [24] "ChatUserColor"
-                    [25] "ChatSysopColor"
-                    [26] "FileListTitleColor"
-                    [27] "FileListNameColor"
-                    [28] "FileListSizeColor"
-                    [29] "FileListDescriptionColor"
-                    [30] "FileListOfflineColor"
-                    [31] "Personality"
-                    [32] "NoFossil"
-                    [33] "PortAddress"
-                    [34] "PortIRQ"
-                    [35] "ReceiveBuffer"
-                    [36] "TransmitBuffer"
-                    [37] "PagePromptColor"
-                    [38] "LocalMode"
-                    [39] "PopupMenuTitleColor"
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 194
-
-                    [40] "PopupMenuBorderColor"
-                    [41] "PopupMenuTextColor"
-                    [42] "PopupMenuKeyColor"
-                    [43] "PopupMenuHighlightColor"
-                    [44] "PopupMenuHighKeyColor"
-                    [45] "NoFIFO"
-                    [46] "FIFOTriggerSize"
-                    [47] "DiableDTR"
-                    [48] "NoDTRDisable"
-
-
-
--------------------------------------------------------------------------------
-od_chat        char od_control.od_chat_active;
-_active
-               This variable is set to TRUE when sysop chat mode is active, and
-               is set to FALSE when sysop chat mode is not active. This
-               variable can be used to determine whether or not chat mode is
-               active, and to force chat mode to end. When the sysop presses
-               the chat mode key ([ALT]-[C] if the default personality is being
-               used) while chat mode is active, this variable is set to FALSE.
-
-
-
--------------------------------------------------------------------------------
-od_clear       char od_control.od_clear_on_exit;
-_on_exit
-               This variable contains a Boolean value, which indicates whether
-               or not you wish OpenDoors to clear the screen prior to exiting.
-               This variable defaults to a value of TRUE, which causes the
-               screen to be cleared when a door program exits. However, you may
-               wish to set this variable to a value of FALSE, which will cause
-               the contents of the screen to remain unchanged when the door
-               exits. While setting this variable to FALSE will probably result
-               in a messy display if the door is to return control to a batch
-               file, if the door returns directly to the BBS, it will result in
-               a smoother transition from the door back to the BBS (as the
-               sysop is not left with a blank screen). If your door has a
-               configuration file or configuration program, you may wish to
-               have an option which will allow the individual sysop to
-               determine whether or not the screen should be cleared when the
-               door exits.
-
-
-
--------------------------------------------------------------------------------
-od_color       char od_control.od_color_delimiter;
-_delimiter
-               This variable sets the character that is used to delimit color
-               codes in the od_printf() function, and defaults to the back-
-               quote (`) character. If you wish to be able to display the back-
-               quote (`) character using the od_printf() function, and thus
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 195
-
-               wish to use a different character to delimit color codes in the
-               od_printf() function, simply set this variable to the
-               alternative character you wish to use. If you wish to disable
-               the imbedded color codes feature of the od_printf() function,
-               simply set this variable to a value of zero. For more
-               information on od_printf() imbedded color codes, see the
-               description of the od_printf() function, which begins on page
-               110.
-
-
-
--------------------------------------------------------------------------------
-od_color       char od_control.od_color_names[12][33];
-_names
-               This array sets the strings that OpenDoors will recognize as
-               color description keywords. These are the keywords that can be
-               imbedded in od_printf() format strings, and are also the
-               keywords that can be used to change color settings in the
-               OpenDoors configuration file. If you wish to change these
-               keywords, you will normally do so before calling any OpenDoors
-               functions. These keywords should always be supplied in upper-
-               case characters. The defaults values for this array are as
-               follows:
-
-                    [0]  "BLACK"
-                    [1]  "BLUE"
-                    [2]  "GREEN"
-                    [3]  "CYAN"
-                    [4]  "RED"
-                    [5]  "MAGENTA"
-                    [6]  "YELLOW"
-                    [7]  "WHITE"
-                    [8]  "BROWN"
-                    [9]  "GREY"
-                    [10] "BRIGHT"
-                    [11] "FLASHING"
-
-
-
--------------------------------------------------------------------------------
-od_config      void (*od_control.od_config_file)(void);
-_file
-               Set this variable to INCLUDE_CONFIG_FILE to enable the OpenDoors
-               configuration file system, or set it to NO_CONFIG_FILE to
-               disable the configuration file system. This variable should only
-               be set prior to your first call to an OpenDoors function. For
-               more information on the OpenDoors configuration file system, see
-               page 224.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 196
-
--------------------------------------------------------------------------------
-od_config      char *od_control.od_config_filename;
-_filename
-               If set, this variable should point to a string containing the
-               filename that you wish the OpenDoors configuration file system
-               to read. If this variable has its default value of NULL, the
-               filename DOOR.CFG will be used by default.
-
-
-
--------------------------------------------------------------------------------
-od_config      void (*od_control.od_config_function)(char *keyword, char
-_function      *options);
-
-               If set, this variable should point to the function that
-               OpenDoors should call when lines with unrecognized keywords are
-               encountered in the configuration file. This allows you to add
-               your own configuration file keywords. The first parameter to
-               this function will be a pointer to a string containing the
-               unrecognized keywords, and the second parameter will be a
-               pointer to a string containing any options that were specified
-               after the keyword. If no options were specified after the
-               keyword, this string will have a length of 0.
-
-
-
--------------------------------------------------------------------------------
-od_default     void (*od_control.od_default_personality)(unsigned char
-_personality   operation);
-
-               This variable sets the default personality that OpenDoors will
-               use if the multiple personality system is active. If the
-               multiple personality system is not active, the personality set
-               by this variable will be the only personality available. This
-               variable should only be set prior to calling an OpenDoors
-               function. This variable can be set to point to your own
-               personality function, or it can be set to one of the manifest
-               constants that represent one of the built-in personalities:
-
-                    PER_OPENDOORS
-                    PER_PCBOARD
-                    PER_RA
-                    PER_WILDCAT
-
-               For more information on the OpenDoors Multiple Personality
-               System, see page 230.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 197
-
--------------------------------------------------------------------------------
-od_default     char od_control.od_default_rip_win;
-_rip_win
-               This variable defaults to FALSE. When set to FALSE, OpenDoors
-               resets the RIP text window to a 23-line window that is most
-               appropriate for doors that support both RIP-graphics and non-RIP
-               mode. When this variable is set to TRUE, OpenDoors will use the
-               default sized text output window, 43 lines in size.
-
-
-
--------------------------------------------------------------------------------
-od_disable          unsigned int od_control.od_disable;
-
-               This variable is a bit-mapped flag which can be used to disable
-               certain OpenDoors features which are normally active, in order
-               to allow for maximum customization of OpenDoors. Each bit of
-               this variable represents a different feature that can be
-               disabled. To DISABLE a feature, you set the bit that corresponds
-               to the particular feature. To ENABLE the feature, the bit is
-               reset. Each bit is represented by a keyword, as follows:
-
-               DIS_INFOFILE - Setting the DIS_INFOFILE bit of the
-                    od_control.od_disable variable allows you to prevent
-                    OpenDoors from reading or re-writing a door information
-                    file. If you wish to disable OpenDoors' reading of the door
-                    information file, you must  do so prior to calling
-                    od_init() or any other OpenDoors door-driver functions. At
-                    the same time, you must also manually set any required
-                    variables that are normally set by the information obtained
-                    from the door information file, such as the comm port
-                    number, baud rate, user name, and so on. You may wish to
-                    disable reading of the door information file in a number of
-                    cases. For example, you may wish to manually read another
-                    format of door information file not supported by OpenDoors,
-                    or to obtain the necessary door information from your
-                    program's command line. Also, if you are using OpenDoors to
-                    write a non-door communications program, such as a terminal
-                    program, you want to prevent OpenDoors from attempting to
-                    read a door information file on startup.
-
-               DIS_CARRIERDETECT - Setting this bit allows you to prevent
-                    OpenDoors from exiting when it the carrier detect signal
-                    from the modem disappears. This bit may be set or rest at
-                    any time. If you use this bit to disable OpenDoors' carrier
-                    detection, you will probably want to monitor the state of
-                    the carrier detect signal yourself, using the od_carrier()
-                    function, which is described on page 51.
-
-               DIS_TIMEOUT - This flag allows you to prevent OpenDoors from
-                    exiting when the user runs out of time. As with the
-                    DIS_CARRIERDETECT flag, you may set or reset this bit at
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 198
-
-                    any time. You will most often want to use this setting when
-                    writing a non-door program, which you would not want to
-                    have exit after a particular amount of time has elapsed. Be
-                    sure that you do not confuse this flag with the user's
-                    inactivity timeout. To disable the inactivity timeout, set
-                    the do_control.od_inactivity variable to 0.
-
-               DIS_LOCAL_OVERRIDE - This setting affects OpenDoors' behavior
-                    when a locked BPS rate is specified in the configuration
-                    file, and another BPS rate is specified in the door
-                    information file. By default, OpenDoors will initialize the
-                    modem at the BPS rate specified in the configuration file,
-                    unless the BPS rate specified in the door information file
-                    is 0. In this case, the 0 BPS rate is used to indicate that
-                    the door is operating in local mode, and will override the
-                    BPS rate specified in the configuration file. Setting this
-                    flag disables the local mode override, causing the modem to
-                    always be initialized at the locked BPS rate, even when the
-                    door information file specifies that local mode should be
-                    used.
-
-               DIS_BPS_SETTING - When used with a FOSSIL driver, OpenDoors
-                    normally changes the BPS rate to that passed from the BBS
-                    (if the BBS passes a valid FOSSIL BPS rate). Setting the
-                    DIS_BPS_SETTING flag disables this BPS rate setting.
-
-               DIS_LOCAL_INPUT -  The local keyboard may be disabled by setting
-                    this bit. This only affects the sysop's input in
-                    circumstances that input is also accepted from the remote
-                    user; this setting has no effect on the sysop function
-                    keys.
-
-               DIS_SYSOP_KEYS - This setting also disables the local keyboard.
-                    However, unlike the DIS_LOCAL_INPUT, this function disables
-                    both sysop function keys and door input from the local
-                    keyboard.
-
-               DIS_DTR_DISABLE - This setting prevents OpenDoors from
-                    disabiling DTR response from the modem. Even if not
-                    specified, OpenDoors only disables DTR response in the when
-                    exiting under the Win32 version if an open serial port
-                    handle was not provided to OpenDoors at startup.
-
-               DIS_NAME_PROMPT - Prevents OpenDoors from prompting for a user
-                    name when operating in automatic local mode (by setting
-                    od_force_local to TRUE or specifying -local on the command
-                    line).
-
-               Note that in order to disable the OpenDoors status line, the
-               od_control.od_status_on variable is used, instead of the
-               od_disable variable. You may also disable the user's inactivity
-               timeout by setting the od_control.od_inactivity variable to 0.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 199
-
-               The od_control.od_status_on variable is described later in this
-               section.
-
-
-
--------------------------------------------------------------------------------
-od_disable_    char od_control.od_disable_dtr[40];
-dtr
-               Unles the DIS_DTR_DISABLE od_disable flag is set, the Win32
-               version of OpenDoors will attempt to disable DTR response by the
-               modem when closing the serial port, if the serial port was
-               opened by OpenDoors. This is done by sending a series of
-               commands to the modem, and possibly waiting for responses to the
-               command. The string format specifies each command, followed by
-               the required response. The command and response is separated by
-               a single space character. If no response is required between two
-               commands, then those commands may be separated by two space
-               characters. A '|' character is translated into a carriage
-               return, and a '~' character is translated into a one second
-               pause. The default value of this string is "~+++~  AT&D0  ATO".
-
-
-
--------------------------------------------------------------------------------
-od_emu_        BOOL od_control.od_emu_simulate_modem;
-simulate_modem
-               When this flag is set to its default value of FALSE, the
-               OpenDoors terminal emulator displays text at full speed. When
-               this flag is set to TRUE, the emulation functions will display
-               text at approximately the same speed as it would be displayed
-               when sent over the modem, based on the current connect speed. In
-               local mode, an average modem speed of 9600bps is assumed. This
-               allows animations to be displayed locally at the same speed as
-               they would appear on the remote system. This switch affects the
-               following functions:
-                    od_disp_emu()
-                    od_send_file()
-                    od_hotkey_menu()
-
-
-
--------------------------------------------------------------------------------
-od             unsigned char od_control.od_errorlevel[8];
-_errorlevel
-               Allows you to configure the errorlevel (program exit code) which
-               OpenDoors exits with under various circumstances. The elements
-               of this array are as follows:
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 200
-
-               [ERRORLEVEL_ENABLE]     Enables or disables custom errorlevels
-               [ERRORLEVEL_CRITICAL]   Critical error errorlevel
-               [ERRORLEVEL_NOCARRIER]  Carrier lost errorlevel
-               [ERRORLEVEL_HANGUP]     Sysop manually terminated call
-               [ERRORLEVEL_TIMEOUT]    User time expired errorlevel
-               [ERRORLEVEL_INACTIVITY] Keyboard inactivity timeout errorlevel
-               [ERRORLEVEL_DROPTOBBS]  Sysop returned user to BBS errorlevel
-               [ERRORLEVEL_NORMAL]     Door has exited normally
-
-               If you wish to override the default errorlevels used by
-               OpenDoors, you should set element [ERRORLEVEL_ENABLE] of this
-               array to TRUE, and set the remaining array elements to the
-               appropriate errorlevels. Note that the settings in this array
-               only affect the errorlevels which OpenDoors uses when it causes
-               the door to exit for one of the reasons listed above. This
-               setting has no effect on the errorlevel returned when your
-               program explicitly exits by calling the od_exit() function, or
-               your program returns by calling exit() or returning from the
-               main() function.
-
-
-
--------------------------------------------------------------------------------
-od             char od_control.od_force_local;
-_force_local
-               This variable defaults to FALSE, which causes OpenDoors to
-               behave normally. When this variable is set to TRUE prior to
-               calling od_init() or any other OpenDoors functions, OpenDoors
-               will operate in local mode. In this case, no door information
-               file will be read. Also, the user name will be used if
-               od_control.user_name has not been set prior to calling od_init()
-               or the first OpenDoors function.
-
-               The default OpenDoors settings when od_control.od_force_local is
-               set are as follows:
-
-               - ANSI mode is on
-               - Time limit is 60 minutes
-               - User's location is the name of the BBS, or "Unknown Location"
-               otherwise if BBS name is not known.
-               - User name is set to sysop's name ("Sysop" if no sysop name is
-               specified in the configuration file).
-
-               You may wish to add a "-local" type parameter to your program's
-               command line, which will permit the sysop to easily operate the
-               door in local mode, as an interface to the
-               od_control.od_force_local setting.
-
-
-
--------------------------------------------------------------------------------
-od_help        void (*od_control.od_help_callback)(void);
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 201
-
-_callback
-               If this variable is set to a non-NULL value, the Win32 version
-               of OpenDoors will provide a Contents item on the help menu, and
-               call the function pointed to by this variable when the user
-               chooses the Contents menu item.
-
-
-
--------------------------------------------------------------------------------
-od_in_buf      unsigned int od_control.od_in_buf_size;
-_size
-               Specifies the size, in characters, of the OpenDoor's internal
-               local/remote inbound buffer size. Two bytes of storage are
-               required for each character in this buffer. This variable should
-               only be changed prior to calling od_init() or the first
-               OpenDoors function. If not set, this variable defaults to a
-               value of 256.
-
-               The buffer corresponding to this variable should not be confused
-               with the FOSSIL or internal communications receive buffer (which
-               is set by od_control.od_com_rx_buf). Unlike the serial I/O
-               receive buffer, which is used only for characters received from
-               the remote system, this buffer serves as a queue for input from
-               both the remote system and the local keyboard. If you find that
-               characters are lost when information is being set to your door
-               from the user, you may wish to increase the size of this buffer.
-
-
-
--------------------------------------------------------------------------------
-od             unsigned int od_control.od_inactivity;
-_inactivity
-               OpenDoors has a built in user-inactivity timeout facility, which
-               will automatically disconnect a user who appears .to be sleeping
-               at the keyboard. If the user has not pressed any keys on their
-               keyboard for to great a length of time, they will be warned that
-               they are about to be disconnected due to inactivity. If they
-               still do not respond after another few seconds, OpenDoors will
-               automatically disconnect the user and return control to the BBS
-               software. The od_control.od_inactivity variable allows you to
-               set the maximum length of time, in seconds, after which the user
-               will be disconnected for inactivity. This variable defaults to a
-               value of 200 seconds. You may disable OpenDoors' inactivity
-               timeout altogether, by setting the od_control.od_inactivity
-               variable to a value of 0.
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 202
-
--------------------------------------------------------------------------------
-od_inactive    int od_control.od_inactive_warning.
-_warning
-               This variable sets the number of seconds prior to hanging up
-               that OpenDoors displays the inactivity timeout warning. This
-               variable should only be changed after your first call to an
-               OpenDoors API function. If not explicitly set by your program,
-               this setting defaults to 10 seconds.
-
-
-
--------------------------------------------------------------------------------
-od_ker_exec    void (*od_control.od_ker_exec)(void);
-
-               When od_control.od_ker_exec is set to point to a function,
-               OpenDoors will call this function whenever od_kernel() executes.
-               This provides any easy way for you to perform your own
-               processing on a regular basis during door execution. The
-               od_control.od_ker_exec variable defaults to NULL.
-
-
-
--------------------------------------------------------------------------------
-od_last        char od_control.od_last_input;
-_input
-               Indicates whether the last key retrieved using the od_get_key()
-               function originated from the remote user, or the local sysop. If
-               the input originated from the remote, this variable is set to 0.
-               If the input originated from the local keyboard, this variables
-               is set to 1.
-
-
-
--------------------------------------------------------------------------------
-od_list        char od_control.od_list_pause;
-_pause
-               This variable contains a Boolean value, which allows you to
-               control whether or not the user may pause displaying within the
-               od_list_files() and od_send_file() function. When this variable
-               is set to its default value of TRUE, the user will be able to
-               pause the display by pressing the [P] key, and resume display by
-               pressing any other key. However, the pause feature may be
-               disabled by setting this variable to FALSE.
-
-
-
--------------------------------------------------------------------------------
-od_list        char od_control.od_list_stop;
-_stop
-               This variable contains a Boolean value, which allows you to
-               control whether or not the user may abort displaying within the
-               od_list_files() and od_send_file() function. When this variable
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 203
-
-               is set to its default value of TRUE, the user will be able to
-               pause the display by pressing the [S], [CTRL]-[K] or [CTRL]-[C]
-               keys. However, the stop feature may be disabled by setting this
-               variable to FALSE.
-
-
-
--------------------------------------------------------------------------------
-od_local       void (*od_control.od_local_input)(int);
-_input
-               If set, this function is called whenever the sysop presses a
-               non-sysop-function key on the local keyboard. The key pressed is
-               passed to the function in the single int parameter that it
-               accepts.
-
-
-
--------------------------------------------------------------------------------
-od_logfile     void *(od_control.od_logfile)(void);
-
-               To make the OpenDoors log file system available in your program,
-               set this variable to INCLUDE_LOGFILE, prior to calling any
-               OpenDoors functions. If not set, or if set to NO_LOGFILE, the
-               OpenDoors log file system will not automatically be enabled.
-
-
-
--------------------------------------------------------------------------------
-od_logfile     char od_control.od_logfile_disable;
-_disable
-               This variable defaults to the value of FALSE, unless the
-               "LogfileDisable" option is specified in the configuration file,
-               in which case the variable will be set to TRUE. If this variable
-               is set to TRUE, OpenDoors will not write to a logfile, even if
-               the logfile system is enabled using od_control.od_logfile.
-
-
-
--------------------------------------------------------------------------------
-od_logfile     char *od_control.od_logfile_messages[14];
-_messages
-               This array of pointers to strings contains the messages that
-               OpenDoors will automatically write to the log file, if the log
-               file system is enabled. If you wish to change the settings of
-               this array, you should do so before calling any OpenDoors
-               functions. The default strings for this array are as follows:
-
-               [0] "Carrier lost, exiting door"
-               [1] "System operator terminating call, exiting door"
-               [2] "User's time limit expired, exiting door"
-               [3] "User keyboard inactivity time limit exceeded, exiting door"
-               [4] "System operator returning user to BBS, exiting door"
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 204
-
-               [5] "Exiting door with errorlevel %d,
-               [6] "Invoking operating system shell"
-               [7] "Returning from operating system shell"
-               [8] "User paging system operator"
-               [9] "Entering sysop chat mode"
-               [10] "Terminating sysop chat mode"
-               [11] "%s entering door"
-               [12] "Reason for chat: %s"
-               [13] "Exiting door"
-
-
-
--------------------------------------------------------------------------------
-od_logfile     char od_control.od_logfile_name[80];
-_name
-               This variable specifies the filename, and optionally the full
-               path of the logfile where OpenDoors should perform logging. This
-               variable only has an effect when set prior to calling any
-               OpenDoors functions. If the log file name is specified in the
-               configuration file, that name will be stored in this variable.
-               If you do not set this variable, and the log file name is not
-               specified in the configuration file, the default name "DOOR.LOG"
-               will be used. If you wish to set this variable, you should do so
-               prior to calling od_init() or any OpenDoors function.
-
-
-
--------------------------------------------------------------------------------
-od_            unsigned int od_control.od_maxtime;
-maxtime
-               This variable specifies the maximum length of time that any user
-               is permitted to use the door, and is normally set from a
-               configuration file option. If upon entering the door, the user's
-               time remaining online is greater than the od_maxtime setting,
-               their time remaining is temporarily decreased to the maximum
-               value. Then upon exit of the door, the number of subtracted
-               minutes is added back onto the user's remaining time. If the
-               user's remaining time is less than this value, then the setting
-               has no effect. A value of 0 disables the maximum time setting
-               altogether.
-
-
-
--------------------------------------------------------------------------------
-od_maxtime     int od_control.od_maxtime_deduction;
-_deduction
-               This variable store the amount of time that should be added to
-               the user's time upon exit of the door, as a result of the
-               maximum time deduction, described above. If the maximum time
-               feature is not used, this variable will be given a value of 0.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 205
-
-
--------------------------------------------------------------------------------
-od_mps         void (*od_control.od_mps)(void);
-
-               To make the OpenDoors Multiple Personality system available in
-               your program, set this variable to INCLUDE_MPS before calling
-               any OpenDoors functions. If this variable is not set, or is set
-               to NO_MPS, the Multiple Personality System will be disabled. For
-               more information on the OpenDoors Multiple Personality System,
-               see page 233.
-
-
-
--------------------------------------------------------------------------------
-od_no_         void (*od_control.od_no_file_func)();
-file_func
-               If od_no_file_func is set to point to a function, that function
-               will be called whenever a door information (drop) file cannot be
-               located or read. This provides an easy mechanism to add your own
-               door information file reader, or to provide a local login prompt
-               when no drop file is present. If you wish the door to operate in
-               local mode, you should set od_control.od_force_local to TRUE
-               prior to returning from your function. If you have successfully
-               read your own door information file format, you should set
-               od_control.od_info_type to CUSTOM. If neither of these variables
-               are set by the od_no_file_function, OpenDoors will report that
-               it is unable to find or read a door information file and will
-               exit immediately.
-
-
-
--------------------------------------------------------------------------------
-od_no_ra       char od_control.od_no_ra_codes;
-_codes
-               This variable defaults to FALSE. When set to TRUE, the
-               translation of the RemoteAccess/QuickBBS control codes by the
-               functions od_send_file(), od_hotkey_menu() and od_disp_emu() is
-               disabled.
-
-
-
--------------------------------------------------------------------------------
-od_            char od_control.od_nocopyright;
-nocopyright
-               This variable is a Boolean value that allows you to prevent
-               OpenDoors from displaying its name, version number, copyright
-               notice and registration information when the program begins
-               execution. Set this variable to TRUE to disable the display of
-               copyright and associated information. When this variable is set
-               to TRUE, OpenDoors also does not change the initial display
-               color on startup. For obvious reasons, this variable does not
-               take effect when OpenDoors is operating in unregistered mode.
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 206
-
-
-
-
--------------------------------------------------------------------------------
-od_noexit      char od_control.od_noexit;
-
-               This variable contains a Boolean value, which allows you to
-               prevent OpenDoors from exiting when shutting down. This may be
-               useful when you want to have your program to do more processing
-               after you have called the od_exit() function, or if you do not
-               wish to have your program exit automatically when the user drops
-               carrier. Normally, this variable will default to a value of
-               FALSE, indicating that OpenDoors will exit normally when the
-               od_exit() function is called. However, you may optionally set
-               this variable to TRUE after od_init() or some OpenDoors function
-               has been called. In this case, when the od_exit() function is
-               called, either by your program manually, or automatically by
-               OpenDoors in response to the user dropping carrier, etc.,
-               OpenDoors will not exit. However, the normal operations of
-               closing the serial port and re-writing the door information file
-               will be carried out. If you set the od_noexit variable to TRUE,
-               you will probably have to provide some mechanism to allow your
-               program to detect when OpenDoors shutdowns due to the loss of
-               carrier, etc. The best way of doing this is to provide a
-               function which is to be called at the beginning of the od_exit()
-               function, by setting the od_control.od_before_exit pointer,
-               described above.
-
-
-
--------------------------------------------------------------------------------
-od_page        char od_control.od_page_len;
-_len
-               This variable allows you to control the length, in seconds, of
-               the sysop page beep produced when the user pages the sysop via
-               the od_page() function.
-
-
-
--------------------------------------------------------------------------------
-od_page        char od_control.od_page_pausing;
-_pausing
-               This variable contains a Boolean value that indicates whether or
-               not page pausing is enabled in the od_send_file(),
-               od_hotkey_menu() and od_list_files() functions. The default
-               value of TRUE indicates that page pausing is enabled. A value of
-               FALSE indicates that page pausing is disabled.
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 207
-
--------------------------------------------------------------------------------
-od_page        int od_control.od_pagestartmin;
-startmin       int od_control.od_pageendmin;
-
-od_page        These variables indicate the start and end times for sysop
-endmin         paging, expressed as the number of minutes past midnight.
-               Sysop paging will be available through the od_page() function
-               from the start time, up to but not including the end time.
-
-
-
--------------------------------------------------------------------------------
-od_page        char od_control.od_page_statusline;
-_statusline
-               This variable controls which status line, if any, is activated
-               when the user pages the system operator (via the od_page()
-               function). A value between 0 and 9 causes the corresponding
-               status line to be activated. A value of -1 prevents any change
-               from being made to the current status line setting. This
-               variable will normally be set by personality functions (see page
-               233).
-
-
-
--------------------------------------------------------------------------------
-od_prog_       char od_control.od_prog_copyright[40];
-copyright
-               This variable should contain your program's copyright notice,
-               such as "(C) Copyright 1996 by Your Name". This information is
-               used in the Help|about dialog box under the Win32 version of
-               OpenDoors, and may be used in other places in future versions of
-               OpenDoors.
-
-
-
--------------------------------------------------------------------------------
-od_prog_name   char od_control.od_prog_name[40];
-
-               This variable should contain the full name of your program, up
-               to 39 characters. If not set, OpenDoors will use the string
-               "OpenDoors" in place of this variable. If used, this variable
-               should be set prior to calling any OpenDoors functions, and
-               should not include your program's version number. This
-               information is used to write your program's name in the log file
-               and to indicate your program's name on various windows, among
-               other places.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 208
-
-
-
-
--------------------------------------------------------------------------------
-od_prog_version     char od_control.od_prog_version[40];
-
-               This variable should contain the version information of your
-               program. If used, this variable should be set prior to calling
-               any OpenDoors functions. This information is used in the
-               Help|About dialog box under the Win32 version of OpenDoors,
-               among other places.
-
-
-
--------------------------------------------------------------------------------
-od_reg_key     unsigned log od_control.od_reg_key;
-
-               When you purchase an OpenDoors licence (registration), this
-               variable should be set to your registration key, prior to
-               calling any OpenDoors functions.
-
-
-
--------------------------------------------------------------------------------
-od_reg_name    char od_control.od_reg_name[36];
-
-               When you purchase an OpenDoors licence (registration), this
-               variable should be set to your name, or your company's name, as
-               is listed in your OpenDoors registration record.
-
-
-
--------------------------------------------------------------------------------
-od_spawn       char od_control.od_spawn_freeze_time;
-_freeze_time
-               This variable is a Boolean value which indicates whether or not
-               the user's time remaining is frozen during the execution of one
-               of the od_spawn...() functions. If this variable is set to TRUE,
-               the user's time remaining will not decrease during the time that
-               the od_spawn...() function is executing. However, if this
-               variable is set to FALSE, the user's time remaining will
-               continue to be subtracted during the execution of the
-               od_spawn...() function. The default value of this variable is
-               FALSE.
-
-
-
--------------------------------------------------------------------------------
-od_swapping    char od_control.od_swapping_disable;
-_disable
-               This variable is a Boolean value which specifies whether or not
-               OpenDoors will attempt to swap itself and your entire door upon
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 209
-
-               DOS shell or a call to one of the od_spawn...() functions. This
-               variable defaults to FALSE. If set to TRUE, OpenDoors will not
-               attempt to perform swapping activities.
-
-
-
--------------------------------------------------------------------------------
-od_swapping    char od_control.od_swapping_noems;
-_noems
-               This variable is a Boolean value which can be used to prevent
-               OpenDoors from swapping to EMS memory. This variable defaults to
-               the value FALSE. If set to TRUE, OpenDoors will not attempt to
-               use EMS memory for swapping, and will only swap to disk.
-
-
-
--------------------------------------------------------------------------------
-od_swapping    char od_control.od_swapping_path;
-_path
-               This variable specifies the drive and directory where OpenDoors
-               should create its disk swapping file, if applicable. More than
-               one path can be specified, by separating the paths with a semi-
-               colon (;) character.
-
-
-
--------------------------------------------------------------------------------
-od_status      char od_control.od_status_on;
-_on
-               This variable is a Boolean value which allows your program to
-               completely disable the OpenDoors status line. The variable
-               defaults to a value of TRUE, which causes the OpenDoors status
-               line to be controllable by function keys, displayed and updated
-               as it would normally be. However, if this variable is set to
-               FALSE, then OpenDoors will not update the status line, nor will
-               it allow the status line to be re-displayed as a result of one
-               of the status line ([F1] through [F10]) keys being pressed. When
-               you change the value of this variable from FALSE to TRUE,
-               OpenDoors will automatically redisplay the status line. Note,
-               however, that the status line isn't automatically removed when
-               the value of this variable is changed from TRUE to FALSE. In
-               order to erase the status line after resetting the value of this
-               variable, you should reset the output window to the full screen,
-               by calling the function window(1,1,25,80). Then manually erase
-               the old status line either by clearing the bottom two lines of
-               the screen, or by clearing the entire screen.
-
-               It is important that you do not confuse the use of this variable
-               with the od_set_statusline() function, which is described on
-               page 137. When the status line is enabled, the sysop can change
-               which status line, if any, is being displayed, using the
-               function keys [F1] through [F10]. The od_set_statusline()
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 210
-
-               function allows your program to make the same changes to the
-               status line setting which the sysop can make by pressing one of
-               the function keys. The status line can be removed from the
-               screen, allowing a full 25 lines of text to be displayed, by
-               pressing the [F10] key, or by making the appropriate call to the
-               od_set_statusline() function. Note, however, than when this is
-               done, the status line is still enabled, and can be turned on by
-               pressing any of the other function keys. On the other hand, if
-               the status line is turned off using this variable
-               (od_control.od_status_on), the status line sub-system will be
-               disabled, and pressing function keys will not "bring it back".
-               So, if you were writing a program where a status line would be
-               undesirable - such as a non-door communications program, you
-               would use the od_control.od_status_on variable. On the other
-               hand, if you only wanted to temporarily remove the status line -
-               say in order that all 25 lines of a door program's output could
-               be viewed - while still allowing the status line to be turned on
-               with the sysop function keys, you would use the
-               od_set_statusline() function. For more information on the
-               od_set_statusline() function, see page 137.
-
-
-
--------------------------------------------------------------------------------
-od_time        void (*od_control.od_time_msg_func)(char *string)
-_msg_func
-               This variable defaults to a value of NULL. If set to point to a
-               function, OpenDoors will call this function INSTEAD OF
-               displaying time limit warning messages to the user. The messages
-               redirected to this function are:
-
-                    - Inactivity timeout warning
-                    - Inactivity timeout expired
-                    - Less than 4 minutes left today
-                    - Daily time limit expired
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 211
-
-CONTROL STRUCTURE - FUNCTION KEYS
--------------------------------------------------------------------------------
-
-               Within OpenDoors, as with most BBS software and doors, the sysop
-               has access to a number of function keys, which permits the sysop
-               to carry out various functions such as entering chat mode,
-               hanging up on the user, shelling to DOS, and so on. The
-               variables in this section allow you to customize which keys
-               carry out the standard sysop functions, allowing you to
-               customize your door's interface to mimic any BBS package. By
-               default, OpenDoors emulates the function keys used by the Remote
-               Access BBS package, but you may choose, for example, to have
-               your door use the key combinations used by PC-Board. In
-               addition, OpenDoors provides an interface which allows you to
-               add your own function keys which will be accepted by the door.
-               This could allow you to add additional features, such as giving
-               the sysop access to a status screen which displays information
-               about your door.
-
-               Many of the variables in this section are unsigned ints, which
-               represent a sysop key combination such as [ALT]-[H], [F8], or
-               [CTRL]-[P]. These values are in the same format as is returned
-               by the Turbo C(++) / Borland C++ bioskey() function. The high-
-               order byte represents the scan code of the key, and the low-
-               order byte represents the ASCII value, if any, of the key
-               combination. Note that a complete tutorial on these key codes is
-               beyond the scope of this manual. For more information on these
-               key codes, you should see the documentation on the bioskey()
-               function, which accompanies your compiler. If you wish to
-               determine the key code which corresponds to a particular
-               keystroke, there is a simple program, listed below, which you
-               can compile and use. This program will simply display the key
-               code for any key pressed, until you press the [ESCape] key. So,
-               in order to determine the code for [SHIFT]-[F8], you would
-               simply run this program, press the [SHIFT]-[F8] key combination
-               on your keyboard, and record the value displayed on your screen.
-
-                         #include <stdio.h>
-                         #include <bios.h>
-                         main()
-                         {
-                            int nKey;
-
-                            do
-                               {
-                               nKey = bioskey(0);
-                               printf("%d (from: %x, %x)\n",
-                                  nKey, nKey>>8, nKey&0xff);
-                               } while((nKey & 0xff) != 27);
-                         }
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 212
-
-
--------------------------------------------------------------------------------
-BUILT IN       These variable allow you to customize the sysop function keys
-FUNCTION       which control functions such as hanging up on the user, shelling
-KEYS           to DOS, and so on. All of these variable will be assigned
-               default values, which correspond to the same function keys used
-               by the RemoteAccess BBS package. However, you may change the
-               values of these variables in order to customize the key
-               combinations which carry out these functions in your own door
-               program. Remember that if you wish to change the value of any of
-               these variables, you must do so after having called od_init() or
-               some OpenDoors function. Each of these variables contain a scan-
-               code / ASCII-code combination representing a keystroke, as is
-               described above. These variables are as follows:
-
-               +---------------------+----------------------------------------+
-               | VARIABLE            | CORRESPONDING FUNCTION                 |
-               +---------------------+----------------------------------------+
-               | od_control.         | Enter sysop chat mode                  |
-               | key_chat            | (Normally [ALT]-[C]                    |
-               |                     |                                        |
-               | od_control.         | Invoke sysop DOS shell                 |
-               | key_dosshell        | (Normally [ALT]-[J]                    |
-               |                     |                                        |
-               | od_control.         | Return to the BBS without hanging up   |
-               | key_drop2bbs        | (Normally [ALT]-[D])                   |
-               |                     |                                        |
-               | od_control.         | Hangup on the user                     |
-               | key_hangup          | (Normally [ALT]-[H])                   |
-               |                     |                                        |
-               | od_control.         | Turn off the user's keyboard           |
-               | key_keyboardoff     | (Normally [ALT]-[K])                   |
-               |                     |                                        |
-               | od_control.         | Decreases the user's remaining time    |
-               | key_lesstime        | (Normally [DOWN-ARROW])                |
-               |                     |                                        |
-               | od_control.         | Lock the user out of the BBS system    |
-               | key_lockout         | (Normally [ALT]-[L])                   |
-               |                     |                                        |
-               | od_control.         | Increases the user's remaining time    |
-               | key_moretime        | (Normally [UP-ARROW])                  |
-               |                     |                                        |
-               | od_control.         | Array of eight function keys to set the|
-               | key_status[8]       | current status line.                   |
-               |                     | (Normally [F1], [F2], [F3], [F4], [F5],|
-               |                     |  [F6], [F9], [F10])                    |
-               |                     |                                        |
-               | od_control.         | "Sysop next" toggle key                |
-               | key_sysopnext       | (Normally [ALT]-[N])                   |
-               +---------------------+----------------------------------------+
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 213
-
-
--------------------------------------------------------------------------------
-CUSTOM         In addition to the sysop function keys built into OpenDoors, you
-FUNCTION       may wish to add your own function keys to your door. For
-KEYS           example, you might wish to have the [ALT]-[Z] combination
-               display a window of information about your door, or you may wish
-               to add your own user editor to your door, accessible through the
-               [ALT]-[E] combination. The four variables:
-
-                         unsigned char od_control.od_num_keys;
-                         unsigned int od_control.od_hot_key[16];
-                         unsigned int od_control.od_last_hot;
-                         void (*od_control.od_hot_function[16])(void);
-
-               provide your program with an interface to add your own sysop
-               function keys (not accessible by the remote user) to the door
-               you have written.
-
-               OpenDoors allows you to define up to sixteen custom sysop
-               function keys. The key codes (as described at the beginning of
-               this section) are stored in the od_control.od_hot_key[] array,
-               and the od_control.od_num_keys variable records the number of
-               keys which have been defined. The od_control.od_num_keys
-               variable defaults to a value of 0. So, in order to add your own
-               function keys, simply place the key codes for these keys in the
-               first n elements of the od_control.od_hot_key[] array, and set
-               the od_control.od_num_keys variable to the number of keys you
-               have defined. OpenDoors will then watch the keyboard for any of
-               your predefined sysop function keys being pressed. If one of
-               these keys is pressed, OpenDoors will place the key code of the
-               pressed key in the od_control.od_last_hot variable. Your program
-               will then be able to respond to one of your custom function keys
-               being pressed by checking the value of the
-               od_control.od_last_hot variable. At any time this variable
-               contains a non-zero value. If this is the case, you will then be
-               able to determine which of your function keys has been pressed
-               by checking the key code contained in this variable. After
-               taking the appropriate action for the key pressed, you should be
-               sure to reset the value of the od_control.od_last_hot variable
-               back to zero, which will indicate to OpenDoors that your program
-               has received and responded to the function key which was
-               pressed.
-
-               As an alternative to testing the contents of the
-               od_control.od_last_hot variable, you  can also have your program
-               respond to custom sysop function keys by providing a callback
-               function in the array: void
-               (*od_control.od_hot_function[16])(void);
-
-               The Nth element in this array corresponds to the Nth element in
-               the od_control.od_hot_key array. To use this mechanism, simply
-               set the appropriate element of this array to point to the
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 214
-
-               function that you wish to have OpenDoors call when the sysop
-               presses the corresponding function key. For instance, assume
-               that the following function is included in your program's source
-               code:
-
-                    void addPoints(void)
-                    {
-                       /* add ten points to the user's score */
-                       currentUser->points += 10;
-                    }
-
-               If you wanted to have this function called when the sysop
-               presses the [Page Up] key, you could do the following:
-
-                    /* get number of new sysop function key, and increment */
-                    /* total number of keys */
-                    int new_key = od_control.od_num_keys++;
-
-                    /* Set next sysop hotkey to Page Up */
-                    od_control.od_hot_key[new_key] = 0x4900;
-
-                    /* Set corresponding function to addPoints() */
-                    od_control.od_hot_function[new_key] = addPoints;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 215
-
-CONTROL STRUCTURE - COLOR CUSTOMIZATION
--------------------------------------------------------------------------------
-
-               These variables allow you to customize the color of text
-               displayed by OpenDoors. Each of these variables are assigned
-               color attributes, in the format used by od_set_attrib()
-               (described on page 128). These variables are as follows:
-
-               +---------------------+----------------------------------------+
-               | VARIABLE            | WHERE COLOR IS USED                    |
-               +---------------------+----------------------------------------+
-               | od_control.         | Text typed by the sysop and user in    |
-               | od_chat_color1 & 2  | chat mode.                             |
-               |                     |                                        |
-               | od_control.         | File description fields in FILES.BBS   |
-               | od_list_comment_col | listings                               |
-               |                     |                                        |
-               | od_control.         | Color of page pausing prompt that is   |
-               | od_continue_col     | displayed at the end of each page      |
-               |                     |                                        |
-               | od_control.         | Filename fields in FILES.BBS listings  |
-               | od_list_name_col    |                                        |
-               |                     |                                        |
-               | od_control.         | "Missing" string in FILES.BBS listings |
-               | od_list_offline_col |                                        |
-               |                     |                                        |
-               | od_control.         | File size fields in FILES.BBS listings |
-               | od_list_size_col    |                                        |
-               |                     |                                        |
-               | od_control.         | Title fields in FILES.BBS listings     |
-               | od_list_title_col   |                                        |
-               |                     |                                        |
-               | od_control.         | Color of the window title as displayed |
-               | od_menu_title_col   | by od_popup_menu()                     |
-               |                     |                                        |
-               | od_control.         | Color of the window border as          |
-               | od_menu_border_col  | displayed by od_popup_menu()           |
-               |                     |                                        |
-               | od_control.         | Color of the normal text displayed     |
-               | od_menu_text_col    | by od_popup_menu()                     |
-               |                     |                                        |
-               | od_control.         | Color of the shortcut keys displayed   |
-               | od_menu_key_col     | by od_popup_menu()                     |
-               |                     |                                        |
-               | od_control.         | Color of the selection bar as          |
-               | od_menu_highlight_  | displayed by od_popup_menu()           |
-               | col                 |                                        |
-               |                     |                                        |
-               | od_control.         | Color of the shortcut keys displayed   |
-               | od_menu_highkey_col | on the selected line by od_popup_menu()|
-               +---------------------+----------------------------------------+
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 216
-
-CONTROL STRUCTURE - TEXT CUSTOMIZATION
--------------------------------------------------------------------------------
-
-               In addition to the other aspects of OpenDoors which may be
-               customized by use of the OpenDoors control structure, all of the
-               text displayed by OpenDoors may also be customized. This may be
-               done either to create doors with OpenDoors that use languages
-               other than English, or to simply give your doors a "personal
-               touch". The variables described in this section allow you to
-               define what text you want to have displayed by OpenDoors at any
-               time. All of these variables are pointers to strings, and are
-               set to default values in the od_init() function. Thus, if you
-               wish to change the string pointed to by any of these variables,
-               you must do so after od_init() or some OpenDoors API function
-               has been called. To set any of these variables, you can simply
-               set them to point to a string-constant in your program. For
-               example, to set the text displayed by OpenDoors prior to a DOS
-               shell, you could:
-
-               od_control.od_before_shell=(char *)"\n\rJust a moment...\n\r";
-
-               The chart below lists each of the text customization variables
-               (without the "od_control." prefix, for the sake of brevity),
-               along with their default strings.
-
-               Note that some of these strings MUST always be the same length
-               as their default string. You may not display longer text within
-               these strings, and if you wish to display shorter text, you must
-               pad the remaining space in the string with spaces, in order to
-               preserve its length. Those string which must be of fixed length
-               also have their length listed in the chart below. Any strings
-               which have an asterisk (*) in their length column may be any
-               length.
-
-               Also keep in mind that any string with "printf-style" formatting
-               sequences, such as "%s", must retain the same sequences in the
-               same order.
-
-               In addition, four of these pointers - od_after_chat,
-               od_after_shell, od_before_chat and od_before_shell - can be set
-               to a value of NULL. In this case, OpenDoors will not display any
-               string where this variable's string is normally displayed.
-
-+-----------------------+-----+----------------------------------------------+
-| VARIABLE NAME         | LEN | DEFAULT VALUE                                |
-+-----------------------+-----+----------------------------------------------+
-| od_after_chat         |  *  | "\n\rChat mode ended...\n\r\n\r"             |
-|                       |     |                                              |
-| od_after_shell        |  *  | "\n\r...Thanks for waiting\n\r\n\r"          |
-|                       |     |                                              |
-| od_before_chat        |  *  | "\n\rSysop breaking in for chat...\n\r\n\r"  |
-|                       |     |                                              |
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 217
-
-| od_before_shell       |  *  | "\n\rPlease wait a moment...\n\r"            |
-|                       |     |                                              |
-| od_chat_reason        |  *  | "                          Why would you "   |
-|                       |     | "like to chat?\n\r"                          |
-|                       |     |                                              |
-| od_continue           |  *  | "Continue? [Y/n/=]"                          |
-|                       |     |                                              |
-| od_continue_no        | char| 'N'                                          |
-|                       |     |                                              |
-| od_continue_nonstop   | char| '='                                          |
-|                       |     |                                              |
-| od_continue_yes       | char| 'Y'                                          |
-|                       |     |                                              |
-| od_day[0]             |  3  | "Sun"                                        |
-|                       |     |                                              |
-| od_day[1]             |  3  | "Mon"                                        |
-|                       |     |                                              |
-| od_day[2]             |  3  | "Tue"                                        |
-|                       |     |                                              |
-| od_day[3]             |  3  | "Wed"                                        |
-|                       |     |                                              |
-| od_day[4]             |  3  | "Thu"                                        |
-|                       |     |                                              |
-| od_day[5]             |  3  | "Fri"                                        |
-|                       |     |                                              |
-| od_day[6]             |  3  | "Sat"                                        |
-|                       |     |                                              |
-| od_hanging_up         |  *  | "Terminating Call"                           |
-|                       |     |                                              |
-| od_help_text          |  80 | "  Alt: [C]hat [H]angup [L]ockout [J]Dos "   |
-|                       |     | "[K]eyboard-Off [D]rop to BBS            "   |
-|                       |     |                                              |
-| od_help_text2         |  79 | "  OpenDoors 6.00 - (C)Copyright 1992, "     |
-|                       |     | "Brian Pirie - Registered Version         "  |
-|                       |     |                                              |
-| od_inactivity_timeout |  *  | "User sleeping at keyboard, inactivity "     |
-|                       |     | "timeout...\n\r\n\r"                         |
-|                       |     |                                              |
-| od_inactivity_warning |  *  | "Warning, only %d minute(s) remaining "      |
-|                       |     | "today...\n\r\n\r"                           |
-|                       |     |                                              |
-| od_month[0]           |  3  | "Jan"                                        |
-|                       |     |                                              |
-| od_month[1]           |  3  | "Feb"                                        |
-|                       |     |                                              |
-| od_month[2]           |  3  | "Mar"                                        |
-|                       |     |                                              |
-| od_month[3]           |  3  | "Apr"                                        |
-|                       |     |                                              |
-| od_month[4]           |  3  | "May"                                        |
-|                       |     |                                              |
-| od_month[5]           |  3  | "Jun"                                        |
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 218
-
-|                       |     |                                              |
-| od_month[6]           |  3  | "Jul"                                        |
-|                       |     |                                              |
-| od_month[7]           |  3  | "Aug"                                        |
-|                       |     |                                              |
-| od_month[8]           |  3  | "Sep"                                        |
-|                       |     |                                              |
-| od_month[9]           |  3  | "Oct"                                        |
-|                       |     |                                              |
-| od_month[10]          |  3  | "Nov"                                        |
-|                       |     |                                              |
-| od_month[11]          |  3  | "Dec"                                        |
-|                       |     |                                              |
-| od_no_keyboard        |  10 | "[Keyboard]"                                 |
-|                       |     |                                              |
-| od_no_sysop           |  *  | "\n\rI'm afraid the sysop is not available " |
-|                       |     | "at this time.\n\r"                          |
-|                       |     |                                              |
-| od_no_response        |  *  | " No response.\n\r\n\r"                      |
-|                       |     |                                              |
-| od_no_time            |  *  | "Sorry, you have used up your time for "     |
-|                       |     | "today...\n\r\n\r"                           |
-|                       |     |                                              |
-| od_offline            |  10 | "[OFFLINE] "                                 |
-|                       |     |                                              |
-| od_paging             |  *  | "\n\rPaging Sysop for Chat"                  |
-|                       |     |                                              |
-| od_press_key          |  *  | "Press [Enter] to continue..."               |
-|                       |     |                                              |
-| od_sending_rip        |  *  | "\xb4 Sending RIP File \xc3"                 |
-|                       |     |                                              |
-| od_status_line[0]     |  80 | "                                        "   |
-|                       |     | "                             [Node:     "   |
-|                       |     |                                              |
-| od_status_line[1]     |  *  | "%s of %s at %u BPS"                         |
-|                       |     |                                              |
-| od_status_line[2]     |  79 | "Security:        Time:                  "   |
-|                       |     | "                             [F9]=Help "    |
-|                       |     |                                              |
-| od_sysop_next         |  5  | "[SN] "                                      |
-|                       |     |                                              |
-| od_time_left          |  10 | "%d mins   "                                 |
-|                       |     |                                              |
-| od_time_warning       |  *  | "Warning, only %d minute(s) remaining tod"   |
-|                       |     | "ay...\n\r\n\r"                              |
-|                       |     |                                              |
-| od_want_chat          |  11 | "[Want-Chat]"                                |
-+-----------------------+-----+----------------------------------------------+
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 219
-
-    66
-   66
-  66
- 66666
- 66  66
- 66  66
-  6666
--------------------------------------------------------------------------------
-CHAPTER 6 - SPECIAL TOPICS
-
-
-
-
-ADDITIONAL INFORMATION ON THE WIN32 VERSION
--------------------------------------------------------------------------------
-
-               This section provides additional information on the Win32
-               version of OpenDoors that isn't found elsewhere in this manual.
-               If you are working with the Win32 version of OpenDoors, you
-               should take the time to read this entire section. You should
-               also read the sections in chapter 3 that describe how to compile
-               and run Win32 programs that use OpenDoors.
-
-               The Win32 version of OpenDoors has been designed to be as
-               similar as possible to the DOS version of OpenDoors. This means
-               that where possible, you can compile the same source code to
-               produce both a DOS and a Windows program. However, if you are
-               porting an existing DOS OpenDoors-based program to the Win32
-               platform, there are some important things to keep in mind.
-
-               The first thing to note is that under DOS, the program's
-               execution begins in the main() function, whereas under Windows,
-               it begins in the WinMain() function. To allow the same source
-               file to build both DOS and Windows versions you can use
-               conditional compilation. OpenDoor.h defines a constant of the
-               form ODPLAT_xxx, indicating which version of OpenDoors is being
-               used. Currently, this will be either ODPLAT_DOS, or
-               ODPLAT_WIN32. However, if a OS/2 or Unix version of OpenDoors
-               were created, they would use definitions such as ODPLAT_OS2, or
-               ODPLAT_UNIX. Under the Win32 version, you should pass the
-               nCmdShow parameter that is passed to WinMain into OpenDoors,
-               through od_control.od_cmd_show. If you do not do this, the
-               program will always start with the main window maximized,
-               regardless of what the user has requested. Also, you will
-               probably want to use the new od_parse_cmd_line() function in
-               both DOS and Windows programs, to allow standard command-line
-               options to be processed. The od_parse_cmd_line() function
-               accepts command line information in the same format as it is
-               passed to the main or WinMain() function. So, the general
-               structure of an OpenDoors program that can be compiled under
-               either DOS or Win32 now becomes:
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 220
-
-               /* Add your own #includes here. */
-
-               #include "opendoor.h"
-
-               #ifdef ODPLAT_WIN32
-               int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-                  LPSTR lpszCmdLine, int nCmdShow)
-               #else
-               int main(int argc, char *argv[])
-               #endif
-               {
-                    /* Add local variables here. */
-
-               #ifdef ODPLAT_WIN32
-                  od_control.od_cmd_show = nCmdShow;
-
-                  od_parse_cmd_line(lpszCmdLine);
-               #else
-                  od_parse_cmd_line(argc, argv);
-               #endif
-
-                    /* Add the rest of your program after this point. */
-               }
-
-               If you are porting existing OpenDoors programs over to the Win32
-               version of OpenDoors, another issue that you will have to pay
-               careful attention to is the fact that you are now working in the
-               32-bit world. While 32-bit programming under a flat memory model
-               has many advantages (no more 64K segments and related
-               limitations, for example), you must be aware that the size of
-               basic data types that you are used to using may have changed.
-               For example, an int is now 32-bits wide instead of 16-bits wide.
-               One of the places where this difference becomes very important
-               is if you are performing file-I/O by directly dumping a
-               structure to or from disk using functions such as fread() and
-               fwrite(). In this case, you must declare your structures using
-               types that are of the same size between the 16-bit and 32-bit
-               worlds, in order for your file formats to be compatible between
-               the DOS and Win32 versions of your program. For example, the
-               EX_VOTE.C example program declares its structure using fixed-
-               sized types that are always available to any program including
-               "opendoor.h". These types are the following size, regardless of
-               what platform you are compiling under:
-
-               INT8     - 8-bit signed integer.
-               INT16    - 16-bit signed integer.
-               INT32    - 32-bit signed integer.
-               BYTE     - 8-bit unsigned integer.
-               WORD     - 16-bit unsigned integer.
-               DWORD    - 32-bit unsigned integer.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 221
-
-               (NOTE: Obviously, the many details of 32-bit programming and
-               Windows programming are beyond the scope of this document. For
-               more information on the issues discussed here, you will probably
-               wish to consult other sources of information on Win32
-               programming.)
-
-               As you are probably aware, the Win32 edition of OpenDoors makes
-               extensive use of multithreading. The number of threads will
-               depend on what mode OpenDoors is operating in. In some
-               situations, all of the following threads may exist:
-
-               - The client thread(s), which executes the code that you write
-                 in your program, along with the OpenDoors API functions.
-               - The local screen thread, which is responsible for drawing
-                 your program's output on the screen, and receiving input from
-                 the local keyboard.
-               - The frame window thread, which handles the OpenDoors menus,
-                 toolbar, status bar and sysop function keys.
-               - The remote input thread, which receives input from the serial
-                 port and adds it to OpenDoors common local/remote input
-                 queue.
-               - The carrier detection thread, which blocks and only executes
-                 if the carrier detect signal goes low.
-               - The time update thread, which updates the user's time
-                 remaining online, and monitors user timeouts.
-
-               Since most of these threads only execute when the operating
-               system determines that there is actually something for them to
-               do, the Win32 version of OpenDoors provides very high
-               performance and responsiveness.
-
-               You may also want to make use of multithreading directly within
-               your program. If you do this, please note that while you may use
-               threads to perform background processing, OpenDoors requires
-               that you only call OpenDoors API functions from one thread.
-
-               If you wish to customize the information that is displayed in
-               the Help|About dialog box (including your program's name and
-               copyright information), provide your own application icon, or
-               add online help to the help menu, refer to the sections in the
-               manual on the following od_control variables:
-
-                    od_control.od_app_icon
-                    od_control.od_help_callback
-                    od_control.od_prog_name
-                    od_control.od_prog_version
-                    od_control.od_prog_copyright
-
-               The section that describes how to run Windows based door
-               programs under DOS-based BBS package indicates that
-               COM<n>AutoAssign=0 should be set in the system.ini file. The
-               explanation for this is as follows: The default value for this
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 222
-
-               setting in Windows 95 is -1, which prevents any Windows-based
-               program from accessing a serial port which has previously been
-               used by a non-Windows-based program, until the window that
-               program was running in is closed. By setting this value to 0,
-               you are allowing the Windows-based door program to immediately
-               use the modem, even while the MS-DOS session (VM) is still
-               active. A value of <x> greater than 0 will allow Windows-based
-               programs to access the serial port, only if the DOS-based
-               program has not accessed the serial port for at least <x>
-               seconds. For example, the default setting in Windows 3.1 was
-               COM1AutoAssign=2, which allowed Windows-based programs to access
-               the serial port if no DOS program had used it for at least 2
-               seconds.
-
-               The section that describes how to run Windows based door
-               programs under DOS-based BBS package also indicates that the
-               DTRON utility should be run after the start command returns. The
-               reason for this is that when a Windows program exits and closes
-               the serial port (by calling the CloseHandle() function), Windows
-               95 lowers the DTR line on the serial port. Most modems are
-               configured to respond to this by hanging up on the remote user.
-               From talking to other people, it seems that this "feature" (or
-               fundamental design flaw, depending on how you want to look at
-               it) is unique to Windows 95, and won't effect OpenDoors when
-               running under Windows NT. However, the majority of people will
-               undoubtedly be using the Win32 version of OpenDoors under
-               Windows 95. This is unfortunate, since the Win32 communications
-               facilities are otherwise _very_ well designed. There is a rumor
-               that Microsoft's next upgrade to Windows 95 will fix this
-               problem. However, I must stress that this is only a rumor, and
-               that I haven't received any confirmation about this from
-               Microsoft.
-
-               OpenDoors currently provides two solutions to this problem.
-
-               First of all, OpenDoors has the ability to use an already open
-               serial port handle, if that information is supplied to it.
-               Hopefully, all Windows 95-based BBS software will provide the
-               option of running a door program with the serial port still
-               open, and allow you to pass that serial port handle on the door
-               program's command line. OpenDoors allows the serial port handle
-               to be passed on the command line, or set directly in the
-               od_control structure, as is described later in this manual. On
-               BBS systems where this form of hot sharing of the serial port is
-               supported, the serial port can remain open at all times, and so
-               the CloseHandle() problem is avoided.
-
-               This means that the only situation where the CloseHandle()
-               problem still has to be dealt with is when OpenDoors is running
-               on a Windows 95 system and OpenDoors has to open the serial port
-               itself (and so must close the serial port before exiting). This
-               would be the case for most MS-DOS based BBS systems running
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 223
-
-               under Windows 95, unless some intermediate layer is provided. By
-               default, in this situation OpenDoors will disable DTR response
-               by the modem just before it closes the serial port, by sending
-               the AT&D0 command to the modem. The exact sequence of commands
-               used by OpenDoors to do this is specified by the
-               od_control.od_disable_dtr string. This DTR response disabling
-               may be turned off by setting the DIS_DTR_DISABLE
-               od_control.od_disable flag. Since many programs (OpenDoors
-               included) assume that they can hangup the modem by lowering the
-               DTR signal, a small utility will usually be run after the door,
-               which first raises the DTR signal again, and then re-enables DTR
-               response by the modem. Such a utility is included in this
-               package, named DTRON.EXE. I wrote the DTRON utility so that you
-               can freely redistributed it with your programs.
-
-               So, to summarize, the DTR disabling by OpenDoors and subsequent
-               reenabling by DTRON is only required for the Win32 version of
-               OpenDoors running under Windows 95 when the modem is configured
-               to hangup if the DTR signal is lowered, and the BBS software
-               does not have the ability to pass a live serial port handle to a
-               door program. Setting COM<n>AutoAssign in system.ini is only
-               required for the Win32 version of OpenDoors when it is being
-               called from an MS-DOS session that has previously accessed the
-               serial port.
-
-               Note that the Win32 version of OpenDoors requires Windows 95 or
-               Windows NT. It will not run under Windows 3.x, even with Win32s.
-               This is because OpenDoors makes use of the Windows 95/NT
-               multitasking and multithreading services that are not available
-               under Win32s.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 224
-
-CONFIGURATION FILE SYSTEM
--------------------------------------------------------------------------------
-
-               One of the most useful OpenDoors features that you can
-               optionally choose to include in your programs is the OpenDoors
-               configuration file system. All that is required to enable the
-               configuration file system is to include the following line
-               before your first call to any OpenDoors function:
-
-                    od_control.od_config_file = INCLUDE_CONFIG_FILE;
-
-               OpenDoors will now search for and read an OpenDoors
-               configuration file. If you do not specify the name of this file,
-               the default name of DOOR.CFG will be used. Using this
-               configuration file, the sysop can set a wide variety of options,
-               such as modem and system configuration information, maximum time
-               limits for the door, and even define custom door information
-               (drop) file formats. The example DOOR.CFG file included in your
-               OpenDoors package shows the format and all options that are
-               automatically supported by the configuration file system. This
-               configuration file format is designed to be easy to use, and the
-               example configuration file contains comments which provide a
-               complete description of each option. Feel free to redistribute
-               DOOR.CFG or a modified version of this file with your door
-               programs. In addition to the many configuration file settings
-               already supported, you can add your own settings that are
-               specific to your particular program.
-
-               To specify your own filename for the configuration file, use the
-               od_config_filename control structure variable. For example, the
-               following line:
-
-                    od_control.od_config_filename = "MYDOOR.CFG"
-
-               causes OpenDoors to look for the configuration file MYDOOR.CFG
-               instead of the default DOOR.CFG.
-
-               OpenDoors fill first search for the configuration file in the
-               directory specified in the od_config_filename variable, if a
-               specific directory name was supplied. If not found, it will then
-               search the current directory. If the configuration file system
-               is unable to locate a configuration file, or if any settings are
-               omitted from the file, the default values for these settings
-               will be used automatically. This means that the configuration
-               file is always optional, unless your program has custom settings
-               that it requires in order to run.
-
-               The format for the configuration file is as follows. Blank lines
-               and any text following the semi-colon (;) character are ignored.
-               Configuration options are specified using a keyword, possibly
-               followed by one or more options. The keywords are not case
-               sensitive, but some of the options are. The order of options in
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 225
-
-               the configuration file is not significant, with the exception of
-               the "CustomFileLine" option. For more information on the
-               "CustomFileLine" setting, see the section that begins on page
-               230. The built-in configuration options are as follow:
-
-               BBSDir - BBS System directory. Indicates where the door
-                    information file (drop file) can be found.
-
-               DoorDir - The door's working directory. This is where the door's
-                    system files are located. OpenDoors will automatically
-                    perform a chdir into this directory at initialization, and
-                    will return to the original directory on exit.
-
-               LogFileName - Specifies the filename (path optional) where the
-                    door should record log information.
-
-               DisableLogging - Prevents door from writing to a log file.
-
-               Node - BBS node number that the door is running on. Only used if
-                    OpenDoors is unable to determine the node number by some
-                    other means.
-
-               ???dayPagingHours - Specifies sysop paging hours. Sysop paging
-                    will be permitted beginning at the start time, up until,
-                    but not including, the end time. Times should be in the 24-
-                    hour format. To disable paging on a particular day, set the
-                    paging start and end times to the same time. ???day can be
-                    one of Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
-                    or Saturday.
-
-               PageDuration - Duration of sysop page. Value indicates the
-                    number of beeps that compose the sysop page alarm.
-
-               MaximumDoorTime - Maximum length of time a user is permitted to
-                    access the door. If the user's total remaining time on the
-                    BBS is less than this value, the user will only be
-                    permitted to access the door for this shorter length of
-                    time. This option is disabled by commenting out the line.
-
-               InactivityTimeout - Specifies the maximum number of seconds that
-                    may elapse without the user pressing a key, before the user
-                    will automatically be disconnected. A value of 0 disables
-                    inactivity timeouts.
-
-               SysopName - Name of the sysop. OpenDoors can usually determine
-                    the sysop's name from the door information (drop) file.
-                    How3ever, some BBS packages do not supply this information.
-                    In such cases, if the sysop's name is required by the door,
-                    it may be supplied here.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 226
-
-               SystemName - Like the sysop's name, this option can usually be
-                    determined from the door information file. If it is not
-                    available, the sysop my supply the information here.
-
-               ChatUserColor - Specifies the color of text typed by the user in
-                    sysop chat mode. The format of the color name is included
-                    in the description of the od_color_config() function.
-
-               ChatSysopColor - Specifies the color of test typed by the sysop
-                    in chat mode.
-
-               FileListTitleColor - Files.BBS listing colors.
-               FileListNameColor
-               FileListSizeColor
-               FileListDescriptionColor
-               FileListOfflineColor
-
-               SwappingDir - Directory where disk swapping will be done.
-
-               SwappingNoEMS - Disables swapping to EMS memory.
-
-               SwappingDisable - Disables swapping entirely.
-
-               LockedBPS -  BPS rate at which door should communicate with the
-                    modem.  Valid rates are 300, 600, 1200, 2400, 4800, 9600,
-                    19200 and 38400. A value of 0 forces the door to always
-                    operate in local mode. This option is not normally needed,
-                    as the information is usually available from the door
-                    information file.
-
-               FossilPort - Specifies the FOSSIL driver port number that the
-                    modem is connected to. FOSSIL port 0 usually corresponds to
-                    COM1, port 1 to COM2, and so on. This option is not
-                    normally needed, as the information is usually available
-                    from the door information file.
-
-               CustomFileName - Specifies the filename used by the custom door
-                    information file format. Described in more detail below.
-
-               CustomFileLine - Specifies the contents of a particular line in
-                    the custom door information file format.
-
-               The last two configuration file options, "CustomFileName" and
-               "CustomFileLine" allow you or the system operator using your
-               program to define your own door information (drop) file formats.
-               For more information on this topic, see the section which begins
-               on page 230.
-
-               You can also extend OpenDoor's configuration file format to add
-               your own options, by supplying a callback function that will be
-               called whenever OpenDoors encounters an unrecognized
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 227
-
-               configuration file keyword. The prototype of this function
-               should be as follows:
-
-                    custom_line_function(char *keyword, char *options)
-
-               To cause OpenDoors to use your function, you would include the
-               following line before your first call to any OpenDoors function:
-
-                    od_control.od_config_function = custom_line_function;
-
-               (You can use a different function name if you wish.) When
-               OpenDoors encounters unrecognized keyword, it will now call your
-               function, passing a pointer to an upper case version the keyword
-               string in the first parameter, and a pointer to any options that
-               follow the keyword in the second parameter. For instance, if the
-               following line were encountered in the configuration file:
-
-                    RegisteredTo    John Smith      ; Sysop's name
-
-               The parameters passed to your function would be:
-
-                    char *keyword = "REGISTEREDTO"
-                    char *options = "John Smith"
-
-               Your custom line function should be written in such a way that
-               if OpenDoors passes a configuration option to your function that
-               your function does not recognize, that option would simply be
-               ignored.
-
-               The example program below demonstrates how to use the custom
-               line function to add your own configuration file options. This
-               program looks for three custom configuration file options,
-               "RegistrationKey", "DefaultColor" and "DisplayWinners". If the
-               "RegistrationKey" option is present, the numerical value
-               following this option is stored in the global variable "key". If
-               the "DefaultColor" option is present, the color description
-               (such as "Bright Red on Black") is translated to an
-               od_set_attr() color code using od_color_config(). This color
-               setting is stored in the global variable default_color. Since
-               this variable is initialized to 0x07 (the value for dark white
-               on black), if this option is omitted, that color is used by
-               default. If the "DisplayWinners" option is included in the
-               configuration file, the global variable display_winners is set
-               to TRUE, regardless of any options that may follow this keyword.
-
-
-               #include "opendoor.h"                  /* Include opendooor.h */
-                                       /* Prototype for custom line function */
-               void custom_line_function(char *keyword, char *options);
-
-               unsigned long key=0L; /* Variables for our own config option */
-               unsigned char default_color=0x07;
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 228
-
-               char display_winners=FALSE;
-
-               main()                     /* Program's execution begins here */
-               {               /* Begin door operations, reading config file */
-                  od_control.od_config_file = INCLUDE_CONFIG_FILE;
-                               /* Tell OpenDoors to use custom line function */
-                  od_control.od_config_function = custom_line_function;
-                  od_init();
-                  /* Main program's operations go here */
-                  od_exit(10, FALSE);                        /* Exit program */
-               }
-                                            /* Code for custom line function */
-               void custom_line_function(char *keyword, char *options)
-               {                            /* If option is registration key */
-                  if(stricmp(keyword,"REGISTRATIONKEY")==0)
-                  {
-                     key=atol(options);             /* Store key in variable */
-                  }                               /* If option is text color */
-                  else if(stricmp(keyword,"DEFAULTCOLOR")==0)
-                  {               /* Get color value using od_color_config() */
-                     default_color=od_color_config(options);
-                  }         /* Example of option enabled by just the keyword */
-                  else if(stricmp(keyword,"DISPLAYWINNERS")==0)
-                  {                 /* If keyword is present, turn on option */
-                     display_winners=TRUE;
-                  }
-               }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 229
-
-DEFINING CUSTOM DOOR INFORMATION FILE FORMATS
--------------------------------------------------------------------------------
-
-               As is mentioned in the previous section, the OpenDoors
-               configuration file system provides two settings which allow the
-               sysop to define a custom door information file format. This
-               permits OpenDoors doors to operate directly on any BBS system
-               that produces a door information file format not directly
-               supported by OpenDoors. A custom door information file format is
-               defined using the "CustomFileName" option, followed by one or
-               more lines beginning with the "CustomFileLine" option.
-
-               The "CustomFileName" option specifies the filename used to
-               distinguish this file format from other file formats. This
-               filename should not include a path. To specify the path where
-               the door information file is located, the sysop should use the
-               BBSDir configuration file setting. If the filename of the custom
-               format is the same as that of one of the built-in formats, the
-               custom format will override the built-in format.
-
-               The actual format of the custom file is specified using a number
-               of lines that begin with the keyword "CustomFileLine". Each of
-               these lines will correspond to a single line in the door
-               information file, with the option following the "CustomFileLine"
-               keyword specifying the information that can be found on that
-               line. This can be one of the following keywords:
-
-                    Ignore - Causes the next line in the door information file
-                         to be ignored. Use on lines for which none of the
-                         options below apply.
-
-                    COMPORT - COM? port the modem is connected to (0 indicates
-                         local mode)
-
-                    FOSSILPORT - Fossil port number the modem is connected to
-
-                    MODEMBPS - BPS rate at which to communicate with modem (0
-                         or non-numerical value indicates local mode)
-
-                    LOCALMODE - 1, T or Y if door is operating in local mode
-
-                    USERNAME - Full name of the user
-
-                    USERFIRSTNAME - First name(s) of the user
-
-                    USERLASTNAME - Last name of the user
-
-                    ALIAS - The user's pseudonym / handle
-
-                    HOURSLEFT - Hours user has left online
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 230
-
-                    MINUTESLEFT - Minutes user has left online, or time left
-                         online in format hh:mm
-
-                    SECONDSLEFT - Seconds user has left online, or time left
-                         online in format hh:mm:ss or format mm:ss (If more
-                         than one of the above time options are used, the user
-                         time left is taken to be the total of all of these
-                         values.)
-
-                    ANSI - 1, T, Y or G for ANSI graphics mode
-
-                    AVATAR - 1, T or Y for AVATAR graphics mode
-
-                    PAGEPAUSING - 1, T or Y if user wishes a pause at end of
-                         screen
-
-                    SCREENLENGTH - Number of lines on user's screen
-
-                    SCREENCLEARING - 1, T or Y if screen clearing mode is on
-
-                    SECURITY - The user's security level / access level
-
-                    CITY - City the user is calling from
-
-                    NODE - Node number user is connected to
-
-                    SYSOPNAME - Full name of the sysop
-
-                    SYSOPFIRSTNAME - The sysop's first name(s)
-
-                    SYSOPLASTNAME - The sysop's last name
-
-                    SYSTEMNAME - Name of the BBS
-
-               As an example of how to define custom door information file
-               formats, consider the following imaginary file format, which we
-               will name DROPINFO.TXT:
-
-                    Brian Pirie         <-- User name
-                    0                   <-- Local mode
-                    COM1:               <-- Serial port to use
-                    9600                <-- BPS rate
-                    22:30:15 05-08-95   <-- File creation time
-                    35                  <-- Time remaining (in minutes)
-                    1                   <-- ANSI mode
-                    Ottawa, Canada      <-- Location
-
-               This format would be defined in an OpenDoors configuration file
-               as follows:
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 231
-
-                    CustomFileName DROPINFO.TXT
-                    CustomFileLine USERNAME
-                    CustomFileLine LOCALMODE
-                    CustomFileLine COMPORT
-                    CustomFileLine MODEMBPS
-                    CustomFileLine IGNORE
-                    CustomFileLine MINUTESLEFT
-                    CustomFileLine ANSI
-                    CustomFileLine CITY
-
-               Notice that the first "CustomFileLine" keyword in the
-               configuration file corresponds to the first line in our
-               DROPINFO.TXT file, the second "CustomFileLine" to the second
-               line, and so on. Also notice that the keyword "IGNORE" is used
-               for the line that contains the file creation time, since there
-               is no CustomFileLine keyword that allows you to read this
-               information.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 232
-
-MULTIPLE PERSONALITY SYSTEM
--------------------------------------------------------------------------------
-
-               The OpenDoors Multiple Personality System allows  the DOS
-               version of OpenDoors to support multiple sysop function key /
-               status line "personalities". Most commonly, you will use this
-               feature in conjunction with the "Personality" setting in the
-               OpenDoors configuration file, to allow the sysop to choose one
-               of the built-in personalities that most closely mimics the BBS
-               software they are using. OpenDoors includes the following
-               personalities:
-
-                    Configuration Keyword         Manifest constant
-                    -----------------------------------------------------------
-                    Standard                      PER_OPENDOORS
-                    PCBoard                       PER_PCBOARD
-                    RemoteAccess                  PER_RA
-                    Wildcat                       PER_WILDCAT
-
-               The PCBoard, RemoteAccess and Wildcat personalities mimic the
-               status lines and function keys used by the BBS packages with
-               those names. The Standard personality, which is the personality
-               used by default, is a trimmed down version of the status lines
-               provided by OpenDoors 4.10 and earlier.
-
-               In addition to using the personalities supplied with OpenDoors,
-               you can create your own personalities. This simply involves
-               writing a function which OpenDoors will call to setup the sysop
-               function keys and to display the status line.
-
-               Include the following line before your first call to any
-               OpenDoors function:
-
-                    od_control.od_mps = INCLUDE_MPS;
-
-               to include the multiple personality system in your program. This
-               also enables the Personality setting in the configuration file,
-               if you are using the configuration file system.
-
-               You can set the default personality to be used by OpenDoors by
-               setting od_control.od_default_personality to one of the manifest
-               constants listed in the table above. If you have included the
-               multiple personality system in your program, this setting will
-               determine the personality to use if the "Personality" option is
-               not set in the configuration file, and your program does not
-               later change the personality using the od_set_personality()
-               function. If you do not include the multiple personality system
-               in your program, this setting will determine the personality
-               that will always be used.
-
-               Creating your own personality involves writing a single
-               function.. Whenever OpenDoors needs to perform an operation that
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 233
-
-               involves the personality, it will call this function, passing
-               one of the following message values:
-
-               PEROP_INITIALIZE    Initialize the personality, installing any
-                                   custom function keys.
-               PEROP_DEINITIALIZE  Deinitialize the personality, returning any
-                                   changed settings to their original values.
-               PEROP_CUSTOMKEY     Indicates that a custom function key has
-                                   been pressed.
-               PEROP_DISPLAYx      Where x is a number from 1 to 10. Indicates
-                                   that the specified status line should be
-                                   drawn from scratch.
-               PEROP_UPDATEx       Where x is a number from 1 to 10. Indicates
-                                   that the specified status line should be
-                                   updated to reflect any changes.
-
-               If you have enabled the multiple personality system by setting
-               od_control.od_mps to INCLUDE_MPS, you can install your
-               personality function into OpenDoors by calling
-               od_add_personality(). When you call od_add_personality(), you
-               supply a string containing the name of the personality, along
-               with the top and bottom output line numbers to use. These line
-               numbers specify the portion of the screen to use for door
-               output, leaving the remainder of the screen available for
-               displaying the personality's status line. Once the personality
-               has been installed into OpenDoors, it can be selected by the
-               sysop using the "Personality" configuration file option, or
-               manually activated using the od_set_personality() function. For
-               more information on the od_add_personality() function, see page
-               47.
-
-               You can make your personality function the default personality
-               by setting od_control.od_default_personality to point to your
-               personality function. As is the case with the built-in
-               personalities, this setting will be used as the default
-               personality if you have enabled the multiple personality system
-               by setting od_control.od_mps to INCLUDE_MPS. If you have not
-               enabled the multiple personality system in this manner, your
-               personality function will become the one and only personality
-               used within your program. When creating your own personality,
-               you can use the od_control.od_page_statusline variable to set
-               which status line (if any) will be activated when the user pages
-               the system operator.
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 234
-
-LOG FILE SYSTEM
--------------------------------------------------------------------------------
-
-               In order for the system operator to monitor system activity and
-               diagnose problems that have occurred while the system was
-               unattended, it is common for BBS software and door programs to
-               record major events in a log file. This log file typically
-               records the date and time of evens such as a user logging on or
-               off, transferring files, sending messages, paging the system
-               operator, and similar activities. Sometimes the system operator
-               will configure all of the pieces of software running on a
-               particular node to write to a single log file. In other cases,
-               the system operator will prefer to have each program write to
-               its own log file. However, software serving one line of a multi-
-               node BBS system should never attempt to write to the same log
-               file that is used by another node.
-
-               OpenDoors uses the "FrontDoor format" log file standard. This
-               was chosen as it is a clearly documented format that is quickly
-               becoming the standard for bulletin board software log files. A
-               segment from a log file produced by OpenDoors is listed below.
-
-                         ----------  Thu 25 Feb 93, Vote 6.00
-                         > 19:42:23  Brian Pirie entering door
-                         > 19:50:55  User paging system operator
-                         > 19:51:02  Entering sysop chat mode
-                         > 20:05:41  Terminating sysop chat mode
-                         > 20:18:32  User time expired, exiting door
-
-               To enable the OpenDoors log file system, simply include the
-               following line before your first call to any OpenDoors function:
-
-                    od_control.od_logfile = INCLUDE_LOGFILE;
-
-               When OpenDoors is initialized, it will open the log file and
-               begin logging activities, unless logging has been disabled with
-               the od_control.od_logfile_disable variable. The log file name
-               will be taken from the od_control.od_logfile_name variable,
-               which is usually set by the configuration file. If no logfile
-               name has been set, OpenDoors will use the logfile named
-               DOOR.LOG. Upon opening the log file, OpenDoors will write an
-               entry indicating the time at which the use entered the door.
-
-               The od_control.od_prog_name variable sets the program name that
-               is written to the log file immediately after the current date
-               information. If this variable is not set, OpenDoors will write
-               its own name and version information in this place.
-
-               When the OpenDoors log file system is enabled, OpenDoors will
-               automatically produce logfile entries for the following events:
-
-                         - User paging sysop, beginning of chat, end of chat
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 235
-
-                         - Sysop entering or returning from DOS shell
-                         - User inactivity timeout or user time expired
-                         - Sysop dropping user back to BBS
-                         - Sysop hanging up on user, sysop locking out user
-                         - User hanging up on BBS
-                         - Your program calling the od_exit() function
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 236
-
-MAKING DOORS MULTI-NODE-AWARE
--------------------------------------------------------------------------------
-
-               While the majority of BBS systems have only a single phone line,
-               allowing only one user to access the system at a time, there are
-               also many multi-node BBS systems. On such systems, it is quite
-               possible that more than one user may be using your door program
-               simultaneously. OpenDoors itself is designed for both single-
-               node and multi-node operation. However, if you want your program
-               to operate correctly on multi-node systems, there are a number
-               of concurrency issues that you must keep in mind when writing
-               your own code.
-
-               Some door programs are designed to behave on multi-node systems
-               just as they would on single-line BBSes. Others add special
-               features only possible in multi-node environments. For instance,
-               you may want to permit users to interact or chat with one
-               another in "real time". Many simple doors may not require any
-               special attention to multi-node capabilities. However, if your
-               door must access any data files or other resources that are to
-               be shared among nodes, it is necessary to carefully coordinate
-               access to these resources.
-
-               There are two primary issues that are often of concern when
-               creating door programs for multi-node systems. The first issue
-               discussed below is how to coordinate concurrent file access
-               between multiple node. The second topic we will deal with is the
-               installation of door programs on multi-node systems.
-
-
-
-CONCURRENT FILE ACCESS
--------------------------------------------------------------------------------
-
-               One of the most important issues that arises when writing door
-               programs for multi-node systems is how to coordinate
-               simultaneous access to a single data file by multiple instances
-               of your program. While it is generally safe to have multiple
-               nodes reading simultaneously from a single file, having multiple
-               nodes updating a file without any coordination can lead to lost
-               updates and other problems. Consider, for example, the EX_VOTE.C
-               example program that is included in your OpenDoors package. When
-               the user votes on a poll, EX_VOTE.C must update the total number
-               of votes for the user's answer. Such a program that is only
-               intended for single node operation could do this by simply
-               reading the current number of votes for the appropriate option,
-               adding one to this total, and writing the updated total back to
-               the file. However, if this approach where to be used on a multi-
-               node system, it is quite possible that two users would vote on
-               the same poll after both nodes have read the poll record into
-               memory. In this situation, one node would add one to the total
-               number of votes for the poll record that it has in memory, and
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 237
-
-               write the updated information to the file. The second node would
-               then add one to its total, without reading the updated
-               information written by the first node. When the second node then
-               writes this information to the file, it overwrites the first
-               node's total with its own. The final effect is that the second
-               user's vote overwrites the first, and so the first user's vote
-               is lost.
-
-               The solution to this problem is to lock a file unit for the
-               entire update operation, to prevent other nodes from accessing
-               the unit at the same time. This unit could be the entire file,
-               or only a single record in the file. EX_VOTE.C locks its entire
-               file when performing an update operation, but in other cases it
-               may be more appropriate to only lock a single record in the
-               file. The important thing to understand is that when one node
-               locks a file unit, other nodes much wait until the first node is
-               finished the update operation. This means that if one node is
-               updating information that other nodes could possibly need access
-               to, it should always perform the lock, read, write and unlock
-               cycle as quickly as possible.
-
-               Let's look again at the approach taken by EX_VOTE.C. After the
-               user has indicated which option he/she wishes to vote on, Vote
-               attempts to open the file for exclusive access. By doing this,
-               EX_VOTE.C in effect locks the entire file for the duration that
-               it has the file open. If another node attempts to open the file
-               while one node has it locked, the open operation will fail, and
-               the C runtime library will set the errno variable to EACCES.
-               This, in effect, tells you that another node is currently
-               working on the file, and that you must wait your turn. In this
-               case, EX_VOTE.C continues to retry the open operation until the
-               other node is finished its update, at which time the open
-               operation will succeed. This approach will even work when there
-               are many nodes that are attempting to update the file at the
-               same time. Whichever node first attempts to open the file will
-               gain exclusive access to the file, and any additional nodes are
-               forced to wait for access to the file. When one node finishes
-               with the file, another node will gain access to the file
-               (whichever happens to be the next node to re-attempt the open
-               operation). This process continues until all waiting nodes have
-               had a chance to perform their update. EX_VOTE.C will repeatedly
-               try to open the file for up to 20 seconds, after which time it
-               will give up, reporting an error which indicate that it is
-               unable to access the file. During this waiting process,
-               EX_VOTE.C repeatedly calls od_kernel(), so that sysop function
-               keys, carrier detection and other essential door operations can
-               continue to be performed.
-
-               After EX_VOTE.C has successfully secured exclusive access to the
-               file, it first reads the record that it is going to update. It
-               is important that this be done after the file unit is locked, in
-               order to ensure that the copy of the record in memory matches
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 238
-
-               what is stored in the file. EX_VOTE.C then updates the record
-               based on the question on which the user has voted, writes this
-               information back to the file. EX_VOTE.C then immediately closes
-               the file, allowing other nodes to also access the file.
-               EX_VOTE.C is very carefully designed so that the file update
-               operation can never be interrupted (for instance, no OpenDoors
-               functions are called, which could detect a time-out and
-               terminate the program while a file update operation is in
-               progress), or delayed until the user makes a response. As such,
-               the file unit is always unlocked (in this case, closed) within a
-               fraction of a second after it was locked, or order that other
-               nodes will never have to wait long for access to the file.
-
-               Here I have presented a detailed account of how EX_VOTE.C
-               handles multi-node file access. While all of the details
-               involved in coordinating multiple file access can be
-               overwhelming at first, they will begin to come naturally to you,
-               as you begin to always think in terms of multi-node scenarios.
-               To summarize, the important elements that are typically involved
-               in multi-node file access are:
-
-               A. Decide on an appropriate file unit to lock for your
-                  application. In simple cases, this can be the entire file.
-                  In other cases, you may wish to lock individual file
-                  records, using the appropriate runtime library functions.
-
-               B. Always perform update operations in lock, read, update,
-                  write, unlock cycles on individual file units. If there is a
-                  chance that other nodes will also need to access the file
-                  unit, ensure that the update operation cannot be interrupted
-                  or delayed until a user makes a response.
-
-               After you have designed your program for concurrent file access,
-               how can you test it? If you don't have a multi-node BBS system
-               that you have access to, you can perform most of your testing
-               under a multitasking environment, with multiple copies of your
-               program running in different windows.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 239
-
-MULTI-NODE CONFIGURATION
--------------------------------------------------------------------------------
-
-               A second issue that you may want to bear in mind is how door
-               programs are typically setup on multi-node systems.
-               Unfortunately, this may differ considerable depending upon which
-               BBS software is being used. However, some of the issues that you
-               may have to consider discussed below:
-
-               A. Your program must be able to locate the correct door
-                  information file for the appropriate node. Most BBS systems
-                  make separate door information files available to each node
-                  by one of the following means:
-
-                         - By naming each node's door information file
-                           uniquely. (e.g. DORINFO1.DEF, DORINFO2.DEF.)
-
-                         - By having a separate directory for each node's door
-                           information file. (e.g. \NODE1\DOOR.SYS,
-                           \NODE2\DOOR.SYS, etc.)
-
-                  In the first case, OpenDoors can automatically select the
-                  correct door information file, assuming that it knows which
-                  node it is running on (see item C, below). In the later
-                  case, you must tell OpenDoors which directory it must look
-                  in to find the appropriate door information file. You may do
-                  this by any of the following means:
-
-                         - By specifying the location of the file on the
-                           command line, if od_parse_cmd_line() is used.
-
-                         - By providing a configuration file keyword to set
-                           the door information file location for each node.
-
-                         - By providing a different configuration file for
-                           each node (See item B, below).
-
-               B. If you are using the OpenDoors configuration file system,
-                  node-specific options should not be used if each node is
-                  accessing the same configuration file. While it is possible
-                  to have a different configuration file for each node (the
-                  filename can be specified on the command line if
-                  od_parse_cmd_line() is used), in most cases the same
-                  configuration file will be used for all nodes. In this case,
-                  the node number, serial port information, and possible door
-                  information file location operations should not be used. If
-                  you are basing your configuration file on the example
-                  DOOR.CFG file that is included in the OpenDoors package, you
-                  may want to remove these options from the file.
-
-               C. In many cases, your program must also be able to determine
-                  which node it is running under. If this information is
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 240
-
-                  available in the door information file, or is stored in a
-                  TASK environment variable, OpenDoors will automatically set
-                  the appropriate node number in od_control.od_node.
-                  Otherwise, if your program requires this information, it
-                  should be specified on the program's command line. The
-                  od_parse_cmd_line() function supports this option. Reasons
-                  that your program might need to know the current node number
-                  include:
-
-                         - In order for OpenDoors to display this information
-                           correctly on the status line.
-
-                         - In order to determine which configuration file to
-                           read or which node directory in which to look for
-                           the door information file.
-
-                         - In order for OpenDoors to know which door
-                           information file to read (e.g. DORINFO1.DEF,
-                           DORINFO2.DEF. etc.)
-
-                         - In order to provide any form of real-time
-                           interaction between nodes, such as inter-node chat.
-
-               D. If your program is running under MS-DOS, and multi-node file
-                  access is being coordinated by locking part or all of a
-                  file, the SHARE.EXE utility must be installed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 241
-
- 7777777
-      77
-     77
-    77
-   77
-  77
- 77
--------------------------------------------------------------------------------
-CHAPTER 7 - TROUBLESHOOTING AND GETTING ASSISTANCE WITH OPENDOORS
-
-
-
-
-ABOUT THIS CHAPTER
--------------------------------------------------------------------------------
-
-               This chapter is perhaps the most important section of this
-               entire manual. Here, we provide detailed instructions to help
-               you in tracing the source of problems in programs written with
-               OpenDoors. Included in this chapter is a step-by-step OpenDoors
-               troubleshooting guide and a chart listing common problems and
-               their solutions. Also included in this chapter is information on
-               the many means available to you for getting more help with
-               OpenDoors, including the OpenDoors support BBS, the OpenDoors
-               EchoMail conference, and how to get in touch with me. It is
-               strongly encouraged that you take the time to read through this
-               chapter.
-
-
-
-TROUBLESHOOTING PROBLEMS
--------------------------------------------------------------------------------
-
-               If you are experiencing difficulty with a program that you are
-               writing using OpenDoors, it is suggested that you follow the
-               steps listed below in order to quickly solve your problem. Also,
-               be sure to check to "solutions to common problems" section of
-               this manual. There are many common difficulties which people
-               have with OpenDoors, that can easily be fixed using the
-               instructions in the "common solutions" section. Also, if you are
-               having difficulty solving a problem yourself, do not hesitate to
-               get in touch with me, as I am always happy to help with any
-               problems. In addition, you may find the other means of OpenDoors
-               support (described latter in this chapter), invaluable in
-               solving difficulties with OpenDoors.
-
-               Keep in mind that most programs you write will have some "bugs"
-               to begin with, and you should expect to spend at least 50% of
-               any programming project tracing down and solving errors and
-               bugs. While it would be nice if every program written worked
-               correctly the first time, it is a fact of life that debugging is
-               and always has been an important part of the software life-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 242
-
-               cycle. In fact, what most often separates the good programs from
-               the bad is the amount of time their programmer's spend debugging
-               and improving them. Unfortunately, it is difficult, if not
-               impossible, to come up with a "magic formula" for debugging
-               software. Debugging software is really more of an art than a
-               science. However, there are some basic guidelines, which if
-               followed, can greatly ease the task of software debugging.
-
-               As with all problem solving, the secret to software debugging
-               lies in obtaining as much information about the problem as
-               possible. While it is sometimes possible to solve a bug by
-               making intuitive changes in your program, or in re-writing a
-               piece of code to solve the problem by a different means,
-               debugging most often requires more of a "planned attack". This
-               planned attack generally involves little more than learning as
-               much about what is going wrong as possible. The first step in
-               solving a bug usually lies in locating the source of the
-               problem. Once you have located the problem, solving it is often
-               a relatively simple procedure. In locating the source of your
-               bug, the use of a software debugger, such as the one built into
-               the Turbo C(++) / Borland C++ integrated development
-               environment, can be invaluable.
-
-               When debugging programs written with OpenDoors, you should also
-               follow the steps listed below, in order to obtain more
-               information related to the problem you are trying to solve:
-
-               1.)  Re-read the section(s) of this manual, your Turbo C(++) /
-                    Borland C++ manuals and your program's source code, which
-                    apply to the problem you are experiencing.
-
-               2.)  Check the solutions to common problems section below. The
-                    most common problems with OpenDoors can be solved using
-                    this simple chart.
-
-               3.)  Check the value in the od_errno variable, which will often
-                    provide vital clues as to the source of the problem. Use of
-                    the od_errno variable is described in the section below.
-
-               4.)  If you are still stuck, please feel more than free to get
-                    in touch with me! (see the end of this chapter for
-                    information on reaching me) I am always more than happy to
-                    help with any OpenDoors or general programming problems!
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 243
-
-SOLUTIONS TO COMMON PROBLEMS
--------------------------------------------------------------------------------
-
-               Below, several common difficulties with OpenDoors are listed,
-               along with suggested solutions to these problems. If you are
-               experiencing any difficulty with a program that you have written
-               with OpenDoors, we would suggest that you read this section
-               thoroughly. Here, the common problem is listed in the left
-               margin, and the solutions listed on the right portion of the
-               page.
-
-
--------------------------------------------------------------------------------
-PROGRAM        1.) Check that the compiler is able to locate the OpenDoors
-WON'T          header file, "OPENDOOR.H". This can be accomplished either by
-COMPILE        placing this header file in the same directory as your other
-               header files (such as STDIO.H, etc.), or by placing the header
-               file in the current directory.
-
-               2.) Be sure that you are linking your program with the correct
-               library for the memory model you are using. (See the section on
-               compiling with OpenDoors). Also be sure that both the source
-               code file for your program (such as EX_VOTE.C) and the library
-               file are listed in your project file, and that the project file
-               is loaded. For more information on compiling programs written
-               with OpenDoors, see page 22.
-
-               3.) If you have tried the above solutions, and your program
-               still won't compile, then the problem is most likely an error in
-               your source code file. If you are unable to resolve your
-               problem, feel free to get in touch with me.
-
-
--------------------------------------------------------------------------------
-SCREEN         If you are using the od_clr_scr() function to clear the screen,
-WILL NOT       but are not getting any results, this is likely because the user
-CLEAR          online has screen clearing turned off. If you wish to force
-               screen clearing regardless of the user's screen clearing
-               settings (this is probably not a good idea), use the function
-               call od_disp_emu("\xc", TRUE);
-
-
--------------------------------------------------------------------------------
-FIXUP          This problem was probably caused by a mismatch between your
-OVERFLOW       memory model selection in your compiler, and the memory model
-ERROR          library you are using. See the section on compiling programs
-               with OpenDoors for more information on the correct library you
-               should be using for your memory model selection.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 244
-
-OPENDOORS SUPPORT
--------------------------------------------------------------------------------
-
-               The powerful and easy to use door toolkit and this comprehensive
-               manual are only two portions of how OpenDoors helps you to write
-               BBS door and similar programs. The third element of OpenDoors is
-               the extensive OpenDoors support mechanisms. The OpenDoors email
-               conference and support BBS each give you a chance to share ideas
-               and source code with other OpenDoors programmers. A lot of
-               information concerning OpenDoors, along with the newest version
-               and online registration, is available through the OpenDoors
-               World Wide Web site. In addition to these sources, I am also
-               more than happy to answer any of your questions, or hear any
-               suggestions for future versions of OpenDoors. The remainder of
-               this chapter provides more information on the various sources of
-               OpenDoors support. Also keep your eyes open for the "OpenDoors
-               Tech Journal", that is produced on a regular basis by the users
-               of OpenDoors. Included in this newsletter is information on
-               OpenDoors and future versions, questions and answers about
-               OpenDoors and BBS door / utility programming in general, sample
-               source code, and much more.
-
-
-
-THE OPENDOORS SUPPORT BBS
--------------------------------------------------------------------------------
-
-               One means of receiving OpenDoors support is via the OpenDoors
-               BBS. Below is an outline of some of what is available from the
-               OpenDoors BBS:
-
-                    -  The newest version of this package is always available
-                       for download.
-
-                    -  Also available for download is example source code and
-                       other files which you may find helpful when writing
-                       programs with OpenDoors.
-
-                    -  Access to the OpenDoors conference where OpenDoors
-                       programmers can share ideas, source code, and receive
-                       help with difficulties or with learning OpenDoors.
-
-                    -  Get in touch with me with any questions, comments,
-                       suggestions or bug reports.
-
-                    -  Other files by yours truly, which may be of use in you
-                       programming, such as a registration key system, and so
-                       on.
-
-               All users receive full access upon their first call to the
-               OpenDoors BBS. The North American phone number for the support
-               BBS is:
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 245
-
-
-                                   +1 (613) 599-5554
-
-               The OpenDoors support BBS also has a FidoNet address, 1:243/8.
-               If you are interested in a list of files available from the
-               support BBS, simply file-request "FILES". To receive the newest
-               version of OpenDoors, you can file-request "ODOORS".
-
-
-
-THE OPENDOORS WORD WIDE WEB SITE
--------------------------------------------------------------------------------
-
-               The OpenDoors World Wide Web site has been setup to provide up-
-               to-date information on OpenDoors. This includes news concerning
-               OpenDoors, OpenDoors tips and techniques, pointers to other
-               sources of OpenDoors support, online registration and access to
-               the newest version of OpenDoors.
-
-               The current URL (address) of the OpenDoors Web site is:
-
-                    http://omega.scs.carleton.ca/~ug930227/opendoor.html
-
-               However, I plan on moving this to a new location some time this
-               year. If you are unable to reach the OpenDoors Web site through
-               the above URL, please get in touch with me, and I will be able
-               to tell you where it has moved to.
-
-
-
-THE OPENDOORS CONFERENCE
--------------------------------------------------------------------------------
-
-               The OpenDoors conference is devoted to OpenDoors and BBS / door
-               / BBS utility programming in general. The OpenDoors conference
-               serves as a place where people working with OpenDoors can share
-               ideas, source code examples, and other tricks and techniques.
-               Through the OpenDoors conference you can receive help with
-               OpenDoors and programming in general. Also available through the
-               OpenDoors conference is information on future versions of
-               OpenDoors and recent developments of concern to BBS door and
-               utility programmers. The OpenDoors conference is also a place
-               for suggestions for future versions of OpenDoors, OpenDoors bug
-               reports, a place to announce the availability of your programs,
-               and much more information of interest to programmers working
-               with OpenDoors.
-
-               You can become involved in the OpenDoors Conference by the
-               following means:
-
-               - The OpenDoors conference is available as an Internet mailing
-                 list. to subscribe, send email to listserv@hms.com and put
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 246
-
-                 SUBSCRIBE OPENDOOR in the message body. For help on using the
-                 listserver you can send email to listserv@hms.com and put
-                 HELP in the message body.
-
-               - The OpenDoors conference is available on the FidoNet North
-                 America echo backbone, and so is available to a large number
-                 of BBS systems. FidoNet capable systems may also obtain an
-                 OpenDoors feed directly from the moderator, Brian Pirie.
-
-
-GETTING IN TOUCH WITH ME
--------------------------------------------------------------------------------
-
-               If you have any questions about OpenDoors, would like help with
-               any programs that your are writing, or have any suggestions for
-               future versions of OpenDoors, please feel free to get in touch
-               with me. You can get in touch with me by any of the following
-               means:
-
-               - The best way to contact me is by Internet email. My primary
-                 email address is:
-
-                              pirie@msn.com
-
-                 If you have difficulty contacting me through this address, I
-                 may also be reached through the address:
-
-                              aa522@freenet.carleton.ca
-
-               - By writing a message to me in the OpenDoors support
-                 conference. For more information on the OpenDoors conference,
-                 see the previous section of this chapter.
-
-               - By calling the OpenDoors support BBS. Information on the
-                 support BBS is provided earlier on in this chapter.
-
-               - By sending your question or comment by Fax. My fax number is:
-
-                              +1 (613) 599-5554
-
-               - By FidoNet NetMail. My address is:
-
-                              1:243/8
-
-                 While I would like to be able to reply to all NetMail
-                 messages by CrashMail, I am afraid I simply can not afford to
-                 do this. So, if you choose to send NetMail, please indicate
-                 whether you would like me to reply by routed NetMail (this
-                 may not work, if routed NetMail is not available in your
-                 area), or to place the message on hold for you to poll and
-                 pick up.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 247
-
-               - By conventional mail. My postal address is:
-
-                              Brian Pirie
-                              117 Cedarock Drive
-                              Kanata ON  K2M 2H5
-                              Canada
-
-
-               I try to respond to all correspondences as soon as possible.
-
-               If you are having some sort of difficulty with OpenDoors, the
-               more detailed information you supply (such as source code to the
-               program that is causing the problem, how to duplicate the
-               problem, and so on), the more quickly I will be able to
-               determine the source of your problem. Also, before you write
-               about a problem with OpenDoors, you may wish to be sure that you
-               have read and followed the instructions in the section on
-               troubleshooting, found on page 242. While I do not mind taking
-               the time to answer any questions related to OpenDoors, you may
-               be able to save yourself the time of writing and waiting for a
-               response - simply by following the instructions in the
-               troubleshooting section. More often than not, the answer to
-               questions I receive is already in this manual.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 248
-
-    A
-   AAA
-  AA AA
- AAAAAAA
- AA   AA
- AA   AA
- AA   AA
--------------------------------------------------------------------------------
-APPENDIX A - CONTENTS OF PACKAGE
-
-
-
-
-               The main OpenDoors package is distributed in the form of a
-               single, compressed archive file. Thus, you should have received
-               this version of OpenDoors in a file whose name began with
-               ODOORS60. The files listed below should be included in your
-               OpenDoors package. If any of these files are missing, you will
-               probably want to look for the most recent version of OpenDoors
-               from another source. Note that the medium and compact memory
-               model libraries are now distributed separately from the main
-               OpenDoors package.
-
-               MISCALENEOUS FILES
-                    FILE_ID.DIZ    Description of the OpenDoors package
-                    DORINFO1.DEF   Sample door info file for testing programs
-                    DOOR.CFG       Sample OpenDoors configuration file
-
-               EXAMPLE PROGRAMS
-                    EX_HELLO.C     A simple program using OpenDoors
-                    EX_CHAT.C      Split-screen sysop chat program
-                    EX_MUSIC.C     Example of ANSI music in OpenDoors
-                    EX_SKI.C       Simple slalom skiing action game
-                    EX_VOTE.C      Example of an online voting program
-                    VOTEDOS.EXE    Compiled version of EX_VOTE.C - DOS version
-                    VOTEWIN.EXE    EX_VOTE.C compiled - Windows version
-                    DTRON.EXE      Free utility for running Win 95 doors
-
-               THE LIBRARY FILES
-                    ODOORS.LIB     DOS, Small memory model library
-                    ODOORL.LIB     DOS, Large memory model library
-                    ODOORH.LIB     DOS, Huge memory model library
-                    ODOORW.LIB     Win32 import library (Microsoft version)
-                    ODOORS60.DLL   The OpenDoors Win32 DLL
-
-               THE HEADER FILE
-                    OPENDOOR.H     OpenDoors header file
-
-               OPENDOORS DOCUMENATION
-                    ORDER.TXT      Easy-to-print order form
-                    OPENDOOR.TXT   OpenDoors programmer's manual (this file)
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 249
-
- BBBBBB
- BB   BB
- BB   BB
- BBBBBB
- BB   BB
- BB   BB
- BBBBBB
--------------------------------------------------------------------------------
-APPENDIX B - CHANGES FOR THIS VERSION
-
-
-
-
-               Since version 5.00, a lot of work has gone into OpenDoors. Many
-               months were spent cleaning up and restructuring the OpenDoors
-               code in a process that has touched nearly every line of the
-               OpenDoors code. As well as making the OpenDoors source code
-               easier to maintain, this has also involved making OpenDoors more
-               easily portable to 32-bit multithreaded platforms.
-
-               After this effort was completed, I began work on a Win32 port of
-               OpenDoors. The OpenDoors package now includes both DOS and Win32
-               versions of the library, giving you the option of developing for
-               one, the other, or both platforms. The Win32 version of
-               OpenDoors is highly multithreaded to give you the best possible
-               performance. With some exciting new BBS packages that are
-               designed specifically for Windows 95/NT in the works, the Win32
-               version of OpenDoors gives you a head start on developing
-               applications that will integrate smoothly with these new BBS
-               packages. Even if your programs will only be used with DOS-based
-               BBS packages, the Win32 version of OpenDoors allows you to take
-               advantage of the Windows 95 GUI, multithreading capabilities and
-               flat 32-bit memory model (no more DOS 64K limitations and
-               different memory models to worry about!). It also allows you to
-               access services that are only available to Windows based
-               programs, such as ODBC for easy database access, and MAPI for
-               email, fax and other messaging.
-
-               While this internal restructuring of OpenDoors and the Win32
-               port of the package would be enough alone to count as a major
-               new version, version 6.00 also includes many exciting new
-               features, enhancements and bug fixes:
-
-               - A new option, "silent mode", has been added. When operating
-                 in silent mode, OpenDoor's local sysop interface is disabled,
-                 so that no output is displayed on the local screen, and no
-                 input is accepted from the local keyboard. Silent mode can be
-                 activated by setting od_control.od_silent_mode = TRUE prior
-                 to the first call to any OpenDoors function, or by specifying
-                 -SILENT on the command-line (if od_parse_cmd_line() is used).
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 250
-
-               - OpenDoors now fully supports RTS/CTS flow control, which is
-                 enabled by default. To disable the use of the RTS/CTS lines
-                 for flow control, use od_control.od_com_flow_control.
-
-               - In version 5.00, the built-in serial I/O module would be
-                 unable to initialize the serial port if the "Uses Serial
-                 Ports" option was turned off in DesqView or other
-                 multitasking environments. When this option is turned off,
-                 multitasking environments typically remove the serial port
-                 information from the BIOS data segment. However, it seems
-                 that other serial I/O software commonly uses the default
-                 address for each port if this information is not available
-                 from the BIOS data area. OpenDoors 6.00 has been changed to
-                 do the same thing.
-
-               - OpenDoors now provides a standard command-line processing
-                 function, od_parse_cmd_line(). This function provides a one-
-                 step method of adding support for many common command-line
-                 options to your program. This function handles options such
-                 as serial port information (including non-standard serial
-                 port configurations), node number information, user
-                 information, drop file and configuration file locations,
-                 silent mode (turns off the local interface for efficiency and
-                 privacy), one step local login without a drop file, and more.
-                 For details, run the included example program (votedos.exe or
-                 votewin.exe) with the -help command line option. The
-                 od_parse_cmd_line() function is particularly helpful in
-                 several situations:
-
-                         - When your program is being used on a multi-node
-                           system.
-                         - Allows potential users to try your program in local
-                           mode by just specifying -local on the command line.
-                         - Allows door information to be specified on the
-                           command line, rather than through a drop file, as
-                           supported by some BBS systems
-                         - Allows serial port handle to be directly passed to
-                           the program under Windows-based BBS systems that
-                           support this.
-                         - Provides customizable command-line help (in a
-                           window in the Win32 version of OpenDoors).
-
-               - A new function, od_sleep(), allows you to suspend program
-                 execution for the specified number of milliseconds, releasing
-                 time to other processes in a multitasking environment. A call
-                 of od_sleep(0) will yield control to any other processes
-                 without forcing program execution to be suspended if no other
-                 processes are waiting.
-
-               - The sysop page timing mechanism has been reworked. By
-                 default, od_control.od_okaytopage is set to PAGE_USE_HOURS,
-                 only allowing the sysop to be paged during the paging hours
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 251
-
-                 set by od_pagestartmin and od_pageendmin. Rather than
-                 allowing the sysop to be paged at any time of the day or
-                 night, the default now only permits sysop paging from 8:00am
-                 to 10:00pm. Setting paging start and end time to the same
-                 value now correctly permits paging 24 hours a day.
-
-               - OpenDoors now provides a multi-line editor function,
-                 od_multiline_edit(). This editor allows the user to enter or
-                 edit any information that spans multiple lines, such as email
-                 messages or text files. The editor can be configured to
-                 operate in full screen mode, or in any smaller area of the
-                 screen that you specify. The editor is designed to be both
-                 easy to use, and highly customizable.
-
-               - One new feature of OpenDoors 5.00 was somehow omitted from
-                 the manual. Since version 5.00, it has been possible to set
-                 the name of the drop file to use by including both a path and
-                 filename in the od_control.info_path variable.
-
-               - All known inaccuracies and missing information from the
-                 version 5.00 manual have been corrected.
-
-               - The example program, ex_chat.c, has been expanded to
-                 demonstrate how OpenDoor's standard chat mode can be replaced
-                 with the split-screen chat mode within your own programs.
-
-               - The multiple ex_vote?.c example files have been combined and
-                 simplified into a single example program, as it was prior to
-                 version 5.00.
-
-               - A memory leak in the od_popup_menu() function has been fixed.
-
-               - od_control.od_open_handle can be used to provide OpenDoors
-                 with an already open serial port handle on platforms that
-                 support it. Currently, this only applies to the Win32 version
-                 of OpenDoors. If this variable is not set to a non-zero value
-                 prior to calling the first OpenDoors function (other than
-                 od_parse_cmd_line()), then OpenDoors proceeds normally,
-                 opening the serial port itself, and closing the serial port
-                 before exiting.
-
-               - A new switch, od_emu_simulate_modem, has been added to
-                 od_control. When this is set to its default value of FALSE,
-                 the OpenDoors terminal emulator displays at full speed, as it
-                 has always done. However, when this flag is set to TRUE, the
-                 emulation functions will display text at approximately the
-                 same speed as it would be displayed when sent over the modem,
-                 based on the current connect speed. This allows animations to
-                 be displayed locally at the same speed as they would appear
-                 on the remote system. This switch affects the following
-                 functions:
-                    od_disp_emu()
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 252
-
-                    od_send_file()
-                    od_hotkey_menu()
-
-               - OpenDoors now distinguishes between the serial port BPS rate
-                 (od_control.baud) and the connection BPS (a new variable,
-                 od_control.od_connect_speed). In situations where a separate
-                 value is available for the connect speed (e.g., this caller
-                 has connected at 14400 bps), OpenDoors will now display that
-                 value on the status line. Currently, a separate connect speed
-                 is only obtained from the DOOR.SYS drop file format.
-
-               - The latest versions of the QBBS EXITINFO.BBS drop file is now
-                 supported.
-
-               - A new od_edit_str() flag, EDIT_FLAG_SHOW_SIZE, has been
-                 added. By default, the fields shown by od_edit_str() are one
-                 character larger than the number of characters that may be
-                 entered. This is for esthetic reasons, so that the cursor
-                 remains within the highlighted field, even after a full
-                 string has been entered. However, you may prefer that the
-                 highlighted area reflect the exact number of characters that
-                 are permitted. This can be accomplished by setting
-                 EDIT_FLAG_SHOW_SIZE.
-
-               - Tab characters ('\t') are now expanded on the local display.
-
-               - The new RemoteAccess 2.50 EXITINFO.BBS fields are now
-                 supported. This has included the addition of the following
-                 new od_control members: user_rip_ver, user_attrib3 and
-                 system_last_handle.
-
-               - When operating in "forced automatic local" mode (where no
-                 door information file used), OpenDoors now displays a window
-                 in which in prompts for the user's name at startup time. This
-                 new feature can be disabled by specifying the DIS_NAME_PROMPT
-                 od_control.od_disable flag.
-
-               - The latest version of the SFDOORS.DAT drop file is now
-                 supported. SFMAIN.DAT, SFSYSOP.DAT, SFFILE.DAT and
-                 SFMESS.DAT, which are in the same format as SFDOORS.DAT, are
-                 also now recognized.
-
-               - A new function, od_get_input(), allows you to easily handle
-                 extended keys in your program, such as arrow keys, insert and
-                 function keys.
-
-               - The OpenDoors configuration file system will now display an
-                 error and exit the program if a particular configuration file
-                 name has been specified, and that configuration file cannot
-                 be found.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 253
-
-   CCCC
-  CC  CC
- CC
- CC
- CC
-  CC  CC
-   CCCC
--------------------------------------------------------------------------------
- APPENDIX C - FUTURE VERSIONS
-
-
-
-
-               While I cannot make any promises about what features and changes
-               will be seen in future versions of OpenDoors, I would like to
-               take a moment to tell you a bit about some of the features you
-               can expect to see in future versions of OpenDoors
-
-               As you are probably already aware, OpenDoors is a constantly
-               evolving package. To help meet the needs of programmers working
-               with OpenDoors, nearly every idea and change that is made to the
-               package results from the suggestions and comments I receive from
-               the people using OpenDoors. For this reason, I will most likely
-               continue to produce new versions of OpenDoors for as long as
-               there is a demand and ideas for upgrades. There certainly is no
-               shortage of either of this right now.
-
-               Some of the features that I am considering for upcoming versions
-               of OpenDoors include:
-
-                    -Telnet support.
-
-                    - HTML support.
-
-                    - Direct interfacing with new Windows 95/NT BBS packages.
-
-                    - Further features to help writing multi-node door
-                     programs.
-
-                    -Direct interfacing with more BBS systems.
-
-                    -Additional RIP graphics support, including possible
-                     display of RIP images on local screen.
-
-                    -Possible support for additional programming languages and
-                     operating systems.
-
-                    - Improvements to existing OpenDoors features, such as more
-                     configuration file options, multiple log file formats,
-                     and many smaller changes.
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 254
-
- DDDDD
- DD  DD
- DD   DD
- DD   DD
- DD   DD
- DD  DD
- DDDDD
--------------------------------------------------------------------------------
- APPENDIX D - SPECIAL THANKS
-
-
-
-
-               There are many people who I would like to thank, for their
-               suggestions, ideas and assistance in making OpenDoors what it is
-               today. Among those I would like to thank are:
-
-                    - Everyone who has registered OpenDoors.
-
-                    - All those who participate in the OpenDoors conference,
-                      who provide many suggestions, bug reports and words of
-                      encouragement.
-
-                    - Those who on the OpenDoors beta team. Thank-you for
-                      putting up with the problems along the way. You have
-                      certainly helped to make OpenDoors a better package. The
-                      people who have helped to beta test OpenDoors 6.00 are:
-
-                              Robert Bouman
-                              Doug Crone
-                              Greg Diener
-                              Patrick Dixon
-                              Joel Downer
-                              Mike Fenton
-                              Les Howie
-                              Vince Jacobs
-                              Scott Jibben
-                              Dean Mills
-                              Jimmy Rose
-                              Jim Woodward
-                              Timothy Ward
-                              Mark Williams
-
-                    - Last but not least, I would like to thank my wife, Pearl,
-                      for her support during the long hours that it has taken
-                      to put OpenDoors together.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 255
-
-  GGGG
- GG  GG
- GG
- GG GGGG
- GG  GG
- GG  GG
-  GGGG
--------------------------------------------------------------------------------
-GLOSSARY
-
-ANSI           ANSI is an acronym for "American National Standards Institute".
-               One of the standards approved by ANSI is a terminal display
-               protocol which allows (in this case), BBS software to perform
-               certain display functions such as changing the color of
-               displayed text, or moving the location of the cursor on the
-               screen. The majority, though not all, BBS users use terminal
-               software with ANSI capabilities. Any users that do not have
-               graphics display capabilities, will be using ASCII mode,
-               instead. The ANSI terminal protocol is sometimes referred to as
-               "ANSI graphics". It is graphic in the sense that it provides
-               more visual control than an ASCII TTY terminal does, but does
-               not imply any support for bit-mapped nor vector graphics.
-               Compare ASCII and AVATAR.
-
-
-API            API is an acronym for "Application Program(er) Interface". An
-               API is a set of well documented functions, variables and data
-               types that you can use to access certain services from your
-               program. When you write any C program that uses standard C
-               library functions such as fopen() or strcpy(), you are using a
-               sort of API. When you use OpenDoors functions such as
-               od_printf() or od_get_key(), you are using functions that are
-               part of the OpenDoors API. Operating systems provide their own
-               APIs that allow programs to gain access to operating system
-               features such as screen display, file I/O and communications.
-               The API provided by Microsoft Windows 95 and Windows NT is
-               called the Win32 API.
-
-
-ASCII          ASCII (pronounced "ass-key") is an acronym for "American
-               Standard Code for Information Interchange", and is a definition
-               of a set of 128 letters, number and symbols, which can be
-               displayed by computer systems. Also, when used within the domain
-               of BBS software, ASCII mode is often used to refer to the lack
-               of any more advanced display capabilities, such as ANSI or
-               AVATAR. When ASCII mode is used, characters can only be
-               displayed in standard Teletype (TTY) fashion, one after another.
-               Also, color and cursor positioning functions are not available
-               in ASCII mode. Compare ANSI and AVATAR.
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 256
-
-AVATAR         AVATAR is an acronym for "Advanced Video Attribute Terminal
-               Assembler and Recreator". AVATAR is a graphics display protocol,
-               similar to ANSI. Like ANSI-graphics, AVATAR graphics allow
-               functions such as cursor positioning, and color changing.
-               However, AVATAR also offers many capabilities not available from
-               ANSI, and performs the same functions as ANSI much more quickly.
-               AVATAR graphics is less common than both ANSI or ASCII, but is
-               becoming more popular as time goes by. Compare ASCII and ANSI.
-
-
-BAUD           "baud" or "baud rate" are generally used as a synonym for "BPS".
-
-
-BPS            BPS is an acronym for "Bits Per Second", and refers to the rate
-               at which data is being sent over a communications medium. There
-               are two important BPS rates which are relevant to OpenDoors. The
-               serial port BPS rate (also called the DCE rate) is the speed at
-               which the computer is communicating with the local modem. The
-               connect speed, on the other hand, is the speed at which the
-               local modem is communicating with the remote modem. The serial
-               port speed must be at least as fast as the connection speed.
-               Often the serial port speed will be locked at a fixed speed that
-               is higher than the fastest possible connection speed of the
-               modem. For example, the serial port might be locked at a speed
-               of 38400 BPS, while the modem could be connected at 28,800,
-               14,400 or slower speeds. OpenDoors usually needs to know the
-               serial port BPS rate in order to function correctly (as stored
-               in od_control.baud). Under certain situations, OpenDoors will
-               also be able to report the connection speed to you (as stored in
-               od_control.od_connect_speed), although OpenDoors does never
-               requires this information to operate.
-
-
-BIT-MAPPED     As with Boolean values, described below, bit mapped flags
-FLAGS          are used to indicate whether or not various conditions exist.
-               (For example, whether or not a certain setting is enabled, or
-               whether or not a particular event has occurred.) However, unlike
-               Boolean variables, a single bit-mapped flag represents more than
-               one of these TRUE/FALSE values. In fact, each bit (BInary
-               Digit), which makes of the variable can be used to represent a
-               separate TRUE/FALSE state. (ie, each bit maps to a particular
-               piece of information, and hence the term "Bit Map").
-
-               For an example of using bit-mapped flags, let us take a case of
-               a single "unsigned char" which contains three independent
-               TRUE/FALSE values. We will call this variable user_info, and it
-               will indicate whether or not a user has ANSI graphics, whether
-               or not the user has screen clearing turned on, and whether or
-               not the user has end-of-page "more" prompts enabled. Internally,
-               the bits of the user_info variable will be as follows:
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 257
-
-                     Bit:  7 6 5 4 3 2 1 0
-                                     | | |
-                                     | | +--- ANSI Graphics
-                                     | +----- Screen Clearing
-                                     +------- More prompts
-
-               In this case, we will have three constants which we define in
-               order to simplify access to these bit-mapped flags, as follows:
-
-                     #define ANSI_GRAPHICS        0x01
-                     #define SCREEN_CLEARING      0x02
-                     #define MORE_PROMPTS         0x04
-
-               Note that normally within OpenDoors, these constants will be
-               defined for you, and you will have no need to know what their
-               values are, nor in which bit which piece of information is
-               stored.
-
-               Using bit-mapped flags, you are able to set or clear any of the
-               individual flags, and check whether any of the flags are set,
-               using these simple methods: (Not that a set flag is the
-               equivalent of a Boolean value of "True", and a cleared flag is
-               the equivalent of a Boolean value of "False".)
-
-                    Set Flag:      variable |= FLAG_CONSTANT;
-                    Clear Flag:    variable &=~ FLAG_CONSTANT;
-                    Test Flag:     variable & FLAG_CONSTANT
-
-               Where "variable" is the name of the bit-mapped flag variable,
-               and "FLAG_CONSTANT" is the pre-defined constant for the
-               individual setting. To return to our example, you could turn on
-               the user's ANSI graphics setting by using the line:
-
-                    user_info |= ANSI_GRAPHICS;
-
-               and to turn off screen clearing you would:
-
-                    user_info &=~ ANSI_GRAPHICS;
-
-               To perform an action (such as waiting for the user to press
-               [Return]/[Enter]) only if "More" prompts are enabled, you would:
-
-                    if(user_info & MORE_PROMPTS)
-                    {
-                         ...            /* Whatever you want */
-                    }
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 258
-
-BOOLEAN        Many of the variables used within OpenDoors contain a
-VALUES         "Boolean Value". A Boolean value is a two-state variable, who's
-               states are referred to as "True" and "False'. If the variable
-               contains a value of "True", it indicates that a certain
-               condition is so, and if it contains a value of "False", it
-               indicates that the condition is not so. For example, a Boolean
-               variable "wait" might be used to indicate whether or not
-               OpenDoors should wait for the user to press a key, or continue
-               without waiting. In this case, a value of "True" would indicate
-               that OpenDoors should wait, and a value of "False" would
-               indicate that it should not wait.
-
-               Note that in the C programming language, there is no actual
-               Boolean variable type - usually a char or an int are used to
-               store Boolean values.
-
-               The constants TRUE and FALSE, as defined in the OPENDOOR.H file,
-               are used to represent the two states of a Boolean value. Thus,
-               to set a Boolean variable "wait" to the value of "True", you
-               would use this line:
-
-                         wait=TRUE;
-
-               and to set the variable "wait" to "False", you would:
-
-                         wait=FALSE;
-
-               However, you SHOULD NOT test whether a Boolean variable is
-               "True" or "False" by using the C compare (==) operator, as the
-               value "True" will not always be the same numerical value.
-               (Actually, the TRUE constant represents just one of many
-               possible numerical values for "True"). Instead, to perform an
-               action of the "wait" Boolean variable is "True", you would:
-
-                         if(wait)
-                         {
-                              ...        /* Whatever you want */
-                         }
-
-               and to perform an action if the "wait" Boolean variable is
-               "False', you would:
-
-                         if(!wait)
-                         {
-                              ...       /* Whatever you want */
-                         }
-
-               For interest sake, Boolean values are named after the 19th
-               century English mathematician, who studied formal logic, and
-               created Boolean algebra - an algebra which deals with TRUE and
-               FALSE values.
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 259
-
-
-BPS            BPS is an acronym for "Bits Per Second". For our purposes here,
-               the terms BPS and BAUD refer to the same thing.
-
-
-CARRIER        The term "Carrier" or "Carrier Detect" refers to a signal which
-DETECT         most modems send to the computer, which indicates whether or not
-               the modem is currently connected to (communicating with) another
-               modem. The door driver module of OpenDoors, as with most other
-               BBS software, uses the status of this carrier detect signal in
-               order to know whether the user is still connected to the BBS
-               computer. Thus, if the user hangs up, or if something goes wrong
-               and the connection is lost, OpenDoors is able to detect this
-               state, and exit to the BBS. The BBS will then also detect that
-               the carrier signal has been "lost", and will reset itself, and
-               then again be ready to accept calls.
-
-
-CHAT MODE      The term "chat mode" refers to a means by which the sysop can
-               communicate with a user of the BBS / door. During sysop chat,
-               anything typed by the sysop will appear on the user's screen,
-               and likewise, anything typed by the user will appear on the
-               sysop's screen. Sysop chatting is available on both single and
-               multi-line systems. Sysop chatting is initiated by the sysop,
-               either at any time a user is online, or specifically in response
-               to a sysop page.
-
-
-COMPILE        "Compiling" refers to the process of converting the source code
-               that you write for your program, into an executable file (such
-               as a .EXE file) that an end user can use. The process of
-               building an executable file is generally divided into two
-               stages. In the first stage, called compiling, source files are
-               converted to object files, often named .OBJ. In the second
-               stage, called linking, one or more object files are combined,
-               along with any library files, to produce the final executable
-               file.
-
-
-DLL            DLL is an acronym for "Dynamic Link Library". A dynamic link
-               library is similar to a static library, in that it contains one
-               or more functions that an application program can use. Unlike a
-               static library, the code from a dynamic link library is not
-               added to the program's executable file at link time. Instead,
-               the dynamic link library exists as a separate file which must be
-               loaded when the program is run. The Win32 version of OpenDoors
-               resides in a DLL.
-
-               See also "Library".
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 260
-
-DOOR           A "door" is a program that runs as part of a BBS system, but
-               which is separate from the central BBS software (RemoteAccess,
-               Maximus, QuickBBS, PC-Board, etc.) itself. A door provides
-               additional features not built into the BBS software, such as on-
-               line games, on-line shopping services, voting booths, match
-               making systems, access to special files or messages, and much
-               much more. Since the user also communicates with the door
-               online, as they do with the BBS, it may not necessarily be
-               obvious to the user that the door is even a separate entity from
-               the central BBS software itself.
-
-
-DOOR           Also referred to as a "drop file", "exit file", or "chain
-INFORMATION    file". The door information file is a file passed from the
-FILE           central BBS software to a door program, providing it with
-               information about the user who is online, the BBS the door is
-               running under, and the current modem connection. The door
-               information file may also be used to pass changed information
-               back to the BBS, such as the amount of time that the user has
-               used in the door. OpenDoors takes care of all of the work
-               involved in reading and writing the door information file for
-               you, as described in the "Basics of Door Programming" section,
-               in chapter 4. Examples of door information files supported by
-               OpenDoors include: DOOR.SYS, EXITINFO.BBS, DORINFO?.DAT,
-               SFDOORS.DAT, CALLINFO.BBS and CHAIN.TXT.
-
-DTR            DTR is an acronym for "Data Terminal Ready". This is a signal
-               that the computer sends to the modem, indicating that the
-               computer is ready to send or receive information. Most modems
-               are configured to hangup if the DTR signal is lowered. This is a
-               convenient means of hanging up the modem, but cases problems
-               under Windows 95, where the DTR signal is always lowered when a
-               program closes the serial port.
-
-
-ECHO           See "Local Echo".
-
-
-FOSSIL         The FOSSIL driver, or simply FOSSIL, is a TSR program or
-DRIVER         device driver which OpenDoors can optionally make use of in
-               order to communicate with the modem. The FOSSIL driver is loaded
-               prior to starting up the BBS or your door, usually from the
-               AUTOEXEC.BAT or CONFIG.SYS files. The two most commonly used
-               FOSSIL drivers are X00 and BNU. (FOSSIL is an acronym for
-               "Fido/Opus/SEAdog Standard Interface Layer", although it has now
-               become the standard for nearly all BBS software.) FOSSIL drivers
-               are also available for other specialized serial port hardware,
-               such as the popular "DigiBoard" multi-port serial card.
-
-
-IMPORT LIBRARY See "Library".
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 261
-
-
-LIBRARY        A "library" or "library file" is a collection of precompiled
-               functions and variables that can be used by other programs. All
-               of the features, capabilities and functions of OpenDoors that
-               you can make use of are contained within the OpenDoors library
-               files. (Likewise, the C runtime library, consisting of the
-               familiar functions such as fopen(), printf() and atoi(), is also
-               contained within a library file.) For more information on the
-               different OpenDoors library files, see the section that begins
-               on page 22.
-
-               There are several different kinds of library files. A static
-               library file is actually a collection of individual object
-               files. When you compile a program that makes use of a static
-               library file, only those portions of the library file that your
-               program actually uses are linked into your program's executable
-               (.EXE) file. Static library files can be identified by a .LIB
-               extension. The DOS version of OpenDoors resides in a static
-               library.
-
-               A dynamic link library, on the other hand, is not combined with
-               the program's executable file. Instead dynamic link libraries
-               exist in separate .DLL files that must also be present when the
-               program is executed. The Win32 version of OpenDoors resides in a
-               dynamic link library.
-
-               An import library is a small file that describes a dynamic link
-               library. The most common way for a program to call functions in
-               a dynamic link library requires that an import library be used a
-               program link time.
-
-               See also "DLL".
-
-
-LINK           "Linking" generally refers to the process of combining several
-               object files into a final executable file, during which
-               references to symbol names (such as od_printf()) are resolved to
-               the address of the corresponding object. See also "Compiling".
-
-
-LOCAL MODE     The term "local mode" refers to a mode in which a BBS system or
-               door program may operate. In local mode, the BBS/door behave as
-               they would if a user were connected via modem to the BBS, except
-               that all display and input is done simply on the BBS software,
-               but not through the modem. Local mode allows the sysop or
-               another person with direct access to the BBS computer to use the
-               BBS/door software, either for their own user, or for testing
-               that the software is running correctly. When programming door
-               software, local mode can be very useful in testing and debugging
-               the door, without requiring the door to be connected to a remote
-               system. All doors written with OpenDoors automatically support
-               local mode operation. Compare "Remote".
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 262
-
-
-
-LOCAL ECHO     The term "Local Echo" refers to a door displaying the same
-               characters which are sent to the modem on the local screen
-               ("Output Window"). This allows the sysop to view the same
-               information that is sent to the user's system, in the same
-               manner that it will appear on the user's screen.
-
-
-LOCKED         (eg. "Locked Baud Rate", "Locked BPS Rate", "Locked Commport
-               Speed", etc.) Usually, the communication port to which a modem
-               is connected is set to transfer data at the same BPS rate as the
-               rate at which the modem is communicating. However, many high
-               speed modems allow very high speed data transfer by using built-
-               in data compression methods. In this case, the actual rate of
-               data transfer can easily exceed the true BPS rate of the
-               connection. As a result, the BPS rate of the port is kept a
-               single speed, faster than any of the true modem connections, in
-               order to increase modem speed performance. This is referred to
-               as locking the commport BPS rate. OpenDoors has full support for
-               the use of locked BPS rates.
-
-
-LOG FILE       A log file is a normal text file in which BBS software records
-               all major activities that have taken place. As such, the log
-               file permits the sysop, to review what activities have taken
-               place on the BBS during the time which they have been away from
-               the computer. A log file can be helpful in identifying system
-               errors or crashes that have occurred, in alerting the sysop in
-               the case that any users have been causing problems on the BBS,
-               or in simply letting the sysop know who has called recently, and
-               what when they did when they called.
-
-
-MEMORY MODEL   C and C++ programs can be compiled under a variety of different
-               memory models. Each memory model describes how data and program
-               code are addressed in memory. When writing MS-DOS programs, you
-               generally have the choice of six different memory models (named
-               tiny, small, compact, medium, large and huge), each of which
-               provides a different combination of the maximum sizes of data
-               and code that your program may have. When writing Win32
-               programs, there is a single, flat 32-bit memory model that all
-               programs use. This memory model allows a program to address (in
-               theory) up to 4 gigabytes of data and code.
-
-
-MODEM          A device connected to a computer which permits it to communicate
-               with other computers, usually over standard telephone lines.
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 263
-
-OBJECT FILE    An object file contains the compiled version of a source code
-               file of a program. The source code file may be a .C file, .CPP
-               file, .ASM file, .PAS file, .BAS file, or any number of other
-               extensions associated with other programming languages. When any
-               of these language's source code files are compiled, a .OBJ file
-               is created containing information such as the executable code,
-               and names of symbols (variables and functions) that are to be
-               shared with other .OBJ files. In order to produce a .EXE file
-               that may be executed, a process known as linking must be
-               performed. During the link process, one or more object files
-               composing your program are combined, along with the necessary
-               code from any library files being used, in order to produce the
-               final .EXE file.
-
-
-ONLINE         In the case of BBS software and BBS door programs, the term
-               online refers to the state of a user using the BBS. Usually, the
-               user will be connected to the BBS from a remote location, using
-               a modem. However, it is also possible that the user will be
-               using the actual BBS computer, with the software operating in
-               "local mode".
-
-
-OUTPUT WINDOW  The local screen of the BBS on which BBS software is running is
-               usually divided into two sections. At the bottom of the screen,
-               there is often a one or two line status line, which displays
-               information to the sysop about the BBS and the user who is
-               currently online. The rest of the screen is usually an "output
-               window", in which the information which is being displayed to
-               the user, is also displayed on the local screen. In some cases,
-               there will be no status line, in which case the entire screen
-               will be the output window. Usually, the upper 23 lines of the
-               screen in an OpenDoors door will be the output window, with the
-               bottom two lines being the status line. However, it is possible
-               to disable the OpenDoors status line, in which case the entire
-               screen will be the output window. See also "Status Line"
-
-
-PAGE           See "SYSOP PAGE"
-
-
-PARAMETER      In the C programming language, many tasks are accomplished by
-               calling functions. When a function is called, one or more pieces
-               of information may be passed to a function, in the form of
-               parameters. For example, a function used to set the foreground
-               and background color of displayed text might accept two
-               parameters, one for each of the two color settings. In this
-               example, a function such as od_set_color(), would be called as
-               follows:
-
-                              od_set_color(D_GREEN,D_RED);
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 264
-
-               In this case, D_GREEN, the foreground color, is the first
-               parameter, and D_RED, the background color, is the second
-               parameter.
-
-               In C, parameters are enclosed in parentheses, ( and ), which are
-               located after the name of the function to be called. Each
-               parameter is then separated by a comma character. If a function
-               does not accept any parameters, the parentheses will have
-               nothing between them. (ie. od_clr_scr() ).
-
-
-REGISTRATION   This is a demonstration version of OpenDoors, which may only be
-               used under limited circumstances, for a limited period of time.
-               If you wish to continue using OpenDoors after this "evaluation
-               period", you must "register" it. For more information on
-               registering OpenDoors, please see chapter 2 of this manual.
-
-
-REMOTE         When used in reference to BBS software or door programs, the
-               term remote is used to refer to a user or computer that is
-               communicating with the BBS, for a distant location, by use of a
-               modem. Compare "Local Mode"
-
-
-RIP            "RIP", "RIPScrip" or "Remote Imaging Protocol" is a popular
-               graphical terminal standard that is used with BBS systems.
-               Unlike other terminal emulation standards, such as the ANSI and
-               AVATAR modes supported by OpenDoors, RIP operates in bit mapped
-               graphics mode, allowing features such as lines, circles and
-               icons to be drawn on the remote screen. OpenDoors provides
-               support for RIP graphics, although OpenDoors operates in text
-               mode itself.
-
-
-STATUS LINE    Usually, the bottom two lines of the screen, as displayed by an
-               OpenDoors door, is devoted to a status line (although this
-               status line may be turned off). This status line will display
-               information about the user who is online, along with information
-               about the current state of the BBS system, and a reference to
-               the sysop function keys. See also "Local Window".
-
-
-SYSOP          The term sysop is a short-form for "SYStem OPerator", and refers
-               to the individual who is responsible for running and maintaining
-               the BBS system. The sysop is usually the only person who has
-               direct access to the local keyboard and computer on which the
-               BBS, BBS utilities and BBS doors are running.
-
-
-SYSOP CHAT     See "CHAT MODE".
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 265
-
-SOURCE CODE    The term "source code" refers to the original file or files that
-               where used to produce a library or executable program. The
-               source code files contain the language statements or commands
-               that are directly written by the programmer. These source code
-               files are then compiled to produce an executable file that may
-               be "run".
-
-
-SYSOP PAGE     Sysop paging refers to the process whereby a user of the BBS
-               system may call or page for the sysop's attention, when they
-               wish to "chat" with the sysop, and can be thought of as being
-               similar to the ringing of a telephone. When a user pages the
-               sysop, the BBS system will produce some sort of sound, which the
-               sysop may elect to respond to if they are within hearing range
-               of the computer. The most common reasons for a user to page a
-               sysop include the case that they are having difficulty with some
-               aspect of the BBS, that they have a question, or if they are
-               simply interested in having a friendly conversation with the
-               sysop. Obviously, since the sysop may not wish to be disturbed
-               by users paging at certain times (such as when they are in bed),
-               most BBS software provides controls to allow you to control
-               paging. These features might include the ability to set hours
-               for each day of the week during which paging will be permitted,
-               and the ability to temporarily override the ability of some or
-               all callers to page the sysop.
-
-
-USER           When applied to computers in general, the term user simply
-               refers to any person using the computer hardware and software.
-               However, when applied particularly to BBSes, the term user
-               refers specifically to a person who calls the BBS, to carry out
-               activities such as communicating via messages or chatting,
-               uploading and downloading files, or using doors. Often, the term
-               user is used in contrast with the term sysop. In this case,
-               users are all of the people who call and user the BBS, other
-               than the sysop themselves.
-
-
-WIN32          Win32 is the name of the API that programs written to run under
-               Microsoft Windows 95 and Microsoft Windows NT use to access
-               operating system services. Win32 programs use a flat, 32-bit
-               memory model and have access to advanced operating system
-               services such as multithreading. Win32 programs cannot run under
-               DOS nor OS/2. While some Win32 programs can run under Windows
-               3.x using the Win32s system, OpenDoors cannot since it requires
-               multithreading services that are not provided by Win32s.
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 266
-
- IIIIII
-   II
-   II
-   II
-   II
-   II
- IIIIII
--------------------------------------------------------------------------------
-INDEX
-
-
-
-A                                          D
-
-About This Manual ..................21     Debugging                     21, 241
-Access Level ......................178     Demo Version........................9
-Alias .............................170     Display Functions..............42, 63
-ANSI Graphics                              Displaying Text....30, 41, 42, 60, 62
-Archive Contents ..................248     Door Driver Functions..............40
-ASCII Chart ........................86     Door Driver Module..............6, 40
-ASCII Mode ........................255     Door Functions.....................45
-AVATAR Graphics ....118, 134, 167, 256     Door Information File30, 33, 150, 158
-                                           Door Settings.....................182
-B                                          DORINFOx.DEF File..................33
-                                           DOS Shell.........................192
-Baud Rate .........................154     Download Limit....................169
-BBS Information ...................158
-BBS Name ..........................164     E
-BBS Systems ........................30
-Before Exit Function ..............191     Error Free Connection.............170
-Box Characters ...............185, 191     Example Program - Changing Only
-BPS Rate ..........................154      Foreground/Background Colour ....132
-Built-In Function Keys ............212     Example Program - Choosing Text
-                                            Colour ..........................129
-C                                          Example Program - Clearing A Line..56
-                                           Example Program - Dialog Box.......66
-Caller Information ................158     Example Program - Door And Utility In
-Carrier Detect .................51, 97      One Program ......................92
-Chat ..........................38, 104     Example Program - Drawing A Window118
-Chat Mode ....................104, 259     Example Program - Exiting A Door...79
-Colour Attribute Codes ............128     Example Program - First Door.......29
-Colour Constants ..................132     Example Program - Hanging Up In CBV
-Colour Customization215, 229, 232, 236      Door .............................51
-Colour Functions ...................42     Example Program - Hotkeyed Menu....91
-Colours .................110, 128, 131     Example Program - Input Key.......115
-Common Problems ...................243     Example Program - Setting Door Info
-Compiler Errors ...................243      File Location ...................150
-Compiling With OpenDoors ...........22     Example Program - Shelling To DOS.141
-Custom Function Keys ..............213     Example Program - Terminal Emu.....62
-                                           Example Program - Testing Available
-                                            Door Information ................158
-
-===============================================================================
-OpenDoors 6.00 Manual                                          End of Page 267
-
-
-
-Example Program - Testing Screen           M
-  Clearing Capabilities             57
-Example Program - Transferring A File      Memory Models..................23, 24
-  Using DSZ........................142     Memory Swapping...................209
-Example Program - User Statistics          Modem Port........................157
-  Door.............................113     Modem Settings....................153
-Example Program - Vote .............33
-Example Program - Waiting For CR ...54     N
-Exiting A Door Program .............79
-                                           New Version.......................249
-F                                          Node Number.......................152
-
-Features ............................6     O
-Feedback Form ......................19
-File Display Functions .............44     Object File.......................263
-FILES.BBS File .....................98     od_autodetect() Function...........48
-Fossil Driver .....................260     od_carrier() Function..............51
-FOSSIL port .......................157     od_chat() Function.................50
-Function Keys .................97, 211     od_clear_keybuffer() Function......53
-Future Versions ...................253     od_clr_line() Function.............55
-                                           od_clr_scr() Function.........57, 243
-G                                          od_colour_config() Function........59
-                                           od_control Structure..........31, 148
-Getting In Touch With Us ..........246     od_disable Variable...............198
-Graphics Mode ...........165, 167, 255     od_disp() Function.................60
-                                           od_disp_emu() Function.............62
-H                                          od_disp_str() Function.............63
-                                           od_draw_box() Function.............65
-History ...........................249     od_edit_str() Function.............68
-Hotkeys ............................90     od_exit() Function...31, 79, 191, 195
-                                           od_get_answer() Function...........81
-I                                          od_get_input() Function............82
-                                           od_get_key() Function......30, 53, 85
-IBM Colour Attribute Codes ........128     od_gettext() Function..............89
-IEMSI Session Information .........161     od_hotkey_menu() Function..........90
-Inactivity Timeout ......199, 200, 202     od_init() Function.............31, 92
-Input Functions ............44, 81, 85     od_input_str() Function........53, 95
-                                           od_kernal() Function...............31
-K                                          od_kernel() Function...............97
-                                           od_list_files() Function...........98
-Keyboard Buffer ...........53, 97, 115     od_log_write() Function...........100
-Keys ...............................97     od_multiline_edit() Function......101
-                                           od_page() Function...........104, 207
-L                                          od_parse_cmd_line() Function......105
-                                           od_popup_menu() Function..........107
-Language Customization ............216     od_printf() Function.....29, 110, 195
-Learning OpenDoors .................29     od_putch() Function...............115
-Library ...........................261     od_puttext() Function.............116
-LIBrary Files ......................24     od_repeat() Function..............118
-Line Number .......................152     od_restore_screen() Function......120
-Linking ............................23     od_save_screen() Function.........121
-Local Mode ...............33, 200, 261     od_scroll() Function..............123
-Locked ............................262     od_send_file() Function...........124
-                                           od_set_attrib() Function..........128
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 268
-
-
-
-od_set_color() Function ...........131     Solutions To Problems.............243
-od_set_cursor() Function ..........134     Source Code................10, 17, 20
-od_set_dtr() Function .............135     Special Thanks....................254
-od_set_personality() Function .....136     Status Line...104, 137, 209, 210, 264
-od_set_statusline() Function ......137     Stop Key..........................203
-od_sleep() Function ...............139     Support...........................244
-od_spawn Function .................208     Support BBS.............244, 245, 246
-od_spawn() Function ...............141     Swapping..........................209
-od_spawnvpe() Function ............143     Sysop Chat...............38, 104, 192
-od_window_create() Function .......145     Sysop Function Keys...............211
-od_window_remove() Function ..147, 148     Sysop Keys.........................97
-OPENDOOR.H File ............22, 29, 34     Sysop Name........................164
-OpenDoors BBS ................244, 245     Sysop Next Setting................184
-OpenDoors Customization ...........187     Sysop Page........................207
-OPENDOORS Echo ....................245     Sysop Paging.................104, 265
-OpenDoors History .................249     System Event......................162
-Our Address .......................246     System Name.......................164
-Output Functions ...................42
-Output Window .................34, 263     T
-
-P                                          Terminal Emulator........62, 124, 125
-                                           Terminal Emulator Control Codes...126
-Paging Hours .................182, 183     Text Customization................216
-Paging The Sysop ..................104     Thank-yous........................254
-Pause Key .........................203     Time Left.........................179
-Phone Number ......................171     Timeout............................97
-Printing ..30, 41, 60-63, 90, 110, 115     Troubleshooting....................21
-Printing Manual ....................22
-Problems ...........................21     U
-Product Support ...................244
-Project Files ......................23     User Handle (Alias)...............170
-                                           User Information..................158
-R                                          User Keyboard Off Key..............53
-                                           User Keyboard Setting.............184
-Registration ..9, 10, 12, 18, 246, 264     User Name.........................174
-Registration Form ..............15, 18     User Password.....................176
-RIP ...............................264     User Timeout.......................97
-RIPScrip ..........................264
-                                           V
-S
-                                           Version History...................249
-Screen Functions ...................42
-Screen Length .....................177     W
-Screen Width ......................178
-Security Level ....................178     Want-Chat Setting.................180
-Setting Colours .........110, 128, 131
-
-
-
-
-
-
-
-
-
-===============================================================================
-OpenDoors 6.00 Manual                                           End of Page 269
-
diff --git a/src/odoors/OpenDoor.def b/src/odoors/OpenDoor.def
deleted file mode 100644
index bda50ca8e218173038891440e1a47e84f5d451c8..0000000000000000000000000000000000000000
--- a/src/odoors/OpenDoor.def
+++ /dev/null
@@ -1,98 +0,0 @@
-;  OpenDoors Online Software Programming Toolkit
-;  (C) Copyright 1991 - 1999 by Brian Pirie.
-;
-; Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
-;
-;  This library is free software; you can redistribute it and/or
-;  modify it under the terms of the GNU Lesser General Public
-;  License as published by the Free Software Foundation; either
-;  version 2 of the License, or (at your option) any later version.
-;
-;  This library is distributed in the hope that it will be useful,
-;  but WITHOUT ANY WARRANTY; without even the implied warranty of
-;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;  Lesser General Public License for more details.
-;
-;  You should have received a copy of the GNU Lesser General Public
-;  License along with this library; if not, write to the Free Software
-;  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-;
-;
-;         File: OpenDoors.def
-;
-;  Description: Module definition file for the OpenDoors Win32 DLL.
-;
-;    Revisions: Date          Ver   Who  Change
-;               ---------------------------------------------------------------
-;               Dec 12, 1995  6.00  BP   Created.
-;               Jan 11, 1996  6.00  BP   Added exports for undecorated names.
-;               Feb 19, 1996  6.00  BP   Changed version number to 6.00.
-;               Mar 03, 1996  6.10  BP   Begin version 6.10.
-;               Mar 03, 1996  6.10  BP   Added od_get_cursor.
-;               Mar 21, 1996  6.10  BP   Added od_control_get().
-;               Oct 19, 2001  6.20  RS   Added door32.sys and socket support.
-LIBRARY ODOORS62
-DESCRIPTION "OpenDoors"
-VERSION 6.2
-EXPORTS
-   ODConfigInit=_ODConfigInit@0
-   ODLogEnable=_ODLogEnable@0
-   ODMPSEnable=_ODMPSEnable@0
-   od_add_personality=_od_add_personality@16
-   od_autodetect=_od_autodetect@4
-   od_carrier=_od_carrier@0
-   od_chat=_od_chat@0
-   od_clear_keybuffer=_od_clear_keybuffer@0
-   od_clr_line=_od_clr_line@0
-   od_clr_scr=_od_clr_scr@0
-   od_color_config=_od_color_config@4
-   od_control_get=_od_control_get@0
-   od_disp=_od_disp@12
-   od_disp_emu=_od_disp_emu@8
-   od_disp_str=_od_disp_str@4
-   od_draw_box=_od_draw_box@16
-   od_edit_str=_od_edit_str@32
-   od_emulate=_od_emulate@4
-   od_exit=_od_exit@8
-   od_get_answer=_od_get_answer@4
-   od_get_cursor=_od_get_cursor@8
-   od_get_input=_od_get_input@12
-   od_get_key=_od_get_key@4
-   od_gettext=_od_gettext@20
-   od_hotkey_menu=_od_hotkey_menu@12
-   od_init=_od_init@0
-   od_input_str=_od_input_str@16
-   od_kernel=_od_kernel@0
-   od_list_files=_od_list_files@4
-   od_log_open=_od_log_open@0
-   od_log_write=_od_log_write@4
-   od_multiline_edit=_od_multiline_edit@12
-   od_page=_od_page@0
-   od_parse_cmd_line=_od_parse_cmd_line@4
-   od_popup_menu=_od_popup_menu@24
-   _od_printf=od_printf
-   od_printf=od_printf
-   od_putch=_od_putch@4
-   od_puttext=_od_puttext@20
-   od_repeat=_od_repeat@8
-   od_restore_screen=_od_restore_screen@4
-   od_save_screen=_od_save_screen@4
-   od_scroll=_od_scroll@24
-   od_send_file=_od_send_file@4
-   od_set_attrib=_od_set_attrib@4
-   od_set_color=_od_set_color@8
-   od_set_cursor=_od_set_cursor@8
-   od_set_dtr=_od_set_dtr@4
-   od_set_personality=_od_set_personality@4
-   od_set_statusline=_od_set_statusline@4
-   od_sleep=_od_sleep@4
-   od_spawn=_od_spawn@4
-   od_spawnvpe=_od_spawnvpe@16
-   od_window_create=_od_window_create@36
-   od_window_remove=_od_window_remove@4
-   pdef_opendoors=_pdef_opendoors@4
-   pdef_pcboard=_pdef_pcboard@4
-   pdef_ra=_pdef_ra@4
-   pdef_wildcat=_pdef_wildcat@4
-   _od_control=od_control DATA
-   od_control=od_control DATA
diff --git a/src/odoors/OpenDoor.h b/src/odoors/OpenDoor.h
deleted file mode 100644
index bd11ecbaaabd4cbdc18f072cc9ededa7750130f3..0000000000000000000000000000000000000000
--- a/src/odoors/OpenDoor.h
+++ /dev/null
@@ -1,1095 +0,0 @@
-/* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- *        File: OpenDoor.h
- *
- * Description: C/C++ definition of the OpenDoors API. Any program source file
- *              that uses OpenDoors must #include this file.
- *
- *   Revisions: Date          Ver   Who  Change
- *              ---------------------------------------------------------------
- *              Dec 02, 1995  6.00  BP   New file header format.
- *              Dec 09, 1995  6.00  BP   Added od_multiline_edit() prototype.
- *              Dec 12, 1995  6.00  BP   Cleaned up, added DLL definitions.
- *              Dec 12, 1995  6.00  BP   Moved ODPLAT_??? to OpenDoor.h.
- *              Dec 21, 1995  6.00  BP   Add ability to use already open port.
- *              Dec 22, 1995  6.00  BP   Added od_connect_speed.
- *              Dec 23, 1995  6.00  BP   Added EDIT_FLAG_SHOW_SIZE.
- *              Dec 30, 1995  6.00  BP   Added ODCALL for calling convention.
- *              Jan 01, 1996  6.00  BP   BCC32 compatibility changes.
- *              Jan 01, 1996  6.00  BP   Added new mulitline editor options.
- *              Jan 01, 1996  6.00  BP   Added od_disable_dtr, DIS_DTR_DISABLE.
- *              Jan 03, 1996  6.00  BP   Further BCC32 compatiblity changes.
- *              Jan 04, 1996  6.00  BP   Added od_get_input() and related defs.
- *              Jan 07, 1996  6.00  BP   Added OD_GLOBAL_CONV.
- *              Jan 19, 1996  6.00  BP   Removed some unused stuff.
- *              Jan 19, 1996  6.00  BP   Added od_internal_debug.
- *              Jan 23, 1996  6.00  BP   Added od_exiting and ERR_UNSUPPORTED.
- *              Jan 30, 1996  6.00  BP   New extern "C" decl for od_control.
- *              Jan 30, 1996  6.00  BP   Replaced od_yield() with od_sleep().
- *              Jan 31, 1996  6.00  BP   Added DIS_NAME_PROMPT.
- *              Jan 31, 1996  6.00  BP   Added tODMilliSec, OD_NO_TIMEOUT.
- *              Jan 31, 1996  6.00  BP   Added timeout for od_get_input().
- *              Feb 02, 1996  6.00  BP   Add RA 2.50-related od_control vars.
- *              Feb 03, 1996  6.00  BP   Added more editor options.
- *              Feb 06, 1996  6.00  BP   Added od_silent_mode.
- *              Feb 08, 1996  6.00  BP   Added editor buffer grow option.
- *              Feb 13, 1996  6.00  BP   Added od_get_input() flags parameter.
- *              Feb 14, 1996  6.00  BP   Recognize Borland's __WIN32__ define.
- *              Feb 17, 1996  6.00  BP   Added OD_KEY_F1 thru OD_KEY_F10.
- *              Feb 19, 1996  6.00  BP   Changed version number to 6.00.
- *              Feb 27, 1996  6.00  BP   Added od_max_key_latency.
- *              Mar 03, 1996  6.10  BP   Begin version 6.10.
- *              Mar 03, 1996  6.10  BP   Fixed OD_COMPONENT for medium mem mod.
- *              Mar 06, 1996  6.10  BP   Added TRIBBS.SYS support.
- *              Mar 06, 1996  6.10  BP   Added COM_DOOR32.
- *              Mar 11, 1996  6.10  BP   Added OD_VERSION.
- *              Mar 13, 1996  6.10  BP   Added od_get_cursor().
- *              Mar 13, 1996  6.10  BP   Added od_local_win_col.
- *              Mar 14, 1996  6.10  BP   Added od_config_callback.
- *              Mar 21, 1996  6.10  BP   Added od_control_get().
- *              Apr 08, 1996  6.10  BP   Added command-line parsing callbacks.
- *              Oct 19, 2001  6.20  RS   Added door32.sys and socket support.
- *              Oct 19, 2001  6.21  RS   Fixed socket disconnect bug.
- */
-
-/* Only parse OpenDoor.h once. */
-#ifndef _INC_OPENDOOR
-#define _INC_OPENDOOR
-
-
-/* ========================================================================= */
-/* Version and platform definitions.                                         */
-/* ========================================================================= */
-
-/* OpenDoors API version number. */
-#define OD_VERSION 0x621
-
-/* OpenDoors target platform. */
-#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32)
-#define ODPLAT_WIN32
-#undef ODPLAT_DOS
-#ifdef OD_WIN32_STATIC
-#pragma message("Compiling for Win32 static version of OpenDoors")
-#else /* !OD_WIN32_STATIC */
-#pragma message("Compiling for Win32 DLL version of OpenDoors")
-#define OD_DLL
-#endif /* !OD_WIN32_STATIC */
-#else /* !WIN32 */
-#define ODPLAT_DOS
-#undef ODPLAT_WIN32
-#pragma message("Compiling for DOS version of OpenDoors")
-#endif /* !WIN32 */
-
-/* Include any other headers required by OpenDoor.h. */
-#ifdef ODPLAT_WIN32 
-#include "windows.h"
-#endif /* ODPLAT_WIN32 */
-
-/* For DLL versions, definitions of function or data that is exported from */
-/* a module or imported into a module.                                     */
-#ifdef OD_DLL
-#ifdef _MSC_VER
-#define OD_EXPORT __declspec(dllexport)
-#else /* !_MSC_VER */
-#define OD_EXPORT _export
-#endif /* !_MSC_VER */
-#define OD_IMPORT DECLSPEC_IMPORT
-#else /* !OD_DLL */
-#define OD_EXPORT
-#define OD_IMPORT
-#endif /* !OD_DLL */
-
-/* Definition of function naming convention used by OpenDoors. */
-#ifdef __cplusplus
-#define OD_NAMING_CONVENTION extern "C"
-#else /* !__cplusplus */
-#define OD_NAMING_CONVENTION
-#endif /* !__cplusplus */
-
-/* Definition of function calling convention used by OpenDoors. */
-#ifdef ODPLAT_WIN32
-#define ODCALL WINAPI
-#define ODVCALL WINAPIV
-#define OD_GLOBAL_CONV WINAPI
-#else /* !ODPLAT_WIN32 */
-#define ODCALL
-#define ODVCALL
-#define OD_GLOBAL_CONV
-#endif /* !ODPLAT_WIN32 */
-
-/* OpenDoors API function declaration type. */
-#ifdef BUILDING_OPENDOORS
-#define ODAPIDEF OD_NAMING_CONVENTION OD_EXPORT
-#else /* !BUILDING_OPENDOORS */
-#define ODAPIDEF OD_NAMING_CONVENTION OD_IMPORT
-#endif /* !BUILDING_OPENDOORS */
-
-/* OpenDoors API global variable definition and declaration types. */
-#define OD_API_VAR_DEFN OD_NAMING_CONVENTION OD_EXPORT
-
-#ifdef BUILDING_OPENDOORS
-#define OD_API_VAR_DECL extern OD_EXPORT
-#else /* !BUILDING_OPENDOORS */
-#define OD_API_VAR_DECL extern OD_IMPORT
-#endif /* !BUILDING_OPENDOORS */
-
-/* Explicitly far pointers. */
-#ifdef ODPLAT_DOS
-#define ODFAR far
-#else /* !ODPLAT_DOS */
-#define ODFAR
-#endif /* !ODPLAT_DOS */
-
-
-/* ========================================================================= */
-/* Primitive data types.                                                     */
-/* ========================================================================= */
-
-/* Portable types that are the same size across all platforms */
-#ifndef ODPLAT_WIN32
-typedef unsigned char      BYTE;                        /* Unsigned, 8 bits. */
-typedef unsigned short     WORD;                       /* Unsigned, 16 bits. */
-typedef unsigned long      DWORD;                      /* Unsigned, 32 bits. */
-typedef char               CHAR;         /* Native character representation. */
-#endif /* !ODPLAT_WIN32 */
-
-typedef signed char        INT8;                          /* Signed, 8 bits. */
-typedef signed short int   INT16;                        /* Signed, 16 bits. */
-#ifndef _WIN32	/* avoid type redefinition from basetsd.h */
-typedef signed long int    INT32;                        /* Signed, 32 bits. */
-#endif
-
-
-/* Types that vary in size depending on platform. These are guranteed to be */
-/* at least the given size, but may be larger if this platform can          */
-/* represent a larger value more efficiently (or as efficiently).           */
-#ifndef ODPLAT_WIN32
-typedef int                INT;                /* Integer, at least 16 bits. */
-typedef unsigned int       UINT;      /* Unsigned integer, at least 16 bits. */
-#ifndef BOOL
-typedef char               BOOL;           /* Boolean value, at least 1 bit. */
-#endif /* !BOOL */
-#endif /* !ODPLAT_WIN32 */
-
-/* TRUE and FALSE manifest constants, for use with BOOL data type. */
-#ifndef FALSE
-#define FALSE 0
-#endif /* !FALSE */
-#ifndef TRUE
-#define TRUE 1
-#endif /* !TRUE */
-
-
-/* ========================================================================= */
-/* OpenDoors complex data types and defines.                                 */
-/* ========================================================================= */
-
-/* Millisecond time type. */
-typedef DWORD tODMilliSec;
-
-/* Special value tODMilliSec value for no timeouts. */
-#ifdef ODPLAT_WIN32
-#define OD_NO_TIMEOUT INFINITE
-#else /* !ODPLAT_WIN32 */
-#define OD_NO_TIMEOUT 0xffffffffL
-#endif /* !ODPLAT_WIN32 */
-
-
-/* Multi-line editor defintions. */
-
-/* Editor text formats. */
-typedef enum
-{
-   FORMAT_PARAGRAPH_BREAKS,
-   FORMAT_LINE_BREAKS,
-   FORMAT_FTSC_MESSAGE,
-   FORMAT_NO_WORDWRAP,
-} tODEditTextFormat;
-
-/* Menu callback function return values. */
-typedef enum
-{
-   EDIT_MENU_DO_NOTHING,
-   EDIT_MENU_EXIT_EDITOR,
-} tODEditMenuResult;
-
-/* Editor flags. */
-#define EFLAG_NORMAL       0x00000000
-
-/* Optional multi-line editor settings. */
-typedef struct
-{
-   INT nAreaLeft;
-   INT nAreaTop;
-   INT nAreaRight;
-   INT nAreaBottom;
-   tODEditTextFormat TextFormat;
-   tODEditMenuResult (*pfMenuCallback)(void *pUnused);
-   void * (*pfBufferRealloc)(void *pOriginalBuffer, UINT unNewSize);
-   DWORD dwEditFlags;
-   char *pszFinalBuffer;
-   UINT unFinalBufferSize;
-} tODEditOptions;
-
-/* Editor return values. */
-#define OD_MULTIEDIT_ERROR          0
-#define OD_MULTIEDIT_SUCCESS        1
-
-
-/* Input event information. */
-
-/* Input event types. */
-typedef enum
-{
-   EVENT_CHARACTER,
-   EVENT_EXTENDED_KEY,
-} tODInputEventType;
-
-/* Extended key codes. */
-#define OD_KEY_F1          0x3b
-#define OD_KEY_F2          0x3c
-#define OD_KEY_F3          0x3d
-#define OD_KEY_F4          0x3e
-#define OD_KEY_F5          0x3f
-#define OD_KEY_F6          0x40
-#define OD_KEY_F7          0x41
-#define OD_KEY_F8          0x42
-#define OD_KEY_F9          0x43
-#define OD_KEY_F10         0x44
-#define OD_KEY_UP          0x48
-#define OD_KEY_DOWN        0x50
-#define OD_KEY_LEFT        0x4b
-#define OD_KEY_RIGHT       0x4d
-#define OD_KEY_INSERT      0x52
-#define OD_KEY_DELETE      0x53
-#define OD_KEY_HOME        0x47
-#define OD_KEY_END         0x4f
-#define OD_KEY_PGUP        0x49
-#define OD_KEY_PGDN        0x51
-#define OD_KEY_SHIFTTAB    0x0f
-
-/* Input event structure. */
-typedef struct
-{
-   tODInputEventType EventType;
-   BOOL bFromRemote;
-   char chKeyPress;
-} tODInputEvent;
-
-
-/* Third option (in addition to TRUE and FALSE) for tri-state options. */
-#define MAYBE 2
-
-/* od_spawnvpe() flags. */
-#define P_WAIT                  0
-#define P_NOWAIT                1
-#define CURRENT                 0
-#define IRET                    1
-
-/* od_edit_str() flags. */
-#define EDIT_FLAG_NORMAL        0x0000
-#define EDIT_FLAG_NO_REDRAW     0x0001
-#define EDIT_FLAG_FIELD_MODE    0x0002
-#define EDIT_FLAG_EDIT_STRING   0x0004
-#define EDIT_FLAG_STRICT_INPUT  0x0008
-#define EDIT_FLAG_PASSWORD_MODE 0x0010
-#define EDIT_FLAG_ALLOW_CANCEL  0x0020
-#define EDIT_FLAG_FILL_STRING   0x0040
-#define EDIT_FLAG_AUTO_ENTER    0x0080
-#define EDIT_FLAG_AUTO_DELETE   0x0100
-#define EDIT_FLAG_KEEP_BLANK    0x0200
-#define EDIT_FLAG_PERMALITERAL  0x0400
-#define EDIT_FLAG_LEAVE_BLANK   0x0800
-#define EDIT_FLAG_SHOW_SIZE     0x1000
-
-/* od_edit_str() return values. */
-#define EDIT_RETURN_ERROR       0
-#define EDIT_RETURN_CANCEL      1
-#define EDIT_RETURN_ACCEPT      2
-#define EDIT_RETURN_PREVIOUS    3
-#define EDIT_RETURN_NEXT        4
-
-/* od_popup_menu() flag values. */
-#define MENU_NORMAL             0x0000
-#define MENU_ALLOW_CANCEL       0x0001
-#define MENU_PULLDOWN           0x0002
-#define MENU_KEEP               0x0004
-#define MENU_DESTROY            0x0008
-
-/* od_autodetect() flag values. */
-#define DETECT_NORMAL           0x0000
-
-/* od_scroll() flags. */
-#define SCROLL_NORMAL           0x0000
-#define SCROLL_NO_CLEAR         0x0001
-
-/* OpenDoors status line settings */
-#define STATUS_NORMAL           0
-#define STATUS_NONE             8
-#define STATUS_ALTERNATE_1      1
-#define STATUS_ALTERNATE_2      2
-#define STATUS_ALTERNATE_3      3
-#define STATUS_ALTERNATE_4      4
-#define STATUS_ALTERNATE_5      5
-#define STATUS_ALTERNATE_6      6
-#define STATUS_ALTERNATE_7      7
-
-/* OpenDoors color definitions. */
-#define D_BLACK                 0
-#define D_BLUE                  1
-#define D_GREEN                 2
-#define D_CYAN                  3
-#define D_RED                   4
-#define D_MAGENTA               5
-#define D_BROWN                 6
-#define D_GREY                  7
-#define L_BLACK                 8
-#define L_BLUE                  9
-#define L_GREEN                 10
-#define L_CYAN                  11
-#define L_RED                   12
-#define L_MAGENTA               13
-#define L_YELLOW                14
-#define L_WHITE                 15
-#define B_BLACK                 L_BLACK
-#define B_BLUE                  L_BLUE
-#define B_GREEN                 L_GREEN
-#define B_CYAN                  L_CYAN
-#define B_RED                   L_RED
-#define B_MAGENTA               L_MAGENTA
-#define B_BROWN                 L_YELLOW
-#define B_GREY                  L_WHITE
-
-/* Door information file formats (od_control.od_info_type). */
-#define DORINFO1              0                              /* DORINFO?.DEF */
-#define EXITINFO              1     /* QBBS 2.6? EXITINFO.BBS & DORINFO?.DEF */
-#define RA1EXITINFO           2       /* RA 1.?? EXITINFO.BBS & DORINFO?.DEF */
-#define CHAINTXT              3                                 /* CHAIN.TXT */
-#define SFDOORSDAT            4                               /* SFDOORS.DAT */
-#define CALLINFO              5                              /* CALLINFO.BBS */
-#define DOORSYS_GAP           6                     /* GAP/PC-Board DOOR.SYS */
-#define DOORSYS_DRWY          7                          /* DoorWay DOOR.SYS */
-#define QBBS275EXITINFO       8               /* QuickBBS 2.75+ EXITINFO.BBS */
-#define CUSTOM                9                /* User-defined custom format */
-#define DOORSYS_WILDCAT       10                        /* WildCat! DOOR.SYS */
-#define RA2EXITINFO           11                    /* RA 2.00+ EXITINFO.BBS */
-#define TRIBBSSYS             12                               /* TRIBBS.SYS */
-#define DOOR32SYS             13                               /* DOOR32.SYS */
-#define NO_DOOR_FILE          100      /* No door information file was found */
-
-/* Error type (od_control.od_error). */
-#define ERR_NONE              0                              /* No error yet */
-#define ERR_MEMORY            1          /* Unable to allocate enough memory */
-#define ERR_NOGRAPHICS        2    /* Function requires ANSI/AVATAR/RIP mode */
-#define ERR_PARAMETER         3    /* Invalid value was passed to a function */
-#define ERR_FILEOPEN          4                       /* Unable to open file */
-#define ERR_LIMIT             5       /* An internal limit has been exceeded */
-#define ERR_FILEREAD          6                  /* Unable to read from file */
-#define ERR_NOREMOTE          7  /* Function may not be called in local mode */
-#define ERR_GENERALFAILURE    8       /* Percise cause of failure is unknown */
-#define ERR_NOTHINGWAITING    9    /* A request for data when none was ready */
-#define ERR_NOMATCH           10                       /* No match was found */
-#define ERR_UNSUPPORTED       11            /* Not supported in this version */
-
-/* od_control.od_errorlevel indicies. */
-#define ERRORLEVEL_ENABLE     0
-#define ERRORLEVEL_CRITICAL   1
-#define ERRORLEVEL_NOCARRIER  2
-#define ERRORLEVEL_HANGUP     3
-#define ERRORLEVEL_TIMEOUT    4
-#define ERRORLEVEL_INACTIVITY 5
-#define ERRORLEVEL_DROPTOBBS  6
-#define ERRORLEVEL_NORMAL     7
-
-/* Special od_popup_menu() return values. */
-#define POPUP_ERROR           -1
-#define POPUP_ESCAPE          0
-#define POPUP_LEFT            -2
-#define POPUP_RIGHT           -3
-
-/* od_get_input() flags. */
-#define GETIN_NORMAL          0x0000
-#define GETIN_RAW             0x0001
-#define GETIN_RAWCTRL         0x0002
-
-/* od_control.od_box_chars array indicies. */
-#define BOX_UPPERLEFT         0
-#define BOX_TOP               1
-#define BOX_UPPERRIGHT        2
-#define BOX_LEFT              3
-#define BOX_LOWERLEFT         4
-#define BOX_LOWERRIGHT        5
-#define BOX_BOTTOM            6
-#define BOX_RIGHT             7
-
-/* od_control.od_okaytopage settings. */
-#define PAGE_DISABLE          0
-#define PAGE_ENABLE           1
-#define PAGE_USE_HOURS        2
-
-/*  Method used for serial I/O (od_control.od_com_method). */
-#define COM_FOSSIL            1
-#define COM_INTERNAL          2
-#define COM_WIN32             3
-#define COM_DOOR32            4
-#define COM_SOCKET				5
-
-/* Flow control method (od_control.od_com_flow_control). */
-#define COM_DEFAULT_FLOW      0
-#define COM_RTSCTS_FLOW       1
-#define COM_NO_FLOW           2
-
-/* Optional component initialization functions. */
-ODAPIDEF void ODCALL ODConfigInit(void);
-ODAPIDEF void ODCALL ODLogEnable(void);
-ODAPIDEF void ODCALL ODMPSEnable(void);
-
-/* Optional OpenDoors component settings. */
-typedef void ODFAR OD_COMPONENT;
-#define INCLUDE_CONFIG_FILE   (OD_COMPONENT *)ODConfigInit
-#define NO_CONFIG_FILE        NULL
-#define INCLUDE_LOGFILE       (OD_COMPONENT *)ODLogEnable
-#define NO_LOGFILE            NULL
-#define INCLUDE_MPS           (OD_COMPONENT *)ODMPSEnable
-#define NO_MPS                NULL
-
-/* Built-in personality defintion functions. */
-ODAPIDEF void ODCALL pdef_opendoors(BYTE btOperation);
-ODAPIDEF void ODCALL pdef_pcboard(BYTE btOperation);
-ODAPIDEF void ODCALL pdef_ra(BYTE btOperation);
-ODAPIDEF void ODCALL pdef_wildcat(BYTE btOperation);
-
-/* Personality proc type. */
-typedef void OD_PERSONALITY_PROC;
-
-/* Personality identifiers. */
-#define PER_OPENDOORS         (void *)pdef_opendoors
-#define PER_PCBOARD           (void *)pdef_pcboard
-#define PER_RA                (void *)pdef_ra
-#define PER_WILDCAT           (void *)pdef_wildcat
-
-/* od_control.od_disable flags. */
-#define DIS_INFOFILE          0x0001
-#define DIS_CARRIERDETECT     0x0002
-#define DIS_TIMEOUT           0x0004
-#define DIS_LOCAL_OVERRIDE    0x0008
-#define DIS_BPS_SETTING       0x0010
-#define DIS_LOCAL_INPUT       0x0020
-#define DIS_SYSOP_KEYS        0x0040
-#define DIS_DTR_DISABLE       0x0080
-#define DIS_NAME_PROMPT       0x0100
-
-/* Event status settings. */
-#define ES_DELETED            0
-#define ES_ENABLED            1
-#define ES_DISABLED           2
-
-/* Personality proceedure operations. */
-#define PEROP_DISPLAY1        0
-#define PEROP_DISPLAY2        1
-#define PEROP_DISPLAY3        2
-#define PEROP_DISPLAY4        3
-#define PEROP_DISPLAY5        4
-#define PEROP_DISPLAY6        5
-#define PEROP_DISPLAY7        6
-#define PEROP_DISPLAY8        7
-#define PEROP_UPDATE1         10
-#define PEROP_UPDATE2         11
-#define PEROP_UPDATE3         12
-#define PEROP_UPDATE4         13
-#define PEROP_UPDATE5         14
-#define PEROP_UPDATE6         15
-#define PEROP_UPDATE7         16
-#define PEROP_UPDATE8         17
-#define PEROP_INITIALIZE      20
-#define PEROP_CUSTOMKEY       21
-#define PEROP_DEINITIALIZE    22
-
-
-/* ========================================================================= */
-/* The OpenDoors control structure (od_control)                              */
-/* ========================================================================= */
-
-/* Force byte alignment, if possible */
-#ifdef __TURBOC__
-#if(__TURBOC__ >= 0x295)
-#pragma option -a-
-#endif /* __TURBOC__ >= 0x295 */
-#endif /* __TURBOC__ */
-#ifdef _MSC_VER
-#pragma pack(1)
-#endif /* _MSC_VER */
-
-typedef struct
-{
-   /* Location or name of door information file (if one is to be used). */
-   char          info_path[60];
-
-   /* Serial port settings. */
-   DWORD         baud;
-   DWORD         od_connect_speed;
-   INT16         od_com_address;
-   BYTE          od_com_irq;
-   BYTE          od_com_method;
-   BYTE          od_com_flow_control;
-   WORD          od_com_rx_buf;
-   WORD          od_com_tx_buf;
-   BYTE          od_com_fifo_trigger;
-   BOOL          od_com_no_fifo;
-   BOOL          od_no_fossil;
-   BOOL          od_use_socket;
-   INT16         port;
-   DWORD         od_open_handle;
-
-   /* Caller and system information. */
-   char          system_name[40];
-   char          sysop_name[40];
-   INT32         system_calls;
-   char          system_last_caller[36];
-   char          timelog_start_date[9];
-   INT16         timelog_busyperhour[24];
-   INT16         timelog_busyperday[7];
-
-   char          user_name[36];
-   char          user_location[26];
-   char          user_password[16];
-   char          user_dataphone[16];
-   char          user_homephone[16];
-   char          user_lasttime[6];
-   char          user_lastdate[9];
-   BYTE          user_attribute;
-   BYTE          user_flags[4];
-   DWORD         user_net_credit;
-   DWORD         user_pending;
-   WORD          user_messages;
-   DWORD         user_lastread;
-   WORD          user_security;
-   DWORD         user_numcalls;
-   DWORD         user_uploads;
-   DWORD         user_downloads;
-   DWORD         user_upk;
-   DWORD         user_downk;
-   DWORD         user_todayk;
-   WORD          user_time_used;
-   WORD          user_screen_length;
-   BYTE          user_last_pwdchange;
-   BYTE          user_attrib2;
-   WORD          user_group;
-
-   BYTE          event_status;
-   char          event_starttime[6];
-   BYTE          event_errorlevel;
-   BYTE          event_days;
-   BYTE          event_force;
-   char          event_last_run[9];
-
-   BYTE          user_netmailentered;
-   BYTE          user_echomailentered;
-   char          user_logintime[6];
-   char          user_logindate[9];
-   INT16         user_timelimit;
-   INT32         user_loginsec;
-   INT32         user_credit;
-   WORD          user_num;
-   INT16         user_readthru;
-   INT16         user_numpages;
-   INT16         user_downlimit;
-   char          user_timeofcreation[6];
-   char          user_logonpassword[16];
-   BYTE          user_wantchat;
-   BYTE          user_ansi;
-   INT16         user_deducted_time;
-   char          user_menustack[50][9];
-   BYTE          user_menustackpointer;
-   char          user_handle[36];
-   char          user_comment[81];
-   char          user_firstcall[9];
-   BYTE          user_combinedrecord[200];
-   char          user_birthday[9];
-   char          user_subdate[9];
-   BYTE          user_screenwidth;
-   BYTE          user_language;
-   BYTE          user_date_format;
-   char          user_forward_to[36];
-   BYTE          user_error_free;
-   BYTE          sysop_next;
-   BYTE          user_emsi_session;
-   char          user_emsi_crtdef[41];
-   char          user_emsi_protocols[41];
-   char          user_emsi_capabilities[41];
-   char          user_emsi_requests[41];
-   char          user_emsi_software[41];
-   BYTE          user_hold_attr1;
-   BYTE          user_hold_attr2;
-   BYTE          user_hold_len;
-   char          user_reasonforchat[78];
-   char          user_callsign[12];
-   WORD          user_msg_area;
-   WORD          user_file_area;
-   char          user_protocol;
-   WORD          user_file_group;
-   BYTE          user_last_birthday_check;
-   char          user_sex;
-   DWORD         user_xi_record;
-   WORD          user_msg_group;
-   BYTE          user_avatar;
-   char          user_org[51];
-   char          user_address[3][51];
-   INT32         user_pwd_crc;
-   INT32         user_logon_pwd_crc;
-   char          user_last_cost_menu[9];
-   WORD          user_menu_cost;
-   BYTE          user_rip;
-   BYTE          user_rip_ver;
-   BYTE          user_attrib3;
-   BOOL          user_expert;
-   char          system_last_handle[36];
-
-   /* Door information file statistics. */
-   BYTE          od_info_type;
-   BYTE          od_extended_info;
-   WORD          od_node;
-   BYTE          od_ra_info;
-
-   /* Current program settings. */
-   BOOL          od_always_clear;
-   BOOL          od_force_local;
-   BOOL          od_chat_active;
-   BOOL          od_current_statusline;
-   INT16         od_error;
-   BYTE          od_last_input;
-   BOOL          od_logfile_disable;
-   char          od_logfile_name[80];
-   WORD          od_maxtime;
-   INT16         od_maxtime_deduction;
-   BOOL          od_okaytopage;
-   INT16         od_pagestartmin;
-   INT16         od_pageendmin;
-   BOOL          od_page_pausing;
-   INT16         od_page_statusline;
-   BOOL          od_user_keyboard_on;
-   BOOL          od_update_status_now;
-   INT16         od_cur_attrib;
-
-   /* OpenDoors customization settings. */
-   char          od_box_chars[8];
-   char          od_cfg_text[48][33];
-   char          od_cfg_lines[25][33];
-   OD_COMPONENT  *od_config_file;
-   char *        od_config_filename;
-   void          (*od_config_function)(char *keyword, char *options);
-   char          od_color_char;
-   char          od_color_delimiter;
-   char          od_color_names[12][33];
-   BOOL          od_clear_on_exit;
-   void          (*od_cmd_line_handler)(char *pszKeyword, char *pszOptions);
-   void          (*od_cmd_line_help_func)(void);
-   void          (*od_default_personality)(BYTE operation);
-   BOOL          od_default_rip_win;
-   WORD          od_disable;
-   char          od_disable_dtr[40];
-   BOOL          od_disable_inactivity;
-   BOOL          od_emu_simulate_modem;
-   BYTE          od_errorlevel[8];
-   BOOL          od_full_color;
-   BOOL          od_full_put;
-   WORD          od_in_buf_size;
-   INT16         od_inactivity;
-   INT16         od_inactive_warning;
-   BOOL          od_internal_debug;
-   tODMilliSec   od_max_key_latency;
-   char          od_list_pause;
-   char          od_list_stop;
-   OD_COMPONENT  *od_logfile;
-   char          *od_logfile_messages[14];
-   OD_COMPONENT  *od_mps;
-   BOOL          od_nocopyright;
-   BOOL          od_noexit;
-   BOOL          od_no_ra_codes;
-   BYTE          od_page_len;
-   char          od_prog_copyright[40];
-   char          od_prog_name[40];
-   char          od_prog_version[40];
-   DWORD         od_reg_key;
-   char          od_reg_name[36];
-   BOOL          od_silent_mode;
-   BOOL          od_status_on;
-   BOOL          od_spawn_freeze_time;
-   BOOL          od_swapping_disable;
-   BOOL          od_swapping_noems;
-   char          od_swapping_path[80];
-
-   /* Custom function hooks. */
-   void          (*od_no_file_func)(void);
-   void          (*od_before_exit)(void);
-   void          (*od_cbefore_chat)(void);
-   void          (*od_cafter_chat)(void);
-   void          (*od_cbefore_shell)(void);
-   void          (*od_cafter_shell)(void);
-   void          (*od_config_callback)(void);
-   void          (*od_help_callback)(void);
-   void          (*od_ker_exec)(void);
-   void          (*od_local_input)(INT16 key);
-   void          (*od_time_msg_func)(char *string);
-
-   /* OpenDoors function key customizations. */
-   WORD          key_chat;
-   WORD          key_dosshell;
-   WORD          key_drop2bbs;
-   WORD          key_hangup;
-   WORD          key_keyboardoff;
-   WORD          key_lesstime;
-   WORD          key_lockout;
-   WORD          key_moretime;
-   WORD          key_status[9];
-   WORD          key_sysopnext;
-
-   /* Additional function keys. */
-   BYTE          od_num_keys;
-   INT16         od_hot_key[16];
-   INT16         od_last_hot;
-   void          (*od_hot_function[16])(void);
-
-   /* OpenDoors prompt customizations. */
-   char *        od_after_chat;
-   char *        od_after_shell;
-   char *        od_before_chat;
-   char *        od_before_shell;
-   char *        od_chat_reason;
-   char *        od_continue;
-   char          od_continue_yes;
-   char          od_continue_no;
-   char          od_continue_nonstop;
-   char *        od_day[7];
-   char *        od_hanging_up;
-   char *        od_exiting;
-   char *        od_help_text;
-   char *        od_help_text2;
-   char *        od_inactivity_timeout;
-   char *        od_inactivity_warning;
-   char *        od_month[12];
-   char *        od_no_keyboard;
-   char *        od_no_sysop;
-   char *        od_no_response;
-   char *        od_no_time;
-   char *        od_offline;
-   char *        od_paging;
-   char *        od_press_key;
-   char *        od_sending_rip;
-   char *        od_status_line[3];
-   char *        od_sysop_next;
-   char *        od_time_left;
-   char *        od_time_warning;
-   char *        od_want_chat;
-   char *        od_cmd_line_help;
-
-   /* OpenDoors color customizations. */
-   BYTE          od_chat_color1;
-   BYTE          od_chat_color2;
-   BYTE          od_list_comment_col;
-   BYTE          od_list_name_col;
-   BYTE          od_list_offline_col;
-   BYTE          od_list_size_col;
-   BYTE          od_list_title_col;
-   BYTE          od_local_win_col;
-   BYTE          od_continue_col;
-   BYTE          od_menu_title_col;
-   BYTE          od_menu_border_col;
-   BYTE          od_menu_text_col;
-   BYTE          od_menu_key_col;
-   BYTE          od_menu_highlight_col;
-   BYTE          od_menu_highkey_col;
-
-   /* Platform-specific settings. */
-#ifdef ODPLAT_WIN32
-   HICON         od_app_icon;
-   int           od_cmd_show;
-#endif /* ODPLAT_WIN32 */
-} tODControl;
-
-/* Restore original structure alignment, if possible. */
-#ifdef _MSC_VER
-#pragma pack()
-#endif /* _MSC_VER */
-
-
-/* The od_control external variable. */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-OD_API_VAR_DECL tODControl 
-#ifndef _WIN32	/* warning C4229: anachronism used : modifiers on data are ignored */
-OD_GLOBAL_CONV 
-#endif
-od_control;
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-/* ========================================================================= */
-/* OpenDoors API function prototypes.                                        */
-/* ========================================================================= */
-
-/* Programs interface with OpenDoors by calling any of the OpenDoors API
- * functions. A summary of these functions appears below, followed by the
- * function definition prototypes. Full information on these functions is
- * provided by the OpenDoors manual. Functions denoted (ANS/AVT) require ANSI
- * or AVATAR display modes to be active.
- *
- * OUTPUT FUNCTIONS - TEXT DISPLAY
- *    od_printf()             - Performs formatted output, with color settings
- *    od_disp_str()           - Displays a normal, nul-terminated string.
- *    od_disp()               - Sends chars to modem, with/without local echo
- *    od_disp_emu()           - Displays a string, translating ANSI/AVT codes
- *    od_repeat()             - Efficiently displays a character repeatedly
- *    od_putch()              - Displays a single character.
- *
- * OUTPUT FUNCTIONS - COLOUR AND CURSOR CONTROL
- *    od_set_color()          - Sets color according to fore/background values
- *    od_set_attrib()         - Sets color to specified IBM-PC attribute
- *    od_set_cursor()         - Positions cursor on screen            (ANS/AVT)
- *    od_get_cursor()         - Estimates the current cursor position on screen
- *
- * OUTPUT FUNCTIONS - SCREEN MANIPULATION
- *    od_clr_scr()            - Clears the screen
- *    od_save_screen()        - Saves the contents of entire screen
- *    od_restore_screen()     - Restores the contents of entire screen
- *
- * OUTPUT FUNCTIONS - BLOCK MANIPULATION
- *    od_clr_line()           - Clears the remainder of the current line
- *    od_gettext()            - Gets the contents a block of screen   (ANS/AVT)
- *    od_puttext()            - Displays block stored by gettext()    (ANS/AVT)
- *    od_scroll()             - Scrolls a portion of the screen       (ANS/AVT)
- *
- * OUTPUT FUNCTIONS - WINDOWS & MENUS
- *    od_draw_box()           - Draws a box on the screen             (ANS/AVT)
- *    od_window_create()      - Creates a window, storing underlying  (ANS/AVT)
- *    od_window_remove()      - Removes window, restoring underlying  (ANS/AVT)
- *    od_popup_menu()         - Displays popup menu with "light" bar  (ANS/AVT)
- *
- * OUTPUT FUNCTIONS - FILE DISPLAY
- *    od_send_file()          - Displays an ASCII/ANSI/AVATAR/RIP file
- *    od_hotkey_menu()        - Displays ASC/ANS/AVATAR/RIP menu, with hotkeys
- *    od_list_files()         - Lists files avail for download using FILES.BBS
- *
- * INPUT FUNCTIONS
- *    od_get_answer()         - Inputs a key, allowing only specified responses
- *    od_get_key()            - Inputs a key, optionally waiting for next key
- *    od_get_input()          - Obtains next input, with translation
- *    od_input_str()          - Inputs string of specified length from keyboard
- *    od_edit_str()           - Fancy formatted string input function (ANS/AVT)
- *    od_clear_keybuffer()    - Removes any waiting keys in keyboard buffer
- *    od_multiline_edit()     - Edits text that spans multiple lines  (ANS/AVT)
- *
- * COMMON DOOR ACTIVITY FUNCTIONS
- *    od_page()               - Allows user to page sysop
- *    od_spawn()              - Suspends OpenDoors & starts another program
- *    od_spawnvpe()           - Like od_spawn, but with more options
- *    od_log_write()          - Writes a logfile entry
- *    od_parse_cmd_line()     - Handles standard command-line parameters
- *
- * SPECIAL CONTROL FUNCTIONS
- *    od_init()               - Forces OpenDoors initialization
- *    od_color_config()       - Translates color description to color value
- *    od_add_personality()    - Adds another local interface personality
- *    od_set_statusline()     - Sets the current status line setting
- *    od_autodetect()         - Determines the remote system terminal type
- *    od_kernel()             - Call when not calling other functions
- *    od_exit()               - Ends OpenDoors program
- *    od_carrier()            - Indicates whether remote connection is present
- *    od_set_dtr()            - Raises / lowers the DTR signal to the modem
- *    od_chat()               - Manually starts chat mode
- *    od_sleep()              - Yield to other processes
- *    od_control_get()        - Returns a pointer to the od_control structure.
- */
-ODAPIDEF BOOL ODCALL   od_add_personality(char *pszName, BYTE btOutputTop,
-                          BYTE btOutputBottom,
-                          OD_PERSONALITY_PROC *pfPerFunc);
-ODAPIDEF void ODCALL   od_autodetect(INT nFlags);
-ODAPIDEF BOOL ODCALL   od_carrier(void);
-ODAPIDEF void ODCALL   od_chat(void);
-ODAPIDEF void ODCALL   od_clear_keybuffer(void);
-ODAPIDEF void ODCALL   od_clr_line(void);
-ODAPIDEF void ODCALL   od_clr_scr(void);
-ODAPIDEF BYTE ODCALL   od_color_config(char *pszColorDesc);
-ODAPIDEF tODControl *  ODCALL od_control_get(void);
-ODAPIDEF void ODCALL   od_disp(char *pachBuffer, INT nSize, BOOL bLocalEcho);
-ODAPIDEF void ODCALL   od_disp_emu(char *pszToDisplay, BOOL bRemoteEcho);
-ODAPIDEF void ODCALL   od_disp_str(char *pszToDisplay);
-ODAPIDEF BOOL ODCALL   od_draw_box(BYTE btLeft, BYTE btTop, BYTE btRight,
-                          BYTE btBottom);
-ODAPIDEF WORD ODCALL   od_edit_str(char *pszInput, char *pszFormat, INT nRow,
-                          INT nColumn, BYTE btNormalColour,
-                          BYTE btHighlightColour, char chBlank,
-                          WORD nFlags);
-ODAPIDEF void ODCALL   od_exit(INT nErrorLevel, BOOL bTermCall);
-ODAPIDEF char ODCALL   od_get_answer(char *pszOptions);
-ODAPIDEF void ODCALL   od_get_cursor(INT *pnRow, INT *pnColumn);
-ODAPIDEF BOOL ODCALL   od_get_input(tODInputEvent *pInputEvent,
-                          tODMilliSec TimeToWait, WORD wFlags);
-ODAPIDEF char ODCALL   od_get_key(BOOL bWait);
-ODAPIDEF BOOL ODCALL   od_gettext(INT nLeft, INT nTop, INT nRight,
-                          INT nBottom, void *pBlock);
-ODAPIDEF char ODCALL   od_hotkey_menu(char *pszFileName, char *pszHotKeys,
-                          BOOL bWait);
-ODAPIDEF void ODCALL   od_init(void);
-ODAPIDEF void ODCALL   od_input_str(char *pszInput, INT nMaxLength,
-                          unsigned char chMin, unsigned char chMax);
-ODAPIDEF void ODCALL   od_kernel(void);
-ODAPIDEF BOOL ODCALL   od_list_files(char *pszFileSpec);
-ODAPIDEF BOOL ODCALL   od_log_write(char *pszMessage);
-ODAPIDEF INT ODCALL    od_multiline_edit(char *pszBufferToEdit,
-                          UINT unBufferSize, tODEditOptions *pEditOptions);
-ODAPIDEF void ODCALL   od_page(void);
-#ifdef ODPLAT_WIN32
-ODAPIDEF void ODCALL   od_parse_cmd_line(LPSTR pszCmdLine);
-#else /* !ODPLAT_WIN32 */
-ODAPIDEF void ODCALL   od_parse_cmd_line(INT nArgCount,
-                          char *papszArguments[]);
-#endif /* !ODPLAT_WIN32 */
-ODAPIDEF INT ODCALL    od_popup_menu(char *pszTitle, char *pszText,
-                          INT nLeft, INT nTop, INT nLevel, WORD uFlags);
-ODAPIDEF void ODVCALL  od_printf(char *pszFormat, ...);
-ODAPIDEF void ODCALL   od_putch(char chToDisplay);
-ODAPIDEF BOOL ODCALL   od_puttext(INT nLeft, INT nTop, INT nRight,
-                          INT nBottom, void *pBlock);
-ODAPIDEF void ODCALL   od_repeat(char chValue, BYTE btTimes);
-ODAPIDEF BOOL ODCALL   od_restore_screen(void *pBuffer);
-ODAPIDEF BOOL ODCALL   od_save_screen(void *pBuffer);
-ODAPIDEF BOOL ODCALL   od_scroll(INT nLeft, INT nTop, INT nRight,
-                          INT nBottom, INT nDistance, WORD nFlags);
-ODAPIDEF BOOL ODCALL   od_send_file(char *pszFileName);
-ODAPIDEF BOOL ODCALL   od_send_file_section(char *pszFileName, char *pszSectionName);
-ODAPIDEF void ODCALL   od_set_attrib(INT nColour);
-ODAPIDEF void ODCALL   od_set_color(INT nForeground, INT nBackground);
-ODAPIDEF void ODCALL   od_set_cursor(INT nRow, INT nColumn);
-ODAPIDEF void ODCALL   od_set_dtr(BOOL bHigh);
-ODAPIDEF BOOL ODCALL   od_set_personality(char *pszName);
-ODAPIDEF void ODCALL   od_set_statusline(INT nSetting);
-ODAPIDEF void ODCALL   od_sleep(tODMilliSec Milliseconds);
-ODAPIDEF BOOL ODCALL   od_spawn(char *pszCommandLine);
-ODAPIDEF INT16 ODCALL  od_spawnvpe(INT16 nModeFlag, char *pszPath,
-                          char *papszArg[], char *papszEnv[]);
-ODAPIDEF void * ODCALL od_window_create(INT nLeft, INT nTop, INT nRight,
-                          INT nBottom, char *pszTitle, BYTE btBorderCol,
-                          BYTE btTitleCol, BYTE btInsideCol, INT nReserved);
-ODAPIDEF BOOL ODCALL   od_window_remove(void *pWinInfo);
-
-
-/* ========================================================================= */
-/* Definitions for compatibility with previous versions.                     */
-/* ========================================================================= */
-
-/* Alternative spelling for the word color (colour). */
-#define od_chat_colour1                od_chat_color1
-#define od_chat_colour2                od_chat_color2
-#define od_colour_char                 od_color_char
-#define od_colour_delimiter            od_color_delimiter
-#define od_colour_names                od_color_names
-#define od_full_colour                 od_full_color
-#define od_colour_config               od_color_config
-#define od_set_colour                  od_set_color
-
-/* Definitions for renamed od_control members and manifest constants. */
-#define key_help                       key_status[6]
-#define key_nohelp                     key_status[0]
-#define user_credit                    user_net_credit
-#define caller_netmailentered          user_netmailentered
-#define caller_echomailentered         user_echomailentered
-#define caller_logintime               user_logintime
-#define caller_logindate               user_logindate
-#define caller_timelimit               user_timelimit
-#define caller_loginsec                user_loginsec
-#define caller_credit                  user_credit
-#define caller_userrecord              user_num
-#define caller_readthru                user_readthru
-#define caller_numpages                user_numpages
-#define caller_downlimit               user_downlimit
-#define caller_timeofcreation          user_timeofcreation
-#define caller_logonpassword           user_logonpassword
-#define caller_wantchat                user_wantchat
-#define caller_ansi                    user_ansi
-#define ra_deducted_time               user_deducted_time
-#define ra_menustack                   user_menustack
-#define ra_menustackpointer            user_menustackpointer
-#define ra_userhandle                  user_handle
-#define ra_comment                     user_comment
-#define ra_firstcall                   user_firstcall
-#define ra_combinedrecord              user_combinedrecord
-#define ra_birthday                    user_birthday
-#define ra_subdate                     user_subdate
-#define ra_screenwidth                 user_screenwidth
-#define ra_msg_area                    user_msg_area
-#define ra_file_area                   user_file_area
-#define ra_language                    user_language
-#define ra_date_format                 user_date_format
-#define ra_forward_to                  user_forward_to
-#define ra_error_free                  user_error_free
-#define ra_sysop_next                  sysop_next
-#define ra_emsi_session                user_emsi_session
-#define ra_emsi_crtdef                 user_emsi_crtdef
-#define ra_emsi_protocols              user_emsi_protocols
-#define ra_emsi_capabilities           user_emsi_capabilities
-#define ra_emsi_requests               user_emsi_requests
-#define ra_emsi_software               user_emsi_software
-#define ra_hold_attr1                  user_hold_attr1
-#define ra_hold_attr2                  user_hold_attr2
-#define ra_hold_len                    user_hold_len
-#define caller_usernum                 user_num
-#define caller_callsign                user_callsign
-#define caller_sex                     user_sex
-#define od_avatar                      user_avatar
-#define B_YELLOW                       L_YELLOW
-#define B_WHITE                        L_WHITE
-#define od_rbbs_node                   od_node
-#define STATUS_USER1                   STATUS_ALTERNATE_1
-#define STATUS_USER2                   STATUS_ALTERNATE_2
-#define STATUS_USER3                   STATUS_ALTERNATE_3
-#define STATUS_USER4                   STATUS_ALTERNATE_4
-#define STATUS_SYSTEM                  STATUS_ALTERNATE_5
-#define STATUS_HELP                    STATUS_ALTERNATE_7
-#define od_registered_to               od_control.od_reg_name
-#define od_registration_key            od_control.od_reg_key
-#define od_program_name                od_control.od_prog_name
-#define od_log_messages                od_control.od_logfile_messages
-#define od_config_text                 od_control.od_cfg_text
-#define od_config_lines                od_control.od_cfg_lines
-#define od_config_colours              od_control.od_colour_names
-#define od_config_colors               od_control.od_colour_names
-#define config_file                    od_config_file
-#define config_filename                od_config_filename
-#define config_function                od_config_function
-#define default_personality            od_default_personality
-#define logfile                        od_logfile
-#define mps                            od_mps
-#define od_kernal                      od_kernel
-
-/* Obsolete functions. */
-#define od_init_with_config(filename,function)\
-                                  od_control.config_file=INCLUDE_CONFIG_FILE;\
-                                  od_control.config_filename=filename;\
-                                  od_control.config_function=function;\
-                                  od_init()
-ODAPIDEF BOOL ODCALL                   od_log_open(void);
-ODAPIDEF void ODCALL                   od_emulate(register char in_char);
-
-#endif /* _INC_OPENDOOR */
diff --git a/src/odoors/Toolbar.bmp b/src/odoors/Toolbar.bmp
deleted file mode 100644
index 3c0b88c870ef66d1c21889161ec45d3e08f58960..0000000000000000000000000000000000000000
Binary files a/src/odoors/Toolbar.bmp and /dev/null differ
diff --git a/src/odoors/buildall.bat b/src/odoors/buildall.bat
deleted file mode 100755
index 7de401db33567209faa15e602578a10b38b9a8fb..0000000000000000000000000000000000000000
--- a/src/odoors/buildall.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-make -fDOS.mak -DTARGET=s > out.txt
-make -fDOS.mak -DTARGET=c >> out.txt
-make -fDOS.mak -DTARGET=m >> out.txt
-make -fDOS.mak -DTARGET=l >> out.txt
-make -fDOS.mak -DTARGET=h >> out.txt
-set INCLUDE=c:\msdev\include;c:\msdev\mfc\include
-nmake -fWin32.mak >> out.txt
diff --git a/src/odoors/builddos.bat b/src/odoors/builddos.bat
deleted file mode 100755
index 15746df5da33253096d43a02aeb2b11b1e4b3d6a..0000000000000000000000000000000000000000
--- a/src/odoors/builddos.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-make -fDOS.mak -DTARGET=s > out.txt
-make -fDOS.mak -DTARGET=c >> out.txt
-make -fDOS.mak -DTARGET=m >> out.txt
-make -fDOS.mak -DTARGET=l >> out.txt
-make -fDOS.mak -DTARGET=h >> out.txt
diff --git a/src/odoors/ex_chat.c b/src/odoors/ex_chat.c
deleted file mode 100644
index 8a19b4b0289c3cf1dab4c4e549d218d12cc48622..0000000000000000000000000000000000000000
--- a/src/odoors/ex_chat.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* EX_CHAT.C - Example of a multi-window full-screen chat program written    */
-/*             with OpenDoors. See manual for instructions on how to compile */
-/*             a program using OpenDoors.                                    */
-/*                                                                           */
-/*             This program shows how to do the following:                   */
-/*                                                                           */
-/*                - Replace the standard OpenDoors chat mode with your own   */
-/*                  chat mode implementation. See instructions below.        */
-/*                - How to scroll a portion of the screen, leaving the rest  */
-/*                  of the screen unaltered.                                 */
-/*                - How to determine whether input came from the local or    */
-/*                  remote keyboard.                                         */
-/*                - How to display a popup window with a message in it when  */
-/*                  the sysop shells to DOS. (DOS version only.)             */
-/*                - How to save and restore the entire contents of the       */
-/*                  screen.                                                  */
-/*                                                                           */
-/*             Conditional compilation directives allow this program to      */
-/*             be compiled as a stand-alone chat door, or as a               */
-/*             replacement chat mode to be integrated into any OpenDoors     */
-/*             program. If STANDALONE is #defined, ex_chat.c will be         */
-/*             compiled as a split-screen chat door that can be run like     */
-/*             any door program. If STANDALONE is not #defined, the chat     */
-/*             mode function will be compiled as a replacement chat mode     */
-/*             for the chat mode built into OpenDoors. In this case,  the    */
-/*             demo mainline function simply displays a prompt, and will     */
-/*             exit the door as soon as you press the [ENTER] key. While     */
-/*             the program is running, if you invoke chat mode (press        */
-/*             [ALT]-[C]), the current screen will be saved and the          */
-/*             split-screen chat mode will be activated. When you press      */
-/*             [ESC] the split-screen chat mode will end, and the            */
-/*             original screen will be restored. To integrate this chat      */
-/*             mode into your own program, you should simply set             */
-/*             od_control.od_cbefore_chat to point to the                    */
-/*             fullscreen_chat function, as shown, and remove the mainline   */
-/*             (main()/WinMain()) function from this file. The compile this  */
-/*             file into your program after removing the #define STANDALONE  */
-/*             line.                                                         */
-
-/* Include required header files. */
-#include "opendoor.h"
-#include <string.h>
-
-
-/* The following #define forces this code to compile as a stand-alone door */
-/* program. If you wish to use this code to replace the standard OpenDoors */
-/* chat mode in your own program, remove this #define.                     */
-#define STANDALONE
-
-
-/* Full-screen chat function prototypes. */
-void fullscreen_chat(void);
-void chat_new_line(void);
-void display_shell_window(void);
-void remove_shell_window(void);
-
-
-
-/* The main() or WinMain() function: program execution begins here. */
-#ifdef ODPLAT_WIN32
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-   LPSTR lpszCmdLine, int nCmdShow)
-#else
-int main(int argc, char *argv[])
-#endif
-{
-   /* Handle standard command-line options and perform other needed setup. */
-#ifdef ODPLAT_WIN32
-   od_control.od_cmd_show = nCmdShow;
-   od_parse_cmd_line(lpszCmdLine);
-#else
-   od_parse_cmd_line(argc, argv);
-#endif
-
-#ifdef STANDALONE               /* If compiled as a stand-alone chat program */
-   od_init();                                        /* Initialize OpenDoors */
-
-   fullscreen_chat();                    /* Invoke full-screen chat function */
-
-#else                  /* If compiled as replacement for OpenDoors chat mode */
-                      /* Setup OpenDoors to use our custom chat mode instead */
-   od_control.od_cbefore_chat=fullscreen_chat;
-
-   od_printf("Press [Enter] to exit door, or invoke chat mode.\n\r");
-   od_get_answer("\n\r");
-#endif
-
-   od_exit(0, FALSE);                                       /* Exit program. */
-   return(0);                                                   
-}
-
-
-
-
-
-                                   /* FULL-SCREEN CHAT CUSTOMIZATION OPTIONS */
-
-char window_colour[2]={0x0b,0x0c};       /* Text colour used for each person */
-char bar_colour=0x70;                     /* Colour of window seperation bar */
-char top_line[2]={13,1};      /* Specifies location of each window on screen */
-char bottom_line[2]={23,11};         /* Line number of bottom of each window */
-char bar_line=12;                    /* Line number of window seperation bar */
-char scroll_distance=2;           /* Distance to scroll window when required */
-char shell_window_title=0x1a;  /* Colour of title of DOS shell notice window */
-char shell_window_boarder=0x1f;        /* Colour of DOS shell window boarder */
-char shell_window_text=0x1b;           /* Colour of text in DOS shell window */
-
-
-
-char cursor_window;                   /* FULL-SCREEN CHAT INTERNAL VARIABLES */
-char current_word[2][81];
-int word_length[2];
-int cursor_col[2];
-int cursor_line[2];
-unsigned char key;
-int old_chat_key;
-void *shell_window;
-char *before_shell_text;
-char *after_shell_text;
-#ifndef STANDALONE     /* If compiled as replacement for OpenDoors chat mode */
-char screen_buffer[4004];
-#endif
-
-                                                /* FULL-SCREEN CHAT FUNCTION */
-void fullscreen_chat(void)
-{
-   cursor_window=0;                               /* Reset working variables */
-   word_length[0]=word_length[1]=0;
-   cursor_col[0]=cursor_col[1]=1;
-   cursor_line[0]=top_line[0];
-   cursor_line[1]=top_line[1];
-
-
-                         /* If ANSI or AVATAR graphics mode is not available */
-   if(!od_control.user_ansi && !od_control.user_avatar)
-   {                           /* Then use OpenDoor's line chat mode instead */
-#ifdef STANDALONE               /* If compiled as a stand-alone chat program */
-      od_chat();
-#endif
-      return;
-   }
-
-   od_control.od_cbefore_shell=display_shell_window;   /* Set shell settings */
-   od_control.od_cafter_shell=remove_shell_window;
-   before_shell_text=od_control.od_before_shell;
-   after_shell_text=od_control.od_after_shell;
-   od_control.od_before_shell=NULL;
-   od_control.od_after_shell=NULL;
-   od_control.od_chat_active=TRUE;
-
-#ifdef STANDALONE               /* If compiled as a stand-alone chat program */
-   old_chat_key=od_control.key_chat;      /* Prevent internal chat mode from */
-   od_control.key_chat=0;                                   /* being invoked */
-
-#else                  /* If compiled as replacement for OpenDoors chat mode */
-   od_save_screen(screen_buffer);           /* Save current screen contents. */
-#endif
-
-                                                     /* DRAW THE CHAT SCREEN */
-   od_set_attrib(window_colour[0]);
-   od_clr_scr();                                         /* Clear the screen */
-
-   od_set_cursor(bar_line,1);                  /* Draw window separation bar */
-   od_set_attrib(bar_colour);
-   od_clr_line();
-   od_set_cursor(bar_line,67);
-   od_printf("Ctrl-A: Clear");
-   od_set_cursor(bar_line,1);
-   od_printf(" Top : %-.28s    Bottom : %-.28s    ",
-      od_control.sysop_name, od_control.user_name);
-
-   od_set_cursor(top_line[0],1);    /* Locate cursor where typing will begin */
-   od_set_attrib(window_colour[0]);           /* Set appropriate text colour */
-
-                                                           /* MAIN CHAT LOOP */
-   for(;;)                             /* (Repeats for each character typed) */
-   {
-      do
-      {
-         key=(char)od_get_key(FALSE);    /* Get next keystroke from keyboard */
-
-                                                    /* CHECK FOR SYSOP ABORT */
-         if((key==27 && od_control.od_last_input==1) /* If sysop pressed ESC */
-            || !od_control.od_chat_active)
-         {
-            od_set_attrib(0x07);                     /* Reset display colour */
-            od_clr_scr();                                /* Clear the screen */
-
-            od_control.od_cbefore_shell=NULL;  /* Restore DOS shell settings */
-            od_control.od_cafter_shell=NULL;
-            od_control.od_before_shell=before_shell_text;
-            od_control.od_after_shell=after_shell_text;
-#ifdef STANDALONE               /* If compiled as a stand-alone chat program */
-            od_control.key_chat=old_chat_key;/* Re-enable internal chat mode */
-
-#else                  /* If compiled as replacement for OpenDoors chat mode */
-            od_control.od_chat_active=FALSE;           /* Turn off chat mode */
-            od_restore_screen(screen_buffer);      /* Restore orignal screen */
-#endif
-            return;                                 /* Exit full-screen chat */
-
-         }
-      } while(key==0);
-
-                                                     /* CHECK FOR NEW TYPIST */
-      if(od_control.od_last_input!=cursor_window)/* If new person typing now */
-      {                               /* Switch cursor to appropriate window */
-         cursor_window=od_control.od_last_input;       /* Set current typist */
-
-                                                /* Move cursor to new window */
-         od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
-
-         od_set_attrib(window_colour[cursor_window]);  /* Change text colour */
-      }
-
-
-      if(key==13 || key==10)           /* IF USER PRESSED [ENTER] / [RETURN] */
-      {
-         word_length[cursor_window]=0;      /* Enter constitutes end of word */
-
-         chat_new_line();                               /* Move to next line */
-      }
-
-
-      else if(key==8)                           /* IF USER PRESS [BACKSPACE] */
-      {
-         if(cursor_col[cursor_window] > 1)       /* If not at left of screen */
-         {
-            --cursor_col[cursor_window];    /* Move cursor back on character */
-            if(word_length[cursor_window] > 0) --word_length[cursor_window];
-            od_printf("\b \b");          /* Erase last character from screen */
-         }
-      }
-
-
-      else if(key==32)                            /* IF USER PRESSED [SPACE] */
-      {
-         word_length[cursor_window]=0;    /* [Space] constitutes end of word */
-
-         if(cursor_col[cursor_window]==79)              /* If at end of line */
-            chat_new_line();                     /* Move cursor to next line */
-         else                                       /* If not at end of line */
-         {
-            ++cursor_col[cursor_window];        /* Increment cursor position */
-            od_putch(32);                                 /* Display a space */
-         }
-      }
-
-
-      else if(key==1)                    /* IF USER PRESSED CLEAR WINDOW KEY */
-      {                                               /* Clear user's window */
-         od_scroll(1,top_line[cursor_window],79,bottom_line[cursor_window],
-            bottom_line[cursor_window]-top_line[cursor_window]+1,0);
-
-         word_length[cursor_window]=0;  /* We are no longer composing a word */
-
-         cursor_col[cursor_window]=1;               /* Reset cursor position */
-         cursor_line[cursor_window]=top_line[cursor_window];
-         od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
-      }
-
-
-      else if(key>32)                 /* IF USER TYPED A PRINTABLE CHARACTER */
-      {                                    /* PERFORM WORD WRAP IF NECESSARY */
-         if(cursor_col[cursor_window]==79)    /* If cursor is at end of line */
-         {
-                                               /* If there is a word to wrap */
-            if(word_length[cursor_window]>0 && word_length[cursor_window]<78)
-            {
-                                         /* Move cursor to beginning of word */
-               od_set_cursor(cursor_line[cursor_window],
-                          cursor_col[cursor_window]-word_length[cursor_window]);
-
-               od_clr_line();                /* Erase word from current line */
-
-               chat_new_line();                  /* Move cursor to next line */
-
-                                                           /* Redisplay word */
-               od_disp(current_word[cursor_window],word_length[cursor_window],
-                                                                          TRUE);
-               cursor_col[cursor_window]+=word_length[cursor_window];
-            }
-
-            else                            /* If there is no word to "wrap" */
-            {
-               chat_new_line();                  /* Move cursor to next line */
-               word_length[cursor_window]=0;             /* Start a new word */
-            }
-         }
-
-                                            /* ADD CHARACTER TO CURRENT WORD */
-                              /* If there is room for more character in word */
-         if(strlen(current_word[cursor_window])<79)     /* Add new character */
-            current_word[cursor_window][word_length[cursor_window]++]=key;
-
-                                            /* DISPLAY NEWLY TYPED CHARACTER */
-         ++cursor_col[cursor_window];
-         od_putch(key);
-      }
-   }
-}
-
-
-
-              /* FUNCTION USED BY FULL-SCREEN CHAT TO START A NEW INPUT LINE */
-void chat_new_line(void)
-{                                        /* If cursor is at bottom of window */
-   if(cursor_line[cursor_window]==bottom_line[cursor_window])
-   {                                  /* Scroll window up one line on screen */
-      od_scroll(1,top_line[cursor_window],79, bottom_line[cursor_window],
-                scroll_distance, 0);
-      cursor_line[cursor_window]-=(scroll_distance - 1);
-   }
-
-   else                              /* If cursor is not at bottom of window */
-   {
-      ++cursor_line[cursor_window];             /* Move cursor down one line */
-   }
-
-                                         /* Move cursor's position on screen */
-   od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]=1);
-
-   od_set_attrib(window_colour[cursor_window]);        /* Change text colour */
-}
-
-
-void display_shell_window(void)
-{
-   if((shell_window=od_window_create(17,9,63,15,"DOS Shell",
-                                     shell_window_boarder, shell_window_title, 
-                                     shell_window_text, 0))==NULL) return;
-
-   od_set_attrib(shell_window_text);
-   od_set_cursor(11,26);
-   od_printf("The Sysop has shelled to DOS");
-   od_set_cursor(13,21);
-   od_printf("He/She will return in a few moments...");
-}
-
-
-void remove_shell_window(void)
-{
-   od_window_remove(shell_window);
-   od_set_cursor(cursor_line[cursor_window],cursor_col[cursor_window]);
-   od_set_attrib(window_colour[cursor_window]);
-}
diff --git a/src/odoors/ex_diag.c b/src/odoors/ex_diag.c
deleted file mode 100644
index c9da837e603f9b7490a953c273d00e185abcce84..0000000000000000000000000000000000000000
--- a/src/odoors/ex_diag.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/* ex_diag.c - Diagnostic door program, written to test environment in which
- *             an OpenDooors door will run. Reads configuration settings from
- *             command line and configuration file, and displays diagnostic
- *             information on the local (and when possible, remote) screens.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "opendoor.h"
-
-typedef enum
-{
-   kParamLocal,
-   kParamBPS,
-   kParamPort,
-   kParamNode,
-   kParamHelp,
-   kParamPersonality,
-   kParamMaxTime,
-   kParamAddress,
-   kParamIRQ,
-   kParamNoFOSSIL,
-   kParamNoFIFO,
-   kParamDropFile,
-   kParamUserName,
-   kParamTimeLeft,
-   kParamSecurity,
-   kParamLocation,
-   kParamUnknown
-} tCommandLineParameter;
-
-char *BoolAsStr(int bValue);
-void ParseStandardCommandLine(int nArgCount, char *papszArguments[]);
-static void AdvanceToNextArg(int *pnCurrentArg, int nArgCount,
-			     char *pszOption);
-static void GetNextArgName(int *pnCurrentArg, int nArgCount,
-			   char *papszArguments[], char *pszString,
-			   int nStringSize);
-static tCommandLineParameter GetCommandLineParameter(char *pszArgument);
-
-
-int main(int argc, char *argv[])
-{
-   char sz[80];
-   int n;
-
-   /* Parse command-line. */
-   ParseStandardCommandLine(argc, argv);
-
-   /* Initialize OpenDoors. */
-   od_init();
-
-   od_clr_scr();
-
-   od_printf("OpenDoors has been initialized.\n\r");
-   for(;;)
-   {
-      od_printf("\n\rPOST-INITIALIZATION DIAGNOSTIC INFORMATION:\n\r");
-      od_printf("    Running in REMOTE mode : %s\n\r",
-         BoolAsStr(od_control.baud));
-      od_printf("   Port <-> Modem BPS Rate : %lu\n\r", od_control.baud);
-      od_printf("        Serial Port Number : %d (COM%d:)\n\r", od_control.port,
-         od_control.port + 1);
-      od_printf("         Serial I/O Method : ");
-      switch(od_control.od_com_method)
-      {
-         case COM_FOSSIL:
-            od_printf("FOSSIL Driver\n\r");
-            break;
-         case COM_INTERNAL:
-            od_printf("OpenDoors Internal I/O Module\n\r");
-            break;
-         case COM_SOCKET:
-            od_printf("TCP Socket/Telnet\n\r");
-            break;
-         default:
-            od_printf("Unknown\n\r");
-            break;
-      }
-      od_printf("            Drop File Type : ");
-      switch(od_control.od_info_type)
-      {
-         case DORINFO1:
-            od_printf("DORINFO?.DEF\n\r");
-            break;
-         case EXITINFO:
-            od_printf("Basic EXITINFO.BBS & DORINFO1.DEF\n\r");
-            break;
-         case RA1EXITINFO:
-            od_printf("RA 1.x EXITINFO.BBS & DORINFO1.DEF\n\r");
-            break;
-         case CHAINTXT:
-            od_printf("CHAIN.TXT\n\r");
-            break;
-         case SFDOORSDAT:
-            od_printf("SFDOORS.DAT\n\r");
-            break;
-         case CALLINFO:
-            od_printf("CALLINFO.BBS\n\r");
-            break;
-         case DOORSYS_GAP:
-            od_printf("GAP style DOOR.SYS\n\r");
-            break;
-         case DOORSYS_DRWY:
-            od_printf("DoorWay DOOR.SYS\n\r");
-            break;
-         case QBBS275EXITINFO:
-            od_printf("QuickBBS 2.75+ EXITINFO.BBS\n\r");
-            break;
-         case CUSTOM:
-            od_printf("User-Defined Custom Format\n\r");
-            break;
-         case DOORSYS_WILDCAT:
-            od_printf("WildCat! DOOR.SYS\n\r");
-            break;
-         case RA2EXITINFO:
-            od_printf("RA 2.x+ EXITINFO.BBS & DORINFO1.DEF\n\r");
-            break;
-         case NO_DOOR_FILE:
-            od_printf("No Drop File in Use\n\r");
-            break;
-         case DOOR32SYS:
-            od_printf("Door32.sys\n\r");
-            break;
-         default:
-            od_printf("Unknown Type\n\r");
-            break;
-      }
-      od_printf("       ANSI Mode Available : %s\n\r",
-         BoolAsStr(od_control.user_ansi));
-      od_printf("     AVATAR Mode Available : %s\n\r",
-         BoolAsStr(od_control.user_avatar));
-      od_printf("    RIP Graphics Available : %s\n\r",
-         BoolAsStr(od_control.user_rip));
-      od_printf("         User's Time Limit : %d\n\r", od_control.user_timelimit);
-      od_printf("          User's Full Name : %s\n\r", od_control.user_name);
-
-      od_printf("\n\rChoose Option: [E]xit, [T]yping Test,");
-      if(od_control.od_com_method == COM_INTERNAL)
-      {
-         od_printf(" [I]nternal I/O Diags,");
-      }
-      od_printf("\n\r");
-      od_printf("               [A]utodetect ANSI/RIP, [R]e-Display, [D]isplay Tests\n\r");
-		n=od_get_answer("eitard");
-      switch(n)
-      {
-         case 'e':
-            od_clr_scr();
-            od_printf("\n\rExit - Are You Sure (Y/N)? ");
-            if(od_get_answer("yn") == 'y')
-            {
-               return(0);
-            }
-            break;
-
-         case 'i':
-            od_clr_scr();
-            od_printf("INTERNAL SERIAL I/O DIAGNOSTIC INFORMATION:\n\r");
-            od_printf("  Serial Port Base Address : %x\n\r",
-               od_control.od_com_address);
-            od_printf("           IRQ Line Number : %d\n\r",
-               od_control.od_com_irq);
-            od_printf("       Receive Buffer Size : %d\n\r",
-               od_control.od_com_rx_buf);
-            od_printf("      Transmit Buffer Size : %d\n\r",
-               od_control.od_com_tx_buf);
-            od_printf(" Use FIFO Buffer, if avail : %s\n\r",
-               BoolAsStr(!od_control.od_com_no_fifo));
-            od_printf("         FIFO Trigger Size : %d\n\r",
-               od_control.od_com_fifo_trigger);
-
-            od_printf("\n\rPress [ENTER] to return.\n\r");
-            od_get_answer("\n\r");
-            break;
-
-         case 't':
-            od_clr_scr();
-            od_printf("\n\rTyping Test - Type any text below:\n\r");
-            od_printf("[------------------------------------------------------"
-                      "-----------------------]\n\r");
-            od_input_str(sz, 79, 0, 255);
-            od_printf("\n\rEntered Text:\n\r%s\n\r", sz);
-            od_printf("\n\rPress [ENTER] to return.\n\r");
-            od_get_answer("\n\r");
-            break;
-
-         case 'a':
-            od_clr_scr();
-            od_printf("\n\rAutodetecting ANSI/RIP mode ...\n\r");
-            od_printf("(Detected modes will be turned on.)\n\r");
-            od_autodetect(0);
-            od_printf("\n\rDone, press [ENTER] to return.\n\r");
-            od_get_answer("\n\r");
-            break;
-
-         case 'd':
-            od_clr_scr();
-            od_printf("CLEAR SCREEN TEST\n\r");
-            od_printf("About to test clear screen. The screen should\n\r");
-            od_printf("be cleared before the next test if screen\n\r");
-            od_printf("clearing is enabled.\n\r");
-            od_printf("\n\rPress [ENTER] to perform test.\n\r");
-            od_get_answer("\n\r");
-            od_clr_scr();
-
-            od_printf("CARRIAGE RETURN TEST:\n\r");
-            od_printf("This should not be visible\r");
-            od_printf("This should cover it up...\n\r\n\r");
-            od_printf("The text \"This should not be visible\" will\n\r");
-            od_printf("appear above if this test failed.\n\r");
-            od_printf("\n\rPress [ENTER] to perform next test.\n\r");
-            od_get_answer("\n\r");
-
-            od_clr_scr();
-            od_printf("COLOR TEST:\n\r\n\r");
-            for(n = 0; n < 256; ++n)
-            {
-               od_set_attrib(n);
-               od_printf("%x", n % 16);
-               if(n % 32 == 31)
-               {
-                  od_set_attrib(0x07);
-                  od_printf("\n\r");
-               }
-            }
-            od_printf("\n\rIf ANSI or AVATAR modes are available, the\n\r");
-            od_printf("above test pattern should print in color.\n\r");
-            od_printf("\n\rPress [ENTER] to perform next test.\n\r");
-            od_get_answer("\n\r");
-
-            od_clr_scr();
-            od_printf("CURSOR POSITIONING TEST:\n\r");
-            for(n = 15; n > 2; --n)
-            {
-               od_set_cursor(n, n);
-               od_printf("\\");
-            }
-            for(n = 15; n > 2; --n)
-            {
-               od_set_cursor(n, 17 - n);
-               od_printf("/");
-            }
-
-            od_set_cursor(17, 1);
-            od_printf("If ANSI or AVATAR modes are available, a large X\n\r");
-            od_printf("should appear on lines 3 to 15.\n\r");
-            od_printf("\n\rPress [ENTER] to return.\n\r");
-            od_get_answer("\n\r");
-            break;
-      }
-
-      od_clr_scr();
-   }
-
-   /* Return with success. */
-   return(0);
-}
-
-
-char *BoolAsStr(int bValue)
-{
-   return(bValue ? "Yes (TRUE)" : "No (FALSE)");
-}
-
-
-void ParseStandardCommandLine(int nArgCount, char *papszArguments[])
-{
-   char *pszCurrentArg;
-   int nCurrentArg;
-
-   for(nCurrentArg = 1; nCurrentArg < nArgCount; ++nCurrentArg)
-   {
-      pszCurrentArg = papszArguments[nCurrentArg];
-
-      switch(GetCommandLineParameter(pszCurrentArg))
-      {
-	 case kParamLocal:
-	    od_control.od_force_local = TRUE;
-	    break;
-
-	 case kParamBPS:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.baud = atol(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamPort:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.port = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamHelp:
-	    printf("AVALIABLE COMMAND LINE PARAMETERS:\n");
-            printf(" -L or -LOCAL     - Causes door to operate in local mode, without requiring a\n");
-            printf("                    door information (drop) file.\n");
-            printf(" -DROPFILE x      - Door information file directory or directory+filename.\n");
-            printf(" -N x or -NODE x  - Sets the node number to use.\n");
-            printf(" -B x or -BPS x   - Sets the serial port <---> modem bps (baud) rate to use.\n");
-            printf(" -P x or -PORT x  - Sets the serial port to use, were 0=COM1, 1=COM2, etc.\n");
-            printf(" -ADDRESS x       - Sets serial port address in decimal NOT hexidecimal\n");
-            printf("                    (only has effect if FOSSIL driver is not being used).\n");
-            printf(" -IRQ x           - Sets the serial port IRQ line (only has effect if FOSSIL\n");
-            printf("                    driver is not being used).\n");
-            printf(" -NOFOSSIL        - Disables use of FOSSIL driver, even if available.\n");
-            printf(" -NOFIFO          - Disables use of 16550 FIFO buffers (only if FOSSIL driver\n");
-            printf("                    is not being used).\n");
-            printf(" -PERSONALITY x   - Sets the sysop status line / function key personality to\n");
-            printf("                    use - one of Standard, PCBoard, RemoteAccess or Wildcat.\n");
-            printf(" -MAXTIME x       - Sets the maximum number of minutes that any user will be\n");
-            printf("                    permitted to access the door.\n");
-            printf(" -USERNAME x      - Name of user who is currently online.\n");
-            printf(" -TIMELEFT x      - User's time remaining online.\n");
-            printf(" -SECURITY x      - User's security level.\n");
-            printf(" -LOCATION x      - Location from which user is calling.\n");
-            printf(" -?, -H or -HELP  - Displays command-line help and exits.\n");
-	    exit(1);
-	    break;
-
-	 case kParamNode:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.od_node = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamPersonality:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    if(stricmp(papszArguments[nCurrentArg], "Standard") == 0)
-	    {
-	       od_control.od_default_personality = PER_OPENDOORS;
-	    }
-	    else if(stricmp(papszArguments[nCurrentArg], "PCBoard") == 0)
-	    {
-	       od_control.od_default_personality = PER_PCBOARD;
-	    }
-	    else if(stricmp(papszArguments[nCurrentArg], "RemoteAccess") == 0)
-	    {
-	       od_control.od_default_personality = PER_RA;
-	    }
-	    else if(stricmp(papszArguments[nCurrentArg], "Wildcat") == 0)
-	    {
-	       od_control.od_default_personality = PER_WILDCAT;
-	    }
-	    else
-	    {
-	       printf("Unknown personality: %s\n", papszArguments[nCurrentArg]);
-	       exit(1);
-	    }
-	    break;
-
-	 case kParamMaxTime:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.od_maxtime = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamAddress:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.od_com_address = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamIRQ:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.od_com_irq = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamNoFOSSIL:
-	    od_control.od_no_fossil = TRUE;
-	    break;
-
-	 case kParamNoFIFO:
-	    od_control.od_com_no_fifo = TRUE;
-	    break;
-
-	 case kParamDropFile:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    strncpy(od_control.info_path, papszArguments[nCurrentArg],
-	       sizeof(od_control.info_path) - 1);
-	    od_control.info_path[sizeof(od_control.info_path) - 1] = '\0';
-	    break;
-
-	 case kParamUserName:
-	    GetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-	       od_control.user_name, sizeof(od_control.user_name));
-	    break;
-
-	 case kParamTimeLeft:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.user_timelimit = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamSecurity:
-	    AdvanceToNextArg(&nCurrentArg, nArgCount, pszCurrentArg);
-	    od_control.user_security = atoi(papszArguments[nCurrentArg]);
-	    break;
-
-	 case kParamLocation:
-	    GetNextArgName(&nCurrentArg, nArgCount, papszArguments,
-	       od_control.user_location, sizeof(od_control.user_location));
-	    break;
-
-	 default:
-	    printf("Unrecognized command line option: %s\n", pszCurrentArg);
-	    exit(1);
-	    break;
-      }
-   }
-}
-
-
-static void AdvanceToNextArg(int *pnCurrentArg, int nArgCount, char *pszOption)
-{
-   if(++*pnCurrentArg >= nArgCount)
-   {
-      printf("Missing parameter for option: %s\n", pszOption);
-      exit(1);
-   }
-}
-
-
-static void GetNextArgName(int *pnCurrentArg, int nArgCount,
-			   char *papszArguments[], char *pszString,
-			   int nStringSize)
-{
-   int bFirst = TRUE;
-
-   if((*pnCurrentArg) + 1 >= nArgCount)
-   {
-      printf("Missing parameter for option: %s\n",
-         papszArguments[(*pnCurrentArg) - 1]);
-      exit(1);
-   }
-
-   pszString[0] = '\0';
-
-   while(++*pnCurrentArg < nArgCount)
-   {
-      if(GetCommandLineParameter(papszArguments[*pnCurrentArg])
-	 != kParamUnknown)
-      {
-         --*pnCurrentArg;
-	 break;
-      }
-
-      if(strlen(pszString) >= nStringSize - 1)
-      {
-	 break;
-      }
-
-      if(!bFirst)
-      {
-	 strcat(pszString, " ");
-      }
-
-      strncat(pszString, papszArguments[*pnCurrentArg],
-         strlen(pszString) - nStringSize - 1);
-      pszString[nStringSize - 1] = '\0';
-
-      bFirst = FALSE;
-   }
-
-}
-
-
-static tCommandLineParameter GetCommandLineParameter(char *pszArgument)
-{
-   if(*pszArgument == '-' || *pszArgument == '/')
-   {
-      ++pszArgument;
-   }
-
-   if(stricmp(pszArgument, "L") == 0
-      || stricmp(pszArgument, "LOCAL") == 0)
-   {
-      return(kParamLocal);
-   }
-   else if(stricmp(pszArgument, "B") == 0
-      || stricmp(pszArgument, "BPS") == 0
-      || stricmp(pszArgument, "BAUD") == 0)
-   {
-      return(kParamBPS);
-   }
-   else if(stricmp(pszArgument, "P") == 0
-      || stricmp(pszArgument, "PORT") == 0)
-   {
-      return(kParamPort);
-   }
-   else if(stricmp(pszArgument, "N") == 0
-      || stricmp(pszArgument, "NODE") == 0)
-   {
-      return(kParamNode);
-   }
-   else if(stricmp(pszArgument, "?") == 0
-      || stricmp(pszArgument, "H") == 0
-      || stricmp(pszArgument, "HELP") == 0)
-   {
-      return(kParamHelp);
-   }
-   else if(stricmp(pszArgument, "PERSONALITY") == 0)
-   {
-      return(kParamPersonality);
-   }
-   else if(stricmp(pszArgument, "MAXTIME") == 0)
-   {
-      return(kParamMaxTime);
-   }
-   else if(stricmp(pszArgument, "ADDRESS") == 0)
-   {
-      return(kParamAddress);
-   }
-   else if(stricmp(pszArgument, "IRQ") == 0)
-   {
-      return(kParamIRQ);
-   }
-   else if(stricmp(pszArgument, "NOFOSSIL") == 0)
-   {
-      return(kParamNoFOSSIL);
-   }
-   else if(stricmp(pszArgument, "NOFIFO") == 0)
-   {
-      return(kParamNoFIFO);
-   }
-   else if(stricmp(pszArgument, "DROPFILE") == 0)
-   {
-      return(kParamDropFile);
-   }
-   else if(stricmp(pszArgument, "USERNAME") == 0)
-   {
-      return(kParamUserName);
-   }
-   else if(stricmp(pszArgument, "TIMELEFT") == 0)
-   {
-      return(kParamTimeLeft);
-   }
-   else if(stricmp(pszArgument, "SECURITY") == 0)
-   {
-      return(kParamSecurity);
-   }
-   else if(stricmp(pszArgument, "LOCATION") == 0)
-   {
-      return(kParamLocation);
-   }
-   else
-   {
-      return(kParamUnknown);
-   }
-}
-
-
-void NoDoorFileHandler(void)
-{
-   /* Alter OpenDoors behaviour, so that we proceed with defaults if  */
-   /* no door information file is available, rather than exiting with */
-   /* an error. Set od_no_file_func to point to this function.        */
-   if(strlen(od_control.user_name) == 0)
-   {
-      strcpy(od_control.user_name, "Unknown User");
-   }
-   if(strlen(od_control.user_location) == 0)
-   {
-      strcpy(od_control.user_location, "Unknown Location");
-   }
-   if(od_control.user_timelimit == 0)
-   {
-      od_control.user_timelimit = 30;
-   }
-
-   od_control.od_info_type = CUSTOM;
-}
diff --git a/src/odoors/ex_hello.c b/src/odoors/ex_hello.c
deleted file mode 100644
index 1b620aaa2be733d98491aab652769e725f9f349e..0000000000000000000000000000000000000000
--- a/src/odoors/ex_hello.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* EX_HELLO.C - Example of a trivial OpenDoors program. Demonstrates         */
-/*              just how simple a fully functional door program can be. Also */
-/*              shows all the basic elements required by any program using   */
-/*              OpenDoors. See manual for instructions on how to compile     */
-/*              this program.                                                */
-/*                                                                           */
-/*              This program shows how to do the following:                  */
-/*                                                                           */
-/*                 - #include the OpenDoors header file, opendoor.h.         */
-/*                 - Create a mainline function that can be compiled under   */
-/*                   both DOS and Windows versions of OpenDoors.             */
-/*                 - How to display text on multiple lines.                  */
-/*                 - How to wait for a single key to be pressed.             */
-/*                 - How to properly exit a program that uses OpenDoors.     */
-
-
-/* The opendoor.h file must be included by any program using OpenDoors. */
-#include "opendoor.h"
-
-
-/* The main() or WinMain() function: program execution begins here. */
-#ifdef ODPLAT_WIN32
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-   LPSTR lpszCmdLine, int nCmdShow)
-#else
-int main(int argc, char *argv[])
-#endif
-{
-
-   /* Display a message. */
-   od_printf("Hello world! This is a very simple OpenDoors program.\n\r");
-   od_printf("Press any key to return to the BBS!\n\r");
-
-
-   /* Wait for user to press a key. */
-   od_get_key(TRUE);
-
-
-   /* Exit door program, returning to the BBS. */
-   od_exit(0, FALSE);
-   return(0);
-}
diff --git a/src/odoors/ex_music.c b/src/odoors/ex_music.c
deleted file mode 100644
index 637a966f6da37d3ffed4f4eeff2a296fbe1e6808..0000000000000000000000000000000000000000
--- a/src/odoors/ex_music.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* EX_MUSIC.C - Example program plays "Happy Birthday" to the remote user,   */
-/*              if possible. See the manual for instructions on how to       */
-/*              compile this program.                                        */
-/*                                                                           */
-/*              This program shows how to do the following:                  */
-/*                                                                           */
-/*                 - Demonstrates how to play sounds effects or music on a   */
-/*                   remote terminal program that supports the so-called     */
-/*                   "ANSI music" standard.                                  */
-/*                 - Shows how to send text to the remote system without it  */
-/*                   being displayed on the local screen.                    */
-
-
-/* The opendoor.h file must be included by any program using OpenDoors. */
-#include "opendoor.h"
-
-#include <string.h>
-
-/* Functions for playing "ANSI music" and testing "ANSI music" capabilities. */
-void PlayANSISound(char *pszSounds);
-char TestSound(void);
-
-/* Variable indicates whether or not sound is on */
-char bSoundEnabled = TRUE;
-
-
-/* The main() or WinMain() function: program execution begins here. */
-#ifdef ODPLAT_WIN32
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-   LPSTR lpszCmdLine, int nCmdShow)
-#else
-int main(int argc, char *argv[])
-#endif
-{
-   /* Handle standard command-line options and perform other needed setup. */
-#ifdef ODPLAT_WIN32
-   od_control.od_cmd_show = nCmdShow;
-   od_parse_cmd_line(lpszCmdLine);
-#else
-   od_parse_cmd_line(argc, argv);
-#endif
-
-   /* Display introductory message. */
-   od_printf("This is a simple door program that will play the song Happy Birthday\n\r");
-   od_printf("tune on the remote system, if the user's terminal program supports ANSI\n\r");
-   od_printf("music. Music is not played on the local speaker, as BBS system operators\n\r");
-   od_printf("do not wish to have the BBS computer making sounds at any time of the day\n\r");
-   od_printf("or night. However, the program can easily be modified to also echo sound to\n\r");
-   od_printf("the local speaker.\n\r\n\r");
-
-
-   /* Test whether user's terminal supports "ANSI music". */
-   TestSound();
-
-
-   /* Send birthday greetings to the remote user. */
-
-   /* Clear the screen. */
-   od_clr_scr();
-
-   /* Display a message. */
-   od_printf("\n\rHappy Birthday!\n\r");
-
-   /* If "ANSI music" is available, play "Happy Birthday". */
-   PlayANSISound("MBT120L4MFMNO4C8C8DCFE2C8C8DCGF2C8C8O5CO4AFED2T90B-8B-8AFGF2");
-
-   /* Reset sound after finished playing. */
-   PlayANSISound("00m");
-
-
-   /* Wait for user to press a key before returning to the BBS. */
-   od_printf("\n\rPress any key to return to BBS...\n\r");
-   od_get_key(TRUE);
-   od_exit(0, FALSE);
-   return(0);
-}
-
-
-/* Function to test whether the user's terminal program supports ANSI music. */
-/* You can either do this every time the user uses your program, or only the */
-/* first time they use the program, saving the result in a data file.        */
-char TestSound(void)
-{
-   /* Variable to store user's response to question. */
-   char chResponse;
-
-   /* Display description of test to user. */
-   od_printf("We need to know whether or not your terminal program supports ANSI music.\n\r");
-   od_printf("In order to test this, we will send a short ANSI music sequence. We will then\n\r");
-   od_printf("ask whether or not you heard any sound.\n\r");
-   od_printf("Press any key to begin this test... ");
-
-   /* Wait for user to press a key to begin. */
-   od_get_key(TRUE);
-   od_printf("\n\r\n\r");
-
-   /* Temporarily enable sound. */
-   bSoundEnabled = TRUE;
-
-   /* Send sound test sequence. */
-   PlayANSISound("MBT120L4MFMNO4C8C8DC");
-
-   /* Reset sound after finished test. */
-   PlayANSISound("00m");
-
-   /* Clear screen and ask whether user heard the sound. */
-   od_clr_scr();
-   od_printf("Did you just hear sound from your speaker? (Y/n)");
-   chResponse = od_get_answer("YN");
-
-   /* Set ANSI music on/off according to user's response. */
-   bSoundEnabled = (chResponse == 'Y');
-   
-   return(bSoundEnabled);
-}
-
-
-/* Function to play "ANSI" music or sound effects. The play_sound() function
- * can be called with a string of 0 to 250 characters. The caracters of the
- * string define what sounds should be played on the remote speaker, as
- * follows:
- *
- *      A - G       Musical Notes
- *      # or +      Following A-G note means sharp
- *      -           Following A-G note means flat
- *      <           Move down one octave
- *      >           Move up one octave
- *      .           Period acts as dotted note (extend note duration by 3/2)
- *      MF          Music Foreground (pause until finished playing music)
- *      MB          Music Background (continue while music plays)
- *      MN          Music note duration Normal (7/8 of interval between notes)
- *      MS          Music note duration Staccato
- *      ML          Music note duration Legato
- *      Ln          Length of note (n=1-64, 1=whole note, 4=quarter note, etc)
- *      Pn          Pause length (same n values as Ln above)
- *      Tn          Tempo, n=notes/minute (n=32-255, default n=120)
- *      On          Octave number (n=0-6, default n=4)
- */
-
-void PlayANSISound(char *pszSounds)
-{
-   /* Beginning of sound sequence. */
-   char szStartSound[255] = {27, '[', '\0'};
-
-   /* Abort if sound is not enabled. */
-   if(!bSoundEnabled) return;
-
-   /* Send sequence to start playing sound to remote system only. */
-   od_disp(szStartSound, strlen(szStartSound), FALSE);
-
-   /* Send the sounds codes to the remote system only. */
-   od_disp(pszSounds, strlen(pszSounds), FALSE);
-}
diff --git a/src/odoors/ex_ski.c b/src/odoors/ex_ski.c
deleted file mode 100644
index c20fddec2c07819c69768f9145294cb119f5f746..0000000000000000000000000000000000000000
--- a/src/odoors/ex_ski.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/* EX_SKI.C - EX_SKI is a simple but addictive door game that is written     */
-/*            using OpenDoors. In this action game, the player must control  */
-/*            a skier through a downhill slalom course. The user may turn    */
-/*            the skier left or right, and the game ends as soon as the      */
-/*            player skis outside the marked course. The game begins at      */
-/*            an easy level, but quickly becomes more and more difficult     */
-/*            as the course to be navigated becomes more and more narrow.    */
-/*            The game maintains a list of players with high scores, and     */
-/*            this list may be viewed from the main menu.                    */
-/*                                                                           */
-/*            This program shows how to do the following:                    */
-/*                                                                           */
-/*               - Maintain a high-score file in a game, in a multi-node     */
-/*                 compatible manner.                                        */
-/*               - How to use your own terminal control sequences.           */
-/*               - How to perform reasonably percise timing under both DOS   */
-/*                 and Windows.                                              */
-
-
-/* Header file for the OpenDoors API */
-#include "opendoor.h"
-
-/* Other required C header files */
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-#include <errno.h>
-#include <stdlib.h>
-
-
-/* Hard-coded configurable constants - change these values to alter game */
-#define HIGH_SCORES           15       /* Number of high scores in list */
-#define INITIAL_COURSE_WIDTH  30       /* Initial width of ski course */
-#define MINIMUM_COURSE_WIDTH  4        /* Minimum width of course */
-#define DECREASE_WIDTH_AFTER  100      /* # of ticks before course narrows */
-#define CHANGE_DIRECTION      10       /* % of ticks course changes direction */
-#define MAX_NAME_SIZE         35       /* Maximum characters in player name */
-#define WAIT_FOR_FILE         10       /* Time to wait for access to file */
-#define SCORE_FILENAME   "SKIGAME.DAT" /* Name of high score file */
-
-
-/* High-score file format structure */
-typedef struct
-{
-   char szPlayerName[MAX_NAME_SIZE + 1];
-   DWORD lnHighScore;
-   time_t lnPlayDate;
-} tHighScoreRecord;
-
-typedef struct
-{
-   tHighScoreRecord aRecord[HIGH_SCORES];
-} tHighScoreFile;
-
-
-/* Prototypes for functions defined and used in this file */
-FILE *OpenAndReadHighScores(tHighScoreFile *pFileContents);
-void CloseHighScores(FILE *pfHighScoreFile);
-void WriteHighScores(FILE *pfHighScoreFile, tHighScoreFile *pFileContents);
-FILE *OpenExclusiveFile(char *pszFileName, char *pszAccess, time_t Wait);
-int FileExists(char *pszFileName);
-void ShowHighScores(void);
-void PlayGame(void);
-void SpaceRight(int nColumns);
-void MoveLeft(int nColumns);
-int AddHighScore(tHighScoreFile *pHighScores, tHighScoreRecord *pScoreRecord);
-
-
-/* The main() or WinMain() function: program execution begins here. */
-#ifdef ODPLAT_WIN32
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-   LPSTR lpszCmdLine, int nCmdShow)
-#else
-int main(int argc, char *argv[])
-#endif
-{
-   char chMenuChoice;
-
-#ifdef ODPLAT_WIN32
-   /* In Windows, pass in nCmdShow value to OpenDoors. */
-   od_control.od_cmd_show = nCmdShow;
-#endif
-   
-   /* Set program's name for use by OpenDoors. */
-   strcpy(od_control.od_prog_name, "Grand Slalom");
-   strcpy(od_control.od_prog_version, "Version 6.00");
-   strcpy(od_control.od_prog_copyright, "Copyright 1991-1996 by Brian Pirie");
-
-   /* Call the standard command-line parsing function. You will probably     */
-   /* want to do this in most programs that you write using OpenDoors, as it */
-   /* automatically provides support for many standard command-line options  */
-   /* that will make the use and setup of your program easer. For details,   */
-   /* run the vote program with the /help command line option.               */
-#ifdef ODPLAT_WIN32
-   od_parse_cmd_line(lpszCmdLine);
-#else
-   od_parse_cmd_line(argc, argv);
-#endif
-
-   /* Loop until the user chooses to exit the door */
-   do
-   {
-      /* Clear the screen */
-      od_clr_scr();
-
-      /* Display program title */
-      od_printf("`bright white`                ��� ��� ��� �� � ���   ��� �   ��� �   ��� �����\n\r");
-      od_printf("`bright red`����������������`bright white`���`bright red`�`bright white`���`bright red`�`bright white`���`bright red`�`bright white`�`bright red`�`bright white`��`bright red`�`bright white`�");
-      od_printf("`bright red`�`bright white`�`bright red`���`bright white`���`bright red`�`bright white`�`bright red`���`bright white`���`bright red`�`bright white`�`bright red`���`bright white`�");
-      od_printf("`bright red`�`bright white`�`bright red`�`bright white`�`bright red`�`bright white`�`bright red`�`bright white`�`bright red`���������������\n\r");
-      od_printf("`bright white`                ��� � � � � �  � ��    ��� ��� � � ��� ��� � � �\n\r\n\r");
-
-      /* Display instructions */
-      od_printf("`dark green`Prepare yourself for the challenge of Grand Slalom downhill skiing!\n\r\n\r");
-      od_printf("When `flashing dark green`playing`dark green` the game, press:\n\r");
-      od_printf("`dark green`          [`bright green`Q`dark green`] key to ski left\n\r");
-      od_printf("          [`bright green`W`dark green`] key to ski right\n\r\n\r");
-      od_printf("All that you have to do is ski within the slalom course.\n\r");
-      od_printf("It may sound easy - but be warned - it gets harder as you go!\n\r");
-      od_printf("(Each time you hear the beep, the course becomes a bit narrower.)\n\r\n\r");
-
-      /* Get menu choice from user. */
-      od_printf("`bright white`Now, press [ENTER] to begin game, [H] to view High Scores, [E] to Exit: ");
-      chMenuChoice = od_get_answer("HE\n\r");
-
-      /* Perform appropriate action based on user's choice */
-      switch(chMenuChoice)
-      {
-         case '\n':
-         case '\r':
-            /* If user chooses to play the game */
-            PlayGame();
-            break;
-
-         case 'H':
-            /* If user chose to view high scores */
-            ShowHighScores();
-            break;
-
-         case 'E':
-            /* If user chose to return to BBS */
-            od_printf("\n\rGoodbye from SKIGAME!\n\r");
-            break;
-      }
-   } while(chMenuChoice != 'E');
-
-   /* Exit door at errorlevel 10, and do not hang up */
-   od_exit(10, FALSE);
-   return(1);
-}
-
-
-/* OpenAndReadHighScores() - Opens high score file and reads contents. If */
-/*                           file does not exist, it is created. File is  */
-/*                           locked to serialize access by other nodes on */
-/*                           this system.                                 */
-FILE *OpenAndReadHighScores(tHighScoreFile *pFileContents)
-{
-   FILE *pfFile;
-   int iHighScore;
-
-   /* If high score file does not exist */
-   if(!FileExists(SCORE_FILENAME))
-   {
-      /* Open and create it */
-      pfFile = OpenExclusiveFile(SCORE_FILENAME, "wb", WAIT_FOR_FILE);
-
-      /* If open was successful */
-      if(pfFile != NULL)
-      {
-         /* Initialize new high score list */
-         for(iHighScore = 0; iHighScore < HIGH_SCORES; ++iHighScore)
-         {
-            pFileContents->aRecord[iHighScore].lnHighScore = 0L;
-         }
-
-         /* Write high score list to the file */
-         WriteHighScores(pfFile, pFileContents);
-      }
-   }
-
-   /* If high score file does exit */
-   else
-   {
-      /* Open the existing file */
-      pfFile = OpenExclusiveFile(SCORE_FILENAME, "r+b",
-                                WAIT_FOR_FILE);
-
-      /* Read the contents of the file */
-      if(fread(pFileContents, sizeof(tHighScoreFile), 1, pfFile) != 1)
-      {
-         /* If unable to read file, then return with an error */
-         fclose(pfFile);
-         pfFile = NULL;
-      }
-   }
-
-   /* Return pointer to high score file, if avilable */
-   return(pfFile);
-}
-
-
-/* FileExists() - Returns TRUE if file exists, otherwise returns FALSE */
-int FileExists(char *pszFileName)
-{
-   /* Attempt to open the specified file for reading. */
-   FILE *pfFile = OpenExclusiveFile(pszFileName, "rb", WAIT_FOR_FILE);
-
-   if(pfFile != NULL)
-   {
-      /* If we are able to open the file, then close it and return */
-      /* indicating that it exists.                                */
-      fclose(pfFile);
-      return(TRUE);
-   }
-   else
-   {
-      /* If we are unable to open the file, we proceed as if the file        */
-      /* doesn't exist (note that this may not always be a valid assumption) */
-      return(FALSE);
-   }
-}
-
-
-/* OpenExclusiveFile() - Opens a file for exclusive access, waiting if the */
-/*                       file is not currently available.                  */
-FILE *OpenExclusiveFile(char *pszFileName, char *pszAccess, time_t Wait)
-{
-   FILE *pfFile;
-   time_t StartTime = time(NULL);
-
-   for(;;)
-   {
-      /* Attempt to open file */
-      pfFile = fopen(pszFileName, pszAccess);
-
-      /* If file was opened successfuly, then exit */
-      if(pfFile != NULL) break;
-
-      /* If open failed, but not due to access failure, then exit */
-      if(errno != EACCES) break;
-
-      /* If maximum time has elapsed, then exit */
-      if(StartTime + Wait < time(NULL)) break;
-
-      /* Give the OpenDoors kernel a chance to execute before trying again */
-      od_kernel();
-   }
-
-   /* Return pointer to file, if opened */
-   return(pfFile);
-}
-
-
-/* CloseHighScores() - Closes the high score file, allowing other nodes on */
-/*                     system to access it.                                */
-void CloseHighScores(FILE *pfHighScoreFile)
-{
-   if(pfHighScoreFile != NULL)
-   {
-      fclose(pfHighScoreFile);
-   }
-}
-
-
-/* WriteHighScores() - Writes the information from pFileContents to the */
-/*                     high score file.                                 */
-void WriteHighScores(FILE *pfHighScoreFile, tHighScoreFile *pFileContents)
-{
-   if(pfHighScoreFile != NULL)
-   {
-      fseek(pfHighScoreFile, 0L, SEEK_SET);
-      fwrite(pFileContents, sizeof(tHighScoreFile), 1, pfHighScoreFile);
-   }
-}
-
-
-/* ShowHighScores() - Called From DoDoor() to display list of high scores */
-void ShowHighScores(void)
-{
-   FILE *pfFile;
-   tHighScoreFile HighScores;
-   int iHighScore;
-   struct tm *pTimeBlock;
-   char szTimeString[34];
-
-   /* Clear the screen */
-   od_clr_scr();
-
-   /* Attempt to read high scores from file */
-   pfFile = OpenAndReadHighScores(&HighScores);
-   CloseHighScores(pfFile);
-
-   if(pfFile == NULL)
-   {
-      /* If unable to open high score file, display an error message */
-      od_printf("`bright red`Unable to access high score file!\n\r");
-   }
-   else
-   {
-      /* Display header line */
-      od_printf("`bright green`Player                            Score     "
-                "Record Date`dark green`\n\r");
-      od_printf("�������������������������������������������������������������������������������\n\r");
-
-      /* Display high scores */
-      for(iHighScore = 0; iHighScore < HIGH_SCORES; ++iHighScore)
-      {
-         /* Exit loop when we have reached the end of the high scores */
-         if(HighScores.aRecord[iHighScore].lnHighScore == 0L) break;
-
-         /* Get local time when player set the high score */
-         pTimeBlock = localtime(&HighScores.aRecord[iHighScore].lnPlayDate);
-         strftime(szTimeString, sizeof(szTimeString),
-            "%B %d, %Y at %I:%M%p", pTimeBlock);
-
-         /* Display next high score */
-         od_printf("%-32.32s  %-8ld  %s\n\r",
-                   HighScores.aRecord[iHighScore].szPlayerName,
-                   HighScores.aRecord[iHighScore].lnHighScore,
-                   szTimeString);
-      }
-   }
-
-   /* Display footer line */
-   od_printf("�������������������������������������������������������������������������������\n\r\n\r");
-
-   /* Wait for user to press a key */
-   od_printf("`bright white`Press [ENTER]/[RETURN] to continue: ");
-   od_get_answer("\n\r");
-}
-
-
-/* PlayGame() - Called from DoDoor() when user chooses to play a game. */
-void PlayGame(void)
-{
-   int nLeftEdge = 1;
-   int nRightEdge = nLeftEdge + 1 + INITIAL_COURSE_WIDTH;
-   int nPlayerPos = nLeftEdge + 1 + (INITIAL_COURSE_WIDTH / 2);
-   long lnScore = 0;
-   int nDistanceSinceShrink = 0;
-   int bMovingRight = TRUE;
-   char cKeyPress;
-   tHighScoreRecord ScoreRecord;
-   FILE *pfFile;
-   tHighScoreFile HighScores;
-   int nBackup;
-   clock_t StartClock;
-
-   /* Clear the Screen */
-   od_set_color(L_WHITE, B_BLACK);
-   od_clr_scr();
-
-   /* Set current display colour to white */
-   od_set_attrib(L_WHITE);
-
-   /* Re-seed random number generator */
-   srand((unsigned int)time(NULL));
-
-   /* Loop until game is over */
-   for(;;)
-   {
-      StartClock = clock();
-
-      /* Display current line */
-      if(od_control.user_ansi || od_control.user_avatar)
-      {
-         SpaceRight(nLeftEdge - 1);
-         od_set_color(L_WHITE, D_RED);
-         od_putch((char)223);
-         od_repeat((unsigned char)219, 
-            (unsigned char)(nPlayerPos - nLeftEdge - 1));
-         od_putch((char)254);
-         od_repeat((unsigned char)219,
-            (unsigned char)(nRightEdge - nPlayerPos - 1));
-         od_putch((char)223);
-         nBackup = nRightEdge - nPlayerPos + 1;
-      }
-      else
-      {
-         /* If neither ANSI nor AVATAR modes are active, then display */
-         /* course using plain-ASCII.                                 */
-         SpaceRight(nLeftEdge - 1);
-         od_putch((char)(bMovingRight ? '\\' : '/'));
-         SpaceRight(nPlayerPos - nLeftEdge - 1);
-         od_putch('o');
-         SpaceRight(nRightEdge - nPlayerPos - 1);
-         od_putch((char)(bMovingRight ? '\\' : '/'));
-      }
-
-      /* Loop for each key pressed by user */
-      while((cKeyPress = (char)od_get_key(FALSE)) != '\0')
-      {
-         if(cKeyPress == 'q' || cKeyPress == 'Q')
-         {
-            /* Move left */
-            --nPlayerPos;
-         }
-         else if(cKeyPress == 'w' || cKeyPress == 'W')
-         {
-            /* Move right */
-            ++nPlayerPos;
-         }
-      }
-
-      /* Check whether course should turn */
-      if((rand() % 100) < CHANGE_DIRECTION)
-      {
-         bMovingRight = !bMovingRight;
-      }
-      else
-      {
-         /* If no change in direction, then position moves */
-         /* Adjust course position appropriately */
-         if(bMovingRight)
-         {
-            ++nLeftEdge;
-            ++nRightEdge;
-         }
-         else
-         {
-            --nLeftEdge;
-            --nRightEdge;
-         }
-      }
-
-      /* Check whether course size should shink */
-      if(++nDistanceSinceShrink >= DECREASE_WIDTH_AFTER)
-      {
-         /* Reset distance */
-         nDistanceSinceShrink = 0;
-
-         /* Randomly choose a side to shrink */
-         if((rand() % 100) < 50)
-         {
-            ++nLeftEdge;
-         }
-         else
-         {
-            --nRightEdge;
-         }
-
-         /* Beep when we shrink the size. */
-         od_printf("\a");
-      }
-
-      /* Change course direction if it collides with edge of screen */
-      if(nLeftEdge < 1)
-      {
-         bMovingRight = TRUE;
-         ++nLeftEdge;
-         ++nRightEdge;
-      }
-      else if(nRightEdge > 79)
-      {
-         bMovingRight = FALSE;
-         --nLeftEdge;
-         --nRightEdge;
-      }
-
-      /* Check that player is still within the course */
-      if(nPlayerPos <= nLeftEdge || nPlayerPos >= nRightEdge)
-      {
-         /* Player has left course - game over! */
-         od_set_color(D_GREY, D_BLACK);
-         od_clr_scr();
-         od_printf("`bright red`       !!! Game Over !!!\n\r\n\r");
-         od_printf("`dark green`You have veered off the course!\n\r\n\r");
-         od_printf("Your Score is: %ld\n\r", lnScore);
-
-         /* Create a score record */
-         ScoreRecord.lnHighScore = lnScore;
-         strncpy(ScoreRecord.szPlayerName, od_control.user_name, MAX_NAME_SIZE);
-         ScoreRecord.szPlayerName[MAX_NAME_SIZE] = '\0';
-         ScoreRecord.lnPlayDate = time(NULL);
-
-         /* Attempt to read high scores from file */
-         pfFile = OpenAndReadHighScores(&HighScores);
-
-         if(pfFile == NULL)
-         {
-            /* If unable to open high score file, display an error message */
-            od_printf("`bright red`Unable to access high score file!\n\r");
-         }
-         else
-         {
-            /* Check whether user made it to high score list */
-            if(AddHighScore(&HighScores, &ScoreRecord))
-            {
-               od_printf("Congratulations! You have made it to the high score list!\n\r");
-               /* If so, write the new high score list */
-               WriteHighScores(pfFile, &HighScores);
-            }
-
-            /* Close and unlock file */
-            CloseHighScores(pfFile);
-         }
-
-         /* Wait for user to press enter */
-         od_printf("`bright white`\n\rPress [ENTER]/[RETURN] to return to menu: ");
-         od_get_answer("\n\r");
-
-         return;
-      }
-
-      /* Delay for about 1/18th of a second, to add a constant delay after */
-      /* each line is displayed that does not depend on the connect speed. */
-      while(clock() < StartClock + (((clock_t)CLOCKS_PER_SEC) / 18))
-         od_sleep(0);
-
-      /* Increase score */
-      ++lnScore;
-
-      /* Replace skiier character with track character */
-      if(od_control.user_ansi)
-      {
-         MoveLeft(nBackup);
-         od_set_color(L_WHITE, D_GREY);
-         od_putch((char)178);
-         od_set_color(L_WHITE, B_BLACK);
-      }
-
-      /* Move to next line */
-      od_printf("\r\n");
-   }
-}
-
-
-/* SpaceRight() - Moves right the specified number of columns. In ANSI mode, */
-/*                uses the move cursor right control sequence. Otherwise,    */
-/*                uses od_repeat(), which is optimized for ASCII and AVATAR  */
-/*                modes.                                                     */
-void SpaceRight(int nColumns)
-{
-   char szSequence[6];
-
-   /* If we don't have a positive column count, then return immediately */
-   if(nColumns <= 0) return;
-
-   /* If operating in ANSI mode */
-   if(od_control.user_ansi)
-   {
-      /* Move cursor right using ESC[nC control sequence */
-      sprintf(szSequence, "\x1b[%02.2dC", nColumns);
-      od_disp_emu(szSequence, TRUE);
-   }
-
-   /* If not operating in ANSI mode */
-   else
-   {
-      od_repeat(' ', (unsigned char)nColumns);
-   }
-}
-
-
-/* MoveLeft() - Moves the cursor right the specified number of columns. */
-/*              Intended for use in ANSI mode only.                     */
-void MoveLeft(int nColumns)
-{
-   /* Move cursor left using ESC[nD control sequence */
-   char szSequence[6];
-   sprintf(szSequence, "\x1b[%02.2dD", nColumns);
-   od_disp_emu(szSequence, TRUE);
-}
-
-
-/* AddHighScore() - Adds a new score to the high score list, if it is high   */
-/*                  enough. Returns TRUE if score is added, FALSE otherwise. */
-int AddHighScore(tHighScoreFile *pHighScores, tHighScoreRecord *pScoreRecord)
-{
-   int iHighScore;
-   int iExistingScore;
-
-   /* Loop through each existing high score */
-   for(iHighScore = 0; iHighScore < HIGH_SCORES; ++iHighScore)
-   {
-      /* If new score is greater than or equal to this one, then its */
-      /* position has been found.                                    */
-      if(pHighScores->aRecord[iHighScore].lnHighScore <=
-         pScoreRecord->lnHighScore)
-      {
-         /* Move remaining scores down one in list */
-         for(iExistingScore = HIGH_SCORES - 1; iExistingScore >= iHighScore + 1;
-          --iExistingScore)
-         {
-            pHighScores->aRecord[iExistingScore] =
-               pHighScores->aRecord[iExistingScore - 1];
-         }
-
-         /* Add new score to list */
-         pHighScores->aRecord[iHighScore] = *pScoreRecord;
-
-         /* Return with success */
-         return(TRUE);
-      }
-   }
-
-   /* Score did not make it to list */
-   return(FALSE);
-}
diff --git a/src/odoors/ex_vote.c b/src/odoors/ex_vote.c
deleted file mode 100644
index 6d186462fd8f95acfcd7c9a88e7d11edbdb58851..0000000000000000000000000000000000000000
--- a/src/odoors/ex_vote.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/* EX_VOTE.C - This program demonstrates an online voting program that is    */
-/*             written using OpenDoors. The Vote program allows users to     */
-/*             create questions or surveys for other users to respond to.    */
-/*             Users are also able to view the results of voting on each     */
-/*             topic. The program supports up to 200 questions, and can be   */
-/*             configured to either allow or disallow viewing of results     */
-/*             prior to voting.                                              */
-/*                                                                           */
-/*             This program shows how to do the following:                   */
-/*                                                                           */
-/*                - How to display text using od_printf(), using imbedded    */
-/*                  strings to change the display color.                     */
-/*                - Add support for standard command-line options.           */
-/*                - Use the OpenDoors configuration file system, including   */
-/*                  adding your own configuration file options.              */
-/*                - Activate the OpenDoors log file system and write         */
-/*                  information to the log file.                             */
-/*                - Display a menu from an external ASCI/ANSI/Avatar/RIP     */
-/*                  file.                                                    */
-/*                - How to setup a user file and general data file, and how  */
-/*                  to access it in a multi-node compatible way (if          */
-/*                  MULTINODE_AWARE is defined).                             */
-/*                                                                           */
-/*             To recompile this program, follow the instructions in the     */
-/*             OpenDoors manual. For a DOS compiler, be sure to set your     */
-/*             compiler to use the large memory model, and add the           */
-/*             ODOORL.LIB file to your project/makefile.                     */
-
-/* Uncomment the following line for multi-node compatible file access. */
-/* #define MULTINODE_AWARE */
-
-/* Include standard C header files required by Vote. */
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <errno.h>
-#include <ctype.h>
-#ifdef MULTINODE_AWARE
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <share.h>
-#endif
-
-/* Include the OpenDoors header file. This line must be done in any program */
-/* using OpenDoors.                                                         */
-#include "opendoor.h"
-
-
-/* Manifest constants used by Vote */
-#define NO_QUESTION              -1
-#define NEW_ANSWER               -1
-
-#define QUESTIONS_VOTED_ON        0x0001
-#define QUESTIONS_NOT_VOTED_ON    0x0002
-
-#define MAX_QUESTIONS             200
-#define MAX_USERS                 30000
-#define MAX_ANSWERS               15
-#define QUESTION_STR_SIZE         71
-#define ANSWER_STR_SIZE           31
-
-#define USER_FILENAME             "VOTE.USR"
-#define QUESTION_FILENAME         "VOTE.QST"
-
-#define FILE_ACCESS_MAX_WAIT      20
-
-#define QUESTION_PAGE_SIZE        17
-
-
-/* Structure of records stored in the VOTE.USR file */
-typedef struct
-{
-   char szUserName[36];
-   BYTE bVotedOnQuestion[MAX_QUESTIONS];
-} tUserRecord;
-              
-tUserRecord CurrentUserRecord;
-int nCurrentUserNumber;
-
-
-/* Structure of records stored in the VOTE.QST file */
-typedef struct
-{
-   char szQuestion[72];
-   char aszAnswer[MAX_ANSWERS][32];
-   INT32 nTotalAnswers;
-   DWORD auVotesForAnswer[MAX_ANSWERS];
-   DWORD uTotalVotes;
-   DWORD bCanAddAnswers;
-   char szCreatorName[36];
-   time_t lCreationTime;
-} tQuestionRecord;
-
-
-/* Global variables. */
-int nViewResultsFrom = QUESTIONS_VOTED_ON;
-int nQuestionsVotedOn = 0;
-
-
-/* Prototypes for functions that form EX_VOTE */
-void CustomConfigFunction(char *pszKeyword, char *pszOptions);
-void BeforeExitFunction(void);
-void VoteOnQuestion(void);
-void ViewResults(void);
-int GetQuestion(int nQuestion, tQuestionRecord *pQuestionRecord);
-void AddQuestion(void);
-int ChooseQuestion(int nFromWhichQuestions, char *pszTitle, int *nLocation);
-void DisplayQuestionResult(tQuestionRecord *pQuestionRecord);
-int ReadOrAddCurrentUser(void);
-void WriteCurrentUser(void);
-FILE *ExclusiveFileOpen(char *pszFileName, char *pszMode, int *phHandle);
-void ExclusiveFileClose(FILE *pfFile, int hHandle);
-void WaitForEnter(void);
-
-
-/* main() or WinMain() function - Program execution begins here. */
-#ifdef ODPLAT_WIN32
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-   LPSTR lpszCmdLine, int nCmdShow)
-#else
-int main(int argc, char *argv[])
-#endif
-{
-   /* Variable to store user's choice from the menu */
-   char chMenuChoice = '\0';
-   char chYesOrNo;
-
-#ifdef ODPLAT_WIN32
-   /* In Windows, pass in nCmdShow value to OpenDoors. */
-   od_control.od_cmd_show = nCmdShow;
-
-   /* Ignore unused parameters. */
-   (void)hInstance;
-   (void)hPrevInstance;
-#endif
-   
-   /* Set program's name for use by OpenDoors. */
-   strcpy(od_control.od_prog_name, "Vote");
-   strcpy(od_control.od_prog_version, "Version 6.00");
-   strcpy(od_control.od_prog_copyright, "Copyright 1991-1996 by Brian Pirie");
-
-   /* Call the standard command-line parsing function. You will probably     */
-   /* want to do this in most programs that you write using OpenDoors, as it */
-   /* automatically provides support for many standard command-line options  */
-   /* that will make the use and setup of your program easer. For details,   */
-   /* run the vote program with the /help command line option.               */
-#ifdef ODPLAT_WIN32
-   od_parse_cmd_line(lpszCmdLine);
-#else
-   od_parse_cmd_line(argc, argv);
-#endif
-
-   /* Enable use of OpenDoors configuration file system. */
-   od_control.od_config_file = INCLUDE_CONFIG_FILE;
-
-   /* Set function to process custom configuration file lines. */
-   od_control.od_config_function = CustomConfigFunction;
-
-   /* Include the OpenDoors multiple personality system, which allows    */
-   /* the system operator to set the sysop statusline / function key set */
-   /* to mimic the BBS software of their choice.                         */
-   od_control.od_mps = INCLUDE_MPS;
-   
-   /* Include the OpenDoors log file system, which will record when the */
-   /* door runs, and major activites that the user performs.            */ 
-   od_control.od_logfile = INCLUDE_LOGFILE;
-
-   /* Set filename for log file. If not set, DOOR.LOG will be used by */
-   /* default.                                                        */
-   strcpy(od_control.od_logfile_name, "VOTE.LOG");
-
-   /* Set function to be called before program exits. */
-   od_control.od_before_exit = BeforeExitFunction;
-
-   /* Initialize OpenDoors. This function call is optional, and can be used */
-   /* to force OpenDoors to read the door informtion file and begin door    */
-   /* operations. If a call to od_init() is not included in your program,   */
-   /* OpenDoors initialization will be performed at the time of your first  */
-   /* call to any OpenDoors function. */
-   od_init();
-
-   /* Call the Vote function ReadOrAddCurrentUser() to read the current   */
-   /* user's record from the Vote user file, or to add the user to the    */
-   /* file if this is the first time that they have used Vote.            */
-   if(!ReadOrAddCurrentUser())
-   {
-      /* If unable to obtain a user record for the current user, then exit */
-      /* the door after displaying an error message.                       */
-      od_printf("Unable to access user file. File may be locked or full.\n\r");
-      WaitForEnter();
-      od_exit(1, FALSE);
-   }   
-
-   /* Loop until the user choses to exit the door. For each iteration of  */
-   /* this loop, we display the main menu, get the user's choice from the */
-   /* menu, and perform the appropriate action for their choice.          */
-
-   while(chMenuChoice != 'E' && chMenuChoice != 'H')
-   {
-      /* Clear the screen */
-      od_clr_scr();
-
-      /* Display main menu. */
-      
-      /* First, attempt to display menu from an VOTE.ASC/ANS/AVT/RIP file. */
-      if((chMenuChoice = od_hotkey_menu("VOTE", "VRADPEH", TRUE)) == 0)
-      {
-         /* If the VOTE file could not be displayed, display our own menu. */
-         od_printf("`bright red`                     Vote - OpenDoors 6.00 example program\n\r");\
-         od_printf("`dark red`");
-         if(od_control.user_ansi || od_control.user_avatar)
-         {
-            od_repeat((unsigned char)196, 79);
-         }
-         else
-         {
-            od_repeat('-', 79);
-         }
-         od_printf("\n\r\n\r\n\r`dark green`");
-         od_printf("                        [`bright green`V`dark green`] Vote on a question\n\r\n\r");
-         od_printf("                        [`bright green`R`dark green`] View the results of question\n\r\n\r");
-         od_printf("                        [`bright green`A`dark green`] Add a new question\n\r\n\r");
-         od_printf("                        [`bright green`P`dark green`] Page system operator for chat\n\r\n\r");
-         od_printf("                        [`bright green`E`dark green`] Exit door and return to the BBS\n\r\n\r");
-         od_printf("                        [`bright green`H`dark green`] End call (hangup)\n\r\n\r\n\r");
-         od_printf("`bright white`Press the key corresponding to the option of your choice. (%d mins)\n\r`dark green`",
-            od_control.user_timelimit);
-                                                                                                       \
-         /* Get the user's choice from the main menu. This choice may only be */
-         /* V, R, A, D, P, E or H.                                            */
-         chMenuChoice = od_get_answer("VRADPEH");
-      }
-
-      /* Perform the appropriate action based on the user's choice */
-      switch(chMenuChoice)
-      {
-         case 'V':
-            /* Call Vote's function to vote on question */
-            VoteOnQuestion();
-            break;
-            
-         case 'R':
-            /* Call Vote's function to view the results of voting */
-            ViewResults();
-            break;
-            
-         case 'A':
-            /* Call Vote's function to add a new question. */
-            AddQuestion();
-            break;
-            
-         case 'P':
-            /* If the user pressed P, allow them page the system operator. */
-            od_page();
-            break;
-
-         case 'H':
-            /* If the user pressed H, ask whether they wish to hangup. */
-            od_printf("\n\rAre you sure you wish to hangup? (Y/N) ");
-
-            /* Get user's response */
-            chYesOrNo = od_get_answer("YN");
-
-            if(chYesOrNo == 'N')
-            {
-               /* If user answered no, then reset menu choice, so that */
-               /* program will not exit.                               */
-               chMenuChoice = '\0';
-            }
-            break;
-      }
-   }
-
-   if(chMenuChoice == 'H')
-   {
-      /* If the user chooses to hangup, then hangup when exiting. */
-      od_exit(0, TRUE);
-   }
-   else
-   {
-      /* Otherwise, exit normally (without hanging up). */
-      od_printf("Returning to BBS, please wait...\n\r");
-      od_exit(0, FALSE);
-   }
-
-   return(0);
-}
-
-
-/* CustomConfigFunction() is called by OpenDoors to process custom */
-/* configuration file keywords that Vote uses.                     */
-void CustomConfigFunction(char *pszKeyword, char *pszOptions)
-{
-   if(stricmp(pszKeyword, "ViewUnanswered") == 0)
-   {
-      /* If keyword is ViewUnanswered, set local variable based on contents */
-      /* of options string.                                                 */
-      if(stricmp(pszOptions, "Yes") == 0)
-      {
-         nViewResultsFrom = QUESTIONS_VOTED_ON | QUESTIONS_NOT_VOTED_ON;
-      }
-      else if(stricmp(pszOptions, "No") == 0)
-      {
-         nViewResultsFrom = QUESTIONS_VOTED_ON;
-      }
-   }
-}
-
-
-/* Vote configures OpenDoors to call the BeforeExitFunction() before      */
-/* the door exists for any reason. You can use this function to close any */
-/* files or perform any other operations that you wish to have peformed   */
-/* before OpenDoors exists for any reason. The od_control.od_before_exit  */
-/* variable sets the function to be called before program exit.           */
-void BeforeExitFunction(void)
-{
-   char szLogMessage[80];
-   
-   /* Write number of messages voted on to log file. */
-   sprintf(szLogMessage, "User has voted on %d question(s)",
-      nQuestionsVotedOn);
-   od_log_write(szLogMessage);
-}
-
-
-/* Vote calls the VoteOnQuestion() function when the user chooses the     */
-/* vote command from the main menu. This function displays a list of      */
-/* available topics, asks for the user's answer to the topic they select, */
-/* and display's the results of voting on that topic.                     */
-void VoteOnQuestion(void)
-{
-   int nQuestion;
-   int nAnswer;
-   tQuestionRecord QuestionRecord;
-   char szNewAnswer[ANSWER_STR_SIZE];
-   char szUserInput[3];
-   FILE *fpFile;
-   int hFile;
-   int nPageLocation = 0;
-
-   /* Loop until the user chooses to return to the main menu, or until */
-   /* there are no more questions to vote on.                          */
-   for(;;)   
-   {
-      /* Allow the user to choose a question from the list of questions */
-      /* that they have not voted on.                                   */
-      nQuestion = ChooseQuestion(QUESTIONS_NOT_VOTED_ON,
-         "                              Vote On A Question\n\r",
-         &nPageLocation);
-   
-
-      /* If the user did not choose a question, return to main menu. */   
-      if(nQuestion == NO_QUESTION)
-      {
-         return;
-      }
-
-      /* Read the question chosen by the user. */
-      if(!GetQuestion(nQuestion, &QuestionRecord))
-      {
-         /* If unable to access file, return to main menu. */
-         return;
-      }
-   
-      /* Don't allow addition of new answers if maximum number of answers */
-      /* have already been added.                                         */
-      if(QuestionRecord.nTotalAnswers >= MAX_ANSWERS)
-      {
-         QuestionRecord.bCanAddAnswers = FALSE;
-      }
-   
-      /* Loop until user makes a valid respose. */
-      for(;;)
-      {
-         /* Display question to user. */
-
-         /* Clear the screen. */
-         od_clr_scr();
-
-         /* Display question itself. */
-         od_printf("`bright red`%s\n\r\n\r", QuestionRecord.szQuestion);
-
-         /* Loop for each answer to the question. */   
-         for(nAnswer = 0; nAnswer < QuestionRecord.nTotalAnswers; ++nAnswer)
-         {
-            /* Display answer number and answer. */
-            od_printf("`bright green`%d. `dark green`%s\n\r",
-               nAnswer + 1,
-               QuestionRecord.aszAnswer[nAnswer]);
-         }
-
-         /* Display prompt to user. */
-         od_printf("\n\r`bright white`Enter answer number, ");
-         if(QuestionRecord.bCanAddAnswers)
-         {
-            od_printf("[A] to add your own response, ");
-         }
-         od_printf("[Q] to quit: `dark green`");
-   
-         /* Get response from user. */
-         od_input_str(szUserInput, 2, ' ', 255);
-         /* Add a blank line. */      
-         od_printf("\n\r");
-   
-         /* If user entered Q, return to main menu. */
-         if(stricmp(szUserInput, "Q") == 0)
-         {
-            return;
-         }
-
-         /* If user enetered A, and adding answers is premitted ... */
-         else if (stricmp(szUserInput, "A") == 0
-            && QuestionRecord.bCanAddAnswers)
-         {
-            /* ... Prompt for answer from user. */
-            od_printf("`bright green`Please enter your new answer:\n\r");
-            od_printf("`dark green`[------------------------------]\n\r ");
-         
-            /* Get string from user. */
-            od_input_str(szNewAnswer, ANSWER_STR_SIZE - 1, ' ', 255);
-         
-            /* Record that user entered a new answer answer. */
-            nAnswer = NEW_ANSWER;
-
-            /* If user entered a valid answer, then exit loop. */
-            if(strlen(szNewAnswer) > 0)
-            {
-               break;
-            }         
-         }
-
-         /* Otherwise, attempt to get answer number from user. */      
-         nAnswer = atoi(szUserInput) - 1;
-
-         /* If user input is not a valid answer. */      
-         if(nAnswer < 0 || nAnswer >= QuestionRecord.nTotalAnswers)
-         {
-            /* Display message. */
-            od_printf("That is not a valid response.\n\r");
-            WaitForEnter();
-         }
-         else
-         {
-            /* Otherwise, exit loop. */
-            break;
-         }
-      }
-
-      /* Add user's vote to question. */
-   
-      /* Open question file for exclusive access by this node. */
-      fpFile = ExclusiveFileOpen(QUESTION_FILENAME, "r+b", &hFile);
-      if(fpFile == NULL)
-      {
-         /* If unable to access file, display error and return. */
-         od_printf("Unable to access the question file.\n\r");
-         WaitForEnter();
-         return;
-      }
-   
-      /* Read the answer record from disk, because it may have been changed. */
-      /* by another node. */
-      fseek(fpFile, (long)nQuestion * sizeof(tQuestionRecord), SEEK_SET);
-      if(fread(&QuestionRecord, sizeof(tQuestionRecord), 1, fpFile) != 1)
-      {
-         /* If unable to access file, display error and return. */
-         ExclusiveFileClose(fpFile, hFile);
-         od_printf("Unable to read from question file.\n\r");
-         WaitForEnter();
-         return;
-      }
-   
-      /* If user entered their own answer, try to add it to the question. */
-      if(nAnswer == NEW_ANSWER)
-      {
-         /* Check that there is still room for another answer. */
-         if(QuestionRecord.nTotalAnswers >= MAX_ANSWERS)
-         {
-            ExclusiveFileClose(fpFile, hFile);
-            od_printf("Sorry, this question already has the maximum number of answers.\n\r");
-            WaitForEnter();
-            return;
-         }
-      
-         /* Set answer number to number of new answer. */
-         nAnswer = QuestionRecord.nTotalAnswers;
-      
-         /* Add 1 to total number of answers. */
-         ++QuestionRecord.nTotalAnswers;
-      
-         /* Initialize new answer string and count. */
-         strcpy(QuestionRecord.aszAnswer[nAnswer], szNewAnswer);
-         QuestionRecord.auVotesForAnswer[nAnswer] = 0;
-      }
-   
-      /* Add user's vote to question. */
-      ++QuestionRecord.auVotesForAnswer[nAnswer];
-      ++QuestionRecord.uTotalVotes;
-   
-      /* Write the question record back to the file. */
-      fseek(fpFile, (long)nQuestion * sizeof(tQuestionRecord), SEEK_SET);
-      if(fwrite(&QuestionRecord, sizeof(tQuestionRecord), 1, fpFile) != 1)
-      {
-         /* If unable to access file, display error and return. */
-         ExclusiveFileClose(fpFile, hFile);
-         od_printf("Unable to write question to file.\n\r");
-         WaitForEnter();
-         return;
-      }
-   
-      /* Close the question file to allow access by other nodes. */
-      ExclusiveFileClose(fpFile, hFile);
-   
-      /* Record that user has voted on this question. */
-      CurrentUserRecord.bVotedOnQuestion[nQuestion] = TRUE;
-   
-      /* Open user file for exclusive access by this node. */
-      fpFile = ExclusiveFileOpen(USER_FILENAME, "r+b", &hFile);
-      if(fpFile == NULL)
-      {
-         /* If unable to access file, display error and return. */
-         od_printf("Unable to access the user file.\n\r");
-         WaitForEnter();
-         return;
-      }
-
-      /* Update the user's record in the user file. */
-      fseek(fpFile, nCurrentUserNumber * sizeof(tUserRecord), SEEK_SET);
-      if(fwrite(&CurrentUserRecord, sizeof(tUserRecord), 1, fpFile) != 1)
-      {
-         /* If unable to access file, display error and return. */
-         ExclusiveFileClose(fpFile, hFile);
-         od_printf("Unable to write to user file.\n\r");
-         WaitForEnter();
-         return;
-      }
-   
-      /* Close the user file to allow access by other nodes. */
-      ExclusiveFileClose(fpFile, hFile);
-   
-      /* Display the result of voting on this question to the user. */
-      DisplayQuestionResult(&QuestionRecord);
-
-      /* Add 1 to count of questions that the user has voted on. */
-      nQuestionsVotedOn++;
-   }
-}
-
-
-/* The ViewResults function is called when the user chooses the "view    */
-/* results" command from the main menu. This function alows the user to  */
-/* choose a question from the list of questions, and then displays the   */
-/* results of voting on that question.                                   */
-void ViewResults(void)
-{
-   int nChoice;
-   tQuestionRecord QuestionRecord;
-   int nPageLocation = 0;
-
-   /* Loop until user chooses to return to main menu. */
-   for(;;)
-   {   
-      /* Allow the user to choose a question from the list of questions that */
-      /* they have already voted on.                                         */
-      nChoice = ChooseQuestion(nViewResultsFrom,
-         "                                 View Results\n\r", &nPageLocation);
-
-      /* If the user did not choose a question, return to main menu. */   
-      if(nChoice == NO_QUESTION)
-      {
-         return;
-      }
-   
-      /* Read the specified question number from the question file. */
-      if(!GetQuestion(nChoice, &QuestionRecord))
-      {
-         return;
-      }
-   
-      /* Display the results for the selected question. */
-      DisplayQuestionResult(&QuestionRecord);
-   }
-}
-
-
-/* The GetQuestion function read the record for the specified question */
-/* number from the question file.                                      */
-int GetQuestion(int nQuestion, tQuestionRecord *pQuestionRecord)
-{
-   FILE *fpQuestionFile;
-   int hQuestionFile;
-
-   /* Open the question file for exculsive access by this node. */
-   fpQuestionFile = ExclusiveFileOpen(QUESTION_FILENAME, "r+b",
-      &hQuestionFile);
-   if(fpQuestionFile == NULL)
-   {
-      /* If unable to access file, display error and return. */
-      od_printf("Unable to access the question file.\n\r");
-      WaitForEnter();
-      return(FALSE);
-   }
-   
-   /* Move to location of question in file. */
-   fseek(fpQuestionFile, (long)nQuestion * sizeof(tQuestionRecord), SEEK_SET);
-   
-   /* Read the question from the file. */
-   if(fread(pQuestionRecord, sizeof(tQuestionRecord), 1, fpQuestionFile) != 1)
-   {
-      /* If unable to access file, display error and return. */
-      ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-      od_printf("Unable to read from question file.\n\r");
-      WaitForEnter();
-      return(FALSE);;
-   }
-   
-   /* Close the question file to allow access by other nodes. */
-   ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-
-   /* Return with success. */
-   return(TRUE);
-}
- 
-
-/* The AddQuestion() function is called when the user chooses the "add    */
-/* question" option from the main menu. This function allows the user     */
-/* to enter a new question, possible responses, and save the question for */
-/* other users to vote on.                                                */
-void AddQuestion(void)
-{
-   tQuestionRecord QuestionRecord;
-   FILE *fpQuestionFile;
-   int hQuestionFile;
-   char szLogMessage[100];
-
-   /* Clear the screen. */
-   od_clr_scr();
-   
-   /* Display screen header. */
-   od_printf("`bright red`                                Add A Question\n\r");
-   od_printf("`dark red`");
-   if(od_control.user_ansi || od_control.user_avatar)
-   {
-      od_repeat((unsigned char)196, 79);
-   }
-   else
-   {
-      od_repeat('-', 79);
-   }
-   od_printf("\n\r\n\r");
-   
-   /* Obtain quesiton text from the user. */
-   od_printf("`bright green`Enter Your Question (blank line cancels)\n\r");
-   od_printf("`dark green`[----------------------------------------------------------------------]\n\r ");
-   od_input_str(QuestionRecord.szQuestion, QUESTION_STR_SIZE - 1, ' ', 255);
-   
-   /* If question was empty, then return to main menu. */
-   if(strlen(QuestionRecord.szQuestion) == 0)
-   {
-      return;
-   }
-   
-   /* Display prompt for answers. */
-   od_printf("\n\r`bright green`Enter Possible Answers (blank line when done)\n\r");
-   od_printf("`dark green`   [------------------------------]\n\r");
-   
-   /* Loop, getting answers from user. */
-   for(QuestionRecord.nTotalAnswers = 0;
-       QuestionRecord.nTotalAnswers < MAX_ANSWERS;
-       QuestionRecord.nTotalAnswers++)
-   {
-      /* Display prompt with answer number. */
-      od_printf("`bright green`%2d: `dark green`", QuestionRecord.nTotalAnswers + 1);
-      
-      /* Get string from user. */
-      od_input_str(QuestionRecord.aszAnswer[QuestionRecord.nTotalAnswers],
-         ANSWER_STR_SIZE - 1, ' ', 255);
-         
-      /* If string was empty, then exit loop. */
-      if(strlen(QuestionRecord.aszAnswer[QuestionRecord.nTotalAnswers]) == 0)
-      {
-         break;
-      }
-      
-      /* Reset count of votes for this answer to zero. */
-      QuestionRecord.auVotesForAnswer[QuestionRecord.nTotalAnswers] = 0;
-   }
-   
-   /* If no answers were supplied, then cancel, returning to main menu. */
-   if(QuestionRecord.nTotalAnswers == 0)
-   {
-      return;
-   }
-
-   /* Ask whether users should be able to add their own answers. */
-   od_printf("\n\r`bright green`Should voters be able to add their own options? (Y/N) `dark green`");
-   
-   /* Get answer from user. */
-   if(od_get_answer("YN") == 'Y')
-   {
-      /* If user pressed the 'Y' key. */
-      od_printf("Yes\n\r\n\r");
-      
-      /* Record user's response. */
-      QuestionRecord.bCanAddAnswers = TRUE;
-   }
-   else
-   {
-      /* If user pressed the 'N' key. */
-      od_printf("No\n\r\n\r");
-
-      /* Record user's response. */
-      QuestionRecord.bCanAddAnswers = FALSE;
-   }
-   
-   /* Confirm save of new question. */
-   od_printf("`bright green`Do you wish to save this new question? (Y/N) `dark green`");
-   
-   /* If user does not want to save the question, return to main menu now. */
-   if(od_get_answer("YN") == 'N')
-   {
-      return;
-   }
-
-   /* Set total number of votes for this question to 0. */   
-   QuestionRecord.uTotalVotes = 0;
-   
-   /* Set creator name and creation time for this question. */
-   strcpy(QuestionRecord.szCreatorName, od_control.user_name);
-   QuestionRecord.lCreationTime = time(NULL);
-   
-   /* Open question file for exclusive access by this node. */
-   fpQuestionFile = ExclusiveFileOpen(QUESTION_FILENAME, "a+b",
-      &hQuestionFile);
-   if(fpQuestionFile == NULL)
-   {
-      od_printf("Unable to access the question file.\n\r");
-      WaitForEnter();
-      return;
-   }
-   
-   /* Determine number of records in question file. */
-   fseek(fpQuestionFile, 0, SEEK_END);
-   
-   /* If question file is full, display message and return to main menu */
-   /* after closing file.                                               */
-   if(ftell(fpQuestionFile) / sizeof(tQuestionRecord) >= MAX_QUESTIONS)
-   {
-      ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-      od_printf("Cannot add another question, Vote is limited to %d questions.\n\r", MAX_QUESTIONS);
-      WaitForEnter();
-      return;
-   }
-   
-   /* Add new question to file. */
-   if(fwrite(&QuestionRecord, sizeof(QuestionRecord), 1, fpQuestionFile) != 1)
-   {
-      ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-      od_printf("Unable to write to question file.\n\r");
-      WaitForEnter();
-      return;
-   }
-   
-   /* Close question file, allowing other nodes to access file. */
-   ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-
-   /* Record in the logfile that user has added a new question. */
-   sprintf(szLogMessage, "User adding questions: %s",
-      QuestionRecord.szQuestion);
-   od_log_write(szLogMessage);
-}
-
-
-/* The ChooseQuestion() function provides a list of questions and allows   */
-/* the user to choose a particular question, cancel back to the main menu, */ 
-/* and page up and down in the list of questions. Depending upon the value */
-/* of the nFromWhichQuestions parameter, this function will present a list */
-/* of questions that the user has voted on, a list of questions that the   */
-/* user has not voted on, or a list of all questions.                      */
-int ChooseQuestion(int nFromWhichQuestions, char *pszTitle, int *nLocation)
-{
-   int nCurrent;
-   int nFileQuestion = 0;
-   int nPagedToQuestion = *nLocation;
-   int nDisplayedQuestion = 0;
-   char bVotedOnQuestion;
-   char chCurrent;
-   tQuestionRecord QuestionRecord;
-   FILE *fpQuestionFile;
-   int hQuestionFile;
-   static char szQuestionName[MAX_QUESTIONS][QUESTION_STR_SIZE];
-   static int nQuestionNumber[MAX_QUESTIONS];
-   
-   /* Attempt to open question file. */
-   fpQuestionFile = ExclusiveFileOpen(QUESTION_FILENAME, "r+b",
-      &hQuestionFile);
-
-   /* If unable to open question file, assume that no questions have been */
-   /* created.                                                            */
-   if(fpQuestionFile == NULL)
-   {
-      /* Display "no questions yet" message. */
-      od_printf("\n\rNo questions have been created so far.\n\r");
-      
-      /* Wait for user to press enter. */
-      WaitForEnter();
-      
-      /* Indicate that no question has been chosen. */
-      return(NO_QUESTION);
-   }
-   
-   /* Loop for every question record in the file. */
-   while(fread(&QuestionRecord, sizeof(QuestionRecord), 1, fpQuestionFile) == 1)
-   {
-      /* Determine whether or not the user has voted on this question. */
-      bVotedOnQuestion = CurrentUserRecord.bVotedOnQuestion[nFileQuestion];
-      
-      /* If this is the kind of question that the user is choosing from */
-      /* right now.                                                     */
-      if((bVotedOnQuestion && (nFromWhichQuestions & QUESTIONS_VOTED_ON)) ||
-         (!bVotedOnQuestion && (nFromWhichQuestions & QUESTIONS_NOT_VOTED_ON)))
-      {
-         /* Add this question to list to be displayed. */
-         strcpy(szQuestionName[nDisplayedQuestion],
-            QuestionRecord.szQuestion);
-         nQuestionNumber[nDisplayedQuestion] = nFileQuestion;
-         
-         /* Add one to number of questions to be displayed in list. */
-         nDisplayedQuestion++;
-      }
-      
-      /* Move to next question in file. */
-      ++nFileQuestion;
-   }   
-   
-   /* Close question file to allow other nodes to access the file. */
-   ExclusiveFileClose(fpQuestionFile, hQuestionFile);
-
-   /* If there are no questions for the user to choose, display an */
-   /* appropriate message and return. */
-   if(nDisplayedQuestion == 0)
-   {
-      /* If we were to list all questions. */
-      if((nFromWhichQuestions & QUESTIONS_VOTED_ON)
-         && (nFromWhichQuestions & QUESTIONS_NOT_VOTED_ON))
-      {
-         od_printf("\n\rThere are no questions.\n\r");
-      }
-      /* If we were to list questions that the user has voted on. */
-      else if(nFromWhichQuestions & QUESTIONS_VOTED_ON)
-      {
-         od_printf("\n\rThere are no questions that you have voted on.\n\r");
-      }
-      /* Otherwise, we were to list questions that use has not voted on. */
-      else
-      {
-         od_printf("\n\rYou have voted on all the questions.\n\r");
-      }
-      
-      /* Wait for user to press enter key. */
-      WaitForEnter();
-      
-      /* Return, indicating that no question was chosen. */
-      return(NO_QUESTION);
-   }
-
-   /* Ensure that initial paged to location is within range. */
-   while(nPagedToQuestion >= nDisplayedQuestion)
-   {
-      nPagedToQuestion -= QUESTION_PAGE_SIZE;
-   }
-
-   /* Loop, displaying current page of questions, until the user makes a */
-   /* choice.                                                            */
-   for(;;)
-   {
-      /* Clear the screen. */
-      od_clr_scr();
-
-      /* Display header. */
-      od_printf("`bright red`");
-      od_printf(pszTitle);
-      od_printf("`dark red`");
-      if(od_control.user_ansi || od_control.user_avatar)
-      {
-         od_repeat((unsigned char)196, 79);
-      }
-      else
-      {
-         od_repeat('-', 79);
-      }
-      od_printf("\n\r");
-   
-      /* Display list of questions on this page. */
-      for(nCurrent = 0;
-         nCurrent < QUESTION_PAGE_SIZE
-         && nCurrent < (nDisplayedQuestion - nPagedToQuestion);
-         ++nCurrent)
-      {
-         /* Determine character to display for current line. */
-         if(nCurrent < 9)
-         {
-            chCurrent = (char)('1' + nCurrent);
-         }
-         else
-         {
-            chCurrent = (char)('A' + (nCurrent - 9));
-         }
-      
-         /* Display this question's title. */
-         od_printf("`bright green`%c.`dark green`", chCurrent);
-         od_printf(" %s\n\r", szQuestionName[nCurrent + nPagedToQuestion]);
-      }
-
-      /* Display prompt for input. */
-      od_printf("\n\r`bright white`[Page %d]  Choose a question or",
-         (nPagedToQuestion / QUESTION_PAGE_SIZE) + 1);
-      if(nPagedToQuestion < nDisplayedQuestion - QUESTION_PAGE_SIZE)
-      {
-         od_printf(" [N]ext page,");
-      }
-      if(nPagedToQuestion > 0)
-      {
-         od_printf(" [P]revious page,");
-      }
-      od_printf(" [Q]uit.\n\r");
-      
-      /* Loop until the user makes a valid choice. */
-      for(;;)
-      {      
-         /* Get input from user */
-         chCurrent = (char)od_get_key(TRUE);
-         chCurrent = (char)toupper(chCurrent);
-      
-         /* Respond to user's input. */
-      
-         /* If user pressed Q key. */
-         if(chCurrent == 'Q')
-         {
-            /* Return without a choosing a question. */
-            return(NO_QUESTION);
-         }
-      
-         /* If user pressed P key. */
-         else if(chCurrent == 'P')
-         {
-            /* If we are not at the first page. */
-            if(nPagedToQuestion > 0)
-            {
-               /* Move paged to location up one page. */
-               nPagedToQuestion -= QUESTION_PAGE_SIZE;
-               
-               /* Exit user input loop to display next page. */
-               break;
-            }
-         }
-      
-         /* If user pressed N key. */
-         else if(chCurrent == 'N')
-         {
-            /* If there is more questions after this page. */
-            if(nPagedToQuestion < nDisplayedQuestion - QUESTION_PAGE_SIZE)
-            {
-               /* Move paged.to location down one page. */
-               nPagedToQuestion += QUESTION_PAGE_SIZE;
-
-               /* Exit user input loop to display next page. */
-               break;
-            }
-         }
-      
-         /* Otherwise, check whether the user chose a valid question. */
-         else if ((chCurrent >= '1' && chCurrent <= '9')
-            || (chCurrent >= 'A' && chCurrent <= 'H'))
-         {
-            /* Get question number from key pressed. */
-            if(chCurrent >= '1' && chCurrent <= '9')
-            {
-               nCurrent = chCurrent - '1';
-            }
-            else
-            {
-               nCurrent = (chCurrent - 'A') + 9;
-            }
-         
-            /* Add current paged to position to user's choice. */
-            nCurrent += nPagedToQuestion;
-
-            /* If this is valid question number. */            
-            if(nCurrent < nDisplayedQuestion)
-            {
-               /* Set caller's current question number. */
-               *nLocation = nPagedToQuestion;
-            
-               /* Return actual question number in file. */
-               return(nQuestionNumber[nCurrent]);
-            }
-         }
-      }
-   }
-}
-
-
-/* The DisplayQuestionResult() function is called to display the results */
-/* of voting on a paricular question, and is passed the question record  */
-/* of the question. This function is called when the user selects a      */
-/* question using the "view results" option, and is also called after    */
-/* the user has voted on a question, to display the results of voting on */
-/* that question.                                                        */
-void DisplayQuestionResult(tQuestionRecord *pQuestionRecord)
-{
-   int nAnswer;
-   int uPercent;
-
-   /* Clear the screen. */
-   od_clr_scr();
-
-   /* Check that there have been votes on this question. */
-   if(pQuestionRecord->uTotalVotes == 0)
-   {
-      /* If there have been no votes for this question, display a message */
-      /* and return.                                                      */
-      od_printf("Nobody has voted on this question yet.\n\r");
-      WaitForEnter();
-      return;
-   }
-
-   /* Display question itself. */
-   od_printf("`bright red`%s\n\r", pQuestionRecord->szQuestion);
-
-   /* Display author's name. */
-   od_printf("`dark red`Question created by %s on %s\n\r",
-      pQuestionRecord->szCreatorName,
-      ctime(&pQuestionRecord->lCreationTime));
-   
-   /* Display heading for responses. */
-   od_printf("`bright green`Response                        Votes  Percent  Graph\n\r`dark green`");
-   if(od_control.user_ansi || od_control.user_avatar)
-   {
-      od_repeat((unsigned char)196, 79);
-   }
-   else
-   {
-      od_repeat('-', 79);
-   }
-   od_printf("\n\r");
-
-   /* Loop for each answer to the question. */   
-   for(nAnswer = 0; nAnswer < pQuestionRecord->nTotalAnswers; ++nAnswer)
-   {
-      /* Determine percent of users who voted for this answer. */
-      uPercent = (pQuestionRecord->auVotesForAnswer[nAnswer] * 100)
-         / pQuestionRecord->uTotalVotes;
-      
-      /* Display answer, total votes and percentage of votes. */
-      od_printf("`dark green`%-30.30s  %-5u  %3u%%     `bright white`",
-         pQuestionRecord->aszAnswer[nAnswer],
-         pQuestionRecord->auVotesForAnswer[nAnswer],
-         uPercent);
-
-      /* Display a bar graph corresponding to percent of users who voted */
-      /* for this answer.                                                */
-      if(od_control.user_ansi || od_control.user_avatar)
-      {
-         od_repeat((unsigned char)220, (unsigned char)((uPercent * 31) / 100));
-      }
-      else
-      {
-         od_repeat('=', (unsigned char)((uPercent * 31) / 100));
-      }
-
-      /* Move to next line. */
-      od_printf("\n\r");
-   }
-   
-   /* Display footer. */
-   od_printf("`dark green`");
-   if(od_control.user_ansi || od_control.user_avatar)
-   {
-      od_repeat((unsigned char)196, 79);
-   }
-   else
-   {
-      od_repeat('-', 79);
-   }
-   od_printf("\n\r");
-   od_printf("`dark green`                         TOTAL: %u\n\r\n\r",
-      pQuestionRecord->uTotalVotes);
-   
-   /* Wait for user to press enter. */
-   WaitForEnter();
-}
-
-
-/* The ReadOrAddCurrentUser() function is used by Vote to search the      */
-/* Vote user file for the record containing information on the user who   */
-/* is currently using the door. If this is the first time that the user   */
-/* has used this door, then their record will not exist in the user file. */
-/* In this case, this function will add a new record for the current      */
-/* user. This function returns TRUE on success, or FALSE on failure.      */
-int ReadOrAddCurrentUser(void)
-{
-   FILE *fpUserFile;
-   int hUserFile;
-   int bGotUser = FALSE;
-   int nQuestion;
-
-   /* Attempt to open the user file for exclusize access by this node.     */
-   /* This function will wait up to the pre-set amount of time (as defined */   
-   /* near the beginning of this file) for access to the user file.        */
-   fpUserFile = ExclusiveFileOpen(USER_FILENAME, "a+b", &hUserFile);
-
-   /* If unable to open user file, return with failure. */   
-   if(fpUserFile == NULL)
-   {
-      return(FALSE);
-   }
-
-   /* Begin with the current user record number set to 0. */
-   nCurrentUserNumber = 0;
-
-   /* Loop for each record in the file */
-   while(fread(&CurrentUserRecord, sizeof(tUserRecord), 1, fpUserFile) == 1)
-   {
-      /* If name in record matches the current user name ... */
-      if(strcmp(CurrentUserRecord.szUserName, od_control.user_name) == 0)
-      {
-         /* ... then record that we have found the user's record, */
-         bGotUser = TRUE;
-         
-         /* and exit the loop. */
-         break;
-      }
-
-      /* Move user record number to next user record. */      
-      nCurrentUserNumber++;
-   }
-
-   /* If the user was not found in the file, attempt to add them as a */
-   /* new user if the user file is not already full.                  */
-   if(!bGotUser && nCurrentUserNumber < MAX_USERS)
-   {
-      /* Place the user's name in the current user record. */
-      strcpy(CurrentUserRecord.szUserName, od_control.user_name);
-      
-      /* Record that user hasn't voted on any of the questions. */
-      for(nQuestion = 0; nQuestion < MAX_QUESTIONS; ++nQuestion)
-      {
-         CurrentUserRecord.bVotedOnQuestion[nQuestion] = FALSE;
-      }
-      
-      /* Write the new record to the file. */
-      if(fwrite(&CurrentUserRecord, sizeof(tUserRecord), 1, fpUserFile) == 1)
-      {
-         /* If write succeeded, record that we now have a valid user record. */
-         bGotUser = TRUE;
-      }
-   }
-
-   /* Close the user file to allow other nodes to access it. */
-   ExclusiveFileClose(fpUserFile, hUserFile);
-
-   /* Return, indciating whether or not a valid user record now exists for */
-   /* the user that is currently online.                                   */   
-   return(bGotUser);
-}
-
-
-/* The WriteCurrentUser() function is called to save the information on the */
-/* user who is currently using the door, to the VOTE.USR file.              */
-void WriteCurrentUser(void)
-{
-   FILE *fpUserFile;
-   int hUserFile;
-
-   /* Attempt to open the user file for exclusize access by this node.     */
-   /* This function will wait up to the pre-set amount of time (as defined */   
-   /* near the beginning of this file) for access to the user file.        */
-   fpUserFile = ExclusiveFileOpen(USER_FILENAME, "r+b", &hUserFile);
-
-   /* If unable to access the user file, display an error message and */
-   /* return.                                                         */
-   if(fpUserFile == NULL)
-   {
-      od_printf("Unable to access the user file.\n\r");
-      WaitForEnter();
-      return;
-   }
-   
-   /* Move to appropriate location in user file for the current user's */
-   /* record. */
-   fseek(fpUserFile, (long)nCurrentUserNumber * sizeof(tUserRecord), SEEK_SET);
-
-   /* Write the new record to the file. */
-   if(fwrite(&CurrentUserRecord, sizeof(tUserRecord), 1, fpUserFile) == 1)
-   {
-      /* If unable to write the record, display an error message. */
-      ExclusiveFileClose(fpUserFile, hUserFile);
-      od_printf("Unable to update your user record file.\n\r");
-      WaitForEnter();
-      return;
-   }
-   
-   /* Close the user file to allow other nodes to access it again. */
-   ExclusiveFileClose(fpUserFile, hUserFile);
-}
-
-
-/* This function is used by Vote to open a file. If Vote has been compiled */
-/* with #define MULTINODE_AWARE uncommented (see the beginning of this     */
-/* file), file access is performed in a multinode-aware way. This implies  */
-/* that the file is opened of exclusive access, using share-aware open     */
-/* functions that may not be available using all compilers.                */
-FILE *ExclusiveFileOpen(char *pszFileName, char *pszMode, int *phHandle)
-{
-#ifdef MULTINODE_AWARE
-   /* If Vote is being compiled for multinode-aware file access, then   */
-   /* attempt to use compiler-specific share-aware file open functions. */
-   FILE *fpFile = NULL;
-   time_t StartTime = time(NULL);
-   int hFile;
-
-   /* Attempt to open the file while there is still time remaining. */    
-   while((hFile = sopen(pszFileName, O_BINARY | O_RDWR, SH_DENYRW,
-      S_IREAD | S_IWRITE)) == -1)
-   {
-      /* If we have been unable to open the file for more than the */
-      /* maximum wait time, or if open failed for a reason other   */
-      /* than file access, then attempt to create a new file and   */
-      /* exit the loop.                                            */
-      if(errno != EACCES ||
-         difftime(time(NULL), StartTime) >= FILE_ACCESS_MAX_WAIT)
-      {
-         hFile = sopen(pszFileName, O_BINARY | O_CREAT, SH_DENYRW,
-            S_IREAD | S_IWRITE);
-         break;
-      }
-
-      /* If we were unable to open the file, call od_kernel, so that    */
-      /* OpenDoors can continue to respond to sysop function keys, loss */
-      /* of connection, etc.                                            */
-      od_kernel();
-   }
-
-   /* Attempt to obtain a FILE * corresponding to the handle. */
-   if(hFile != -1)
-   {
-      fpFile = fdopen(hFile, pszMode);
-      if(fpFile == NULL)
-      {
-         close(hFile);
-      }
-   }
-
-   /* Pass file handle back to the caller. */
-   *phHandle = hFile;
-
-   /* Return FILE pointer for opened file, if any. */   
-   return(fpFile);
-#else
-   /* Ignore unused parameters. */
-   (void)phHandle;
-
-   /* If Vote is not being compiled for multinode-aware mode, then just */
-   /* use fopen to access the file.                                     */
-   return(fopen(pszFileName, pszMode));
-#endif
-}
-
-
-/* The ExclusiveFileClose() function closes a file that was opened using */
-/* ExclusiveFileOpen().                                                  */
-void ExclusiveFileClose(FILE *pfFile, int hHandle)
-{
-   fclose(pfFile);
-#ifdef MULTINODE_AWARE
-   close(hHandle);
-#else
-   /* Ignore unused parameters. */
-   (void)hHandle;
-#endif
-}
-
-
-/* The WaitForEnter() function is used by Vote to create its custom   */
-/* "Press [ENTER] to continue." prompt.                               */
-void WaitForEnter(void)
-{
-   /* Display prompt. */
-   od_printf("`bright white`Press [ENTER] to continue.\n\r");
-   
-   /* Wait for a Carriage Return or Line Feed character from the user. */
-   od_get_answer("\n\r");
-}
diff --git a/src/odoors/hbuild.bat b/src/odoors/hbuild.bat
deleted file mode 100755
index 8d76e20e6a6d58d38c6ad5a4dc43448b297ac506..0000000000000000000000000000000000000000
--- a/src/odoors/hbuild.bat
+++ /dev/null
@@ -1 +0,0 @@
-make -fDOS.mak -DTARGET=h > out.txt
diff --git a/src/odoors/lbuild.bat b/src/odoors/lbuild.bat
deleted file mode 100755
index 7249ff858ee0c8ccbcceed28a70daf3759c61491..0000000000000000000000000000000000000000
--- a/src/odoors/lbuild.bat
+++ /dev/null
@@ -1 +0,0 @@
-make -fDOS.mak -DTARGET=l > out.txt
diff --git a/src/odoors/license.txt b/src/odoors/license.txt
deleted file mode 100644
index 5615459b64888409068550b919035cdd03eaeb12..0000000000000000000000000000000000000000
--- a/src/odoors/license.txt
+++ /dev/null
@@ -1,459 +0,0 @@
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
diff --git a/src/odoors/sbuild.bat b/src/odoors/sbuild.bat
deleted file mode 100755
index da4e6d91602ab7e25d1cd10c522e5c91fbcd4894..0000000000000000000000000000000000000000
--- a/src/odoors/sbuild.bat
+++ /dev/null
@@ -1 +0,0 @@
-make -fDOS.mak -DTARGET=s > out.txt
diff --git a/src/odoors/wbuild.bat b/src/odoors/wbuild.bat
deleted file mode 100755
index 63c7d6d5f9f05f56323608979d8515b47e8aeec8..0000000000000000000000000000000000000000
--- a/src/odoors/wbuild.bat
+++ /dev/null
@@ -1 +0,0 @@
-nmake -fWin32.mak > out.txt
diff --git a/src/odoors/win32.mak b/src/odoors/win32.mak
deleted file mode 100644
index 9b5563fa5021c8703bbbf1171a346acc1673f8c4..0000000000000000000000000000000000000000
--- a/src/odoors/win32.mak
+++ /dev/null
@@ -1,372 +0,0 @@
-#  OpenDoors 6.20
-#  (C) Copyright 1991 - 1997 by Brian Pirie. All Rights Reserved.
-#
-#  Oct-2001 door32.sys/socket modifications by Rob Swindell (www.synchro.net)
-#
-#
-#         File: Win32.mak
-#
-#  Description: Makefile used to build the Win32 OpenDoors libraries from
-#               the sources. Usage is described below.
-#
-#    Revisions: Date          Ver   Who  Change
-#               ---------------------------------------------------------------
-#               Oct 13, 1994  6.00  BP   New file header format.
-#               Oct 13, 1994  6.00  BP   Made directories configurable.
-#               Oct 13, 1994  6.00  BP   Erase tlib-created backup file.
-#               Oct 14, 1994  6.00  BP   Added ODGen.h dependencies.
-#               Oct 14, 1994  6.00  BP   Added ODPlat.c module.
-#               Oct 31, 1994  6.00  BP   Added headers dependency constant.
-#               Nov 01, 1994  6.00  BP   Added ODUtil.c module.
-#               Dec 31, 1994  6.00  BP   Added -B option for Borland Cs.
-#               Jan 01, 1995  6.00  BP   Added ODKrnl.c, ODKrnl.h.
-#               Jan 29, 1995  6.00  BP   Added ODCmdLn.c.
-#               Nov 16, 1995  6.00  BP   Added ODInQue.c, and new headers.
-#               Nov 21, 1995  6.00  BP   Created ODInit1.c, ODInit2.c.
-#               Dec 02, 1995  6.00  BP   Added ODRes.h
-#               Dec 02, 1995  6.00  BP   Added ODFrame.c, ODFrame.h.
-#               Dec 02, 1995  6.00  BP   Added ODStat.h, ODSwap.h.
-#               Dec 04, 1995  6.00  BP   Changes for building Win32 version.
-#               Dec 05, 1995  6.00  BP   Split into makefiles for each platform
-#               Dec 07, 1995  6.00  BP   Added ODEdit.c.
-#               Dec 21, 1995  6.00  BP   Changes for building as DLL.
-#               Jan 04, 1996  6.00  BP   Added ODGetIn.c.
-#               Feb 09, 1996  6.00  BP   Renamed ODInit?.* to ODInEx?.*
-#               Feb 19, 1996  6.00  BP   Turned off OD_DEBUG
-#               Feb 19, 1996  6.00  BP   Changed version number to 6.00.
-#               Mar 03, 1996  6.10  BP   Begin version 6.10.
-#               Oct 19, 2001  6.20  RS   Added door32.sys and socket support.
-#
-###############################################################################
-#
-# USAGE INFORMATION
-#
-###############################################################################
-#
-# Command Line:   make -fWin32.mak
-#                     or
-#                 nmake /f Win32.mak
-#
-###############################################################################
-#
-# CONFIGURATION
-#
-# Customize this section of the makefile to provide the relevant information
-# for your compiler, assembler (if any) and build environment.
-#
-###############################################################################
-# Compiler executable file name. Use:
-#
-#                  tcc - For Borland Turbo C and Turbo C++
-#                  bcc - For Borland C++
-#                   cl - For Microsoft compilers
-#
-CC=cl
-#
-#------------------------------------------------------------------------------
-#
-# Linker executable file name. Use:
-#
-#                tlink - For Borland compilers
-#                 link - For Microsoft compilers
-#
-LINK=link
-#
-#------------------------------------------------------------------------------
-#
-# Resource compiler exectuable file name.
-#
-RC=rc
-#
-#------------------------------------------------------------------------------
-#
-# Win32 compiler command-line flags. Use:
-#
-# /c /W3 /D "WIN32" /D "_WINDOWS"  - For Microsoft compilers
-#
-CFLAGS=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "_WINDOWS" /c
-# /MTd /Zi - for debug
-#
-#------------------------------------------------------------------------------
-#
-# Link flags.
-#
-LINKFLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib\
-          uuid.lib comctl32.lib /NOLOGO /DLL /INCREMENTAL:no\
-	  /MAP\
-#          /DEBUG\
-          /MACHINE:I386\
-          /DEF:$(SOURCEDIR)"OpenDoor.def" /OUT:$(LIBDIR)"ODoors62.dll"\
-          /IMPLIB:$(LIBDIR)"ODoorW.lib" /SUBSYSTEM:windows,4.0
-#
-#------------------------------------------------------------------------------
-#
-# Output directories. customize for your own preferences. Note that trailing
-# backslash (\) characters are required.
-#
-SOURCEDIR=.\                                               # Comments required
-ODHEADERDIR=.\                                             # in order to
-OBJDIR=.\ 	# was ..\obj                               # avoid line
-LIBDIR=.\       # was ..\lib                          	   # concatentation
-#
-###############################################################################
-#
-# DEPENDENCIES
-#
-# You won't normally have to change anything after this point in this makefile.
-#
-###############################################################################
-#
-# Define primary target.
-#
-TARGET=w
-all: $(LIBDIR)ODoors62.dll
-#
-#------------------------------------------------------------------------------
-#
-# Name of all headers.
-#
-HEADERS= $(HEADERDIR)ODCom.h\
-         $(HEADERDIR)ODCore.h\
-         $(HEADERDIR)ODFrame.h\
-         $(HEADERDIR)ODGen.h\
-         $(HEADERDIR)ODInEx.h\
-         $(HEADERDIR)ODInQue.h\
-         $(HEADERDIR)ODKrnl.h\
-         $(HEADERDIR)ODPlat.h\
-         $(HEADERDIR)ODRes.h\
-         $(HEADERDIR)ODScrn.h\
-         $(HEADERDIR)ODStat.h\
-         $(HEADERDIR)ODSwap.h\
-         $(HEADERDIR)ODTypes.h\
-         $(HEADERDIR)ODUtil.h\
-         $(HEADERDIR)OpenDoor.h
-#
-#------------------------------------------------------------------------------
-#
-#
-DEF_FILE=$(SOURCEDIR)OpenDoor.def
-#
-#------------------------------------------------------------------------------
-#
-# Build from C sources.
-#
-$(OBJDIR)odauto$(TARGET).obj : $(SOURCEDIR)odauto.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odauto.c
-   command /c erase $(OBJDIR)odauto$(TARGET).obj
-   move odauto.obj $(OBJDIR)odauto$(TARGET).obj
-
-$(OBJDIR)odblock$(TARGET).obj : $(SOURCEDIR)odblock.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odblock.c
-   command /c erase $(OBJDIR)odblock$(TARGET).obj
-   move odblock.obj $(OBJDIR)odblock$(TARGET).obj
-
-$(OBJDIR)odcfile$(TARGET).obj : $(SOURCEDIR)odcfile.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcfile.c
-   command /c erase $(OBJDIR)odcfile$(TARGET).obj
-   move odcfile.obj $(OBJDIR)odcfile$(TARGET).obj
-
-$(OBJDIR)odcmdln$(TARGET).obj : $(SOURCEDIR)odcmdln.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcmdln.c
-   command /c erase $(OBJDIR)odcmdln$(TARGET).obj
-   move odcmdln.obj $(OBJDIR)odcmdln$(TARGET).obj
-
-$(OBJDIR)odcom$(TARGET).obj : $(SOURCEDIR)odcom.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcom.c
-   command /c erase $(OBJDIR)odcom$(TARGET).obj
-   move odcom.obj $(OBJDIR)odcom$(TARGET).obj
-
-$(OBJDIR)odcore$(TARGET).obj : $(SOURCEDIR)odcore.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odcore.c
-   command /c erase $(OBJDIR)odcore$(TARGET).obj
-   move odcore.obj $(OBJDIR)odcore$(TARGET).obj
-
-$(OBJDIR)oddrbox$(TARGET).obj : $(SOURCEDIR)oddrbox.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)oddrbox.c
-   command /c erase $(OBJDIR)oddrbox$(TARGET).obj
-   move oddrbox.obj $(OBJDIR)oddrbox$(TARGET).obj
-
-$(OBJDIR)odedit$(TARGET).obj : $(SOURCEDIR)odedit.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odedit.c
-   command /c erase $(OBJDIR)odedit$(TARGET).obj
-   move odedit.obj $(OBJDIR)odedit$(TARGET).obj
-
-$(OBJDIR)odedstr$(TARGET).obj : $(SOURCEDIR)odedstr.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odedstr.c
-   command /c erase $(OBJDIR)odedstr$(TARGET).obj
-   move odedstr.obj $(OBJDIR)odedstr$(TARGET).obj
-
-$(OBJDIR)odemu$(TARGET).obj : $(SOURCEDIR)odemu.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odemu.c
-   command /c erase $(OBJDIR)odemu$(TARGET).obj
-   move odemu.obj $(OBJDIR)odemu$(TARGET).obj
-
-$(OBJDIR)odframe$(TARGET).obj : $(SOURCEDIR)odframe.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odframe.c
-   command /c erase $(OBJDIR)odframe$(TARGET).obj
-   move odframe.obj $(OBJDIR)odframe$(TARGET).obj
-
-$(OBJDIR)odgetin$(TARGET).obj : $(SOURCEDIR)odgetin.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odgetin.c
-   command /c erase $(OBJDIR)odgetin$(TARGET).obj
-   move odgetin.obj $(OBJDIR)odgetin$(TARGET).obj
-
-$(OBJDIR)odgraph$(TARGET).obj : $(SOURCEDIR)odgraph.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odgraph.c
-   command /c erase $(OBJDIR)odgraph$(TARGET).obj
-   move odgraph.obj $(OBJDIR)odgraph$(TARGET).obj
-
-$(OBJDIR)odinex1$(TARGET).obj : $(SOURCEDIR)odinex1.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinex1.c
-   command /c erase $(OBJDIR)odinex1$(TARGET).obj
-   move odinex1.obj $(OBJDIR)odinex1$(TARGET).obj
-
-$(OBJDIR)odinex2$(TARGET).obj : $(SOURCEDIR)odinex2.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinex2.c
-   command /c erase $(OBJDIR)odinex2$(TARGET).obj
-   move odinex2.obj $(OBJDIR)odinex2$(TARGET).obj
-
-$(OBJDIR)odinque$(TARGET).obj : $(SOURCEDIR)odinque.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odinque.c
-   command /c erase $(OBJDIR)odinque$(TARGET).obj
-   move odinque.obj $(OBJDIR)odinque$(TARGET).obj
-
-$(OBJDIR)odkrnl$(TARGET).obj : $(SOURCEDIR)odkrnl.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odkrnl.c
-   command /c erase $(OBJDIR)odkrnl$(TARGET).obj
-   move odkrnl.obj $(OBJDIR)odkrnl$(TARGET).obj
-
-$(OBJDIR)odlist$(TARGET).obj : $(SOURCEDIR)odlist.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odlist.c
-   command /c erase $(OBJDIR)odlist$(TARGET).obj
-   move odlist.obj $(OBJDIR)odlist$(TARGET).obj
-
-$(OBJDIR)odlog$(TARGET).obj : $(SOURCEDIR)odlog.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odlog.c
-   command /c erase $(OBJDIR)odlog$(TARGET).obj
-   move odlog.obj $(OBJDIR)odlog$(TARGET).obj
-
-$(OBJDIR)odmulti$(TARGET).obj : $(SOURCEDIR)odmulti.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odmulti.c
-   command /c erase $(OBJDIR)odmulti$(TARGET).obj
-   move odmulti.obj $(OBJDIR)odmulti$(TARGET).obj
-
-$(OBJDIR)odplat$(TARGET).obj : $(SOURCEDIR)odplat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odplat.c
-   command /c erase $(OBJDIR)odplat$(TARGET).obj
-   move odplat.obj $(OBJDIR)odplat$(TARGET).obj
-
-$(OBJDIR)odpcb$(TARGET).obj : $(SOURCEDIR)odpcb.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odpcb.c
-   command /c erase $(OBJDIR)odpcb$(TARGET).obj
-   move odpcb.obj $(OBJDIR)odpcb$(TARGET).obj
-
-$(OBJDIR)odpopup$(TARGET).obj : $(SOURCEDIR)odpopup.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odpopup.c
-   command /c erase $(OBJDIR)odpopup$(TARGET).obj
-   move odpopup.obj $(OBJDIR)odpopup$(TARGET).obj
-
-$(OBJDIR)odprntf$(TARGET).obj : $(SOURCEDIR)odprntf.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odprntf.c
-   command /c erase $(OBJDIR)odprntf$(TARGET).obj
-   move odprntf.obj $(OBJDIR)odprntf$(TARGET).obj
-
-$(OBJDIR)odra$(TARGET).obj : $(SOURCEDIR)odra.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odra.c
-   command /c erase $(OBJDIR)odra$(TARGET).obj
-   move odra.obj $(OBJDIR)odra$(TARGET).obj
-
-$(OBJDIR)odscrn$(TARGET).obj : $(SOURCEDIR)odscrn.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odscrn.c
-   command /c erase $(OBJDIR)odscrn$(TARGET).obj
-   move odscrn.obj $(OBJDIR)odscrn$(TARGET).obj
-
-$(OBJDIR)odspawn$(TARGET).obj : $(SOURCEDIR)odspawn.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odspawn.c
-   command /c erase $(OBJDIR)odspawn$(TARGET).obj
-   move odspawn.obj $(OBJDIR)odspawn$(TARGET).obj
-
-$(OBJDIR)odstand$(TARGET).obj : $(SOURCEDIR)odstand.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odstand.c
-   command /c erase $(OBJDIR)odstand$(TARGET).obj
-   move odstand.obj $(OBJDIR)odstand$(TARGET).obj
-
-$(OBJDIR)odstat$(TARGET).obj : $(SOURCEDIR)odstat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odstat.c
-   command /c erase $(OBJDIR)odstat$(TARGET).obj
-   move odstat.obj $(OBJDIR)odstat$(TARGET).obj
-
-# This file (odsys.c) wasn't included in 6.1.1 source <shrug>
-#$(OBJDIR)odsys$(TARGET).obj : $(SOURCEDIR)odsys.c $(HEADERS)
-#   $(CC) $(CFLAGS) $(SOURCEDIR)odsys.c
-#   command /c erase $(OBJDIR)odsys$(TARGET).obj
-#   move odsys.obj $(OBJDIR)odsys$(TARGET).obj
-
-$(OBJDIR)odutil$(TARGET).obj : $(SOURCEDIR)odutil.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odutil.c
-   command /c erase $(OBJDIR)odutil$(TARGET).obj
-   move odutil.obj $(OBJDIR)odutil$(TARGET).obj
-
-$(OBJDIR)odwcat$(TARGET).obj : $(SOURCEDIR)odwcat.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odwcat.c
-   command /c erase $(OBJDIR)odwcat$(TARGET).obj
-   move odwcat.obj $(OBJDIR)odwcat$(TARGET).obj
-
-$(OBJDIR)odwin$(TARGET).obj : $(SOURCEDIR)odwin.c $(HEADERS)
-   $(CC) $(CFLAGS) $(SOURCEDIR)odwin.c
-   command /c erase $(OBJDIR)odwin$(TARGET).obj
-   move odwin.obj $(OBJDIR)odwin$(TARGET).obj
-#
-#------------------------------------------------------------------------------
-#
-# Build from resource script.
-#
-$(OBJDIR)ODoor$(TARGET).res: $(SOURCEDIR)ODRes.rc
-   $(RC) $(SOURCEDIR)ODRes.rc
-   command /c erase $(LIBDIR)ODoor$(TARGET).res
-   move $(SOURCEDIR)ODRes.res $(OBJDIR)ODoor$(TARGET).res
-#
-#------------------------------------------------------------------------------
-#
-# Build DLL from objects.
-#
-OBJECTS= $(OBJDIR)odauto$(TARGET).obj\
-         $(OBJDIR)odblock$(TARGET).obj\
-         $(OBJDIR)odcfile$(TARGET).obj\
-         $(OBJDIR)odcmdln$(TARGET).obj\
-         $(OBJDIR)odcom$(TARGET).obj\
-         $(OBJDIR)odcore$(TARGET).obj\
-         $(OBJDIR)oddrbox$(TARGET).obj\
-         $(OBJDIR)odedit$(TARGET).obj\
-         $(OBJDIR)odedstr$(TARGET).obj\
-         $(OBJDIR)odemu$(TARGET).obj\
-         $(OBJDIR)odframe$(TARGET).obj\
-         $(OBJDIR)odgetin$(TARGET).obj\
-         $(OBJDIR)odgraph$(TARGET).obj\
-         $(OBJDIR)odinex1$(TARGET).obj\
-         $(OBJDIR)odinex2$(TARGET).obj\
-         $(OBJDIR)odinque$(TARGET).obj\
-         $(OBJDIR)odkrnl$(TARGET).obj\
-         $(OBJDIR)odlist$(TARGET).obj\
-         $(OBJDIR)odlog$(TARGET).obj\
-         $(OBJDIR)odmulti$(TARGET).obj\
-         $(OBJDIR)odplat$(TARGET).obj\
-         $(OBJDIR)odpcb$(TARGET).obj\
-         $(OBJDIR)odpopup$(TARGET).obj\
-         $(OBJDIR)odprntf$(TARGET).obj\
-         $(OBJDIR)odra$(TARGET).obj\
-         $(OBJDIR)odscrn$(TARGET).obj\
-         $(OBJDIR)odspawn$(TARGET).obj\
-         $(OBJDIR)odstand$(TARGET).obj\
-         $(OBJDIR)odstat$(TARGET).obj\
-#         $(OBJDIR)odsys$(TARGET).obj\	this file is missing
-         $(OBJDIR)odutil$(TARGET).obj\
-         $(OBJDIR)odwcat$(TARGET).obj\
-         $(OBJDIR)odwin$(TARGET).obj\
-         $(OBJDIR)ODoor$(TARGET).res
-$(LIBDIR)ODoors62.dll : $(DEF_FILE) $(OBJECTS)
-   $(LINK) @<<
-   $(LINKFLAGS) $(OBJECTS)
-<<
-#
-#------------------------------------------------------------------------------
diff --git a/src/sbbs2/addfiles/addfiles.c b/src/sbbs2/addfiles/addfiles.c
deleted file mode 100644
index 3a878b34617b05909230bd08ffbc901c16960c1a..0000000000000000000000000000000000000000
--- a/src/sbbs2/addfiles/addfiles.c
+++ /dev/null
@@ -1,1668 +0,0 @@
-/* ADDFILES.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Program to add files to a Synchronet file database */
-
-#include "sbbs.h"
-
-#define ADDFILES_VER "2.24"
-
-char tmp[256];
-char *crlf="\r\n";
-
-#ifdef __TURBOC__
-unsigned _stklen=16000;
-#else
-unsigned _stacksize=16000;
-#endif
-
-int cur_altpath=0;
-
-long files=0,removed=0,mode=0;
-
-#define DEL_LIST	(1L<<0)
-#define NO_EXTEND	(1L<<1)
-#define FILE_DATE	(1L<<2)
-#define TODAYS_DATE (1L<<3)
-#define FILE_ID 	(1L<<4)
-#define NO_UPDATE	(1L<<5)
-#define NO_NEWDATE	(1L<<6)
-#define ASCII_ONLY	(1L<<7)
-#define UL_STATS	(1L<<8)
-#define ULDATE_ONLY (1L<<9)
-#define KEEP_DESC	(1L<<10)
-#define AUTO_ADD	(1L<<11)
-#define SEARCH_DIR	(1L<<12)
-#define SYNC_LIST	(1L<<13)
-#define KEEP_SPACE	(1L<<14)
-
-#ifndef __FLAT__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char HUGE16 *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-
-/****************************************************************************/
-/* This function writes files that are potentially larger than 32767 bytes  */
-/* Up to one megabytes of data can be written with each call.				*/
-/****************************************************************************/
-long lwrite(int file, char HUGE16 *buf, long bytes)
-{
-
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(write(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(write(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-/****************************************************************************/
-/* Returns string for 2 digit hex+ numbers up to 575						*/
-/****************************************************************************/
-char *hexplus(uint num, char *str)
-{
-sprintf(str,"%03x",num);
-str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
-str[1]=str[2];
-str[2]=0;
-return(str);
-}
-
-
-/****************************************************************************/
-/* Places into 'strout', 'strin' starting at 'start' and ending at			*/
-/* 'start'+'length'   														*/
-/****************************************************************************/
-void putrec(char *strout,int start,int length,char *strin)
-{
-	int i=0,j;
-
-j=strlen(strin);
-while(i<j && i<length)
-	strout[start++]=strin[i++];
-while(i++<length)
-	strout[start++]=ETX;
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,_A_NORMAL,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the time/date of the file in 'filespec' in time_t (unix) format  */
-/****************************************************************************/
-long fdate(char *filespec)
-{
-	int 	file;
-	ushort	fd,ft;
-	struct	tm t;
-
-if((file=nopen(filespec,O_RDONLY))==-1)
-	return(0);
-_dos_getftime(file,&fd,&ft);
-close(file);
-memset(&t,0,sizeof(t));
-t.tm_year=((fd&0xfe00)>>9)+80;
-t.tm_mon=((fd&0x01e0)>>5)-1;
-t.tm_mday=fd&0x1f;
-t.tm_hour=(ft&0xf800)>>11;
-t.tm_min=(ft&0x07e0)>>5;
-t.tm_sec=(ft&0x001f)<<1;
-return(mktime(&t));
-}
-
-/*****************************************************************************/
-/* Returns command line generated from instr with %c replacments             */
-/*****************************************************************************/
-char *cmdstr(char *instr, char *fpath, char *fspec, char *outstr)
-{
-    static char cmd[128];
-    char str[256];
-    int i,j,len;
-
-len=strlen(instr);
-for(i=j=0;i<len && j<128;i++) {
-    if(instr[i]=='%') {
-        i++;
-        cmd[j]=0;
-        switch(toupper(instr[i])) {
-            case 'F':   /* File path */
-                strcat(cmd,fpath);
-                break;
-            case 'G':   /* Temp directory */
-                if(temp_dir[0]!='\\' && temp_dir[1]!=':')
-                    strcat(cmd,node_dir);
-                strcat(cmd,temp_dir);
-                break;
-            case 'N':   /* Node Directory (same as SBBSNODE environment var) */
-                strcat(cmd,node_dir);
-                break;
-            case 'S':   /* File Spec */
-                strcat(cmd,fspec);
-                break;
-            case '!':   /* EXEC Directory */
-                if(exec_dir[0]!='\\' && exec_dir[1]!=':')
-                    strcat(cmd,node_dir);
-                strcat(cmd,exec_dir);
-                break;
-            case '#':   /* Node number (same as SBBSNNUM environment var) */
-                sprintf(str,"%d",node_num);
-                strcat(cmd,str);
-                break;
-            case '%':   /* %% for percent sign */
-                strcat(cmd,"%");
-                break;
-            default:    /* unknown specification */
-                break; }
-        j=strlen(cmd); }
-    else
-        cmd[j++]=instr[i]; }
-cmd[j]=0;
-
-return(cmd);
-}
-
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct tm *t;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	t=gmtime(&unix);
-	sprintf(str,"%02u/%02u/%02u",t->tm_mon+1,t->tm_mday
-		,TM_YEAR(t->tm_year)); }
-return(str);
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(access&O_WRONLY) access|=O_RDWR; 	/* fdopen can't open WRONLY */
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&(O_RDONLY|O_RDWR))
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&(O_WRONLY|O_RDWR))
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-void allocfail(uint size)
-{
-lprintf("\7Error allocating %u bytes of memory.\r\n",size);
-bail(1);
-}
-
-void bail(int code)
-{
-exit(code);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,_A_NORMAL,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-	return(f.size);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Turns FILE.EXT into FILE    .EXT                                         */
-/* Called from upload                                                       */
-/****************************************************************************/
-char *padfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0;c<8;c++)
-    if(filename[c]=='.' || !filename[c]) break;
-    else str[c]=filename[c];
-d=c;
-if(filename[c]=='.') c++;
-while(d<8)
-    str[d++]=SP;
-str[d++]='.';
-while(d<12)
-    if(!filename[c]) break;
-    else str[d++]=filename[c++];
-while(d<12)
-    str[d++]=SP;
-str[d]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Turns FILE    .EXT into FILE.EXT                                         */
-/****************************************************************************/
-char *unpadfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0,d=0;c<strlen(filename);c++)
-    if(filename[c]!=SP) str[d++]=filename[c];
-str[d]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Checks  directory data file for 'filename' (must be padded). If found,   */
-/* it returns the 1, else returns 0.                                        */
-/* Called from upload and bulkupload                                        */
-/****************************************************************************/
-char findfile(uint dirnum, char *filename)
-{
-	char str[256],c,fname[128],HUGE16 *ixbbuf;
-    int file;
-    ulong length,l;
-
-strcpy(fname,filename);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) return(0);
-length=filelength(file);
-if(!length) {
-    close(file);
-    return(0); }
-if((ixbbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-	printf("ERR_ALLOC %s %lu\n",str,length);
-    return(0); }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-	FREE((char *)ixbbuf);
-    return(0); }
-close(file);
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        if(fname[c]!=ixbbuf[l+c]) break;
-    if(c==11) break; }
-FREE((char *)ixbbuf);
-if(l<length)
-    return(1);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Adds the data for struct filedat to the directory's data base.           */
-/* changes the .datoffset field only                                        */
-/****************************************************************************/
-char addfiledat(file_t *f)
-{
-	char str[256],fdat[F_LEN+1],fname[128],idx[128],c,HUGE16 *ixbbuf;
-    int i,file;
-    ulong length,l,uldate;
-
-/************************/
-/* Add data to DAT File */
-/************************/
-sprintf(str,"%s%s.DAT",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-	printf("ERROR opening %s\n",str);
-	return(0); }
-length=filelength(file);
-if(length==0L)
-    l=0L;
-else {
-    if(length%F_LEN) {
-        close(file);
-		printf("ERR_LEN %s %lu\n",str,length);
-		return(0); }
-    for(l=0;l<length;l+=F_LEN) {    /* Find empty slot */
-        lseek(file,l,SEEK_SET);
-        read(file,&c,1);
-        if(c==ETX) break; } }
-putrec(fdat,F_CDT,7,ultoa(f->cdt,tmp,10));
-putrec(fdat,F_CDT+7,2,crlf);
-putrec(fdat,F_DESC,LEN_FDESC,f->desc);
-putrec(fdat,F_DESC+LEN_FDESC,2,crlf);
-putrec(fdat,F_ULER,LEN_ALIAS+5,f->uler);
-putrec(fdat,F_ULER+LEN_ALIAS+5,2,crlf);
-putrec(fdat,F_TIMESDLED,5,ultoa(f->timesdled,tmp,10));
-putrec(fdat,F_TIMESDLED+5,2,crlf);
-putrec(fdat,F_OPENCOUNT,3,itoa(f->opencount,tmp,10));
-putrec(fdat,F_OPENCOUNT+3,2,crlf);
-fdat[F_MISC]=f->misc+SP;
-putrec(fdat,F_ALTPATH,2,hexplus(f->altpath,tmp));
-putrec(fdat,F_ALTPATH+2,2,crlf);
-f->datoffset=l;
-idx[0]=l&0xff;          /* Get offset within DAT file for IXB file */
-idx[1]=(l>>8)&0xff;
-idx[2]=(l>>16)&0xff;
-lseek(file,l,SEEK_SET);
-if(write(file,fdat,F_LEN)!=F_LEN) {
-    close(file);
-	return(0); }
-length=filelength(file);
-close(file);
-if(length%F_LEN)
-	printf("ERR_LEN %s %lu\n",str,length);
-
-/*******************************************/
-/* Update last upload date/time stamp file */
-/*******************************************/
-sprintf(str,"%s%s.DAB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-	printf("ERR_OPEN %s\r\n",str);
-else {
-	uldate=time(NULL);
-	write(file,&uldate,4);
-    close(file); }
-
-/************************/
-/* Add data to IXB File */
-/************************/
-strcpy(fname,f->name);
-for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[i]=fname[i+1];
-sprintf(str,"%s%s.IXB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-	printf("ERR_OPEN %s\n",str);
-	return(0); }
-length=filelength(file);
-if(length) {    /* IXB file isn't empty */
-    if(length%F_IXBSIZE) {
-        close(file);
-		printf("ERR_LEN %s %lu\n",str,length);
-		return(0); }
-	if((ixbbuf=(char *)MALLOC(length))==NULL) {
-        close(file);
-		printf("ERR_ALLOC %s %lu\n",str,length);
-		return(0); }
-	if(lread(file,ixbbuf,length)!=length) {
-        close(file);
-		printf("ERR_READ %s %lu\n",str,length);
-		FREE((char *)ixbbuf);
-		return(0); }
-/************************************************/
-/* Sort by Name or Date, Assending or Decending */
-/************************************************/
-    if(dir[f->dir]->sort==SORT_NAME_A || dir[f->dir]->sort==SORT_NAME_D) {
-        for(l=0;l<length;l+=F_IXBSIZE) {
-            for(i=0;i<12 && fname[i]==ixbbuf[l+i];i++);
-			if(i==12) { 	/* file already in directory index */
-                close(file);
-				printf("ERR_CHK %s\n",fname);
-				FREE((char *)ixbbuf);
-				return(0); }
-            if(dir[f->dir]->sort==SORT_NAME_A && fname[i]<ixbbuf[l+i])
-                break;
-            if(dir[f->dir]->sort==SORT_NAME_D && fname[i]>ixbbuf[l+i])
-                break; } }
-    else {  /* sort by date */
-        for(l=0;l<length;l+=F_IXBSIZE) {
-            uldate=(ixbbuf[l+15]|((long)ixbbuf[l+16]<<8)
-                |((long)ixbbuf[l+17]<<16)|((long)ixbbuf[l+18]<<24));
-            if(dir[f->dir]->sort==SORT_DATE_A && f->dateuled>uldate)
-                break;
-            if(dir[f->dir]->sort==SORT_DATE_D && f->dateuled<uldate)
-                break; } }
-    lseek(file,l,SEEK_SET);
-    if(write(file,fname,11)!=11) {  /* Write filename to IXB file */
-        close(file);
-		FREE((char *)ixbbuf);
-		return(0); }
-    if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
-        close(file);
-		FREE((char *)ixbbuf);
-		return(0); }
-    write(file,&f->dateuled,sizeof(time_t));
-    write(file,&f->datedled,4);              /* Write 0 for datedled */
-	if(lwrite(file,&ixbbuf[l],length-l)!=length-l) { /* Write rest of IXB */
-        close(file);
-		FREE((char *)ixbbuf);
-		return(0); }
-	FREE((char *)ixbbuf); }
-else {              /* IXB file is empty... No files */
-    if(write(file,fname,11)!=11) {  /* Write filename it IXB file */
-        close(file);
-		return(0); }
-    if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
-        close(file);
-		return(0); }
-    write(file,&f->dateuled,sizeof(time_t));
-    write(file,&f->datedled,4); }
-length=filelength(file);
-close(file);
-if(length%F_IXBSIZE)
-	printf("ERR_LEN %s %lu\n",str,length);
-return(1);
-}
-
-void putextdesc(uint dirnum, ulong datoffset, char *ext)
-{
-	char str[256],nulbuf[512];
-	int file;
-
-sprintf(str,"%s%s.EXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-	return;
-lseek(file,0L,SEEK_END);
-while(filelength(file)<(datoffset/F_LEN)*512L)
-    write(file,nulbuf,512);
-lseek(file,(datoffset/F_LEN)*512L,SEEK_SET);
-write(file,ext,512);
-close(file);
-}
-
-/****************************************************************************/
-/* Gets file data from dircode.IXB file										*/
-/* Need fields .name and .dir filled.                                       */
-/* only fills .offset, .dateuled, and .datedled                             */
-/****************************************************************************/
-void getfileixb(file_t *f)
-{
-	uchar HUGE16 *ixbbuf,str[256],fname[128];
-	int file;
-	ulong l,length;
-
-sprintf(str,"%s%s.IXB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-	return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-	close(file);
-	printf("ERR_LEN %s\n");
-	return; }
-if((ixbbuf=(uchar HUGE16 *)MALLOC(length))==NULL) {
-	close(file);
-	printf("ERR_ALLOC %s\n",str);
-	return; }
-if(lread(file,ixbbuf,length)!=length) {
-	close(file);
-	FREE((char *)ixbbuf);
-	printf("ERR_READ %s\n",str);
-	return; }
-close(file);
-strcpy(fname,f->name);
-for(l=8;l<12;l++)	/* Turn FILENAME.EXT into FILENAMEEXT */
-	fname[l]=fname[l+1];
-for(l=0;l<length;l+=F_IXBSIZE) {
-	sprintf(str,"%11.11s",ixbbuf+l);
-	if(!strcmp(str,fname))
-		break; }
-if(l>=length) {
-	printf("getfileixb: ERR_CHK %s\n",fname);
-	FREE((char *)ixbbuf);
-	return; }
-l+=11;
-f->datoffset=ixbbuf[l]|((long)ixbbuf[l+1]<<8)|((long)ixbbuf[l+2]<<16);
-f->dateuled=ixbbuf[l+3]|((long)ixbbuf[l+4]<<8)
-	|((long)ixbbuf[l+5]<<16)|((long)ixbbuf[l+6]<<24);
-f->datedled=ixbbuf[l+7]|((long)ixbbuf[l+8]<<8)
-	|((long)ixbbuf[l+9]<<16)|((long)ixbbuf[l+10]<<24);
-FREE((char *)ixbbuf);
-}
-
-/****************************************************************************/
-/* Puts filedata into DIR_code.DAT file                                     */
-/* Called from removefiles                                                  */
-/****************************************************************************/
-void putfiledat(file_t f)
-{
-    char buf[F_LEN+1],str[256];
-    int file;
-    long length;
-
-putrec(buf,F_CDT,7,ultoa(f.cdt,tmp,10));
-putrec(buf,F_CDT+7,2,crlf);
-putrec(buf,F_DESC,LEN_FDESC,f.desc);
-putrec(buf,F_DESC+LEN_FDESC,2,crlf);
-putrec(buf,F_ULER,LEN_ALIAS+5,f.uler);
-putrec(buf,F_ULER+LEN_ALIAS+5,2,crlf);
-putrec(buf,F_TIMESDLED,5,itoa(f.timesdled,tmp,10));
-putrec(buf,F_TIMESDLED+5,2,crlf);
-putrec(buf,F_OPENCOUNT,3,itoa(f.opencount,tmp,10));
-putrec(buf,F_OPENCOUNT+3,2,crlf);
-buf[F_MISC]=f.misc+SP;
-putrec(buf,F_ALTPATH,2,hexplus(f.altpath,tmp));
-putrec(buf,F_ALTPATH+2,2,crlf);
-sprintf(str,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-length=filelength(file);
-if(length%F_LEN) {
-    close(file);
-	printf("ERR_LEN %s\n",str);
-    return; }
-if(f.datoffset>length) {
-    close(file);
-	printf("ERR_LEN %s\n",str);
-    return; }
-lseek(file,f.datoffset,SEEK_SET);
-if(write(file,buf,F_LEN)!=F_LEN) {
-    close(file);
-	printf("ERR_WRITE %s\n",str);
-    return; }
-length=filelength(file);
-close(file);
-if(length%F_LEN)
-	printf("ERR_LEN %s\n",str);
-}
-
-/****************************************************************************/
-/* Update the upload date for the file 'f'                                  */
-/****************************************************************************/
-void update_uldate(file_t f)
-{
-	char str[256],fname[128];
-	int i,file;
-	long l,length;
-
-/*******************/
-/* Update IXB File */
-/*******************/
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDWR))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-    close(file);
-	printf("ERR_LEN %s\n",str);
-    return; }
-strcpy(fname,f.name);
-for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[i]=fname[i+1];
-for(l=0;l<length;l+=F_IXBSIZE) {
-    read(file,str,F_IXBSIZE);      /* Look for the filename in the IXB file */
-    str[11]=0;
-    if(!strcmp(fname,str)) break; }
-if(l>=length) {
-    close(file);
-	printf("ERR_CHK %s\n",f.name);
-    return; }
-lseek(file,l+14,SEEK_SET);
-write(file,&f.dateuled,4);	/* Write the current time stamp for datedled */
-close(file);
-
-/*******************************************/
-/* Update last upload date/time stamp file */
-/*******************************************/
-sprintf(str,"%s%s.DAB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-	printf("ERR_OPEN %s\r\n",str);
-else {
-	write(file,&f.dateuled,4);
-    close(file); }
-
-}
-
-
-void strip_ctrl(char *str)
-{
-	char tmp[1024];
-	int i,j,k;
-
-k=strlen(str);
-for(i=j=0;i<k;i++)
-	if(j && str[i]==SP && tmp[j-1]==SP && (mode&KEEP_SPACE))
-		tmp[j++]=str[i];
-	else if(j && str[i]<=SP && tmp[j-1]==SP)
-		continue;
-	else if(i && !isalnum(str[i]) && str[i]==str[i-1])
-		continue;
-	else if((uchar)str[i]>=SP)
-		tmp[j++]=str[i];
-	else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
-		tmp[j++]=SP;
-tmp[j]=0;
-strcpy(str,tmp);
-}
-
-
-void strip_exascii(char *str)
-{
-	char tmp[1024];
-	int i,j,k;
-
-k=strlen(str);
-for(i=j=0;i<k;i++)
-	if(!(str[i]&0x80))
-		tmp[j++]=str[i];
-tmp[j]=0;
-strcpy(str,tmp);
-}
-
-/****************************************************************************/
-/* Updates dstst.dab file													*/
-/****************************************************************************/
-void updatestats(ulong size)
-{
-    char str[256];
-    int i,file;
-	ulong l;
-
-sprintf(str,"%sDSTS.DAB",ctrl_dir);
-if((file=nopen(str,O_RDWR))==-1) {
-	printf("ERR_OPEN %s\n",str);
-	return; }
-lseek(file,20L,SEEK_SET);	/* Skip timestamp, logons and logons today */
-read(file,&l,4);			/* Uploads today		 */
-l++;
-lseek(file,-4L,SEEK_CUR);
-write(file,&l,4);
-read(file,&l,4);			/* Upload bytes today	 */
-l+=size;
-lseek(file,-4L,SEEK_CUR);
-write(file,&l,4);
-close(file);
-}
-
-void addlist(char *inpath, file_t f, char dskip, char sskip)
-{
-	uchar str[256],fname[256],listpath[256],filepath[256]
-		,curline[256],nextline[256],*p,exist,ext[1024],tmpext[513];
-	int i,file;
-	long l;
-	FILE *stream;
-	struct find_t ff;
-
-if(mode&SEARCH_DIR) {
-	strcpy(str,cur_altpath ? altpath[cur_altpath-1] : dir[f.dir]->path);
-	if(str[0]=='.') {
-		sprintf(tmp,"%s%s",node_dir,str);
-		strcpy(str,tmp); }
-	strcat(str,"*.*");
-	printf("Searching %s\n\n",str);
-	for(i=_dos_findfirst(str,0,&ff);!i;i=_dos_findnext(&ff)) {
-		strupr(ff.name);
-		sprintf(filepath,"%s%s",cur_altpath ? altpath[cur_altpath-1]
-            : dir[f.dir]->path,ff.name);
-        if(filepath[0]=='.') { /* relative path */
-            sprintf(tmp,"%s%s",node_dir,filepath);
-            strcpy(filepath,tmp); }
-		f.misc=0;
-		f.desc[0]=0;
-		f.cdt=flength(filepath);
-		padfname(ff.name,f.name);
-		printf("%s  %10lu  %s\n"
-			,f.name,f.cdt,unixtodstr(fdate(filepath),str));
-		exist=findfile(f.dir,f.name);
-		if(exist) {
-			if(mode&NO_UPDATE)
-				continue;
-			getfileixb(&f);
-			if(mode&ULDATE_ONLY) {
-				f.dateuled=time(NULL);
-				update_uldate(f);
-				continue; } }
-
-		if(mode&FILE_DATE) {		/* get the file date and put into desc */
-			unixtodstr(fdate(filepath),f.desc);
-			strcat(f.desc,"  "); }
-
-		if(mode&TODAYS_DATE) {		/* put today's date in desc */
-			unixtodstr(time(NULL),f.desc);
-			strcat(f.desc,"  "); }
-
-		if(mode&FILE_ID) {
-			for(i=0;i<total_fextrs;i++)
-				if(!stricmp(fextr[i]->ext,f.name+9))
-					break;
-			if(i<total_fextrs) {
-				sprintf(tmp,"%sFILE_ID.DIZ",temp_dir);
-				remove(tmp);
-				system(cmdstr(fextr[i]->cmd,filepath,"FILE_ID.DIZ",NULL));
-				if(!fexist(tmp)) {
-					sprintf(tmp,"%sDESC.SDI",temp_dir);
-					remove(tmp);
-					system(cmdstr(fextr[i]->cmd,filepath,"DESC.SDI",NULL)); }
-				if((file=nopen(tmp,O_RDONLY))!=-1) {
-					memset(ext,0,513);
-					read(file,ext,512);
-					for(i=512;i;i--)
-						if(ext[i-1]>SP)
-							break;
-					ext[i]=0;
-					if(mode&ASCII_ONLY)
-						strip_exascii(ext);
-					if(!(mode&KEEP_DESC)) {
-						sprintf(tmpext,"%.256s",ext);
-						strip_ctrl(tmpext);
-						for(i=0;tmpext[i];i++)
-							if(isalpha(tmpext[i]))
-								break;
-						sprintf(f.desc,"%.*s",LEN_FDESC,tmpext+i);
-						for(i=0;f.desc[i]>=SP && i<LEN_FDESC;i++)
-							;
-						f.desc[i]=0; }
-					close(file);
-					f.misc|=FM_EXTDESC; } } }
-
-		f.dateuled=time(NULL);
-		f.altpath=cur_altpath;
-		strip_ctrl(f.desc);
-		if(mode&ASCII_ONLY)
-			strip_exascii(f.desc);
-		if(exist) {
-			putfiledat(f);
-			if(!(mode&NO_NEWDATE))
-				update_uldate(f); }
-		else
-			addfiledat(&f);
-		if(f.misc&FM_EXTDESC) {
-			truncsp(ext);
-			putextdesc(f.dir,f.datoffset,ext); }
-
-		if(mode&UL_STATS)
-			updatestats(f.cdt);
-		files++; }
-#ifdef __WATCOMC__
-   _dos_findclose(&ff);
-#endif
-	return; }
-
-
-strcpy(listpath,inpath);
-if((stream=fnopen(&file,listpath,O_RDONLY))==NULL) {
-	sprintf(listpath,"%s%s",cur_altpath ? altpath[cur_altpath-1]
-			: dir[f.dir]->path,inpath);
-	if(listpath[0]=='.') { /* relative path */
-		sprintf(str,"%s%s",node_dir,listpath);
-		strcpy(listpath,str); }
-	if((stream=fnopen(&file,listpath,O_RDONLY))==NULL) {
-		printf("Can't open: %s\n"
-			   "        or: %s\n",inpath,listpath);
-		return; } }
-
-printf("Adding %s to %s %s\n\n"
-	,listpath,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-
-fgets(nextline,255,stream);
-while(!feof(stream) && !ferror(stream)) {
-	f.misc=0;
-	f.desc[0]=0;
-	strcpy(curline,nextline);
-	nextline[0]=0;
-	fgets(nextline,255,stream);
-	truncsp(curline);
-	if(curline[0]<=SP || (uchar)curline[0]>=0x7e)
-		continue;
-	printf("%s\n",curline);
-	strcpy(fname,curline);
-
-	p=strchr(fname,'.');
-	if(!p || p==fname || p>fname+8)    /* no dot or invalid dot location */
-		continue;
-	p=strchr(p,SP);
-	if(p) *p=0;
-	else				   /* no space after filename? */
-		continue;
-	strupr(fname);
-	strcpy(fname,unpadfname(fname,tmp));
-
-	padfname(fname,f.name);
-	if(strcspn(f.name,"\\/|<>+[]:=\";,")!=strlen(f.name))
-		continue;
-
-    for(i=0;i<12;i++)
-        if(f.name[i]<SP || (uchar)f.name[i]>0x7e)
-            break;
-
-	if(i<12)					/* Ctrl chars or EX-ASCII in filename? */
-		continue;
-	exist=findfile(f.dir,f.name);
-    if(exist) {
-        if(mode&NO_UPDATE)
-            continue;
-		getfileixb(&f);
-		if(mode&ULDATE_ONLY) {
-			f.dateuled=time(NULL);
-			update_uldate(f);
-			continue; } }
-
-	sprintf(filepath,"%s%s",cur_altpath ? altpath[cur_altpath-1]
-		: dir[f.dir]->path,fname);
-	if(filepath[0]=='.') { /* relative path */
-		sprintf(tmp,"%s%s",node_dir,filepath);
-		strcpy(filepath,tmp); }
-
-	if(mode&FILE_DATE) {		/* get the file date and put into desc */
-		l=fdate(filepath);
-		unixtodstr(l,f.desc);
-		strcat(f.desc,"  "); }
-
-	if(mode&TODAYS_DATE) {		/* put today's date in desc */
-		l=time(NULL);
-		unixtodstr(l,f.desc);
-		strcat(f.desc,"  "); }
-
-	if(dskip && strlen(curline)>=dskip) p=curline+dskip;
-	else {
-		p++;
-		while(*p==SP) p++; }
-	sprintf(tmp,"%.*s",LEN_FDESC-strlen(f.desc),p);
-	strcat(f.desc,tmp);
-
-	if(nextline[0]==SP || strlen(p)>LEN_FDESC) {	/* ext desc */
-		if(!(mode&NO_EXTEND)) {
-			memset(ext,0,513);
-			f.misc|=FM_EXTDESC;
-			sprintf(ext,"%s\r\n",p); }
-
-		if(nextline[0]==SP) {
-			strcpy(str,nextline);				   /* tack on to end of desc */
-			p=str+dskip;
-			i=LEN_FDESC-strlen(f.desc);
-			if(i>1) {
-				p[i-1]=0;
-				truncsp(p);
-				if(p[0]) {
-					strcat(f.desc," ");
-					strcat(f.desc,p); } } }
-
-		while(!feof(stream) && !ferror(stream) && strlen(ext)<512) {
-			if(nextline[0]!=SP)
-				break;
-			truncsp(nextline);
-			printf("%s\n",nextline);
-			if(!(mode&NO_EXTEND)) {
-				f.misc|=FM_EXTDESC;
-				p=nextline+dskip;
-				while(*p==SP) p++;
-				strcat(ext,p);
-				strcat(ext,"\r\n"); }
-			nextline[0]=0;
-			fgets(nextline,255,stream); } }
-
-
-	if(sskip) l=atol(fname+sskip);
-	else {
-		l=flength(filepath);
-		if(l<1L) {
-			printf("%s not found.\n",filepath);
-			continue; } }
-
-	if(mode&FILE_ID) {
-        for(i=0;i<total_fextrs;i++)
-            if(!stricmp(fextr[i]->ext,f.name+9))
-                break;
-        if(i<total_fextrs) {
-            sprintf(tmp,"%sFILE_ID.DIZ",temp_dir);
-            remove(tmp);
-			system(cmdstr(fextr[i]->cmd,filepath,"FILE_ID.DIZ",NULL));
-            if(!fexist(tmp)) {
-                sprintf(tmp,"%sDESC.SDI",temp_dir);
-                remove(tmp);
-				system(cmdstr(fextr[i]->cmd,filepath,"DESC.SDI",NULL)); }
-			if((file=nopen(tmp,O_RDONLY))!=-1) {
-				memset(ext,0,513);
-				read(file,ext,512);
-				for(i=512;i;i--)
-					if(ext[i-1]>SP)
-						break;
-				ext[i]=0;
-				if(mode&ASCII_ONLY)
-					strip_exascii(ext);
-				if(!(mode&KEEP_DESC)) {
-					sprintf(tmpext,"%.256s",ext);
-					strip_ctrl(tmpext);
-					for(i=0;tmpext[i];i++)
-						if(isalpha(tmpext[i]))
-							break;
-					sprintf(f.desc,"%.*s",LEN_FDESC,tmpext+i);
-					for(i=0;f.desc[i]>=SP && i<LEN_FDESC;i++)
-						;
-					f.desc[i]=0; }
-				close(file);
-				f.misc|=FM_EXTDESC; } } }
-
-	f.cdt=l;
-	f.dateuled=time(NULL);
-	f.altpath=cur_altpath;
-	strip_ctrl(f.desc);
-	if(mode&ASCII_ONLY)
-		strip_exascii(f.desc);
-	if(exist) {
-		putfiledat(f);
-		if(!(mode&NO_NEWDATE))
-			update_uldate(f); }
-	else
-		addfiledat(&f);
-	if(f.misc&FM_EXTDESC) {
-		truncsp(ext);
-		putextdesc(f.dir,f.datoffset,ext); }
-
-	if(mode&UL_STATS)
-		updatestats(l);
-	files++; }
-fclose(stream);
-if(mode&DEL_LIST && !(mode&SYNC_LIST)) {
-	printf("\nDeleting %s\n",listpath);
-	remove(listpath); }
-
-}
-
-/***********************/
-/* Hex-plus to integer */
-/***********************/
-uint hptoi(char *str)
-{
-	char tmp[128];
-	uint i;
-
-if(!str[1] || toupper(str[0])<='F')
-	return(strtol(str,0,16));
-strcpy(tmp,str);
-tmp[0]='F';
-i=strtol(tmp,0,16)+((toupper(str[0])-'F')*0x10);
-return(i);
-}
-
-/****************************************************************************/
-/* Places into 'strout' CR or ETX terminated string starting at             */
-/* 'start' and ending at 'start'+'length' or terminator from 'strin'        */
-/****************************************************************************/
-void getrec(char *strin,int start,int length,char *strout)
-{
-    int i=0,stop;
-
-stop=start+length;
-while(start<stop) {
-    if(strin[start]==ETX)
-        break;
-    strout[i++]=strin[start++]; }
-strout[i]=0;
-}
-
-
-/****************************************************************************/
-/* Gets filedata from dircode.DAT file										*/
-/* Need fields .name ,.dir and .offset to get other info    				*/
-/* Does not fill .dateuled or .datedled fields.                             */
-/****************************************************************************/
-void getfiledat(file_t *f)
-{
-	char buf[F_LEN+1],str[256];
-	int file;
-	long length;
-
-sprintf(str,"%s%s.DAT",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-	return; }
-length=filelength(file);
-if(f->datoffset>length) {
-	close(file);
-	printf("ERR_LEN %s %lu\n",str,length);
-	return; }
-if(length%F_LEN) {
-	close(file);
-	printf("ERR_LEN %s %lu\n",str,length);
-	return; }
-lseek(file,f->datoffset,SEEK_SET);
-if(read(file,buf,F_LEN)!=F_LEN) {
-    close(file);
-	printf("ERR_READ %s %lu\n",str,F_LEN);
-	return; }
-close(file);
-getrec(buf,F_ALTPATH,2,str);
-f->altpath=hptoi(str);
-getrec(buf,F_CDT,7,str);
-f->cdt=atol(str);
-f->timetodl=0;
-
-getrec(buf,F_DESC,LEN_FDESC,f->desc);
-getrec(buf,F_ULER,LEN_ALIAS,f->uler);
-getrec(buf,F_TIMESDLED,5,str);
-f->timesdled=atoi(str);
-getrec(buf,F_OPENCOUNT,3,str);
-f->opencount=atoi(str);
-if(buf[F_MISC]!=ETX)
-	f->misc=buf[F_MISC]-SP;
-else
-	f->misc=0;
-}
-
-/****************************************************************************/
-/* Removes any files in the user transfer index (XFER.IXT) that match the   */
-/* specifications of dest, or source user, or filename or any combination.  */
-/****************************************************************************/
-void rmuserxfers(int fromuser, int destuser, char *fname)
-{
-    char str[256],*ixtbuf;
-    int file;
-    long l,length;
-
-sprintf(str,"%sXFER.IXT",data_dir);
-if(!fexist(str))
-    return;
-if(!flength(str)) {
-    remove(str);
-    return; }
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-length=filelength(file);
-if((ixtbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-	printf("ERR_ALLOC %s\n",str,length);
-    return; }
-if(read(file,ixtbuf,length)!=length) {
-    close(file);
-	FREE(ixtbuf);
-	printf("ERR_READ %s %lu\n",str,length);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-	FREE(ixtbuf);
-	printf("ERR_OPEN %s\n",str);
-    return; }
-for(l=0;l<length;l+=24) {
-    if(fname!=NULL && fname[0]) {               /* fname specified */
-        if(!strncmp(ixtbuf+l+5,fname,12)) {     /* this is the file */
-            if(destuser && fromuser) {          /* both dest and from user */
-                if(atoi(ixtbuf+l)==destuser && atoi(ixtbuf+l+18)==fromuser)
-                    continue; }                 /* both match */
-            else if(fromuser) {                 /* from user */
-                if(atoi(ixtbuf+l+18)==fromuser) /* matches */
-                    continue; }
-            else if(destuser) {                 /* dest user */
-                if(atoi(ixtbuf+l)==destuser)    /* matches */
-                    continue; }
-            else continue; } }                  /* no users, so match */
-    else if(destuser && fromuser) {
-        if(atoi(ixtbuf+l+18)==fromuser && atoi(ixtbuf+l)==destuser)
-            continue; }
-    else if(destuser && atoi(ixtbuf+l)==destuser)
-        continue;
-    else if(fromuser && atoi(ixtbuf+l+18)==fromuser)
-        continue;
-    write(file,ixtbuf+l,24); }
-close(file);
-FREE(ixtbuf);
-}
-
-
-
-/****************************************************************************/
-/* Removes DAT and IXB entries for the file in the struct 'f'               */
-/****************************************************************************/
-void removefiledat(file_t f)
-{
-	char c,str[256],ixbname[12],HUGE16 *ixbbuf,fname[13];
-    int file;
-    ulong l,length;
-
-strcpy(fname,f.name);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-length=filelength(file);
-if(!length) {
-	close(file);
-	return; }
-if((ixbbuf=(char *)MALLOC(length))==0) {
-    close(file);
-	printf("ERR_ALLOC %s %lu\n",str,length);
-    return; }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-	printf("ERR_READ %s %lu\n",str,length);
-	FREE((char *)ixbbuf);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        ixbname[c]=ixbbuf[l+c];
-    ixbname[c]=0;
-    if(strcmp(ixbname,fname))
-		if(lwrite(file,&ixbbuf[l],F_IXBSIZE)!=F_IXBSIZE) {
-            close(file);
-			printf("ERR_WRITE %s %lu\n",str,F_IXBSIZE);
-			FREE((char *)ixbbuf);
-            return; } }
-FREE((char *)ixbbuf);
-close(file);
-sprintf(str,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-    return; }
-lseek(file,f.datoffset,SEEK_SET);
-c=ETX;          /* If first char of record is ETX, record is unused */
-if(write(file,&c,1)!=1) { /* So write a D_T on the first byte of the record */
-    close(file);
-	printf("ERR_WRITE %s 1",str);
-    return; }
-close(file);
-if(f.dir==user_dir)  /* remove file from index */
-    rmuserxfers(0,0,f.name);
-
-}
-
-
-void synclist(char *inpath, int dirnum)
-{
-	uchar str[1024],fname[256],listpath[256], HUGE16 *ixbbuf,*p;
-	int i,file,found;
-	long l,m,length;
-	FILE *stream;
-	file_t f;
-
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERR_OPEN %s\n",str);
-	return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-	close(file);
-	printf("ERR_LEN %s\n");
-	return; }
-if((ixbbuf=(uchar HUGE16 *)MALLOC(length))==NULL) {
-	close(file);
-	printf("ERR_ALLOC %s\n",str);
-	return; }
-if(lread(file,ixbbuf,length)!=length) {
-	close(file);
-	FREE((char *)ixbbuf);
-	printf("ERR_READ %s\n",str);
-	return; }
-close(file);
-
-strcpy(listpath,inpath);
-if((stream=fnopen(&file,listpath,O_RDONLY))==NULL) {
-	sprintf(listpath,"%s%s",cur_altpath ? altpath[cur_altpath-1]
-			: dir[dirnum]->path,inpath);
-	if(listpath[0]=='.') { /* relative path */
-		sprintf(str,"%s%s",node_dir,listpath);
-		strcpy(listpath,str); }
-	if((stream=fnopen(&file,listpath,O_RDONLY))==NULL) {
-		printf("Can't open: %s\n"
-			   "        or: %s\n",inpath,listpath);
-		return; } }
-
-printf("\nSynchronizing %s with %s %s\n\n"
-	,listpath,lib[dir[dirnum]->lib]->sname,dir[dirnum]->sname);
-
-for(l=0;l<length;l+=F_IXBSIZE) {
-	m=l;
-	for(i=0;i<12 && l<length;i++)
-		if(i==8)
-			str[i]='.';
-		else
-			str[i]=ixbbuf[m++]; 	/* Turns FILENAMEEXT into FILENAME.EXT */
-	str[i]=0;
-	unpadfname(str,fname);
-	rewind(stream);
-	found=0;
-	while(!found) {
-		if(!fgets(str,1000,stream))
-			break;
-		truncsp(str);
-		p=strchr(str,SP);
-		if(p) *p=0;
-		if(!stricmp(str,fname))
-			found=1; }
-	if(found)
-		continue;
-	padfname(fname,f.name);
-	printf("%s not found in list - ",f.name);
-	f.dir=dirnum;
-	f.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
-	getfiledat(&f);
-	if(f.opencount) {
-		printf("currently OPEN by %u users\n",f.opencount);
-		continue; }
-	removefiledat(f);
-	sprintf(str,"%s%s"
-		,f.altpath>0 && f.altpath<=altpaths ? altpath[f.altpath-1]
-		: dir[f.dir]->path,fname);
-	if(str[0]=='.') {
-		sprintf(tmp,"%s%s",node_dir,str);
-        strcpy(str,tmp); }
-	if(remove(str))
-		printf("Error removing %s\n",str);
-	removed++;
-	printf("Removed from database\n"); }
-
-if(mode&DEL_LIST) {
-	printf("\nDeleting %s\n",listpath);
-	remove(listpath); }
-}
-
-char *usage="\nusage: addfiles code [.alt_path] [/opts] [\"*user\"] +list "
-			 "[desc_off] [size_off]"
-	"\n   or: addfiles code [.alt_path] [/opts] [\"*user\"]  file "
-		"\"description\"\n"
-	"\navailable opts:"
-	"\n       a    import ASCII only (no extended ASCII)"
-	"\n       b    synchronize database with file list (use with caution)"
-	"\n       c    do not remove extra spaces from file description"
-	"\n       d    delete list after import"
-	"\n       e    do not import extended descriptions"
-	"\n       f    include file date in descriptions"
-	"\n       t    include today's date in descriptions"
-	"\n       i    include added files in upload statistics"
-	"\n       n    do not update information for existing files"
-	"\n       o    update upload date only for existing files"
-	"\n       u    do not update upload date for existing files"
-	"\n       z    check for and import FILE_ID.DIZ and DESC.SDI"
-	"\n       k    keep original short description (not DIZ)"
-	"\n       s    search directory for files (no file list)"
-	"\n"
-	"\nAuto-ADD:   use * in place of code for Auto-ADD of FILES.BBS"
-	"\n            use *filename to Auto-ADD a different filename"
-	"\n"
-	;
-
-/*********************/
-/* Entry point (duh) */
-/*********************/
-int main(int argc, char **argv)
-{
-	uchar str[256],str2[256],*p,exist,listgiven=0,namegiven=0,ext[513]
-		,auto_name[13]="FILES.BBS";
-	int i,j,k,file;
-	long l;
-	read_cfg_text_t txt;
-	file_t f;
-
-putenv("TZ=UCT0");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-fprintf(stderr,"\nADDFILES Version %s (%s) - Adds files to Synchronet "
-	"Filebase\n"
-	,ADDFILES_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-    ,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	);
-
-if(argc<2) {
-	printf(usage);
-	return(1); }
-
-p=getenv("SBBSNODE");
-if(p==NULL) {
-	printf("\nSBBSNODE environment variable not set.\n");
-	printf("\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-	exit(1); }
-
-putenv("TZ=UCT0");
-
-strcpy(node_dir,p);
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-txt.openerr="\7\nError opening %s for read.\n";
-txt.reading="\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\nError allocating %u bytes of memory\n";
-txt.error="\7\nERROR: Offset %lu in %s\r\n\n";
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str); }
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str); }
-if(temp_dir[1]!=':' && temp_dir[0]!='\\') {
-	strcpy(str,temp_dir);
-	sprintf(temp_dir,"%s%s",node_dir,str); }
-read_file_cfg(txt);
-printf("\n\n");
-
-if(argv[1][0]=='*') {
-	if(argv[1][1])
-		sprintf(auto_name,"%.12s",argv[1]+1);
-	mode|=AUTO_ADD;
-	i=0; }
-else {
-	for(i=0;i<total_dirs;i++)
-		if(!stricmp(dir[i]->code,argv[1]))
-			break;
-
-	if(i>=total_dirs) {
-		printf("Directory code '%s' not found.\n",argv[1]);
-		exit(1); } }
-
-memset(&f,0,sizeof(file_t));
-f.dir=i;
-strcpy(f.uler,"-> ADDFILES <-");
-
-for(j=2;j<argc;j++) {
-	if(argv[j][0]=='*')     /* set the uploader name */
-		sprintf(f.uler,"%.25s",argv[j]+1);
-	else if(argv[j][0]=='/') {      /* options */
-		for(i=1;i<strlen(argv[j]);i++)
-			switch(toupper(argv[j][i])) {
-				case 'A':
-					mode|=ASCII_ONLY;
-					break;
-				case 'B':
-					mode|=(SYNC_LIST|NO_UPDATE);
-					break;
-				case 'C':
-					mode|=KEEP_SPACE;
-					break;
-				case 'D':
-					mode|=DEL_LIST;
-					break;
-				case 'E':
-					mode|=NO_EXTEND;
-					break;
-				case 'I':
-					mode|=UL_STATS;
-					break;
-				case 'Z':
-					mode|=FILE_ID;
-					break;
-				case 'K':
-					mode|=KEEP_DESC;	 /* Don't use DIZ for short desc */
-					break;
-				case 'N':
-					mode|=NO_UPDATE;
-					break;
-				case 'O':
-					mode|=ULDATE_ONLY;
-					break;
-				case 'U':
-					mode|=NO_NEWDATE;
-					break;
-				case 'F':
-					mode|=FILE_DATE;
-					break;
-				case 'T':
-					mode|=TODAYS_DATE;
-					break;
-				case 'S':
-					mode|=SEARCH_DIR;
-					break;
-				default:
-					printf(usage);
-					return(1); } }
-	else if(argv[j][0]=='+') {      /* filelist - FILES.BBS */
-		listgiven=1;
-		if(isdigit(argv[j+1][0])) { /* skip x characters before description */
-			if(isdigit(argv[j+2][0])) { /* skip x characters before size */
-				addlist(argv[j]+1,f,atoi(argv[j+1]),atoi(argv[j+2]));
-				j+=2; }
-			else {
-				addlist(argv[j]+1,f,atoi(argv[j+1]),0);
-				j++; } }
-		else
-			addlist(argv[j]+1,f,0,0);
-		if(mode&SYNC_LIST)
-			synclist(argv[j]+1,f.dir); }
-	else if(argv[j][0]=='.') {      /* alternate file path */
-		cur_altpath=atoi(argv[j]+1);
-		if(cur_altpath>altpaths) {
-			printf("Invalid alternate path.\n");
-			exit(1); } }
-	else {
-		namegiven=1;
-		padfname(argv[j],f.name);
-		f.desc[0]=0;
-		strupr(f.name);
-		if(j+1==argc) {
-			printf("%s no description given.\n",f.name);
-			continue; }
-		sprintf(str,"%s%s",cur_altpath ? altpath[cur_altpath-1]
-			: dir[f.dir]->path,argv[j]);
-		if(str[0]=='.') {
-			sprintf(tmp,"%s%s",node_dir,str);
-			strcpy(str,tmp); }
-		if(mode&FILE_DATE)
-			sprintf(f.desc,"%s  ",unixtodstr(fdate(str),tmp));
-		if(mode&TODAYS_DATE)
-			sprintf(f.desc,"%s  ",unixtodstr(time(NULL),tmp));
-		sprintf(tmp,"%.*s",LEN_FDESC-strlen(f.desc),argv[++j]);
-		strcpy(f.desc,tmp);
-		l=flength(str);
-		if(l==-1) {
-			printf("%s not found.\n",str);
-			continue; }
-		exist=findfile(f.dir,f.name);
-		if(exist) {
-			if(mode&NO_UPDATE)
-				continue;
-			getfileixb(&f);
-			if(mode&ULDATE_ONLY) {
-				f.dateuled=time(NULL);
-				update_uldate(f);
-				continue; } }
-		f.cdt=l;
-		f.dateuled=time(NULL);
-		f.altpath=cur_altpath;
-		strip_ctrl(f.desc);
-		if(mode&ASCII_ONLY)
-			strip_exascii(f.desc);
-		printf("%s %7lu %s\n",f.name,f.cdt,f.desc);
-		if(mode&FILE_ID) {
-			for(i=0;i<total_fextrs;i++)
-				if(!stricmp(fextr[i]->ext,f.name+9))
-					break;
-			if(i<total_fextrs) {
-				sprintf(tmp,"%sFILE_ID.DIZ",temp_dir);
-				remove(tmp);
-				system(cmdstr(fextr[i]->cmd,str,"FILE_ID.DIZ",NULL));
-				if(!fexist(tmp)) {
-					sprintf(tmp,"%sDESC.SDI",temp_dir);
-					remove(tmp);
-					system(cmdstr(fextr[i]->cmd,str,"DESC.SDI",NULL)); }
-				if((file=nopen(tmp,O_RDONLY))!=-1) {
-					memset(ext,0,513);
-					read(file,ext,512);
-					if(!(mode&KEEP_DESC)) {
-						sprintf(f.desc,"%.*s",LEN_FDESC,ext);
-						for(i=0;f.desc[i]>=SP && i<LEN_FDESC;i++)
-							;
-						f.desc[i]=0; }
-					close(file);
-					f.misc|=FM_EXTDESC; } } }
-		if(exist) {
-			putfiledat(f);
-			if(!(mode&NO_NEWDATE))
-				update_uldate(f); }
-		else
-			addfiledat(&f);
-
-		if(f.misc&FM_EXTDESC)
-			putextdesc(f.dir,f.datoffset,ext);
-
-		if(mode&UL_STATS)
-			updatestats(l);
-		files++; } }
-
-if(mode&AUTO_ADD) {
-	for(i=0;i<total_dirs;i++) {
-		if(dir[i]->misc&DIR_NOAUTO)
-			continue;
-		f.dir=i;
-		if(mode&SEARCH_DIR) {
-			addlist("",f,0,0);
-			continue; }
-        sprintf(str,"%s.LST",dir[f.dir]->code);
-        if(flength(str)>0L) {
-			printf("Auto-adding %s\n",str);
-            addlist(str,f,0,0);
-			if(mode&SYNC_LIST)
-				synclist(str,i);
-            continue; }
-		sprintf(str,"%s%s",dir[f.dir]->path,auto_name);
-		if(str[0]=='.') {
-			sprintf(tmp,"%s%s",node_dir,str);
-			strcpy(str,tmp); }
-		if(flength(str)>0L) {
-			printf("Auto-adding %s\n",str);
-			addlist(str,f,0,0);
-			if(mode&SYNC_LIST)
-				synclist(str,i);
-			continue; } } }
-
-else {
-	if(!listgiven && !namegiven) {
-		sprintf(str,"%s.LST",dir[f.dir]->code);
-		if(flength(str)<=0L)
-			strcpy(str,"FILES.BBS");
-		addlist(str,f,0,0);
-		if(mode&SYNC_LIST)
-			synclist(str,f.dir); } }
-
-printf("\n%lu file(s) added.",files);
-if(removed)
-	printf("\n%lu files(s) removed.",removed);
-printf("\n");
-return(0);
-}
-
diff --git a/src/sbbs2/addfiles/makeall.bat b/src/sbbs2/addfiles/makeall.bat
deleted file mode 100755
index d68900c3d3397527fe45f8723f77457287880eda..0000000000000000000000000000000000000000
--- a/src/sbbs2/addfiles/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOSX %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/addfiles/makefile b/src/sbbs2/addfiles/makefile
deleted file mode 100644
index f83c75e37a9b9608ae8bb2b51efb0dfc74cdfd1e..0000000000000000000000000000000000000000
--- a/src/sbbs2/addfiles/makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-############################################
-# Makefile for Synchronet ADDFILES Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..;..\smb;..\rio
-
-
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml
-!else
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-!ifeq OS NT
-SYSTEM	= NT
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\addfiles.exe
-OBJS	= $(OS)\addfiles.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\ars.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
diff --git a/src/sbbs2/addfiles/makefile.bc b/src/sbbs2/addfiles/makefile.bc
deleted file mode 100644
index 892ff8a1962f2353480ee023c07a15fe72ad5b7c..0000000000000000000000000000000000000000
--- a/src/sbbs2/addfiles/makefile.bc
+++ /dev/null
@@ -1,76 +0,0 @@
-############################################
-# Makefile for Synchronet ADDFILES Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC	= bcc
-LD	= tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -N -d -C -I$(INCLUDE)
-LFLAGS  = -c
-!else
-OS	= DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -N -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-!endif
-MAIN	= $(OS)\addfiles.exe
-OBJS	= $(OS)\addfiles.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj \
-	  $(OS)\scfglib2.obj $(OS)\ars.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL).obj $(OBJS)
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_TEXT_CFG
--DNO_XTRN_CFG 
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib2.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_TEXT_CFG
--DNO_XTRN_CFG 
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
diff --git a/src/sbbs2/allusers/allusers.c b/src/sbbs2/allusers/allusers.c
deleted file mode 100644
index f64638bb2321d65f079190384ac520a4ac64f081..0000000000000000000000000000000000000000
--- a/src/sbbs2/allusers/allusers.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* ALLUSERS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************************************/
-/* Makes global changes to Synchronet user database (USER.DAT)				*/
-/* Compatible with Version 2.1 of Synchronet BBS Software					*/
-/****************************************************************************/
-
-#include <io.h>
-#include <share.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-#include "sbbsdefs.h"
-
-int  min=0,max=99;
-long reqflags[4]={0},reqrest=0,reqexempt=0;
-
-char *usage=
-"\nusage: allusers [data\\user path] [[-require] [...]] "
-	"/modify [[/modify] [...]]\n"
-"\nwhere require is one of:\n"
-"       L#                  set minimum level to # (default=0)\n"
-"       M#                  set maximum level to # (default=99)\n"
-"       F#<flags>           set required flags from flag set #\n"
-"       E<flags>            set required exemptions\n"
-"       R<flags>            set required restrictions\n"
-"\nwhere modify is one of:\n"
-"       L#                  change security level to #\n"
-"       F#[+|-]<flags>      add or remove flags from flag set #\n"
-"       E[+|-]<flags>       add or remove exemption flags\n"
-"       R[+|-]<flags>       add or remove restriction flags\n"
-"\nExamples:\n"
-"       ALLUSERS -L30 /FA   add 'A' to flag set #1 for all level 30+ users\n"
-"       ALLUSERS /F3-G      remove 'G' from flag set #3 for all users\n"
-"       ALLUSERS -F2B /E-P  remove 'P' exemption for all users with FLAG '2B'\n"
-"       ALLUSERS /R+W       add 'W' restriction for all users\n"
-;
-
-/****************************************************************************/
-/* Attempts to lock a user record, retries for up to 10 seconds 			*/
-/* Returns 0 on success, -1 on failure										*/
-/****************************************************************************/
-int lockuser(FILE *stream, ulong offset)
-{
-	time_t start;
-
-if(lock(fileno(stream),offset,U_LEN)==0)
-	return(0);
-start=time(NULL);
-while(1) {
-	if(lock(fileno(stream),offset,U_LEN)==0)
-		return(0);
-	if(time(NULL)-start>=10L)
-		break; }
-return(-1);
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong								*/
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Returns bytes offset into user record for flag set # 'set'               */
-/****************************************************************************/
-long getflagoff(int set)
-{
-switch(set) {
-	default:
-		return(U_FLAGS1);
-	case 2:
-		return(U_FLAGS2);
-	case 3:
-		return(U_FLAGS3);
-	case 4:
-		return(U_FLAGS4); }
-}
-
-/****************************************************************************/
-/* Checks a user record against the requirements set on the command line	*/
-/* Returns 1 if the user meets the requirements (or no requirements were	*/
-/* specified) or 0 if the user does not meet any of the requirements.		*/
-/****************************************************************************/
-int chkuser(FILE *stream, long offset)
-{
-	char str[128];
-	int i;
-
-if(min || max!=99) {			/* Check security level */
-	fseek(stream,offset+U_LEVEL,SEEK_SET);
-	if(!fread(str,2,1,stream))
-		return(0);
-	str[2]=0;
-	i=atoi(str);
-	if(i<min || i>max)			/* not within range */
-		return(0); }			/* so skip this user */
-
-for(i=0;i<4;i++)
-	if(reqflags[i]) {
-		fseek(stream,offset+getflagoff(i+1),SEEK_SET);
-		if(!fread(str,8,1,stream))
-			return(0);
-		str[8]=0;
-		truncsp(str);
-		if((ahtoul(str)&reqflags[i])!=reqflags[i])
-			return(0); }	/* doesn't have 'em all */
-
-if(reqrest) {
-	fseek(stream,offset+U_REST,SEEK_SET);
-	if(!fread(str,8,1,stream))
-		return(0);
-	str[8]=0;
-	truncsp(str);
-	if((ahtoul(str)&reqrest)!=reqrest)
-		return(0); }
-
-if(reqexempt) {
-	fseek(stream,offset+U_REST,SEEK_SET);
-	if(!fread(str,8,1,stream))
-		return(0);
-	str[8]=0;
-	truncsp(str);
-	if((ahtoul(str)&reqexempt)!=reqexempt)
-        return(0); }
-
-return(1);
-}
-
-int main(int argc, char **argv)
-{
-	char	dir[128],str[128];
-	int 	i,j,k,file,set,sub,mod;
-	long	l,f,flags,flagoff,length,offset;
-	FILE	*stream;
-
-printf("\nALLUSERS v2.10 - Bulk User Editor for Synchronet User Database\n");
-
-if(argc<2) {
-	printf(usage);
-	exit(1); }
-dir[0]=0;
-for(i=1;i<argc;i++) {
-	flags=flagoff=sub=mod=0;
-	if(argv[i][0]=='-')
-		switch(toupper(argv[i][1])) {
-			case 'L':                       /* Set minimum sec level */
-				min=atoi(argv[i]+2);
-				break;
-			case 'M':                       /* Set maximum sec level */
-				max=atoi(argv[i]+2);
-				break;
-			case 'F':                       /* Set required flags */
-				j=3;
-				set=1;
-				if(isdigit(argv[i][2]))
-					set=argv[i][2]&0xf;
-				else
-					j=2;
-				for(;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqflags[set-1]|=FLAG(toupper(argv[i][j]));
-				break;
-			case 'R':                       /* Set required restrictions */
-				for(j=2;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqrest|=FLAG(toupper(argv[i][j]));
-				break;
-			case 'E':                       /* Set required exemptions */
-				for(j=2;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqexempt|=FLAG(toupper(argv[i][j]));
-                break;
-			default:						/* Unrecognized include */
-				printf(usage);
-                exit(1); }
-
-	else if(argv[i][0]=='/')
-		switch(toupper(argv[i][1])) {
-			case 'F':   /* flags */
-				j=3;
-				set=1;
-				if(isdigit(argv[i][2]))
-					set=argv[i][2]&0xf;
-				else
-					j=2;
-				if(argv[i][j]=='+')
-					j++;
-				else if(argv[i][j]=='-') {
-					j++;
-					sub=1; }
-				for(;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-                        flags|=FLAG(toupper(argv[i][j]));
-				sprintf(str,"%sUSER.DAT",dir);
-				if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				if((stream=fdopen(file,"w+b"))==NULL) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				setvbuf(stream,NULL,_IOFBF,2048);
-				length=filelength(file);
-				printf("\n%s Flags %s Set #%d\n",sub ? "Removing":"Adding"
-					,sub ? "from":"to",set);
-				for(offset=0;offset<length;offset+=U_LEN) {
-					printf("%lu of %lu (%u modified)\r"
-						,(offset/U_LEN)+1,length/U_LEN,mod);
-					if(lockuser(stream,offset)) {
-						printf("Error locking offset %lu\n",offset);
-						continue; }
-					if(!chkuser(stream,offset)) {
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					flagoff=getflagoff(set);
-					fseek(stream,offset+flagoff,SEEK_SET);
-					fread(str,8,1,stream);
-					str[8]=0;
-					truncsp(str);
-					l=f=ahtoul(str);
-					if(sub)
-						l&=~flags;
-					else
-						l|=flags;
-					if(l==f) {	/* no change */
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					mod++;
-					sprintf(str,"%lx",l);
-					while(strlen(str)<8)
-						strcat(str,"\3");
-					fseek(stream,offset+flagoff,SEEK_SET);
-					fwrite(str,8,1,stream);
-					unlock(fileno(stream),offset,U_LEN); }
-				fclose(stream);
-				printf("\n");
-				break;
-		   case 'E':    /* Exemptions */
-				flagoff=U_EXEMPT;
-		   case 'R':    /* Restrictions */
-				if(!flagoff)
-					flagoff=U_REST;
-				j=2;
-				if(argv[i][j]=='+')
-					j++;
-				else if(argv[i][j]=='-') {
-					j++;
-					sub=1; }
-				for(;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-                        flags|=FLAG(toupper(argv[i][j]));
-				sprintf(str,"%sUSER.DAT",dir);
-				if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				if((stream=fdopen(file,"w+b"))==NULL) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				setvbuf(stream,NULL,_IOFBF,2048);
-				length=filelength(file);
-				printf("\n%s %s\n"
-					,sub ? "Removing":"Adding"
-					,flagoff==U_REST ? "Restrictions":"Exemptions");
-				for(offset=0;offset<length;offset+=U_LEN) {
-					printf("%lu of %lu (%u modified)\r"
-						,(offset/U_LEN)+1,length/U_LEN,mod);
-					if(lockuser(stream,offset)) {
-						printf("Error locking offset %lu\n",offset);
-                        continue; }
-					if(!chkuser(stream,offset)) {
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					fseek(stream,offset+flagoff,SEEK_SET);
-					fread(str,8,1,stream);
-					str[8]=0;
-					truncsp(str);
-					l=f=ahtoul(str);
-					if(sub)
-						l&=~flags;
-					else
-						l|=flags;
-					if(l==f) {	/* no change */
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					mod++;
-					sprintf(str,"%lx",l);
-					while(strlen(str)<8)
-						strcat(str,"\3");
-					fseek(stream,offset+flagoff,SEEK_SET);
-					fwrite(str,8,1,stream);
-					unlock(fileno(stream),offset,U_LEN); }
-				fclose(stream);
-				printf("\n");
-                break;
-		   case 'L':    /* Level */
-				j=atoi(argv[i]+2);
-				if(j>99)
-					j=99;
-				if(j<0)
-					j=0;
-				sprintf(str,"%sUSER.DAT",dir);
-				if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				if((stream=fdopen(file,"w+b"))==NULL) {
-					printf("Error opening %s\n",str);
-					exit(1); }
-				setvbuf(stream,NULL,_IOFBF,2048);
-				length=filelength(file);
-				printf("\nChanging Levels\n");
-				for(offset=0;offset<length;offset+=U_LEN) {
-					printf("%lu of %lu (%u modified)\r"
-						,(offset/U_LEN)+1,length/U_LEN,mod);
-					if(lockuser(stream,offset)) {
-						printf("Error locking offset %lu\n",offset);
-                        continue; }
-					if(!chkuser(stream,offset)) {
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					fseek(stream,offset+U_LEVEL,SEEK_SET);
-					fread(str,2,1,stream);
-					str[2]=0;
-					truncsp(str);
-					if(atoi(str)==j) {		/* no change */
-						unlock(fileno(stream),offset,U_LEN);
-						continue; }
-					sprintf(str,"%02u",j);
-					fseek(stream,offset+U_LEVEL,SEEK_SET);
-					fwrite(str,2,1,stream);
-					unlock(fileno(stream),offset,U_LEN);
-					mod++; }
-				fclose(stream);
-				printf("\n");
-                break;
-			default:
-				printf(usage);
-				exit(1); }
-	else {
-		strcpy(dir,argv[i]);
-		if(dir[strlen(dir)-1]!='\\' && dir[strlen(dir)-1]!=':')
-			strcat(dir,"\\"); } }
-return(0);
-}
diff --git a/src/sbbs2/allusers/make.bat b/src/sbbs2/allusers/make.bat
deleted file mode 100755
index 402dbfbb19d26a93f701c9ade8491dcfb98bd56b..0000000000000000000000000000000000000000
--- a/src/sbbs2/allusers/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -I.. -w-pro allusers.c
diff --git a/src/sbbs2/ans2msg/ans2msg.c b/src/sbbs2/ans2msg/ans2msg.c
deleted file mode 100644
index 7ef485826b16616c2e17987f4ddb75002c079165..0000000000000000000000000000000000000000
--- a/src/sbbs2/ans2msg/ans2msg.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* ANS2MSG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Convert ANSI messages to Synchronet .MSG (Ctrl-A code) format */
-
-#include <stdio.h>
-#include <conio.h>
-
-int main(int argc, char **argv)
-{
-	char esc,n[25],ni;
-	int i,ch;
-	FILE *in,*out;
-
-if(argc<3) {
-	printf("\nANS2MSG v1.06\n");
-	printf("\nusage: ans2msg infile.ans outfile.msg\n");
-	exit(0); }
-
-if((in=fopen(argv[1],"rb"))==NULL) {
-	printf("\nerror opening %s\n",argv[1]);
-	exit(1); }
-
-if((out=fopen(argv[2],"wb"))==NULL) {
-	printf("\nerror opening %s\n",argv[2]);
-	exit(1); }
-
-esc=0;
-while((ch=fgetc(in))!=EOF) {
-	if(ch=='[' && esc) {    /* ANSI escape sequence */
-		ni=0;				/* zero number index */
-		while((ch=fgetc(in))!=EOF) {
-			if(isdigit(ch)) {			/* 1 digit */
-				n[ni]=ch&0xf;
-				ch=fgetc(in);
-				if(ch==EOF)
-					break;
-				if(isdigit(ch)) {		/* 2 digits */
-					n[ni]*=10;
-					n[ni]+=ch&0xf;
-					ch=fgetc(in);
-					if(ch==EOF)
-						break;
-					if(isdigit(ch)) {	/* 3 digits */
-						n[ni]*=10;
-						n[ni]+=ch&0xf;
-						ch=fgetc(in); } }
-				ni++; }
-			if(ch==';')
-				continue;
-			switch(ch) {
-				case '=':
-				case '?':
-					ch=fgetc(in);	   /* First digit */
-					if(isdigit(ch)) ch=fgetc(in);	/* l or h ? */
-					if(isdigit(ch)) ch=fgetc(in);
-					if(isdigit(ch)) fgetc(in);
-					break;
-				case 'J':
-					if(n[0]==2) 					/* clear screen */
-						fputs("\1l",out);           /* ctrl-al */
-					break;
-				case 'K':
-					fputs("\1>",out);               /* clear to eol */
-					break;
-				case 'm':
-					for(i=0;i<ni;i++) {
-						fputc(1,out);				/* ctrl-ax */
-						switch(n[i]) {
-							default:
-							case 0:
-							case 2: 				/* no attribute */
-								fputc('n',out);
-								break;
-							case 1: 				/* high intensity */
-								fputc('h',out);
-								break;
-							case 3:
-							case 4:
-							case 5: 				/* blink */
-							case 6:
-							case 7:
-								fputc('i',out);
-								break;
-							case 8: 				/* concealed */
-								fputc('e',out);
-								break;
-							case 30:
-								fputc('k',out);
-								break;
-							case 31:
-								fputc('r',out);
-								break;
-							case 32:
-								fputc('g',out);
-								break;
-							case 33:
-								fputc('y',out);
-								break;
-							case 34:
-								fputc('b',out);
-								break;
-							case 35:
-								fputc('m',out);
-								break;
-							case 36:
-								fputc('c',out);
-								break;
-							case 37:
-								fputc('w',out);
-								break;
-							case 40:
-								fputc('0',out);
-								break;
-							case 41:
-								fputc('1',out);
-								break;
-							case 42:
-								fputc('2',out);
-								break;
-							case 43:
-								fputc('3',out);
-								break;
-							case 44:
-								fputc('4',out);
-								break;
-							case 45:
-								fputc('5',out);
-								break;
-							case 46:
-								fputc('6',out);
-								break;
-							case 47:
-								fputc('7',out);
-								break; } }
-					break;
-				case 'C':
-					fprintf(out,"\1%c",0x7f+n[0]);
-					break;
-				default:
-					printf("Unsupported ANSI code '%c'\r\n",ch);
-					break; }
-			break; }	/* end of while */
-		esc=0;
-		continue; } 	/* end of ANSI expansion */
-	if(ch=='\x1b')
-		esc=1;
-	else {
-		esc=0;
-		fputc(ch,out); } }
-fcloseall();
-return(0);
-}
-
diff --git a/src/sbbs2/ars.c b/src/sbbs2/ars.c
deleted file mode 100644
index f9dff33a27664c9b64c3811659ced620e690206b..0000000000000000000000000000000000000000
--- a/src/sbbs2/ars.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/* ARS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifdef __WATCOMC__
-	#include <malloc.h>
-#else
-	#include <alloc.h>
-#endif
-#include "ars_defs.h"
-
-#ifdef SBBS
-#include "sbbs.h"
-#endif
-
-char *arstr(ushort *count, char *str)
-{
-	static char *nular="";
-	char ar[256],*p;
-	uint i,j,n,artype=AR_LEVEL,not=0,equal=0,x;
-
-for(i=j=0;str[i];i++) {
-    if(str[i]==SP)
-        continue;
-
-    if(str[i]=='(') {
-        if(not)
-            ar[j++]=AR_NOT;
-        not=equal=0;
-        ar[j++]=AR_BEGNEST;
-        continue; }
-
-    if(str[i]==')') {
-        ar[j++]=AR_ENDNEST;
-        continue; }
-
-    if(str[i]=='|') {
-        ar[j++]=AR_OR;
-        continue; }
-    
-    if(str[i]=='!') {
-        not=1;
-        continue; }
-
-    if(str[i]=='=') {
-        equal=1;
-        continue; }
-
-    if(str[i]=='&')
-        continue;
-
-    if(isalpha(str[i])) {
-        if(!strncmp(str+i,"OR",2)) {
-            ar[j++]=AR_OR;
-            i++;
-            continue; }
-
-        if(!strncmp(str+i,"AND",3)) {    /* AND is ignored */
-            i+=2;
-            continue; }
-
-        if(!strncmp(str+i,"NOT",3)) {
-            not=1;
-            i+=2;
-            continue; }
-
-        if(!strncmp(str+i,"EQUAL TO",8)) {
-            equal=1;
-            i+=7;
-            continue; }
-
-        if(!strncmp(str+i,"EQUAL",5)) {
-            equal=1;
-            i+=4;
-            continue; }
-
-        if(!strncmp(str+i,"EQUALS",6)) {
-            equal=1;
-            i+=5;
-            continue; } }
-
-    if(str[i]=='$') {
-        switch(str[i+1]) {
-            case 'A':
-                artype=AR_AGE;
-                break;
-            case 'B':
-                artype=AR_BPS;
-                break;
-            case 'C':
-                artype=AR_CREDIT;
-                break;
-            case 'D':
-                artype=AR_UDFR;
-                break;
-            case 'E':
-                artype=AR_EXPIRE;
-                break;
-            case 'F':
-                artype=AR_FLAG1;
-                break;
-            case 'G':
-                artype=AR_LOCAL;
-				if(not)
-					ar[j++]=AR_NOT;
-				not=0;
-				ar[j++]=artype;
-                break;
-            case 'H':
-                artype=AR_SUB;
-                break;
-            case 'I':
-                artype=AR_LIB;
-                break;
-            case 'J':
-                artype=AR_DIR;
-                break;
-            case 'K':
-                artype=AR_UDR;
-                break;
-            case 'L':
-                artype=AR_LEVEL;
-                break;
-            case 'M':
-                artype=AR_GROUP;
-                break;
-            case 'N':
-                artype=AR_NODE;
-                break;
-            case 'O':
-                artype=AR_TUSED;
-                break;
-            case 'P':
-                artype=AR_PCR;
-                break;
-			case 'Q':
-				artype=AR_RANDOM;
-				break;
-            case 'R':
-                artype=AR_TLEFT;
-                break;
-            case 'S':
-                artype=AR_SEX;
-                break;
-            case 'T':
-                artype=AR_TIME;
-                break;
-            case 'U':
-                artype=AR_USER;
-                break;
-			case 'V':
-				artype=AR_LOGONS;
-				break;
-            case 'W':
-                artype=AR_DAY;
-                break;
-            case 'X':
-                artype=AR_EXEMPT;
-                break;
-			case 'Y':   /* Days since last on */
-				artype=AR_LASTON;
-				break;
-            case 'Z':
-                artype=AR_REST;
-                break;
-            case '[':
-                artype=AR_ANSI;
-				if(not)
-					ar[j++]=AR_NOT;
-				not=0;
-				ar[j++]=artype;
-                break;
-            case '0':
-                artype=AR_NULL;
-                break;
-            case '*':
-                artype=AR_RIP;
-				if(not)
-					ar[j++]=AR_NOT;
-				not=0;
-				ar[j++]=artype;
-                break;
-
-            }
-        i++;
-        continue; }
-
-    if(isalpha(str[i])) {
-        n=i;
-        if(!strncmp(str+i,"AGE",3)) {
-            artype=AR_AGE;
-            i+=2; }
-        else if(!strncmp(str+i,"BPS",3)) {
-            artype=AR_BPS;
-            i+=2; }
-        else if(!strncmp(str+i,"PCR",3)) {
-            artype=AR_PCR;
-            i+=2; }
-        else if(!strncmp(str+i,"SEX",3)) {
-            artype=AR_SEX;
-            i+=2; }
-        else if(!strncmp(str+i,"UDR",3)) {
-            artype=AR_UDR;
-            i+=2; }
-        else if(!strncmp(str+i,"DAY",3)) {
-            artype=AR_DAY;
-            i+=2; }
-        else if(!strncmp(str+i,"RIP",3)) {
-            artype=AR_RIP;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-			i+=2; }
-		else if(!strncmp(str+i,"WIP",3)) {
-			artype=AR_WIP;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=2; }
-		else if(!strncmp(str+i,"OS2",3)) {
-			artype=AR_OS2;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=2; }
-		else if(!strncmp(str+i,"DOS",3)) {
-			artype=AR_DOS;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=2; }
-		else if(!strncmp(str+i,"SUBCODE",7)) {
-            artype=AR_SUBCODE;
-            i+=6; }
-        else if(!strncmp(str+i,"SUB",3)) {
-            artype=AR_SUB;
-            i+=2; }
-		else if(!strncmp(str+i,"LIB",3)) {
-            artype=AR_LIB;
-            i+=2; }
-		else if(!strncmp(str+i,"DIRCODE",7)) {
-            artype=AR_DIRCODE;
-            i+=6; }
-        else if(!strncmp(str+i,"DIR",3)) {
-            artype=AR_DIR;
-            i+=2; }
-		else if(!strncmp(str+i,"ANSI",4)) {
-            artype=AR_ANSI;
-			if(not)
-				ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=3; }
-        else if(!strncmp(str+i,"UDFR",4)) {
-            artype=AR_UDFR;
-            i+=3; }
-        else if(!strncmp(str+i,"FLAG",4)) {
-            artype=AR_FLAG1;
-            i+=3; }
-        else if(!strncmp(str+i,"NODE",4)) {
-            artype=AR_NODE;
-            i+=3; }
-        else if(!strncmp(str+i,"NULL",4)) {
-            artype=AR_NULL;
-            i+=3; }
-        else if(!strncmp(str+i,"USER",4)) {
-            artype=AR_USER;
-            i+=3; }
-        else if(!strncmp(str+i,"TIME",4)) {
-            artype=AR_TIME;
-            i+=3; }
-        else if(!strncmp(str+i,"REST",4)) {
-            artype=AR_REST;
-            i+=3; }
-        else if(!strncmp(str+i,"LEVEL",5)) {
-            artype=AR_LEVEL;
-            i+=4; }
-        else if(!strncmp(str+i,"TLEFT",5)) {
-            artype=AR_TLEFT;
-            i+=4; }
-        else if(!strncmp(str+i,"TUSED",5)) {
-            artype=AR_TUSED;
-            i+=4; }
-        else if(!strncmp(str+i,"LOCAL",5)) {
-            artype=AR_LOCAL;
-			if(not)
-				ar[j++]=AR_NOT;
-			not=0;
-			ar[j++]=artype;
-            i+=4; }
-        else if(!strncmp(str+i,"GROUP",5)) {
-            artype=AR_GROUP;
-            i+=4; }
-        else if(!strncmp(str+i,"EXPIRE",6)) {
-			artype=AR_EXPIRE;
-            i+=5; }
-		else if(!strncmp(str+i,"EXPERT",6)) {
-			artype=AR_EXPERT;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=5; }
-		else if(!strncmp(str+i,"SYSOP",5)) {
-			artype=AR_SYSOP;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-			i+=4; }
-		else if(!strncmp(str+i,"QUIET",5)) {
-			artype=AR_QUIET;
-			if(not)
-                ar[j++]=AR_NOT;
-            not=0;
-			ar[j++]=artype;
-            i+=4; }
-        else if(!strncmp(str+i,"EXEMPT",6)) {
-            artype=AR_EXEMPT;
-            i+=5; }
-		else if(!strncmp(str+i,"RANDOM",6)) {
-			artype=AR_RANDOM;
-            i+=5; }
-		else if(!strncmp(str+i,"LASTON",6)) {
-			artype=AR_LASTON;
-            i+=5; }
-		else if(!strncmp(str+i,"LOGONS",6)) {
-			artype=AR_LOGONS;
-            i+=5; }
-        else if(!strncmp(str+i,"CREDIT",6)) {
-            artype=AR_CREDIT;
-            i+=5; }
-		else if(!strncmp(str+i,"MAIN_CMDS",9)) {
-			artype=AR_MAIN_CMDS;
-			i+=8; }
-		else if(!strncmp(str+i,"FILE_CMDS",9)) {
-			artype=AR_FILE_CMDS;
-            i+=8; }
-        if(n!=i)            /* one of the above */
-            continue; }
-
-    if(not)
-        ar[j++]=AR_NOT;
-    if(equal)
-        ar[j++]=AR_EQUAL;
-    not=equal=0;
-
-    if(artype==AR_FLAG1 && isdigit(str[i])) {   /* flag set specified */
-        switch(str[i]) {
-            case '2':
-                artype=AR_FLAG2;
-                break;
-            case '3':
-                artype=AR_FLAG3;
-                break;
-            case '4':
-                artype=AR_FLAG4;
-                break; }
-        continue; }
-
-	if(artype==AR_SUB && !isdigit(str[i]))
-		artype=AR_SUBCODE;
-	if(artype==AR_DIR && !isdigit(str[i]))
-		artype=AR_DIRCODE;
-
-    ar[j++]=artype;
-    if(isdigit(str[i])) {
-        if(artype==AR_TIME) {
-            n=atoi(str+i)*60;
-            p=strchr(str+i,':');
-            if(p)
-                n+=atoi(p+1);
-			*((short *)(ar+j))=n;
-            j+=2;
-            while(isdigit(str[i+1]) || str[i+1]==':') i++;
-            continue; }
-		n=atoi(str+i);
-        switch(artype) {
-            case AR_DAY:
-                if(n>6)     /* not past saturday */
-                    n=6;
-            case AR_AGE:    /* byte operands */
-            case AR_PCR:
-            case AR_UDR:
-            case AR_UDFR:
-            case AR_NODE:
-            case AR_LEVEL:
-            case AR_TLEFT:
-            case AR_TUSED:
-                ar[j++]=n;
-                break;
-            case AR_BPS:    /* int operands */
-                if(n<300)
-                    n*=100;
-			case AR_MAIN_CMDS:
-			case AR_FILE_CMDS:
-            case AR_EXPIRE:
-            case AR_CREDIT:
-            case AR_USER:
-			case AR_RANDOM:
-			case AR_LASTON:
-			case AR_LOGONS:
-				*((short *)(ar+j))=n;
-                j+=2;
-                break;
-            case AR_GROUP:
-            case AR_LIB:
-            case AR_DIR:
-            case AR_SUB:
-                if(n) n--;              /* convert to 0 base */
-				*((short *)(ar+j))=n;
-                j+=2;
-                break;
-            default:                    /* invalid numeric AR type */
-                j--;
-                break; }
-        while(isdigit(str[i+1])) i++;
-        continue; }
-	if(artype==AR_SUBCODE || artype==AR_DIRCODE) {
-		for(n=0;n<8
-			&& str[i]
-			&& str[i]!=SP
-			&& str[i]!='('
-			&& str[i]!=')'
-			&& str[i]!='='
-			&& str[i]!='|'
-			;n++)
-			ar[j++]=str[i++];
-		ar[j++]=0;
-		continue; }
-    switch(artype) {
-        case AR_FLAG1:
-        case AR_FLAG2:
-        case AR_FLAG3:
-        case AR_FLAG4:
-        case AR_EXEMPT:
-        case AR_SEX:
-        case AR_REST:
-            ar[j++]=str[i];
-            break;
-#ifdef SBBS
-        case AR_SUB:
-            for(n=0;n<total_subs;n++)
-                if(!strnicmp(str+i,sub[n]->code,strlen(sub[n]->code)))
-                    break;
-            if(n<total_subs) {
-				*((short *)(ar+j))=n;
-                j+=2; }
-            else        /* Unknown sub-board */
-                j--;
-            while(isalpha(str[i+1])) i++;
-            break;
-        case AR_DIR:
-            for(n=0;n<total_dirs;n++)
-                if(!strnicmp(str+i,dir[n]->code,strlen(dir[n]->code)))
-                    break;
-            if(n<total_dirs) {
-				*((short *)(ar+j))=n;
-                j+=2; }
-            else        /* Unknown directory */
-                j--;
-            while(isalpha(str[i+1])) i++;
-            break;
-#endif
-        case AR_DAY:
-            if(str[i]=='S' && str[i+1]=='U')            /* Sunday */
-                ar[j++]=0;
-            else if(str[i]=='M')                        /* Monday */
-                ar[j++]=1;
-            else if(str[i]=='T' && str[i+1]=='U')       /* Tuesday */
-                ar[j++]=2;
-            else if(str[i]=='W')                        /* Wednesday */
-                ar[j++]=3;
-            else if(str[i]=='T' && str[i+1]=='H')       /* Thursday */
-                ar[j++]=4;
-            else if(str[i]=='F')                        /* Friday */
-                ar[j++]=5;
-            else ar[j++]=6;                             /* Saturday */
-            while(isalpha(str[i+1])) i++;
-            break;
-            } }
-if(!j)
-	return(nular);	/* Save memory */
-
-ar[j++]=AR_NULL;
-/** DEBUG stuff
-for(i=0;i<j;i++)
-    lprintf("%02X ",(uint)ar[i]);
-lputs("\r\n");
-***/
-if((p=(char *)MALLOC(j))==NULL)
-    return(NULL);
-memcpy(p,ar,j);
-if(count)
-	(*count)=j;
-return(p);
-}
-
diff --git a/src/sbbs2/ars_defs.h b/src/sbbs2/ars_defs.h
deleted file mode 100644
index 2782811b8298884b2ccc1276127f20363ac4c946..0000000000000000000000000000000000000000
--- a/src/sbbs2/ars_defs.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ARS_DEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _ARS_DEFS_H
-#define _ARS_DEFS_H
-
-/************************************************************************/
-/* Synchronet Access Requirement Strings fucntion prototypes and type	*/
-/* definitions															*/
-/************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "gen_defs.h"
-
-char *arstr(ushort *count, char *str);
-
-enum {                              /* Access requirement binaries */
-     AR_NULL
-    ,AR_OR
-    ,AR_NOT
-    ,AR_EQUAL
-    ,AR_BEGNEST
-    ,AR_ENDNEST
-    ,AR_LEVEL
-    ,AR_AGE
-    ,AR_BPS
-    ,AR_NODE
-    ,AR_TLEFT
-    ,AR_TUSED
-    ,AR_USER
-	,AR_TIME
-    ,AR_PCR
-	,AR_FLAG1
-	,AR_FLAG2
-	,AR_FLAG3
-	,AR_FLAG4
-	,AR_EXEMPT
-	,AR_REST
-    ,AR_SEX
-	,AR_UDR
-	,AR_UDFR
-	,AR_EXPIRE
-	,AR_CREDIT
-	,AR_DAY
-	,AR_ANSI
-	,AR_RIP
-	,AR_LOCAL
-	,AR_GROUP
-	,AR_SUB
-	,AR_LIB
-	,AR_DIR
-	,AR_EXPERT
-	,AR_SYSOP
-	,AR_QUIET
-	,AR_MAIN_CMDS
-	,AR_FILE_CMDS
-	,AR_RANDOM
-	,AR_LASTON
-	,AR_LOGONS
-	,AR_WIP
-	,AR_SUBCODE
-	,AR_DIRCODE
-	,AR_OS2
-	,AR_DOS
-    };
-
-#endif		/* Don't add anything after this line */
diff --git a/src/sbbs2/atcodes.c b/src/sbbs2/atcodes.c
deleted file mode 100644
index cd1ff9425827339c0728700099b5b6d999dd1b54..0000000000000000000000000000000000000000
--- a/src/sbbs2/atcodes.c
+++ /dev/null
@@ -1,514 +0,0 @@
-#line 1 "ATCODES.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-extern char *wday[];    /* 3 char days of week */
-char question[128];
-
-int syncatcodes(char *sp, int len)
-{
-	char str2[128],*tp;
-
-/* Synchronet Specific */
-
-if(!strncmp(sp,"SETSTR:",7))
-    strcpy(main_csi.str,sp+7);
-
-else if(!strncmp(sp,"EXEC:",5))
-	exec_bin(sp+5,&main_csi);
-
-else if(!strncmp(sp,"MENU:",5))
-    menu(sp+5);
-
-else if(!strncmp(sp,"TYPE:",5))
-    printfile(cmdstr(sp+5,nulstr,nulstr,str2),0);
-
-else if(!strcmp(sp,"QUESTION"))
-    bputs(question);
-
-else if(!strncmp(sp,"NAME-L",6))
-    bprintf("%-*.*s",len,len,useron.alias);
-
-else if(!strncmp(sp,"NAME-R",6))
-    bprintf("%*.*s",len,len,useron.alias);
-
-else if(!strcmp(sp,"HANDLE"))
-    bputs(useron.handle);
-
-else if(!strcmp(sp,"CID") || !strcmp(sp,"IP"))
-    bputs(cid);
-
-else if(!strcmp(sp,"GRP"))
-    bputs(usrgrps ? grp[usrgrp[curgrp]]->sname : nulstr);
-
-else if(!strncmp(sp,"GRP-L",5))
-    bprintf("%-*.*s",len,len,usrgrps ? grp[usrgrp[curgrp]]->sname : nulstr);
-
-else if(!strncmp(sp,"GRP-R",5))
-    bprintf("%*.*s",len,len,usrgrps ? grp[usrgrp[curgrp]]->sname : nulstr);
-
-else if(!strcmp(sp,"GRPL"))
-    bputs(usrgrps ? grp[usrgrp[curgrp]]->lname : nulstr);
-
-else if(!strncmp(sp,"GRPL-L",6))
-    bprintf("%-*.*s",len,len,usrgrps ? grp[usrgrp[curgrp]]->lname : nulstr);
-
-else if(!strncmp(sp,"GRPL-R",6))
-    bprintf("%*.*s",len,len,usrgrps ? grp[usrgrp[curgrp]]->lname : nulstr);
-
-else if(!strcmp(sp,"GN"))
-    bprintf("%u",usrgrps ? curgrp+1 : 0);
-
-else if(!strcmp(sp,"GL"))
-    bprintf("%-4u",usrgrps ? curgrp+1 : 0);
-
-else if(!strcmp(sp,"GR"))
-    bprintf("%4u",usrgrps ? curgrp+1 : 0);
-
-else if(!strcmp(sp,"SUB"))
-    bputs(usrgrps ? sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
-
-else if(!strncmp(sp,"SUB-L",5))
-    bprintf("%-*.*s",len,len,usrgrps
-        ? sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
-
-else if(!strncmp(sp,"SUB-R",5))
-    bprintf("%*.*s",len,len,usrgrps
-        ? sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
-
-else if(!strcmp(sp,"SUBL"))
-    bputs(usrgrps  ? sub[usrsub[curgrp][cursub[curgrp]]]->lname : nulstr);
-
-else if(!strncmp(sp,"SUBL-L",6))
-    bprintf("%-*.*s",len,len,usrgrps
-        ? sub[usrsub[curgrp][cursub[curgrp]]]->lname : nulstr);
-
-else if(!strncmp(sp,"SUBL-R",6))
-    bprintf("%*.*s",len,len,usrgrps
-        ? sub[usrsub[curgrp][cursub[curgrp]]]->lname : nulstr);
-
-else if(!strcmp(sp,"SN"))
-    bprintf("%u",usrgrps ? cursub[curgrp]+1 : 0);
-
-else if(!strcmp(sp,"SL"))
-    bprintf("%-4u",usrgrps ? cursub[curgrp]+1 : 0);
-
-else if(!strcmp(sp,"SR"))
-    bprintf("%4u",usrgrps ? cursub[curgrp]+1 : 0);
-
-else if(!strcmp(sp,"LIB"))
-    bputs(usrlibs ? lib[usrlib[curlib]]->sname : nulstr);
-
-else if(!strncmp(sp,"LIB-L",5))
-    bprintf("%-*.*s",len,len,usrlibs ? lib[usrlib[curlib]]->sname : nulstr);
-
-else if(!strncmp(sp,"LIB-R",5))
-    bprintf("%*.*s",len,len,usrlibs ? lib[usrlib[curlib]]->sname : nulstr);
-
-else if(!strcmp(sp,"LIBL"))
-    bputs(usrlibs ? lib[usrlib[curlib]]->lname : nulstr);
-
-else if(!strncmp(sp,"LIBL-L",6))
-    bprintf("%-*.*s",len,len,usrlibs ? lib[usrlib[curlib]]->lname : nulstr);
-
-else if(!strncmp(sp,"LIBL-R",6))
-    bprintf("%*.*s",len,len,usrlibs ? lib[usrlib[curlib]]->lname : nulstr);
-
-else if(!strcmp(sp,"LN"))
-    bprintf("%u",usrlibs ? curlib+1 : 0);
-
-else if(!strcmp(sp,"LL"))
-    bprintf("%-4u",usrlibs ? curlib+1 : 0);
-
-else if(!strcmp(sp,"LR"))
-    bprintf("%4u",usrlibs  ? curlib+1 : 0);
-
-else if(!strcmp(sp,"DIR"))
-    bputs(usrlibs ? dir[usrdir[curlib][curdir[curlib]]]->sname :nulstr);
-
-else if(!strncmp(sp,"DIR-L",5))
-    bprintf("%-*.*s",len,len,usrlibs
-        ? dir[usrdir[curlib][curdir[curlib]]]->sname : nulstr);
-
-else if(!strncmp(sp,"DIR-R",5))
-    bprintf("%*.*s",len,len,usrlibs
-        ? dir[usrdir[curlib][curdir[curlib]]]->sname : nulstr);
-
-else if(!strcmp(sp,"DIRL"))
-    bputs(usrlibs ? dir[usrdir[curlib][curdir[curlib]]]->lname : nulstr);
-
-else if(!strncmp(sp,"DIRL-L",6))
-    bprintf("%-*.*s",len,len,usrlibs
-        ? dir[usrdir[curlib][curdir[curlib]]]->lname : nulstr);
-
-else if(!strncmp(sp,"DIRL-R",6))
-    bprintf("%*.*s",len,len,usrlibs
-        ? dir[usrdir[curlib][curdir[curlib]]]->lname : nulstr);
-
-else if(!strcmp(sp,"DN"))
-    bprintf("%u",usrlibs ? curdir[curlib]+1 : 0);
-
-else if(!strcmp(sp,"DL"))
-    bprintf("%-4u",usrlibs ? curdir[curlib]+1 : 0);
-
-else if(!strcmp(sp,"DR"))
-    bprintf("%4u",usrlibs ? curdir[curlib]+1 : 0);
-
-else if(!strcmp(sp,"NOACCESS")) {
-    if(noaccess_str==text[NoAccessTime])
-        bprintf(noaccess_str,noaccess_val/60,noaccess_val%60);
-    else if(noaccess_str==text[NoAccessDay])
-        bprintf(noaccess_str,wday[noaccess_val]);
-    else
-        bprintf(noaccess_str,noaccess_val); }
-
-else if(!strcmp(sp,"LAST")) {
-    tp=strrchr(useron.alias,SP);
-    if(tp) tp++;
-    else tp=useron.alias;
-    bputs(tp); }
-
-else if(!strcmp(sp,"REAL")) {
-    strcpy(str2,useron.name);
-    tp=strchr(str2,SP);
-    if(tp) *tp=0;
-    bputs(str2); }
-
-else if(!strcmp(sp,"FIRSTREAL")) {
-    strcpy(str2,useron.name);
-    tp=strchr(str2,SP);
-    if(tp) *tp=0;
-    bputs(str2); }
-
-else if(!strcmp(sp,"LASTREAL")) {
-    tp=strrchr(useron.name,SP);
-    if(tp) tp++;
-    else tp=useron.name;
-    bputs(tp); }
-
-else if(!strcmp(sp,"MAILW"))
-	bprintf("%u",getmail(useron.number,0));
-
-else if(!strcmp(sp,"MAILP"))
-	bprintf("%u",getmail(useron.number,1));
-
-else if(!strncmp(sp,"MAILW:",6))
-	bprintf("%u",getmail(atoi(sp+6),0));
-
-else if(!strncmp(sp,"MAILP:",6))
-	bprintf("%u",getmail(atoi(sp+6),1));
-
-else return(0);
-
-return(len);
-}
-
-/****************************************************************************/
-/* Returns 0 if invalid @ code. Returns length of @ code if valid.          */
-/****************************************************************************/
-int atcodes(char *instr)
-{
-	char	str[64],str2[64],*p,*tp,*sp;
-    int     i,len;
-	long	l;
-    stats_t stats;
-    node_t  node;
-    struct  dfree d;
-
-sprintf(str,"%.40s",instr);
-tp=strchr(str+1,'@');
-if(!tp)                 /* no terminating @ */
-    return(0);
-sp=strchr(str+1,SP);
-if(sp && sp<tp)         /* space before terminating @ */
-    return(0);
-len=(tp-str)+1;
-(*tp)=0;
-sp=(str+1);
-
-if(!strcmp(sp,"VER"))
-    bputs(VERSION);
-
-else if(!strcmp(sp,"REV"))
-	bprintf("%c",REVISION);
-
-else if(!strcmp(sp,"BBS") || !strcmp(sp,"BOARDNAME"))
-    bputs(sys_name);
-
-else if(!strcmp(sp,"BAUD") || !strcmp(sp,"BPS"))
-	bprintf("%lu",cur_rate);
-
-else if(!strcmp(sp,"CONN"))
-	bputs(connection);
-
-else if(!strcmp(sp,"SYSOP"))
-    bputs(sys_op);
-
-else if(!strcmp(sp,"LOCATION"))
-	bputs(sys_location);
-
-else if(!strcmp(sp,"NODE"))
-    bprintf("%u",node_num);
-
-else if(!strcmp(sp,"TNODE"))
-    bprintf("%u",sys_nodes);
-
-else if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
-    now=time(NULL);
-    unixtodos(now,&date,&curtime);
-    bprintf("%02d:%02d %s"
-        ,curtime.ti_hour==0 ? 12
-        : curtime.ti_hour>12 ? curtime.ti_hour-12
-        : curtime.ti_hour, curtime.ti_min, curtime.ti_hour>11 ? "pm":"am"); }
-
-else if(!strcmp(sp,"DATE") || !strcmp(sp,"SYSDATE")) {
-    now=time(NULL);
-    bputs(unixtodstr(now,str2)); }
-
-else if(!strcmp(sp,"TMSG")) {
-	l=0;
-    for(i=0;i<total_subs;i++)
-		l+=getposts(i); 		/* l=total posts */
-    bprintf("%lu",l); }
-
-else if(!strcmp(sp,"TUSER"))
-    bprintf("%u",lastuser());
-
-else if(!strcmp(sp,"TFILE")) {
-	l=0;
-    for(i=0;i<total_dirs;i++)
-        l+=getfiles(i);
-    bprintf("%lu",l); }
-
-else if(!strcmp(sp,"TCALLS") || !strcmp(sp,"NUMCALLS")) {
-    getstats(0,&stats);
-    bprintf("%lu",stats.logons); }
-
-else if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
-    || !strcmp(sp,"LASTCALLERSYSTEM"))
-    bputs(lastuseron);
-
-else if(!strcmp(sp,"CLS"))
-    CLS;
-
-else if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE"))
-    pause();
-
-else if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF"))
-    sys_status^=SS_PAUSEOFF;
-
-else if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE"))
-    sys_status^=SS_PAUSEON;
-
-/* NOSTOP */
-
-/* STOP */
-
-else if(!strcmp(sp,"BELL") || !strcmp(sp,"BEEP"))
-    outchar(7);
-
-// else if(!strcmp(sp,"EVENT"))
-//	  bputs(sectostr(sys_eventtime,str2));
-
-/* LASTCALL */
-
-else if(!strncmp(sp,"NODE",4)) {
-    i=atoi(sp+4);
-    if(i && i<=sys_nodes) {
-        getnodedat(i,&node,0);
-        printnodedat(i,node); } }
-
-else if(!strcmp(sp,"WHO"))
-    whos_online(1);
-
-/* User Codes */
-
-else if(!strcmp(sp,"USER") || !strcmp(sp,"ALIAS") || !strcmp(sp,"NAME"))
-    bputs(useron.alias);
-
-else if(!strcmp(sp,"FIRST")) {
-    strcpy(str2,useron.alias);
-    tp=strchr(str2,SP);
-    if(tp) *tp=0;
-    bputs(str2); }
-
-else if(!strcmp(sp,"PHONE") || !strcmp(sp,"HOMEPHONE")
-    || !strcmp(sp,"DATAPHONE") || !strcmp(sp,"DATA"))
-    bputs(useron.phone);
-
-else if(!strcmp(sp,"ADDR1"))
-    bputs(useron.address);
-
-else if(!strcmp(sp,"FROM"))
-    bputs(useron.location);
-
-else if(!strcmp(sp,"CITY")) {
-    strcpy(str2,useron.location);
-    p=strchr(str2,',');
-    if(p) {
-        *p=0;
-        bputs(str2); } }
-
-else if(!strcmp(sp,"STATE")) {
-    p=strchr(useron.location,',');
-    if(p) {
-        p++;
-        if(*p==SP)
-            p++;
-        bputs(p); } }
-
-else if(!strcmp(sp,"CPU") || !strcmp(sp,"HOST"))
-    bputs(useron.comp);
-
-else if(!strcmp(sp,"BDATE"))
-    bputs(useron.birth);
-
-else if(!strcmp(sp,"CALLS") || !strcmp(sp,"NUMTIMESON"))
-    bprintf("%u",useron.logons);
-
-else if(!strcmp(sp,"MEMO"))
-    bputs(unixtodstr(useron.pwmod,str2));
-
-else if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY"))
-    bprintf("%u",useron.level);
-
-else if(!strcmp(sp,"SINCE"))
-    bputs(unixtodstr(useron.firston,str2));
-
-else if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
-	now=time(NULL);
-	bprintf("%u",(now-logontime)/60); }
-
-else if(!strcmp(sp,"TUSED")) {              /* Synchronet only */
-	now=time(NULL);
-	bputs(sectostr(now-logontime,str2)+1); }
-
-else if(!strcmp(sp,"TLEFT")) {              /* Synchronet only */
-	gettimeleft();
-	bputs(sectostr(timeleft,str2)+1); }
-
-else if(!strcmp(sp,"TPERD"))                /* Synchronet only */
-    bputs(sectostr(level_timeperday[useron.level],str)+1);
-
-else if(!strcmp(sp,"TPERC"))                /* Synchronet only */
-    bputs(sectostr(level_timepercall[useron.level],str)+1);
-
-else if(!strcmp(sp,"TIMELIMIT"))
-    bprintf("%u",level_timepercall[useron.level]);
-
-else if(!strcmp(sp,"MINLEFT") || !strcmp(sp,"LEFT") || !strcmp(sp,"TIMELEFT")) {
-	gettimeleft();
-	bprintf("%u",timeleft/60); }
-
-else if(!strcmp(sp,"LASTON"))
-    bputs(timestr(&useron.laston));
-
-else if(!strcmp(sp,"LASTDATEON"))
-    bputs(unixtodstr(useron.laston,str2));
-
-else if(!strcmp(sp,"LASTTIMEON")) {
-    unixtodos(useron.laston,&date,&curtime);
-    bprintf("%02d:%02d %s"
-        ,curtime.ti_hour==0 ? 12
-        : curtime.ti_hour>12 ? curtime.ti_hour-12
-        : curtime.ti_hour, curtime.ti_min, curtime.ti_hour>11 ? "pm":"am"); }
-
-else if(!strcmp(sp,"MSGLEFT") || !strcmp(sp,"MSGSLEFT"))
-    bprintf("%u",useron.posts);
-
-else if(!strcmp(sp,"MSGREAD"))
-    bprintf("%u",posts_read);
-
-else if(!strcmp(sp,"FREESPACE")) {
-    if(temp_dir[1]==':')
-        i=temp_dir[0]-'A'+1;
-    else i=0;
-    getdfree(i,&d);
-    if(d.df_sclus!=0xffff)
-        bprintf("%lu",(ulong)d.df_bsec*(ulong)d.df_sclus*(ulong)d.df_avail); }
-
-else if(!strcmp(sp,"UPBYTES"))
-    bprintf("%lu",useron.ulb);
-
-else if(!strcmp(sp,"UPK"))
-    bprintf("%lu",useron.ulb/1024L);
-
-else if(!strcmp(sp,"UPS") || !strcmp(sp,"UPFILES"))
-    bprintf("%u",useron.uls);
-
-else if(!strcmp(sp,"DLBYTES"))
-    bprintf("%lu",useron.dlb);
-
-else if(!strcmp(sp,"DOWNK"))
-    bprintf("%lu",useron.dlb/1024L);
-
-else if(!strcmp(sp,"DOWNS") || !strcmp(sp,"DLFILES"))
-    bprintf("%u",useron.dls);
-
-else if(!strcmp(sp,"LASTNEW"))
-    bputs(unixtodstr(ns_time,str2));
-
-else if(!strcmp(sp,"NEWFILETIME"))
-	bputs(timestr(&ns_time));
-
-/* MAXDL */
-
-else if(!strcmp(sp,"MAXDK") || !strcmp(sp,"DLKLIMIT") || !strcmp(sp,"KBLIMIT"))
-    bprintf("%lu",level_freecdtperday[useron.level]/1024L);
-
-else if(!strcmp(sp,"DAYBYTES"))     /* amt of free cdts used today */
-    bprintf("%lu",level_freecdtperday[useron.level]-useron.freecdt);
-
-else if(!strcmp(sp,"BYTELIMIT"))
-    bprintf("%lu",level_freecdtperday[useron.level]);
-
-else if(!strcmp(sp,"KBLEFT"))
-    bprintf("%lu",(useron.cdt+useron.freecdt)/1024L);
-
-else if(!strcmp(sp,"BYTESLEFT"))
-    bprintf("%lu",useron.cdt+useron.freecdt);
-
-else if(!strcmp(sp,"CONF"))
-    bprintf("%s %s"
-		,usrgrps ? grp[usrgrp[curgrp]]->sname :nulstr
-		,usrgrps ? sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
-
-else if(!strcmp(sp,"CONFNUM"))
-    bprintf("%u %u",curgrp+1,cursub[curgrp]+1);
-
-else if(!strcmp(sp,"NUMDIR"))
-	bprintf("%u %u",usrlibs ? curlib+1 : 0,usrlibs ? curdir[curlib]+1 : 0);
-
-else if(!strcmp(sp,"EXDATE") || !strcmp(sp,"EXPDATE"))
-    bputs(unixtodstr(useron.expire,str2));
-
-else if(!strcmp(sp,"EXPDAYS")) {
-    now=time(NULL);
-	l=useron.expire-now;
-	if(l<0)
-		l=0;
-	bprintf("%u",l/(1440L*60L)); }
-
-else if(!strcmp(sp,"MEMO1"))
-    bputs(useron.note);
-
-else if(!strcmp(sp,"MEMO2") || !strcmp(sp,"COMPANY"))
-    bputs(useron.name);
-
-else if(!strcmp(sp,"ZIP"))
-	bputs(useron.zipcode);
-
-else if(!strcmp(sp,"HANGUP"))
-    hangup();
-
-else
-	return(syncatcodes(sp,len));
-
-return(len);
-}
-
-
-
diff --git a/src/sbbs2/autonode/autonode.c b/src/sbbs2/autonode/autonode.c
deleted file mode 100644
index f8bdde37e4023d55b9bd359af954bf099dfa753f..0000000000000000000000000000000000000000
--- a/src/sbbs2/autonode/autonode.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* AUTONODE.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <io.h>
-#include <dir.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <process.h>
-#include <sys\stat.h>
-
-#define uchar unsigned char
-#define uint unsigned int
-#define ulong unsigned long
-#define LOOP_NODEDAB 100    /* Retries on NODE.DAB locking/unlocking    */
-
-typedef struct {						/* Node information kept in NODE.DAB */
-	uchar	status,						/* Current Status of Node */
-			errors,						/* Number of Critical Errors */
-			action;						/* Action User is doing on Node */
-	uint	useron,						/* User on Node */
-			connection,					/* Connection rate of Node */
-			misc,						/* Miscellaneous bits for node */
-			aux;						/* Auxillary word for node */
-	ulong	extaux;						/* Extended aux dword for node */
-            } node_t;
-
-enum {								/* Node Status */
-	 NODE_WFC			        	/* Waiting for Call */
-	,NODE_LOGON                  	/* at logon prompt */
-	,NODE_NEWUSER         			/* New user applying */
-	,NODE_INUSE			 			/* In Use */
-	,NODE_QUIET			 			/* In Use - quiet mode */
-	,NODE_OFFLINE		 			/* Offline */
-	,NODE_NETTING		 			/* Networking */
-	,NODE_EVENT_WAITING				/* Waiting for all nodes to be inactive */
-	,NODE_EVENT_RUNNING				/* Running an external event */
-	,NODE_EVENT_LIMBO				/* Allowing another node to run an event */
-    };
-
-int nodefile;
-
-void main();
-void getnodedat(uchar number, node_t *node, char lockit);
-void putnodedat(uchar number, node_t node);
-void truncsp(char *str);
-
-void main(int argc,char *argv[])
-{
-	FILE *fp;
-	char str[256],nodepath[256],*p
-		,sbbs_ctrl[256],sbbs_node[256],path[MAXPATH]
-		,*arg[10]={NULL};
-	int file,num_nodes,autonode,disk,x,y;
-	node_t node;
-
-printf("\nSynchronet AUTONODE v2.00\n");
-
-	if(!strcmp(argv[1],"/?")) {
-		printf("\nUsage: AUTONODE [file] [args,...]");
-		printf("\n\nWhere [file]     is the name of the file to run and");
-		printf("\n      [args,...] are the command line arguments to use");
-		printf("\n\nNOTE: The default command line is 'SBBS l q'\n");
-		return; }
-	p=getenv("SBBSCTRL");
-	if(!p) {
-		printf("\n\7You must set the SBBSCTRL environment variable first.");
-		printf("\n\nExample: SET SBBSCTRL=C:\\SBBS\\CTRL\n");
-		return; }
-	sprintf(sbbs_ctrl,"%.40s",p);
-	strupr(sbbs_ctrl);
-	if(sbbs_ctrl[strlen(sbbs_ctrl)-1]!='\\')
-		strcat(sbbs_ctrl,"\\");
-	p=getenv("SBBSNODE");
-	if(!p) {
-		printf("\n\7You must set the SBBSNODE environment variable first.");
-		printf("\n\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-        return; }
-	sprintf(sbbs_node,"%.40s",p);
-	strupr(sbbs_node);
-	if(sbbs_node[strlen(sbbs_node)-1]!='\\')
-		strcat(sbbs_node,"\\");
-
-	sprintf(str,"%sNODE.DAB",sbbs_ctrl);
-	if((nodefile=open(str,O_RDWR|O_BINARY|O_DENYNONE))==-1) {
-        printf("Error opening %s",str); exit(1); }
-
-	sprintf(str,"%sMAIN.CNF",sbbs_ctrl);
-	if((file=open(str,O_RDONLY|O_DENYNONE|O_BINARY))==-1) {
-		printf("Error opening %s",str);
-		exit(1); }
-	lseek(file,227L,SEEK_SET);
-	read(file,&num_nodes,2);
-	printf("\nNumber of Available Nodes = %d",num_nodes);
-	lseek(file,64L*(long)num_nodes,SEEK_CUR);
-	lseek(file,328L,SEEK_CUR);
-	read(file,&autonode,2);
-	printf("\nNumber of First Autonode  = %d",autonode);
-	for(x=autonode;x<=num_nodes;x++) {
-		printf("\nChecking Node #%d",x);
-		getnodedat(x,&node,1);
-		if(node.status==NODE_OFFLINE) {
-			printf("\nFOUND! Node #%d is OFFLINE\n",x);
-			node.status=NODE_WFC;
-			putnodedat(x,node);
-			lseek(file,(229L+((long)(x-1)*64L)),SEEK_SET);
-			read(file,nodepath,128);
-			truncsp(nodepath);
-			if(nodepath[strlen(nodepath)-1]=='\\')
-				nodepath[strlen(nodepath)-1]=0; 	/* remove '\' */
-			if(nodepath[0]=='.')
-				sprintf(path,"%s%s",sbbs_node,nodepath);
-			else strcpy(path,nodepath);
-			if(path[1]==':')
-				setdisk(path[0]-'A');
-			if(chdir(path)) {
-				printf("\nError changing into '%s'",path);
-				getnodedat(x,&node,1);
-				node.status=NODE_OFFLINE;
-				putnodedat(x,node);
-				exit(1); }
-			if(argc==1) {
-				execl(getenv("COMSPEC"),getenv("COMSPEC"),"/c","SBBS","l","q",
-					NULL); }
-			else {
-				arg[0]=argv[0];
-				strcpy(str,"/c"); arg[1]=str;
-				for(x=1;x<argc;x++) arg[1+x]=argv[x];
-				execv(getenv("COMSPEC"),arg); }
-			getnodedat(x,&node,1);
-			node.status=NODE_OFFLINE;
-			putnodedat(x,node);
-			return; } }
-	printf("\n\n\7All local nodes are in use!\n");
-}
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(uchar number, node_t *node, char lockit)
-{
-	char str[256];
-	int count=0;
-
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count==LOOP_NODEDAB)
-	printf("\7Error unlocking and reading NODE.DAB\n");
-}
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(uchar number, node_t node)
-{
-	char str[256];
-	int count;
-
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	printf("\7Error writing NODE.DAB for node %u\n",number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && str[c-1]<=32) c--;
-str[c]=0;
-}
diff --git a/src/sbbs2/baja/baja.c b/src/sbbs2/baja/baja.c
deleted file mode 100644
index 32fee550115ce43bc3acb3133f8cb3447ed31855..0000000000000000000000000000000000000000
--- a/src/sbbs2/baja/baja.c
+++ /dev/null
@@ -1,3115 +0,0 @@
-/* BAJA.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <io.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <share.h>
-#include <alloc.h>
-#include "cmdshell.h"
-#include "ars_defs.h"
-#include "crc32.h"
-
-unsigned _stklen=20000; 		  /* Set stack size in code, not header */
-
-char **label_name=NULL
-	,**goto_file=NULL
-	,**goto_label=NULL
-	,**call_file=NULL
-	,**call_label=NULL;
-
-ulong *var_name=NULL,vars=0;
-
-char **define_str=NULL
-	,**define_val=NULL;
-
-char *linestr="%s %d: %s\n";
-char tmp[256];
-
-uint *label_indx=NULL
-	,*goto_indx=NULL
-	,*goto_line=NULL
-	,*call_indx=NULL
-	,*call_line=NULL;
-
-uint display=0,line=0,labels=0,gotos=0,calls=0,defines=0,case_sens=0;
-
-FILE *out=NULL;
-
-void bail(void)
-{
-if(out)
-	chsize(fileno(out),0);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-c=strlen(str);
-while(c && str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/* C Escape char */
-
-uchar cesc(char ch)
-{
-switch(ch) {
-	case 'r':
-		return(CR);
-	case 'n':
-		return(LF);
-	case 't':
-		return(TAB);
-	case 'b':
-		return(BS);
-	case 'a':
-		return(7);
-	case 'f':
-		return(FF);
-	case 'v':
-		return(11);
-	default:
-		return(ch); }
-}
-
-long val(char *src, char *p)
-{
-	static int inside;
-	long l;
-
-if(isdigit(*p) || *p=='-')      /* Dec, Hex, or Oct */
-	l=strtol(p,&p,0);
-else if(*p=='\'') {  /* Char */
-	p++;
-	if(*p=='\\') {
-		p++;
-		l=cesc(*p); }
-	else
-		l=*p;
-	p++; }
-else if(*p=='.')    /* Bit */
-	l=1L<<strtol(p+1,&p,0);
-else {
-	printf("SYNTAX ERROR (expecting integer constant):\n");
-	printf(linestr,src,line,*p ? p : "<end of line>");
-	exit(1);
-	return(0); }
-if(inside) {
-	return(l); }
-inside=1;
-while(*p)
-	switch(*(p++)) {
-		case '+':
-			l+=val(src,p);
-			break;
-		case '-':
-			l-=val(src,p);
-			break;
-		case '*':
-			l*=val(src,p);
-			break;
-		case '/':
-			l/=val(src,p);
-			break;
-		case '%':
-			l%=val(src,p);
-			break;
-		case '&':
-			l&=val(src,p);
-			break;
-		case '|':
-			l|=val(src,p);
-			break;
-		case '~':
-			l&=~val(src,p);
-			break;
-		case '^':
-			l^=val(src,p);
-			break;
-		case '>':
-			if(*p=='>') {
-				p++;
-				l>>=val(src,p); }
-			break;
-		case '<':
-			if(*p=='<') {
-				p++;
-				l<<=val(src,p); }
-			break;
-		case SP:
-		case '#':
-			inside=0;
-			return(l); }
-inside=0;
-return(l);
-}
-
-
-void writecstr(uchar *p)
-{
-	char str[1024];
-	int j=0,inquotes=0;
-
-while(*p) {
-	if(*p=='"') {   /* ignore quotes */
-		if(inquotes)
-			break;
-		inquotes=1;
-		p++;
-		continue; }
-	if(*p=='\\')    { /* escape */
-		p++;
-		if(isdigit(*p)) {
-			str[j]=atoi(p); 		/* decimal, NOT octal */
-			if(isdigit(*(++p))) 	/* skip up to 3 digits */
-				if(isdigit(*(++p)))
-					p++;
-			j++;
-			continue; }
-		switch(*(p++)) {
-			case 'x':
-				tmp[0]=*(p++);
-                tmp[1]=0;
-				if(isxdigit(*p)) {	/* if another hex digit, skip too */
-					tmp[1]=*(p++);
-                    tmp[2]=0; }
-				str[j]=(char)ahtoul(tmp);
-                break;
-			case 'r':
-				str[j]=CR;
-				break;
-			case 'n':
-				str[j]=LF;
-				break;
-			case 't':
-				str[j]=TAB;
-				break;
-			case 'b':
-				str[j]=BS;
-				break;
-			case 'a':
-				str[j]=7;	/* BEL */
-				break;
-			case 'f':
-				str[j]=FF;
-				break;
-			case 'v':
-				str[j]=11;	/* VT */
-				break;
-			default:
-				str[j]=*(p-1);
-				break; }
-		j++;
-		continue; }
-	str[j++]=*(p++); }
-str[j]=0;
-fwrite(str,1,j+1,out);
-}
-
-void writestr(uchar *p)
-{
-	char str[1024];
-	int j=0;
-
-while(*p) {
-	if(*p=='"') {   /* ignore quotes */
-		p++;
-		continue; }
-	if(*p=='\\' && *(p+1)=='"' && *(p+2))
-		p++;
-	str[j++]=*(p++); }
-str[j]=0;
-fwrite(str,1,j+1,out);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-void cvttab(char *str)
-{
-	int i;
-
-for(i=0;str[i];i++)
-	if(str[i]==TAB)
-		str[i]=SP;
-}
-
-void newvar(uchar *in)
-{
-	uchar name[128];
-	long i,l;
-
-sprintf(name,"%.80s",in);
-if(!case_sens)
-	strupr(name);
-l=crc32(name);
-for(i=0;i<vars;i++)
-	if(var_name[i]==l)
-		break;
-if(i<vars)
-	return;
-if((var_name=(ulong *)REALLOC(var_name,sizeof(long)*(vars+1)))==NULL) {
-	printf("Too many (%lu) variables!\r\n",vars);
-	exit(1); }
-var_name[vars]=l;
-if(display)
-	printf("newvar(%08lX)=%s\n",l,in);
-vars++;
-}
-
-void writecrc(uchar *src, uchar *in)
-{
-	uchar name[128];
-	long i,l;
-
-sprintf(name,"%.80s",in);
-if(!case_sens)
-	strupr(name);
-if(!stricmp(name,"STR") || !name[0])
-	l=0;
-else {
-	l=crc32(name);
-
-	for(i=0;i<vars;i++)
-		if(var_name[i]==l)
-			break;
-	if(i==vars) {
-		printf("SYNTAX ERROR (expecting variable name):\n");
-		printf(linestr,src,line,*in ? in : "<end of line>");
-		exit(1); }
-
-		}
-fwrite(&l,4,1,out);
-}
-
-long isvar(uchar *arg)
-{
-	uchar name[128],*p;
-	long i,l;
-
-if(!arg || !*arg)
-	return(0);
-
-sprintf(name,"%.80s",arg);
-if((p=strchr(name,SP))!=NULL)	// Truncate at first space
-	*p=0;
-if(!case_sens)
-	strupr(name);
-l=crc32(name);
-
-for(i=0;i<vars;i++)
-	if(var_name[i]==l)
-		break;
-if(i==vars)
-	return(0);
-return(l);
-}
-
-int str_cmp(char *s1, char *s2)
-{
-if(case_sens)
-	return(strcmp(s1,s2));
-return(stricmp(s1,s2));
-}
-
-void expdefs(uchar *line)
-{
-	uchar str[512],*p,*sp,sav[2]={0};
-	int i;
-
-str[0]=0;
-for(p=line;*p;p++) {
-	if(*p==SP) {
-		strcat(str," ");
-		continue; }
-
-	if(*p=='"') {               /* Skip quoted text */
-		sp=strchr(p+1,'"');
-		if(sp) *sp=0;
-		strcat(str,p);
-		if(!sp)
-			break;
-		strcat(str,"\"");
-		p+=strlen(p);
-		continue; }
-
-	for(sp=p;*sp;sp++)
-		if(!isalnum(*sp) && *sp!='_')
-			break;
-	sav[0]=*sp; 		/* Save delimiter */
-	sav[1]=0;
-	*sp=0;
-	for(i=0;i<defines;i++)
-		if(!str_cmp(define_str[i],p))
-			break;
-	if(i<defines)
-		strcat(str,define_val[i]);
-	else
-		strcat(str,p);
-	if(!sav[0]) 		/* Last argument */
-		break;
-	p+=strlen(p);
-	strcat(str,sav);	/* Restore delimiter */
-	}
-strcpy(line,str);
-}
-
-
-
-void compile(char *src)
-{
-	uchar str[1024],save[1024],*p,*sp,*tp,*arg,*arg2,*arg3,*ar,ch;
-    ushort i,j;
-	long l,v,savline;
-	FILE *in;
-
-strupr(src);
-if((in=fopen(src,"rb"))==NULL) {
-    printf("error opening %s for read\n",src);
-    exit(1); }
-line=0;
-
-while(!feof(in) && !ferror(in)) {
-    if(!fgets(str,1000,in))
-        break;
-    truncsp(str);
-    cvttab(str);
-    line++;
-    strcpy(save,str);
-    p=str;
-    while(*p && *p<=SP)   /* look for beginning of command */
-        p++;
-    if(!*p)
-        continue;
-    if(*p=='#')             /* remarks start with # */
-        continue;
-	expdefs(p); 			/* expand defines */
-	if(display)
-		printf("%s\n",p);
-    sp=strchr(p,SP);
-    arg=arg2=arg3="";
-    if(sp) {
-        *sp=0;
-        arg=sp+1;
-        while(*arg && *arg<=SP) arg++;
-        sp=strchr(arg,SP);
-        if(sp) {
-            arg2=sp+1;
-            while(*arg2 && *arg2<=SP) arg2++;
-            sp=strchr(arg2,SP);
-            if(sp) {
-                arg3=sp+1;
-                while(*arg3 && *arg3<=SP) arg3++; } } }
-
-	if(!stricmp(p,"!INCLUDE")) {
-		savline=line;
-		sp=strchr(arg,SP);
-		if(sp) *sp=0;
-		compile(arg);
-		line=savline;
-		continue; }
-
-	if(!stricmp(p,"!DEFINE")) {                     /* define */
-		sp=strchr(arg,SP);
-		if(sp)
-			*sp=0;
-		else
-			break;
-		tp=strrchr(arg2,'\"');
-		if(!tp)
-			tp=arg2;
-		sp=strchr(tp,'#');
-		if(sp)
-            *sp=0;
-        truncsp(arg2);
-		if((define_str=(char **)REALLOC(define_str,sizeof(char *)*defines+1))
-            ==NULL) {
-			printf("Too many defines.\r\n");
-            exit(1); }
-		if((define_str[defines]=(char *)MALLOC(strlen(arg)+1))==NULL) {
-			printf("Too many defines.\r\n");
-            exit(1); }
-		if((define_val=(char **)REALLOC(define_val,sizeof(char *)*defines+1))
-            ==NULL) {
-			printf("Too many defines.\r\n");
-            exit(1); }
-		if((define_val[defines]=(char *)MALLOC(strlen(arg2)+1))==NULL) {
-			printf("Too many defines.\r\n");
-            exit(1); }
-		strcpy(define_str[defines],arg);
-		strcpy(define_val[defines],arg2);
-		defines++;
-        continue; }
-
-	if(!stricmp(p,"!GLOBAL")) {             /* declare global variables */
-		if(!*arg) break;
-		for(p=arg;*p && *p!='#';) {
-            sp=strchr(p,SP);
-            if(sp) *sp=0;
-			newvar(p);
-            if(!sp)
-                break;
-            p=sp+1;
-            while(*p && *p<=SP)
-                p++; }
-        continue; }
-
-	if(!stricmp(p,"PATCH")) {
-        if(!*arg) break;
-        p=arg;
-        while(*p) {
-            while(*p && *p<=SP) p++;
-            tmp[0]=*p++;
-            tmp[1]=*p++;
-            tmp[2]=0;
-            if(!tmp[0])
-                break;
-            ch=ahtoul(tmp);
-            fputc(ch,out); }
-        continue; }
-
-	if(!stricmp(p,"SHOW_VARS")) {
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SHOW_VARS,out);
-        continue; }
-
-	if(!stricmp(p,"COMPARE_ARS")) {
-        if(!*arg) break;
-        strupr(arg);
-        ar=arstr(&i,arg);
-        fprintf(out,"%c%c",CS_COMPARE_ARS,(uchar)i);
-        fwrite(ar,i,1,out);
-        FREE(ar);
-        continue; }
-
-	if(!stricmp(p,"CHKSYSPASS")) {
-        fprintf(out,"%c",CS_CHKSYSPASS);
-        continue; }
-	if(!stricmp(p,"INFO_SYSTEM")) {
-        fprintf(out,"%c",CS_INFO_SYSTEM);
-        continue; }
-	if(!stricmp(p,"INFO_SUBBOARD")) {
-        fprintf(out,"%c",CS_INFO_SUBBOARD);
-        continue; }
-	if(!stricmp(p,"INFO_DIRECTORY")) {
-        fprintf(out,"%c",CS_INFO_DIRECTORY);
-        continue; }
-	if(!stricmp(p,"INFO_VERSION")) {
-        fprintf(out,"%c",CS_INFO_VERSION);
-        continue; }
-	if(!stricmp(p,"INFO_USER")) {
-        fprintf(out,"%c",CS_INFO_USER);
-        continue; }
-	if(!stricmp(p,"INFO_XFER_POLICY")) {
-        fprintf(out,"%c",CS_INFO_XFER_POLICY);
-        continue; }
-	if(!stricmp(p,"LOGKEY")) {
-        fprintf(out,"%c",CS_LOGKEY);
-        continue; }
-	if(!stricmp(p,"LOGKEY_COMMA")) {
-        fprintf(out,"%c",CS_LOGKEY_COMMA);
-        continue; }
-	if(!stricmp(p,"LOGSTR")) {
-        fprintf(out,"%c",CS_LOGSTR);
-        continue; }
-
-	if(!stricmp(p,"ONLINE")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_ONLINE);
-		continue; }
-	if(!stricmp(p,"OFFLINE")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_OFFLINE);
-		continue; }
-	if(!stricmp(p,"NEWUSER")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_NEWUSER);
-        continue; }
-	if(!stricmp(p,"LOGON")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_LOGON);
-        continue; }
-	if(!stricmp(p,"LOGOUT")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_LOGOUT);
-        continue; }
-	if(!stricmp(p,"EXIT")) {
-		fprintf(out,"%c%c",CS_ONE_MORE_BYTE,CS_EXIT);
-        continue; }
-
-	if(!stricmp(p,"USER_EVENT")) {
-		if(!*arg)
-			break;
-		if((l=isvar(arg))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(2,out);		// int offset
-            fputc(1,out);       // int length
-            ch=0; }             // place holder
-        else
-            ch=val(src,arg);
-		fprintf(out,"%c%c",CS_TWO_MORE_BYTES,CS_USER_EVENT);
-		fwrite(&ch,1,1,out);
-		continue; }
-
-	if(!stricmp(p,"PUT_NODE")) {
-		fprintf(out,"%c",CS_PUT_NODE);
-		continue; }
-	if(!stricmp(p,"SYNC")) {
-        fprintf(out,"%c",CS_SYNC);
-        continue; }
-	if(!stricmp(p,"ASYNC")) {
-        fprintf(out,"%c",CS_ASYNC);
-        continue; }
-	if(!stricmp(p,"RIOSYNC")) {
-        fprintf(out,"%c",CS_RIOSYNC);
-        continue; }
-	if(!stricmp(p,"GETTIMELEFT")) {
-        fprintf(out,"%c",CS_GETTIMELEFT);
-        continue; }
-	if(!stricmp(p,"SAVELINE")) {
-        fprintf(out,"%c",CS_SAVELINE);
-        continue; }
-	if(!stricmp(p,"RESTORELINE")) {
-        fprintf(out,"%c",CS_RESTORELINE);
-        continue; }
-	if(!stricmp(p,"IF_TRUE") || !stricmp(p,"IF_EQUAL")) {
-        fprintf(out,"%c",CS_IF_TRUE);
-        continue; }
-	if(!stricmp(p,"IF_FALSE") || !stricmp(p,"IF_NOT_EQUAL")) {
-        fprintf(out,"%c",CS_IF_FALSE);
-        continue; }
-	if(!stricmp(p,"IF_GREATER")) {
-        fprintf(out,"%c",CS_IF_GREATER);
-        continue; }
-	if(!stricmp(p,"IF_GREATER_OR_EQUAL")
-		|| !stricmp(p,"IF_EQUAL_OR_GREATER")) {
-        fprintf(out,"%c",CS_IF_GREATER_OR_EQUAL);
-        continue; }
-	if(!stricmp(p,"IF_LESS")) {
-        fprintf(out,"%c",CS_IF_LESS);
-        continue; }
-	if(!stricmp(p,"IF_LESS_OR_EQUAL")
-		|| !stricmp(p,"IF_EQUAL_OR_LESS")) {
-        fprintf(out,"%c",CS_IF_LESS_OR_EQUAL);
-        continue; }
-	if(!stricmp(p,"ENDIF") || !stricmp(p,"END_IF")) {
-        fprintf(out,"%c",CS_ENDIF);
-        continue; }
-	if(!stricmp(p,"ELSE")) {
-        fprintf(out,"%c",CS_ELSE);
-        continue; }
-    if(p[0]==':') {                     /* :label */
-		p++;
-		sp=strchr(p,SP);
-		if(sp)
-			*sp=0;
-		for(i=0;i<labels;i++)
-			if(!stricmp(label_name[i],p))
-				break;
-		if(i<labels) {
-			printf("SYNTAX ERROR (duplicate label name):\n");
-			printf(linestr,src,line,p);
-			exit(1); }
-        if((label_name=(char **)REALLOC(label_name,sizeof(char *)*labels+1))
-            ==NULL) {
-			printf("Too many labels.\n");
-            exit(1); }
-        if((label_indx=(uint *)REALLOC(label_indx,sizeof(int)*labels+1))
-            ==NULL) {
-			printf("Too many labels.\n");
-            exit(1); }
-		if((label_name[labels]=(char *)MALLOC(strlen(p)+1))==NULL) {
-            printf("Too many labels.\r\n");
-            exit(1); }
-		strcpy(label_name[labels],p);
-        label_indx[labels]=ftell(out);
-        labels++;
-        continue; }
-	if(!stricmp(p,"GOTO")) {           /* goto */
-        if(!*arg) break;
-		sp=strchr(arg,SP);
-		if(sp)
-			*sp=0;
-        if((goto_label=(char **)REALLOC(goto_label,sizeof(char *)*gotos+1))
-            ==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-		if((goto_file=(char **)REALLOC(goto_file,sizeof(char *)*gotos+1))
-            ==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-        if((goto_indx=(uint *)REALLOC(goto_indx,sizeof(int)*gotos+1))
-            ==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-        if((goto_line=(uint *)REALLOC(goto_line,sizeof(int)*gotos+1))
-            ==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-        if((goto_label[gotos]=(char *)MALLOC(strlen(arg)+1))==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-		if((goto_file[gotos]=(char *)MALLOC(strlen(str)+1))==NULL) {
-            printf("Too many gotos.\r\n");
-            exit(1); }
-        strcpy(goto_label[gotos],arg);
-		strcpy(goto_file[gotos],str);
-        goto_indx[gotos]=ftell(out);
-        goto_line[gotos]=line;
-        gotos++;
-        fprintf(out,"%c%c%c",CS_GOTO,0xff,0xff);
-        continue; }
-	if(!stricmp(p,"CALL")) {          /* call */
-        if(!*arg) break;
-		sp=strchr(arg,SP);
-		if(sp)
-            *sp=0;
-		if((call_label=(char **)REALLOC(call_label,sizeof(char *)*(calls+1)))
-            ==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-		if((call_file=(char **)REALLOC(call_file,sizeof(char *)*(calls+1)))
-            ==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-		if((call_indx=(uint *)REALLOC(call_indx,sizeof(int)*(calls+1)))
-            ==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-		if((call_line=(uint *)REALLOC(call_line,sizeof(int)*(calls+1)))
-            ==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-        if((call_label[calls]=(char *)MALLOC(strlen(arg)+1))==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-		if((call_file[calls]=(char *)MALLOC(strlen(src)+1))==NULL) {
-            printf("Too many calls.\r\n");
-            exit(1); }
-
-        strcpy(call_label[calls],arg);
-		strcpy(call_file[calls],src);
-        call_indx[calls]=ftell(out);
-        call_line[calls]=line;
-        calls++;
-        fprintf(out,"%c%c%c",CS_CALL,0xff,0xff);
-        continue; }
-
-	if(!stricmp(p,"RETURN")) {
-        fprintf(out,"%c",CS_RETURN);
-        continue; }
-	if(!stricmp(p,"CMD_HOME")) {
-        fprintf(out,"%c",CS_CMD_HOME);
-        continue; }
-	if(!stricmp(p,"CMDKEY")) {
-        if(!*arg) break;
-		if(!stricmp(arg,"DIGIT"))
-            ch=CS_DIGIT;
-		else if(!stricmp(arg,"EDIGIT"))
-            ch=CS_EDIGIT;
-		else
-            ch=toupper(*arg);
-        if(ch=='/')
-            ch=*(arg+1)|0x80;   /* high bit indicates slash required */
-        else if(ch=='^' && *(arg+1)>=0x40)
-            ch=*(arg+1)-0x40;   /* ctrl char */
-		else if(ch=='\\')
-            ch=cesc(*(arg+1));
-		else if(ch=='\'')
-            ch=*(arg+1);
-        fprintf(out,"%c%c",CS_CMDKEY,ch);
-        continue; }
-	if(!stricmp(p,"SETLOGIC") || !stricmp(p,"SET_LOGIC")) {
-        if(!*arg) break;
-		if(!stricmp(arg,"TRUE") || !stricmp(arg,"EQUAL"))
-            ch=LOGIC_TRUE;
-		else if(!stricmp(arg,"GREATER"))
-            ch=LOGIC_GREATER;
-		else if(!stricmp(arg,"LESS"))
-            ch=LOGIC_LESS;
-        else
-            ch=LOGIC_FALSE;
-        fprintf(out,"%c%c",CS_SETLOGIC,ch);
-        continue; }
-
-	if(!stricmp(p,"DEFINE_STR_VAR") || !stricmp(p,"STR")) {
-        if(!*arg) break;
-		for(p=arg;*p && *p!='#';) {
-            sp=strchr(p,SP);
-            if(sp) *sp=0;
-            fputc(CS_VAR_INSTRUCTION,out);
-			fputc(DEFINE_STR_VAR,out);
-			newvar(p);
-			writecrc(src,p);
-            if(!sp)
-                break;
-            p=sp+1;
-            while(*p && *p<=SP)
-                p++; }
-        continue; }
-	if(!stricmp(p,"DEFINE_INT_VAR") || !stricmp(p,"INT")) {
-        if(!*arg) break;
-		for(p=arg;*p && *p!='#';) {
-            sp=strchr(p,SP);
-            if(sp) *sp=0;
-            fputc(CS_VAR_INSTRUCTION,out);
-            fputc(DEFINE_INT_VAR,out);
-			newvar(p);
-			writecrc(src,p);
-            if(!sp)
-                break;
-            p=sp+1;
-            while(*p && *p<=SP)
-                p++; }
-		continue; }
-	if(!stricmp(p,"DEFINE_GLOBAL_STR_VAR") || !stricmp(p,"GLOBAL_STR")) {
-        if(!*arg) break;
-		for(p=arg;*p && *p!='#';) {
-            sp=strchr(p,SP);
-            if(sp) *sp=0;
-            fputc(CS_VAR_INSTRUCTION,out);
-			fputc(DEFINE_GLOBAL_STR_VAR,out);
-			newvar(p);
-			writecrc(src,p);
-            if(!sp)
-                break;
-            p=sp+1;
-            while(*p && *p<=SP)
-                p++; }
-        continue; }
-	if(!stricmp(p,"DEFINE_GLOBAL_INT_VAR") || !stricmp(p,"GLOBAL_INT")) {
-        if(!*arg) break;
-		for(p=arg;*p && *p!='#';) {
-            sp=strchr(p,SP);
-            if(sp) *sp=0;
-            fputc(CS_VAR_INSTRUCTION,out);
-			fputc(DEFINE_GLOBAL_INT_VAR,out);
-			newvar(p);
-			writecrc(src,p);
-            if(!sp)
-                break;
-            p=sp+1;
-            while(*p && *p<=SP)
-                p++; }
-        continue; }
-
-	if(!stricmp(p,"LOGIN")) {
-		if(!*arg) break;
-		fputc(CS_STR_FUNCTION,out);
-		fputc(CS_LOGIN,out);
-		writecstr(arg);
-		continue; }
-
-	if(!stricmp(p,"LOAD_TEXT")) {
-		if(!*arg) break;
-		fputc(CS_STR_FUNCTION,out);
-		fputc(CS_LOAD_TEXT,out);
-		writestr(arg);
-        continue; }
-
-	if(!stricmp(p,"SET_STR_VAR")
-		|| (!stricmp(p,"SET") && strchr(arg,'"'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SET_STR_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecstr(arg2);
-        continue; }
-	if(!stricmp(p,"CAT_STR_VAR")
-		|| (!stricmp(p,"STRCAT") && strchr(arg,'"'))) {
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(CAT_STR_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecstr(arg2);
-        continue; }
-	if((!stricmp(p,"STRSTR") || !stricmp(p,"COMPARE_SUBSTR"))
-		&& strchr(arg,'"')) {
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(STRSTR_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecstr(arg2);
-        continue; }
-	if(!stricmp(p,"STRSTR") || !stricmp(p,"COMPARE_SUBSTR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(STRSTR_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"CAT_STR_VARS") || !stricmp(p,"STRCAT")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(CAT_STR_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"FORMAT") || !stricmp(p,"SPRINTF")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(FORMAT_STR_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);					/* Write destination variable */
-        p++;
-        while(*p && *p<=SP) p++;
-        arg=p;
-        p=strrchr(arg,'"');
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        while(*p && *p<=SP) p++;
-        writecstr(arg);                 /* Write string */
-        l=ftell(out);
-        fputc(0,out);                   /* Write total number of args */
-        i=0;
-        while(p && *p) {
-            arg=p;
-            p=strchr(arg,SP);
-            if(p) {
-                *p=0;
-                p++; }
-			writecrc(src,arg);
-            i++; }
-        fseek(out,l,SEEK_SET);
-        fputc((char)i,out);
-        fseek(out,i*4,SEEK_CUR);
-        continue; }
-
-	if(!stricmp(p,"STRFTIME") || !stricmp(p,"FTIME_STR")) {
-        if(!*arg || !*arg2 || !*arg3) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(FORMAT_TIME_STR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);					/* Write destination variable */
-        p++;
-        while(*p && *p<=SP) p++;
-        arg=p;
-        p=strrchr(arg,'"');
-        if(!p)
-            break;
-        *p=0;
-        writecstr(arg);                 /* Write string */
-		p++;
-		while(*p && *p<=SP) p++;
-		writecrc(src,p);
-        continue; }
-
-	if(!stricmp(p,"TIME_STR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(TIME_STR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"DATE_STR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(DATE_STR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"SECOND_STR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SECOND_STR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-
-	if(!stricmp(p,"SET_INT_VAR")
-		|| (!stricmp(p,"SET") && *arg2!='"')) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SET_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"COMPARE_STR_VAR") ||
-		(!stricmp(p,"COMPARE") && *arg2=='"')) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(COMPARE_STR_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecstr(arg2);
-        continue; }
-
-	if(!stricmp(p,"COMPARE_STRN_VAR") ||
-		((!stricmp(p,"STRNCMP") || !stricmp(p,"COMPARE_STRN"))
-            && *arg3 && strchr(arg3,'"'))) {
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(2,out);		// int offset
-			fputc(1,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-		fputc(CS_VAR_INSTRUCTION,out);
-        fputc(STRNCMP_VAR,out);
-		fwrite(&i,1,1,out); /* Length */
-        p=strchr(arg2,SP);
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        while(*p && *p<=SP) p++;
-		writecrc(src,arg2);
-        writecstr(p);
-        continue; }
-
-	if(!stricmp(p,"COMPARE_STRN_VARS") || !stricmp(p,"STRNCMP")
-		|| !stricmp(p,"COMPARE_STRN")) {
-        if(!*arg || !*arg2 || !*arg3)
-            break;
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(2,out);		// int offset
-			fputc(1,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(STRNCMP_VARS,out);
-
-        fwrite(&i,1,1,out); /* Length */
-        p=strchr(arg2,SP);
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        while(*p && *p<=SP) p++;
-		writecrc(src,arg2);
-		writecrc(src,p);
-        continue; }
-
-	if(!stricmp(p,"COMPARE_INT_VAR") ||
-		(!stricmp(p,"COMPARE")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(COMPARE_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"COMPARE")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(COMPARE_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"COPY")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(COPY_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"SWAP")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SWAP_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"TIME")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(TIME_INT_VAR,out);
-		writecrc(src,arg);
-        continue; }
-
-	if(!stricmp(p,"DATE_INT")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(DATE_STR_TO_INT,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"CRC16")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(CRC16_TO_INT,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"CRC32")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(CRC32_TO_INT,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"CHKSUM")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(CHKSUM_TO_INT,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"ADD_INT_VAR")
-		|| (!stricmp(p,"ADD")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(ADD_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        if(!l)
-            break;
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"ADD_INT_VARS") || !stricmp(p,"ADD")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(ADD_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"SUB_INT_VAR")
-		|| (!stricmp(p,"SUB")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SUB_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        if(!l)
-            break;
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"SUB_INT_VARS") || !stricmp(p,"SUB")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(SUB_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"MUL_INT_VAR")
-		|| (!stricmp(p,"MUL")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(MUL_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        if(!l)
-            break;
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"MUL_INT_VARS") || !stricmp(p,"MUL")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(MUL_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"DIV_INT_VAR")
-		|| (!stricmp(p,"DIV")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(DIV_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        if(!l)
-            break;
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"DIV_INT_VARS") || !stricmp(p,"DIV")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(DIV_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"MOD_INT_VAR")
-		|| (!stricmp(p,"MOD")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(MOD_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        if(!l)
-            break;
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"MOD_INT_VARS") || !stricmp(p,"MOD")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-		fputc(MOD_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"AND_INT_VAR")
-		|| (!stricmp(p,"AND")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(AND_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"AND_INT_VARS") || !stricmp(p,"AND")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(AND_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"OR_INT_VAR")
-		|| (!stricmp(p,"OR")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(OR_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"OR_INT_VARS") || !stricmp(p,"OR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(OR_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"NOT_INT_VAR")
-		|| (!stricmp(p,"NOT")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(NOT_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"NOT_INT_VARS") || !stricmp(p,"NOT")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(NOT_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"XOR_INT_VAR")
-		|| (!stricmp(p,"XOR")
-			&& (isdigit(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(XOR_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		l=val(src,arg2);
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"XOR_INT_VARS") || !stricmp(p,"XOR")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(XOR_INT_VARS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-
-	if(!stricmp(p,"RANDOM_INT_VAR") || !stricmp(p,"RANDOM")) {
-        if(!*arg) break;
-		if((l=isvar(arg2))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(6,out);		// int offset
-			fputc(4,out);		// int length
-			l=0; }				// place holder
-		else
-			l=val(src,arg2);
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(RANDOM_INT_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"SWITCH")) {
-        if(!*arg) break;
-        fputc(CS_SWITCH,out);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"END_SWITCH")) {
-        fputc(CS_END_SWITCH,out);
-        continue; }
-	if(!stricmp(p,"CASE")) {
-        if(!*arg) break;
-        fputc(CS_CASE,out);
-		l=val(src,arg);
-        fwrite(&l,4,1,out);
-        continue; }
-	if(!stricmp(p,"DEFAULT")) {
-        fputc(CS_DEFAULT,out);
-        continue; }
-	if(!stricmp(p,"END_CASE")) {
-        fputc(CS_END_CASE,out);
-        continue; }
-
-	if(!stricmp(p,"PRINT") && !strchr(arg,'"') && !strchr(arg,'\\')
-        && !strchr(arg,SP)) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(PRINT_VAR,out);
-		writecrc(src,arg);
-        continue; }
-
-	if(!stricmp(p,"PRINTF")) {
-        if(!*arg) break;
-        fputc(CS_VAR_INSTRUCTION,out);
-        fputc(VAR_PRINTF,out);
-        p=strrchr(arg,'"');
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        while(*p && *p<=SP) p++;
-        writecstr(arg);                 /* Write string */
-        l=ftell(out);
-        fputc(0,out);                   /* Write total number of args */
-        i=0;
-        while(p && *p) {
-            arg=p;
-            p=strchr(arg,SP);
-            if(p) {
-                *p=0;
-                p++; }
-			writecrc(src,arg);
-            i++; }
-        fseek(out,l,SEEK_SET);
-        fputc((char)i,out);
-        fseek(out,i*4,SEEK_CUR);
-        continue; }
-
-	if(!stricmp(p,"FOPEN")) {
-		if(!*arg || !*arg2 || !*arg3) break;
-		if((l=isvar(arg2))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(6,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg2);
-
-        fputc(CS_FIO_FUNCTION,out);
-		if(*arg3=='"')
-			fputc(FIO_OPEN,out);
-		else
-			fputc(FIO_OPEN_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-        p=strchr(arg2,SP);
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        fwrite(&i,2,1,out);
-        while(*p && *p<=SP) p++;
-		if(*p=='"')
-			writestr(p);
-		else
-			writecrc(src,p);
-        continue; }
-	if(!stricmp(p,"FCLOSE")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_CLOSE,out);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"FFLUSH")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-		fputc(FIO_FLUSH,out);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"FREAD")) {
-        if(!*arg) break;
-
-        fputc(CS_FIO_FUNCTION,out);
-        if(!*arg3 || isdigit(*arg3) || atoi(arg3))
-            fputc(FIO_READ,out);
-        else
-            fputc(FIO_READ_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        p=strchr(arg2,SP);
-        if(p)
-            *p=0;
-		writecrc(src,arg2); 		/* Variable */
-		if(isdigit(*arg3))
-			i=val(src,arg3);	 /* Length */
-		else
-			i=0;
-		if(i || !*arg3)
-            fwrite(&i,2,1,out);
-        else
-			writecrc(src,arg3);
-        continue; }
-	if(!stricmp(p,"FWRITE")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        if(!*arg3 || isdigit(*arg3) || atoi(arg3))
-            fputc(FIO_WRITE,out);
-        else
-            fputc(FIO_WRITE_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        p=strchr(arg2,SP);
-        if(p)
-            *p=0;
-		writecrc(src,arg2); 		/* Variable */
-		if(isdigit(*arg3))
-			i=val(src,arg3);	 /* Length */
-		else
-			i=0;
-		if(i || !*arg3)
-            fwrite(&i,2,1,out);
-        else
-			writecrc(src,arg3);
-        continue; }
-	if(!stricmp(p,"FGET_LENGTH")
-		|| !stricmp(p,"FGETLENGTH")
-		|| !stricmp(p,"GETFLENGTH")) {
-        if(!*arg || !*arg2) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_GET_LENGTH,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-		writecrc(src,arg2); 		/* Variable */
-        continue; }
-	if(!stricmp(p,"FREAD_LINE")) {
-        if(!*arg || !*arg2) break;
-        fputc(CS_FIO_FUNCTION,out);
-		fputc(FIO_READ_LINE,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-		writecrc(src,arg2); 		/* Variable */
-        continue; }
-	if(!stricmp(p,"FEOF")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_EOF,out);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"FGET_POS")) {
-        if(!*arg || !*arg2) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_GET_POS,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-		writecrc(src,arg2); 		/* Variable */
-        continue; }
-	if(!stricmp(p,"FSET_POS") || !stricmp(p,"FSEEK")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        if(isdigit(*arg2) || atol(arg2))
-            fputc(FIO_SEEK,out);
-        else
-            fputc(FIO_SEEK_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        p=strchr(arg2,SP);
-        if(p)
-            *p=0;
-        if(atol(arg2) || isdigit(*arg2)) {
-			l=val(src,arg2);
-            fwrite(&l,4,1,out); }
-        else
-			writecrc(src,arg2); 		/* Offset variable */
-        i=0;
-        if(p) {
-            p++;
-            while(*p && *p<=SP) p++;
-            i=atoi(p);
-			if(!stricmp(p,"CUR"))
-                i=SEEK_CUR;
-			else if(!stricmp(p,"END"))
-                i=SEEK_END; }
-        fwrite(&i,2,1,out);
-        continue; }
-	if(!stricmp(p,"FLOCK")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        if(isdigit(*arg2) || atol(arg2))
-            fputc(FIO_LOCK,out);
-        else
-            fputc(FIO_LOCK_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        if(atol(arg2) || isdigit(*arg2)) {
-			l=val(src,arg2);
-            if(!l)
-                break;
-            fwrite(&l,4,1,out); }
-        else
-			writecrc(src,arg2); 	/* Length variable */
-        continue; }
-	if(!stricmp(p,"FUNLOCK")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        if(isdigit(*arg2) || atol(arg2))
-            fputc(FIO_UNLOCK,out);
-        else
-            fputc(FIO_UNLOCK_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        if(atol(arg2) || isdigit(*arg2)) {
-			l=val(src,arg2);
-            if(!l)
-                break;
-            fwrite(&l,4,1,out); }
-        else
-			writecrc(src,arg2); 		/* Length variable */
-        continue; }
-	if(!stricmp(p,"FSET_LENGTH")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        if(isdigit(*arg2) || atol(arg2))
-            fputc(FIO_SET_LENGTH,out);
-        else
-            fputc(FIO_SET_LENGTH_VAR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-        if(atol(arg2) || isdigit(*arg2)) {
-			l=val(src,arg2);
-            fwrite(&l,4,1,out); }
-        else
-			writecrc(src,arg2); 		/* Length variable */
-        continue; }
-	if(!stricmp(p,"FPRINTF")) {
-        if(!*arg) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_PRINTF,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);					/* Write destination variable */
-        p++;
-        while(*p && *p<=SP) p++;
-        arg=p;
-        p=strrchr(arg,'"');
-        if(!p)
-            break;
-        *p=0;
-        p++;
-        while(*p && *p<=SP) p++;
-        writecstr(arg);                 /* Write string */
-        l=ftell(out);
-        fputc(0,out);                   /* Write total number of args */
-        i=0;
-        while(p && *p) {
-            arg=p;
-            p=strchr(arg,SP);
-            if(p) {
-                *p=0;
-                p++; }
-			writecrc(src,arg);
-            i++; }
-        fseek(out,l,SEEK_SET);
-        fputc((char)i,out);
-        fseek(out,i*4,SEEK_CUR);
-        continue; }
-	if(!stricmp(p,"FSET_ETX")) {
-        if(!*arg) break;
-		if((l=isvar(arg))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-            fputc(2,out);       // int offset
-            fputc(1,out);       // int length
-			ch=0; } 			// place holder
-		else
-			ch=val(src,arg);
-
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_SET_ETX,out);
-        fwrite(&ch,1,1,out);
-        continue; }
-	if(!stricmp(p,"FGET_TIME")) {
-        if(!*arg || !*arg2) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_GET_TIME,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-		writecrc(src,arg2); 		/* Variable */
-        continue; }
-	if(!stricmp(p,"FSET_TIME")) {
-        if(!*arg || !*arg2) break;
-        fputc(CS_FIO_FUNCTION,out);
-        fputc(FIO_SET_TIME,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* File handle */
-		writecrc(src,arg2); 		/* Variable */
-        continue; }
-	if(!stricmp(p,"REMOVE_FILE")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(REMOVE_FILE,out);
-		writecrc(src,arg);			/* Str var */
-		continue; }
-	if(!stricmp(p,"RENAME_FILE")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(RENAME_FILE,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* str var */
-		writecrc(src,arg2); 		/* str var */
-        continue; }
-	if(!stricmp(p,"COPY_FILE")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(COPY_FILE,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* str var */
-		writecrc(src,arg2); 		/* str var */
-        continue; }
-	if(!stricmp(p,"MOVE_FILE")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(MOVE_FILE,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* str var */
-		writecrc(src,arg2); 		/* str var */
-        continue; }
-	if(!stricmp(p,"GET_FILE_ATTRIB")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(GET_FILE_ATTRIB,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* str var */
-		writecrc(src,arg2); 		/* int var */
-        continue; }
-	if(!stricmp(p,"SET_FILE_ATTRIB")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(SET_FILE_ATTRIB,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* str var */
-		writecrc(src,arg2); 		/* int var */
-        continue; }
-	if(!stricmp(p,"RMDIR") || !stricmp(p,"REMOVE_DIR")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(REMOVE_DIR,out);
-		writecrc(src,arg);			/* Str var */
-        continue; }
-	if(!stricmp(p,"MKDIR") || !stricmp(p,"MAKE_DIR")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(MAKE_DIR,out);
-		writecrc(src,arg);			/* Str var */
-        continue; }
-	if(!stricmp(p,"CHDIR") || !stricmp(p,"CHANGE_DIR")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(CHANGE_DIR,out);
-		writecrc(src,arg);			/* Str var */
-        continue; }
-	if(!stricmp(p,"OPEN_DIR")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(OPEN_DIR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* int var */
-		writecrc(src,arg2); 		/* str var */
-        continue; }
-	if(!stricmp(p,"READ_DIR")) {
-		if(!*arg || !*arg2) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(READ_DIR,out);
-        p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);			/* int var */
-		writecrc(src,arg2); 		/* str var */
-        continue; }
-	if(!stricmp(p,"REWIND_DIR")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(REWIND_DIR,out);
-		writecrc(src,arg);			/* int var */
-        continue; }
-	if(!stricmp(p,"CLOSE_DIR")) {
-		if(!*arg) break;
-		fputc(CS_FIO_FUNCTION,out);
-		fputc(CLOSE_DIR,out);
-		writecrc(src,arg);			/* int var */
-        continue; }
-
-	if(!stricmp(p,"NODE_ACTION")) {
-        if(!*arg) break;
-		if((l=isvar(arg))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-            fputc(1,out);       // int length
-			ch=0; } 			// place holder
-		else
-			ch=val(src,arg);
-
-        fprintf(out,"%c%c",CS_NODE_ACTION,ch);
-        continue; }
-	if(!stricmp(p,"NODE_STATUS")) {
-        if(!*arg) break;
-		if((l=isvar(arg))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-            fputc(1,out);       // int length
-			ch=0; } 			// place holder
-		else
-            ch=val(src,arg);
-
-		fprintf(out,"%c%c",CS_NODE_STATUS,ch);
-		continue; }
-	if(!stricmp(p,"END_CMD") || !stricmp(p,"ENDCMD")) {
-		fprintf(out,"%c",CS_END_CMD);
-		continue; }
-	if(!stricmp(p,"CMD_POP") || !stricmp(p,"CMDPOP")) {
-		fprintf(out,"%c",CS_CMD_POP);
-		continue; }
-	if(!stricmp(p,"CLS")) {
-        fprintf(out,"%c",CS_CLS);
-        continue; }
-	if(!stricmp(p,"CRLF")) {
-        fprintf(out,"%c",CS_CRLF);
-        continue; }
-	if(!stricmp(p,"PAUSE")) {
-        fprintf(out,"%c",CS_PAUSE);
-        continue; }
-	if(!stricmp(p,"PAUSE_RESET")) {
-        fprintf(out,"%c",CS_PAUSE_RESET);
-        continue; }
-	if(!stricmp(p,"CLEAR_ABORT")) {
-        fprintf(out,"%c",CS_CLEAR_ABORT);
-        continue; }
-	if(!stricmp(p,"GETLINES")) {
-        fprintf(out,"%c",CS_GETLINES);
-        continue; }
-	if(!stricmp(p,"GETFILESPEC")) {
-        fprintf(out,"%c",CS_GETFILESPEC);
-        continue; }
-	if(!stricmp(p,"FINDUSER")) {
-        fprintf(out,"%c",CS_FINDUSER);
-        continue; }
-
-	if(!stricmp(p,"LOG")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_LOG);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"MNEMONICS")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_MNEMONICS);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"PRINT")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_PRINT);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"PRINT_LOCAL")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_PRINT_LOCAL);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"PRINT_REMOTE")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_PRINT_REMOTE);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"PRINTFILE")) {
-        if(!*arg) break;
-		if(*arg=='"') {
-			fprintf(out,"%c",CS_PRINTFILE);
-			writestr(arg); }
-		else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(2,out);		// int length
-				i=0; }				// place holder
-			else
-				i=val(src,arg2);
-
-			fprintf(out,"%c%c",CS_VAR_INSTRUCTION,PRINTFILE_VAR_MODE);
-			p=strchr(arg,SP);
-			if(p) *p=0;
-			writecrc(src,arg);
-			fwrite(&i,2,1,out); }
-		continue; }
-	if(!stricmp(p,"PRINTTAIL")) {
-		if(!*arg || !*arg2)
-			break;
-		if((l=isvar(arg3))!=0) {
-            fputc(CS_USE_INT_VAR,out);
-            fwrite(&l,4,1,out); // variable
-			fputc(8,out);		// int offset
-            fputc(1,out);       // int length
-			j=0; }				// place holder
-		else
-			j=val(src,arg3);
-
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,PRINTTAIL_VAR_MODE);
-		p=strchr(arg,SP);
-		if(p) *p=0;
-		writecrc(src,arg);
-		i=val(src,arg2);
-		fwrite(&i,2,1,out);
-		fwrite(&j,1,1,out);
-		continue; }
-
-	if(!stricmp(p,"PRINTFILE_STR")) {
-        fprintf(out,"%c",CS_PRINTFILE_STR);
-        continue; }
-	if(!stricmp(p,"PRINTFILE_LOCAL")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_PRINTFILE_LOCAL);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"PRINTFILE_REMOTE")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_PRINTFILE_REMOTE);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"EXEC")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_EXEC);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"EXEC_INT")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_EXEC_INT);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"EXEC_BIN")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_EXEC_BIN);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"EXEC_XTRN")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_EXEC_XTRN);
-		writestr(arg);
-        continue; }
-
-	if(!stricmp(p,"SELECT_SHELL")) {
-        fprintf(out,"%c",CS_SELECT_SHELL);
-        continue; }
-	if(!stricmp(p,"SET_SHELL")) {
-        fprintf(out,"%c",CS_SET_SHELL);
-        continue; }
-	if(!stricmp(p,"SELECT_EDITOR")) {
-        fprintf(out,"%c",CS_SELECT_EDITOR);
-        continue; }
-	if(!stricmp(p,"SET_EDITOR")) {
-        fprintf(out,"%c",CS_SET_EDITOR);
-        continue; }
-
-	if(!stricmp(p,"YES_NO")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_YES_NO);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"NO_YES")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_NO_YES);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"MENU")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_MENU);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"SET_MENU_DIR")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_SET_MENU_DIR);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"SET_MENU_FILE")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_SET_MENU_FILE);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"SEND_FILE_VIA")) {
-		if(!*arg || !*arg2) break;
-		if(*arg2=='"') {
-			fprintf(out,"%c%c%c",CS_VAR_INSTRUCTION,SEND_FILE_VIA,*arg);
-			writestr(arg2); }
-		else {
-			fprintf(out,"%c%c%c",CS_VAR_INSTRUCTION,SEND_FILE_VIA_VAR,*arg);
-			writecrc(src,arg2); }
-        continue; }
-	if(!stricmp(p,"RECEIVE_FILE_VIA")) {
-		if(!*arg || !*arg2) break;
-		if(*arg2=='"') {
-			fprintf(out,"%c%c%c",CS_VAR_INSTRUCTION,RECEIVE_FILE_VIA,*arg);
-			writestr(arg2); }
-		else {
-			fprintf(out,"%c%c%c",CS_VAR_INSTRUCTION,RECEIVE_FILE_VIA_VAR,*arg);
-			writecrc(src,arg2); }
-        continue; }
-	if(!stricmp(p,"CHKFILE")) {
-        if(!*arg) break;
-		if(*arg=='"') {
-			fprintf(out,"%c",CS_CHKFILE);
-			writestr(arg); }
-		else {
-			fprintf(out,"%c%c",CS_VAR_INSTRUCTION,CHKFILE_VAR);
-			writecrc(src,arg); }
-        continue; }
-	if(!stricmp(p,"GET_FILE_LENGTH")) {
-		if(!*arg || !*arg2)
-			break;
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,FLENGTH_TO_INT);
-		p=strchr(arg,SP);
-		if(p) *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-		continue; }
-	if(!stricmp(p,"GET_FILE_TIME")) {
-		if(!*arg || !*arg2)
-			break;
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,FTIME_TO_INT);
-		p=strchr(arg,SP);
-		if(p) *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"CHARVAL")) {
-		if(!*arg || !*arg2)
-			break;
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,CHARVAL_TO_INT);
-		p=strchr(arg,SP);
-		if(p) *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"SETSTR")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_SETSTR);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"COMPARE_STR")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_COMPARE_STR);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"GET_TEMPLATE")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_GET_TEMPLATE);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"READ_SIF")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_READ_SIF);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"CREATE_SIF")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_CREATE_SIF);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"TRASHCAN")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_TRASHCAN);
-		writestr(arg);
-        continue; }
-	if(!stricmp(p,"CMDSTR")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_CMDSTR);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"CMDKEYS")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_CMDKEYS);
-		for(p=arg;*p && *p!='#';p++) {
-            ch=*p;
-			if(ch=='"')
-				continue;
-            if(ch=='/') {
-                p++;
-                ch=*p|0x80; }  /* high bit indicates slash required */
-            else if(ch=='^' && *(p+1)>=0x40) {
-                p++;
-                ch=*p;
-                ch-=0x40; }
-			else if(ch=='\\') {
-				p++;
-				ch=cesc(*p); }
-            fputc(ch,out); }
-        fputc(0,out);
-        continue; }
-	if(!stricmp(p,"COMPARE_WORD")) {
-        if(!*arg) break;
-        fprintf(out,"%c",CS_COMPARE_WORD);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"GETSTR")) {
-        p=strchr(arg,SP);
-        if(p) *p=0;
-		if((!*arg || isdigit(*arg) || !stricmp(arg,"STR")) && !*arg3)
-			fprintf(out,"%c%c",CS_GETSTR,atoi(arg) ? atoi(arg)
-				: *arg2 ? atoi(arg2) : 128);
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(1,out);		// int length
-				i=0; }				// place holder
-			else if(*arg2)
-				i=val(src,arg2);
-			else
-				i=0;
-
-			fprintf(out,"%c%c",CS_VAR_INSTRUCTION
-				,*arg3 ? GETSTR_MODE : GETSTR_VAR);
-			writecrc(src,arg);
-	
-            if(!i) i=128;
-			fwrite(&i,1,1,out);
-			if(*arg3) {
-				l=val(src,arg3);
-				fwrite(&l,4,1,out); } }
-        continue; }
-	if(!stricmp(p,"GETNUM")) {
-        if(!*arg) break;
-        p=strchr(arg,SP);
-        if(p) *p=0;
-        if(isdigit(*arg)) {
-			i=val(src,arg);
-			fprintf(out,"%c",CS_GETNUM);
-            fwrite(&i,2,1,out); }
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(2,out);		// int length
-				i=0; }				// place holder
-			else
-				i=val(src,arg2);
-
-            fprintf(out,"%c%c",CS_VAR_INSTRUCTION,GETNUM_VAR);
-			writecrc(src,arg);
-            fwrite(&i,2,1,out); }
-        continue; }
-	if(!stricmp(p,"MSWAIT")) {
-        if(!*arg) break;
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-
-        fprintf(out,"%c",CS_MSWAIT);
-        fwrite(&i,2,1,out);
-        continue; }
-	if(!stricmp(p,"GETLINE")) {
-        p=strchr(arg,SP);
-        if(p) *p=0;
-        if(!*arg || isdigit(*arg))
-            fprintf(out,"%c%c",CS_GETLINE,*arg ? atoi(arg) :128);
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(1,out);		// int length
-				i=0; }				// place holder
-			else
-                i=val(src,arg2);
-
-            fprintf(out,"%c%c",CS_VAR_INSTRUCTION,GETLINE_VAR);
-			writecrc(src,arg);
-            if(!i) i=128;
-            fwrite(&i,1,1,out); }
-        continue; }
-	if(!stricmp(p,"GETSTRUPR")) {
-        p=strchr(arg,SP);
-        if(p) *p=0;
-        if(!*arg || isdigit(*arg))
-            fprintf(out,"%c%c",CS_GETSTRUPR,*arg ? atoi(arg) :128);
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(1,out);		// int length
-				i=0; }				// place holder
-			else
-                i=val(src,arg2);
-
-            fprintf(out,"%c%c",CS_VAR_INSTRUCTION,GETSTRUPR_VAR);
-			writecrc(src,arg);
-            if(!i) i=128;
-            fwrite(&i,1,1,out); }
-        continue; }
-	if(!stricmp(p,"GETNAME")) {
-        p=strchr(arg,SP);
-        if(p) *p=0;
-        if(!*arg || isdigit(*arg))
-            fprintf(out,"%c%c",CS_GETNAME,*arg ? atoi(arg) :25);
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(1,out);		// int length
-				i=0; }				// place holder
-			else
-				i=atoi(arg2);
-
-            fprintf(out,"%c%c",CS_VAR_INSTRUCTION,GETNAME_VAR);
-			writecrc(src,arg);
-            if(!i) i=128;
-            fwrite(&i,1,1,out); }
-        continue; }
-	if(!stricmp(p,"SHIFT_STR")) {
-        if(!*arg) break;
-        p=strchr(arg,SP);
-        if(p) *p=0;
-        if(!*arg || isdigit(*arg))
-            fprintf(out,"%c%c",CS_SHIFT_STR,atoi(arg));
-        else {
-			if((l=isvar(arg2))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(6,out);		// int offset
-				fputc(1,out);		// int length
-				i=0; }				// place holder
-			else
-                i=atoi(arg2);
-
-            fprintf(out,"%c%c",CS_VAR_INSTRUCTION,SHIFT_STR_VAR);
-			writecrc(src,arg);
-            if(!i) i=128;
-            fwrite(&i,1,1,out); }
-        continue; }
-	if(!stricmp(p,"TRUNCSP")) {
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,TRUNCSP_STR_VAR);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"STRIP_CTRL")) {
-		fprintf(out,"%c%c",CS_VAR_INSTRUCTION,STRIP_CTRL_STR_VAR);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"STRUPR")) {
-        fprintf(out,"%c%c",CS_VAR_INSTRUCTION,STRUPR_VAR);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"STRLWR")) {
-        fprintf(out,"%c%c",CS_VAR_INSTRUCTION,STRLWR_VAR);
-		writecrc(src,arg);
-        continue; }
-	if(!stricmp(p,"STRLEN")) {
-        if(!*arg) break;
-        fprintf(out,"%c%c",CS_VAR_INSTRUCTION,STRLEN_INT_VAR);
-		p=strchr(arg,SP);
-        if(!p)
-            break;
-        *p=0;
-		writecrc(src,arg);
-		writecrc(src,arg2);
-        continue; }
-	if(!stricmp(p,"REPLACE_TEXT")) {
-        if(!*arg || !*arg2) break;
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-
-        fprintf(out,"%c",CS_REPLACE_TEXT);
-        fwrite(&i,2,1,out);
-        writecstr(arg2);
-        continue; }
-	if(!stricmp(p,"REVERT_TEXT")) {
-        if(!*arg) break;
-		if(!stricmp(arg,"ALL"))
-            i=0xffff;
-		else {
-			if((l=isvar(arg))!=0) {
-				fputc(CS_USE_INT_VAR,out);
-				fwrite(&l,4,1,out); // variable
-				fputc(1,out);		// int offset
-				fputc(2,out);		// int length
-				i=0; }				// place holder
-			else
-				i=val(src,arg); }
-
-        fprintf(out,"%c",CS_REVERT_TEXT);
-        fwrite(&i,2,1,out);
-        continue; }
-	if(!stricmp(p,"TOGGLE_USER_MISC")
-		|| !stricmp(p,"COMPARE_USER_MISC")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(4,out);		// int length
-			l=0; }				// place holder
-		else
-			l=val(src,arg);
-
-		if(!stricmp(p,"TOGGLE_USER_MISC"))
-            fprintf(out,"%c",CS_TOGGLE_USER_MISC);
-        else
-            fprintf(out,"%c",CS_COMPARE_USER_MISC);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"TOGGLE_USER_CHAT")
-		|| !stricmp(p,"COMPARE_USER_CHAT")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(4,out);		// int length
-			l=0; }				// place holder
-		else
-			l=val(src,arg);
-
-		if(!stricmp(p,"TOGGLE_USER_CHAT"))
-            fprintf(out,"%c",CS_TOGGLE_USER_CHAT);
-        else
-            fprintf(out,"%c",CS_COMPARE_USER_CHAT);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"TOGGLE_USER_QWK")
-		|| !stricmp(p,"COMPARE_USER_QWK")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(4,out);		// int length
-			l=0; }				// place holder
-		else
-			l=val(src,arg);
-
-		if(!stricmp(p,"TOGGLE_USER_QWK"))
-            fprintf(out,"%c",CS_TOGGLE_USER_QWK);
-        else
-            fprintf(out,"%c",CS_COMPARE_USER_QWK);
-        fwrite(&l,4,1,out);
-        continue; }
-
-	if(!stricmp(p,"TOGGLE_NODE_MISC")
-		|| !stricmp(p,"COMPARE_NODE_MISC")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-
-		if(!stricmp(p,"TOGGLE_NODE_MISC"))
-            fprintf(out,"%c",CS_TOGGLE_NODE_MISC);
-        else
-            fprintf(out,"%c",CS_COMPARE_NODE_MISC);
-        fwrite(&i,2,1,out);
-        continue; }
-
-	if(!stricmp(p,"TOGGLE_USER_FLAG")) {
-        if(!*arg) break;
-        p=arg;
-        fprintf(out,"%c%c",CS_TOGGLE_USER_FLAG,toupper(*p++));
-        while(*p && *p<=SP) p++;
-        fprintf(out,"%c",toupper(*p));
-        continue; }
-
-	if(!stricmp(p,"SET_USER_LEVEL")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(1,out);		// int length
-			ch=0; } 			// place holder
-		else
-			ch=val(src,arg);
-
-		fprintf(out,"%c%c",CS_SET_USER_LEVEL,ch);
-        continue; }
-
-	if(!stricmp(p,"SET_USER_STRING")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(1,out);		// int length
-			ch=0; } 			// place holder
-		else
-			ch=val(src,arg);
-
-        fprintf(out,"%c%c",CS_SET_USER_STRING,ch);
-        continue; }
-
-
-	if(!stricmp(p,"ADJUST_USER_CREDITS")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }			   // place holder
-		else
-			i=val(src,arg);
-
-        fprintf(out,"%c",CS_ADJUST_USER_CREDITS);
-        fwrite(&i,2,1,out);
-        continue; }
-
-	if(!stricmp(p,"ADJUST_USER_MINUTES")) {
-        if(!*arg) break;
-
-		if((l=isvar(arg))!=0) {
-			fputc(CS_USE_INT_VAR,out);
-			fwrite(&l,4,1,out); // variable
-			fputc(1,out);		// int offset
-			fputc(2,out);		// int length
-			i=0; }				// place holder
-		else
-			i=val(src,arg);
-
-        fprintf(out,"%c",CS_ADJUST_USER_MINUTES);
-        fwrite(&i,2,1,out);
-        continue; }
-
-	if(!stricmp(p,"SHOW_MEM")) {
-        fprintf(out,"%c",CS_SHOW_MEM);
-        continue; }
-	if(!stricmp(p,"GURU_LOG")) {
-        fprintf(out,"%c",CS_GURU_LOG);
-        continue; }
-	if(!stricmp(p,"ERROR_LOG")) {
-        fprintf(out,"%c",CS_ERROR_LOG);
-        continue; }
-	if(!stricmp(p,"SYSTEM_LOG")) {
-        fprintf(out,"%c",CS_SYSTEM_LOG);
-        continue; }
-	if(!stricmp(p,"SYSTEM_YLOG")) {
-        fprintf(out,"%c",CS_SYSTEM_YLOG);
-        continue; }
-	if(!stricmp(p,"SYSTEM_STATS")) {
-        fprintf(out,"%c",CS_SYSTEM_STATS);
-        continue; }
-	if(!stricmp(p,"NODE_STATS")) {
-        fprintf(out,"%c",CS_NODE_STATS);
-        continue; }
-	if(!stricmp(p,"CHANGE_USER")) {
-        fprintf(out,"%c",CS_CHANGE_USER);
-        continue; }
-	if(!stricmp(p,"ANSI_CAPTURE")) {
-        fprintf(out,"%c",CS_ANSI_CAPTURE);
-        continue; }
-	if(!stricmp(p,"LIST_TEXT_FILE")) {
-        fprintf(out,"%c",CS_LIST_TEXT_FILE);
-        continue; }
-	if(!stricmp(p,"EDIT_TEXT_FILE")) {
-        fprintf(out,"%c",CS_EDIT_TEXT_FILE);
-        continue; }
-
-
-	if(!stricmp(p,"COMPARE_KEY")) {
-		if(!stricmp(arg,"DIGIT"))
-            ch=CS_DIGIT;
-		else if(!stricmp(arg,"EDIGIT"))
-            ch=CS_EDIGIT;
-        else
-            ch=toupper(*arg);
-        if(ch=='/')
-            ch=(*arg)|0x80;   /* high bit indicates slash required */
-		else if(ch=='^' && (*(arg+1))>=0x40)
-			ch=(*(arg+1))-0x40;   /* ctrl char */
-		else if(ch=='\\')
-			ch=cesc(*(arg+1));
-		else if(ch=='\'')
-			ch=*(arg+1);
-        fprintf(out,"%c%c",CS_COMPARE_KEY,ch);
-        continue; }
-	if(!stricmp(p,"COMPARE_KEYS")) {
-        fputc(CS_COMPARE_KEYS,out);
-		for(p=arg;*p && *p!='#';p++) {
-            ch=*p;
-			if(ch=='"')
-				continue;
-            if(ch=='/') {
-                p++;
-                ch=*p|0x80; }  /* high bit indicates slash required */
-            else if(ch=='^' && *(p+1)>=0x40) {
-                p++;
-                ch=*p;
-                ch-=0x40; }
-			else if(ch=='\\') {
-				p++;
-				ch=cesc(*p); }
-            fputc(ch,out); }
-        fputc(0,out);
-        continue; }
-	if(!stricmp(p,"GETCMD")) {
-        fprintf(out,"%c",CS_GETCMD);
-        writecstr(arg);
-        continue; }
-	if(!stricmp(p,"INKEY")) {
-        fprintf(out,"%c",CS_INKEY);
-        continue; }
-	if(!stricmp(p,"GETKEY")) {
-        fprintf(out,"%c",CS_GETKEY);
-        continue; }
-	if(!stricmp(p,"GETKEYE")) {
-        fprintf(out,"%c",CS_GETKEYE);
-        continue; }
-	if(!stricmp(p,"UNGETKEY")) {
-        fprintf(out,"%c",CS_UNGETKEY);
-        continue; }
-	if(!stricmp(p,"UNGETSTR")) {
-        fprintf(out,"%c",CS_UNGETSTR);
-        continue; }
-	if(!stricmp(p,"PRINTKEY")) {
-        fprintf(out,"%c",CS_PRINTKEY);
-        continue; }
-	if(!stricmp(p,"PRINTSTR")) {
-        fprintf(out,"%c",CS_PRINTSTR);
-        continue; }
-
-    /* FUNCTIONS */
-
-	if(!stricmp(p,"NODELIST_ALL")) {
-        fprintf(out,"%c",CS_NODELIST_ALL);
-        continue; }
-	if(!stricmp(p,"NODELIST_USERS")) {
-        fprintf(out,"%c",CS_NODELIST_USERS);
-        continue; }
-
-	if(!stricmp(p,"USERLIST_ALL")) {
-        fprintf(out,"%c",CS_USERLIST_ALL);
-        continue; }
-	if(!stricmp(p,"USERLIST_SUB")) {
-        fprintf(out,"%c",CS_USERLIST_SUB);
-        continue; }
-	if(!stricmp(p,"USERLIST_DIR")) {
-        fprintf(out,"%c",CS_USERLIST_DIR);
-        continue; }
-	if(!stricmp(p,"USERLIST_LOGONS")) {
-        fprintf(out,"%c",CS_USERLIST_LOGONS);
-        continue; }
-
-	if(!stricmp(p,"HANGUP")) {
-        fprintf(out,"%c",CS_HANGUP);
-        continue; }
-
-	if(!stricmp(p,"LOGOFF")) {
-        fprintf(out,"%c",CS_LOGOFF);
-        continue; }
-
-	if(!stricmp(p,"LOGOFF_FAST")) {
-        fprintf(out,"%c",CS_LOGOFF_FAST);
-        continue; }
-
-	if(!stricmp(p,"AUTO_MESSAGE")) {
-        fprintf(out,"%c",CS_AUTO_MESSAGE);
-        continue; }
-
-	if(!stricmp(p,"MINUTE_BANK")) {
-        fprintf(out,"%c",CS_MINUTE_BANK);
-        continue; }
-
-	if(!stricmp(p,"USER_EDIT")) {
-        fprintf(out,"%c",CS_USER_EDIT);
-        continue; }
-
-	if(!stricmp(p,"USER_DEFAULTS")) {
-        fprintf(out,"%c",CS_USER_DEFAULTS);
-        continue; }
-
-	if(!stricmp(p,"PAGE_SYSOP")) {
-        fprintf(out,"%c",CS_PAGE_SYSOP);
-        continue; }
-	if(!stricmp(p,"PAGE_GURU")) {
-        fprintf(out,"%c",CS_PAGE_GURU);
-        continue; }
-
-	if(!stricmp(p,"PRIVATE_CHAT")) {
-        fprintf(out,"%c",CS_PRIVATE_CHAT);
-        continue; }
-
-	if(!stricmp(p,"PRIVATE_MESSAGE")) {
-        fprintf(out,"%c",CS_PRIVATE_MESSAGE);
-        continue; }
-
-	if(!stricmp(p,"MAIL_READ")) {
-        fprintf(out,"%c",CS_MAIL_READ);
-        continue; }
-	if(!stricmp(p,"MAIL_READ_SENT")) {       /* Kill/read sent mail */
-        fprintf(out,"%c",CS_MAIL_READ_SENT);
-        continue; }
-	if(!stricmp(p,"MAIL_READ_ALL")) {
-        fprintf(out,"%c",CS_MAIL_READ_ALL);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND")) {       /* Send E-mail */
-        fprintf(out,"%c",CS_MAIL_SEND);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND_FEEDBACK")) {       /* Feedback */
-        fprintf(out,"%c",CS_MAIL_SEND_FEEDBACK);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND_NETMAIL")) {
-        fprintf(out,"%c",CS_MAIL_SEND_NETMAIL);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND_NETFILE")) {
-        fprintf(out,"%c",CS_MAIL_SEND_NETFILE);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND_FILE")) {   /* Upload Attached File to E-mail */
-        fprintf(out,"%c",CS_MAIL_SEND_FILE);
-        continue; }
-	if(!stricmp(p,"MAIL_SEND_BULK")) {
-        fprintf(out,"%c",CS_MAIL_SEND_BULK);
-        continue; }
-
-
-	if(!stricmp(p,"MSG_SET_AREA")) {
-        fprintf(out,"%c",CS_MSG_SET_AREA);
-        continue; }
-	if(!stricmp(p,"MSG_SET_GROUP")) {
-        fprintf(out,"%c",CS_MSG_SET_GROUP);
-        continue; }
-	if(!stricmp(p,"MSG_SELECT_AREA")) {
-        fprintf(out,"%c",CS_MSG_SELECT_AREA);
-        continue; }
-	if(!stricmp(p,"MSG_SHOW_GROUPS")) {
-        fprintf(out,"%c",CS_MSG_SHOW_GROUPS);
-        continue; }
-	if(!stricmp(p,"MSG_SHOW_SUBBOARDS")) {
-        fprintf(out,"%c",CS_MSG_SHOW_SUBBOARDS);
-        continue; }
-	if(!stricmp(p,"MSG_GROUP_UP")) {
-        fprintf(out,"%c",CS_MSG_GROUP_UP);
-        continue; }
-	if(!stricmp(p,"MSG_GROUP_DOWN")) {
-        fprintf(out,"%c",CS_MSG_GROUP_DOWN);
-        continue; }
-	if(!stricmp(p,"MSG_SUBBOARD_UP")) {
-        fprintf(out,"%c",CS_MSG_SUBBOARD_UP);
-        continue; }
-	if(!stricmp(p,"MSG_SUBBOARD_DOWN")) {
-        fprintf(out,"%c",CS_MSG_SUBBOARD_DOWN);
-        continue; }
-	if(!stricmp(p,"MSG_GET_SUB_NUM")) {
-        fprintf(out,"%c",CS_MSG_GET_SUB_NUM);
-        continue; }
-	if(!stricmp(p,"MSG_GET_GRP_NUM")) {
-        fprintf(out,"%c",CS_MSG_GET_GRP_NUM);
-        continue; }
-	if(!stricmp(p,"MSG_READ")) {
-        fprintf(out,"%c",CS_MSG_READ);
-        continue; }
-	if(!stricmp(p,"MSG_POST")) {
-        fprintf(out,"%c",CS_MSG_POST);
-        continue; }
-	if(!stricmp(p,"MSG_QWK")) {
-        fprintf(out,"%c",CS_MSG_QWK);
-        continue; }
-	if(!stricmp(p,"MSG_PTRS_CFG")) {
-        fprintf(out,"%c",CS_MSG_PTRS_CFG);
-        continue; }
-	if(!stricmp(p,"MSG_PTRS_REINIT")) {
-        fprintf(out,"%c",CS_MSG_PTRS_REINIT);
-        continue; }
-	if(!stricmp(p,"MSG_NEW_SCAN_CFG")) {
-        fprintf(out,"%c",CS_MSG_NEW_SCAN_CFG);
-        continue; }
-	if(!stricmp(p,"MSG_NEW_SCAN")) {
-        fprintf(out,"%c",CS_MSG_NEW_SCAN);
-        continue; }
-	if(!stricmp(p,"MSG_NEW_SCAN_SUB")) {
-        fprintf(out,"%c",CS_MSG_NEW_SCAN_SUB);
-        continue; }
-	if(!stricmp(p,"MSG_NEW_SCAN_ALL")) {
-        fprintf(out,"%c",CS_MSG_NEW_SCAN_ALL);
-        continue; }
-	if(!stricmp(p,"MSG_CONT_SCAN")) {
-        fprintf(out,"%c",CS_MSG_CONT_SCAN);
-        continue; }
-	if(!stricmp(p,"MSG_CONT_SCAN_ALL")) {
-        fprintf(out,"%c",CS_MSG_CONT_SCAN_ALL);
-        continue; }
-	if(!stricmp(p,"MSG_BROWSE_SCAN")) {
-        fprintf(out,"%c",CS_MSG_BROWSE_SCAN);
-        continue; }
-	if(!stricmp(p,"MSG_BROWSE_SCAN_ALL")) {
-        fprintf(out,"%c",CS_MSG_BROWSE_SCAN_ALL);
-        continue; }
-	if(!stricmp(p,"MSG_FIND_TEXT")) {
-        fprintf(out,"%c",CS_MSG_FIND_TEXT);
-        continue; }
-	if(!stricmp(p,"MSG_FIND_TEXT_ALL")) {
-        fprintf(out,"%c",CS_MSG_FIND_TEXT_ALL);
-        continue; }
-	if(!stricmp(p,"MSG_YOUR_SCAN_CFG")) {
-        fprintf(out,"%c",CS_MSG_YOUR_SCAN_CFG);
-        continue; }
-	if(!stricmp(p,"MSG_YOUR_SCAN")) {
-        fprintf(out,"%c",CS_MSG_YOUR_SCAN);
-        continue; }
-	if(!stricmp(p,"MSG_YOUR_SCAN_ALL")) {
-        fprintf(out,"%c",CS_MSG_YOUR_SCAN_ALL);
-        continue; }
-	if(!stricmp(p,"CHAT_SECTION")) {
-        fprintf(out,"%c",CS_CHAT_SECTION);
-        continue; }
-	if(!stricmp(p,"TEXT_FILE_SECTION")) {
-        fprintf(out,"%c",CS_TEXT_FILE_SECTION);
-        continue; }
-	if(!stricmp(p,"XTRN_EXEC")) {
-        fprintf(out,"%c",CS_XTRN_EXEC);
-        continue; }
-	if(!stricmp(p,"XTRN_SECTION")) {
-        fprintf(out,"%c",CS_XTRN_SECTION);
-        continue; }
-
-	if(!stricmp(p,"FILE_SET_AREA")) {
-        fprintf(out,"%c",CS_FILE_SET_AREA);
-        continue; }
-	if(!stricmp(p,"FILE_SET_LIBRARY")) {
-        fprintf(out,"%c",CS_FILE_SET_LIBRARY);
-        continue; }
-	if(!stricmp(p,"FILE_SELECT_AREA")) {
-        fprintf(out,"%c",CS_FILE_SELECT_AREA);
-        continue; }
-	if(!stricmp(p,"FILE_SHOW_LIBRARIES")) {
-        fprintf(out,"%c",CS_FILE_SHOW_LIBRARIES);
-        continue; }
-	if(!stricmp(p,"FILE_SHOW_DIRECTORIES")) {
-        fprintf(out,"%c",CS_FILE_SHOW_DIRECTORIES);
-        continue; }
-	if(!stricmp(p,"FILE_LIBRARY_UP")) {
-        fprintf(out,"%c",CS_FILE_LIBRARY_UP);
-        continue; }
-	if(!stricmp(p,"FILE_LIBRARY_DOWN")) {
-        fprintf(out,"%c",CS_FILE_LIBRARY_DOWN);
-        continue; }
-	if(!stricmp(p,"FILE_DIRECTORY_UP")) {
-        fprintf(out,"%c",CS_FILE_DIRECTORY_UP);
-        continue; }
-	if(!stricmp(p,"FILE_DIRECTORY_DOWN")) {
-        fprintf(out,"%c",CS_FILE_DIRECTORY_DOWN);
-        continue; }
-	if(!stricmp(p,"FILE_GET_DIR_NUM")) {
-        fprintf(out,"%c",CS_FILE_GET_DIR_NUM);
-        continue; }
-	if(!stricmp(p,"FILE_GET_LIB_NUM")) {
-        fprintf(out,"%c",CS_FILE_GET_LIB_NUM);
-        continue; }
-	if(!stricmp(p,"FILE_UPLOAD")) {
-        fprintf(out,"%c",CS_FILE_UPLOAD);
-        continue; }
-	if(!stricmp(p,"FILE_UPLOAD_USER")) {
-        fprintf(out,"%c",CS_FILE_UPLOAD_USER);
-        continue; }
-	if(!stricmp(p,"FILE_UPLOAD_BULK")) {
-        fprintf(out,"%c",CS_FILE_UPLOAD_BULK);
-        continue; }
-	if(!stricmp(p,"FILE_UPLOAD_SYSOP")) {
-        fprintf(out,"%c",CS_FILE_UPLOAD_SYSOP);
-        continue; }
-	if(!stricmp(p,"FILE_RESORT_DIRECTORY")) {
-        fprintf(out,"%c",CS_FILE_RESORT_DIRECTORY);
-        continue; }
-	if(!stricmp(p,"FILE_SET_ALT_PATH")) {
-        fprintf(out,"%c",CS_FILE_SET_ALT_PATH);
-        continue; }
-	if(!stricmp(p,"FILE_GET")) {
-        fprintf(out,"%c",CS_FILE_GET);
-        continue; }
-	if(!stricmp(p,"FILE_SEND")) {
-        fprintf(out,"%c",CS_FILE_SEND);
-        continue; }
-	if(!stricmp(p,"FILE_PUT")) {
-        fprintf(out,"%c",CS_FILE_PUT);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_OLD")) {
-        fprintf(out,"%c",CS_FILE_FIND_OLD);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_OPEN")) {
-        fprintf(out,"%c",CS_FILE_FIND_OPEN);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_OFFLINE")) {
-        fprintf(out,"%c",CS_FILE_FIND_OFFLINE);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_OLD_UPLOADS")) {
-        fprintf(out,"%c",CS_FILE_FIND_OLD_UPLOADS);
-        continue; }
-	if(!stricmp(p,"FILE_DOWNLOAD")) {
-        fprintf(out,"%c",CS_FILE_DOWNLOAD);
-        continue; }
-	if(!stricmp(p,"FILE_DOWNLOAD_USER")) {
-        fprintf(out,"%c",CS_FILE_DOWNLOAD_USER);
-        continue; }
-	if(!stricmp(p,"FILE_DOWNLOAD_BATCH")) {
-        fprintf(out,"%c",CS_FILE_DOWNLOAD_BATCH);
-        continue; }
-	if(!stricmp(p,"FILE_REMOVE")) {
-        fprintf(out,"%c",CS_FILE_REMOVE);
-        continue; }
-	if(!stricmp(p,"FILE_LIST")) {
-        fprintf(out,"%c",CS_FILE_LIST);
-        continue; }
-	if(!stricmp(p,"FILE_LIST_EXTENDED")) {
-        fprintf(out,"%c",CS_FILE_LIST_EXTENDED);
-        continue; }
-	if(!stricmp(p,"FILE_VIEW")) {
-        fprintf(out,"%c",CS_FILE_VIEW);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_TEXT")) {
-        fprintf(out,"%c",CS_FILE_FIND_TEXT);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_TEXT_ALL")) {
-        fprintf(out,"%c",CS_FILE_FIND_TEXT_ALL);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_NAME")) {
-        fprintf(out,"%c",CS_FILE_FIND_NAME);
-        continue; }
-	if(!stricmp(p,"FILE_FIND_NAME_ALL")) {
-        fprintf(out,"%c",CS_FILE_FIND_NAME_ALL);
-        continue; }
-	if(!stricmp(p,"FILE_BATCH_SECTION")) {
-        fprintf(out,"%c",CS_FILE_BATCH_SECTION);
-        continue; }
-	if(!stricmp(p,"FILE_TEMP_SECTION")) {
-        fprintf(out,"%c",CS_FILE_TEMP_SECTION);
-        continue; }
-	if(!stricmp(p,"FILE_NEW_SCAN")) {
-        fprintf(out,"%c",CS_FILE_NEW_SCAN);
-        continue; }
-	if(!stricmp(p,"FILE_NEW_SCAN_ALL")) {
-        fprintf(out,"%c",CS_FILE_NEW_SCAN_ALL);
-        continue; }
-	if(!stricmp(p,"FILE_NEW_SCAN_CFG")) {
-        fprintf(out,"%c",CS_FILE_NEW_SCAN_CFG);
-        continue; }
-	if(!stricmp(p,"FILE_PTRS_CFG")) {
-        fprintf(out,"%c",CS_FILE_PTRS_CFG);
-        continue; }
-	if(!stricmp(p,"FILE_BATCH_ADD")) {
-        fprintf(out,"%c",CS_FILE_BATCH_ADD);
-        continue; }
-	if(!stricmp(p,"FILE_BATCH_ADD_LIST")) {
-		fprintf(out,"%c",CS_FILE_BATCH_ADD_LIST);
-        continue; }
-	if(!stricmp(p,"FILE_BATCH_CLEAR")) {
-        fprintf(out,"%c",CS_FILE_BATCH_CLEAR);
-        continue; }
-
-	if(!stricmp(p,"INC_MAIN_CMDS")) {
-        fprintf(out,"%c",CS_INC_MAIN_CMDS);
-        continue; }
-	if(!stricmp(p,"INC_FILE_CMDS")) {
-        fprintf(out,"%c",CS_INC_FILE_CMDS);
-        continue; }
-
-	break; }
-
-
-if(!feof(in)) {
-	printf("SYNTAX ERROR:\n");
-	printf(linestr,src,line,save);
-    exit(1); }
-fclose(in);
-}
-
-char *usage="\n"
-			"usage: baja [/opts] file[.src]\n"
-			"\n"
-			" opts: /d display debug during compile\n"
-			"       /c case sensitive variables, labels, and macros\n"
-			"       /o set output directory (e.g. /o\\sbbs\\exec)\n"
-			;
-int main(int argc, char **argv)
-{
-	uchar str[128],src[128]="",*p,outdir[128]="",outfname[128]="";
-	int i,j;
-
-printf("\nBAJA v2.10 � Synchronet Shell/Module Compiler � "
-	"Developed 1995-97 Rob Swindell\n");
-
-for(i=1;i<argc;i++)
-	if(argv[i][0]=='/')
-		switch(toupper(argv[i][1])) {
-			case 'D':
-				display=1;
-				break;
-			case 'C':
-				case_sens=1;
-				break;
-			case 'O':
-				strcpy(outdir,argv[i]+2);
-				break;
-			default:
-				printf(usage);
-				exit(1); }
-	else
-		strcpy(src,argv[i]);
-
-if(!src[0]) {
-	printf(usage);
-	exit(1); }
-
-strupr(src);
-strcpy(str,src);
-if(!strchr(str,'.'))
-	sprintf(src,"%s.SRC",str);
-
-strcpy(str,src);
-p=strrchr(str,'.');
-if(p)
-	*p=0;
-strcat(str,".BIN");
-
-if(outdir[0]) {
-	p=strrchr(str,'\\');
-	if(!p)
-		p=strrchr(str,':');
-	if(p)
-		strcpy(outfname,p+1);
-	else
-		strcpy(outfname,str);
-	if(outdir[strlen(outdir)-1]!='\\'
-		&& outdir[strlen(outdir)-1]!=':')
-		strcat(outdir,"\\");
-	sprintf(str,"%s%s",outdir,outfname); }
-
-if((out=fopen(str,"wb"))==NULL) {
-	printf("error opening %s for write\n",str);
-	exit(1); }
-
-atexit(bail);
-
-printf("\nCompiling %s...\n",src);
-
-compile(src);
-
-/****************************/
-/* Resolve GOTOS and CALLS */
-/****************************/
-
-printf("Resolving labels...\n");
-
-for(i=0;i<gotos;i++) {
-	for(j=0;j<labels;j++)
-		if(!stricmp(goto_label[i],label_name[j]))
-			break;
-	if(j>=labels) {
-		printf("%s line %d: label (%s) not found.\n"
-			,goto_file[i],goto_line[i],goto_label[i]);
-		exit(1); }
-	fseek(out,(long)(goto_indx[i]+1),SEEK_SET);
-	fwrite(&label_indx[j],2,1,out); }
-
-for(i=0;i<calls;i++) {
-	for(j=0;j<labels;j++)
-		if((!case_sens
-			&& !strnicmp(call_label[i],label_name[j],strlen(call_label[i])))
-		|| (case_sens
-			&& !strncmp(call_label[i],label_name[j],strlen(call_label[i]))))
-			break;
-	if(j>=labels) {
-		printf("%s line %d: label (%s) not found.\n"
-			,call_file[i],call_line[i],call_label[i]);
-		exit(1); }
-	fseek(out,(long)(call_indx[i]+1),SEEK_SET);
-	fwrite(&label_indx[j],2,1,out); }
-
-fclose(out);
-out=NULL; /* so bail() won't truncate */
-
-printf("\nDone.\n");
-return(0);
-}
-
-
-
diff --git a/src/sbbs2/baja/make.bat b/src/sbbs2/baja/make.bat
deleted file mode 100755
index 8f77b60e3d5c9a23af1411f0ce3c6b3bb7e82958..0000000000000000000000000000000000000000
--- a/src/sbbs2/baja/make.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-bcc -ml -N -lm -I..;..\smb baja.c ..\ars.c
-if errorlevel 1 goto end
-bcc32 -WX -N -lm -I..;..\smb -ebaja32.exe baja.c ..\ars.c
-:end
diff --git a/src/sbbs2/baja/make.cmd b/src/sbbs2/baja/make.cmd
deleted file mode 100755
index 34625ae386d53908f2a95458cd52d54786c263ca..0000000000000000000000000000000000000000
--- a/src/sbbs2/baja/make.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -N -I..;..\smb -eBAJA4OS2.EXE baja.c ..\ars.c
diff --git a/src/sbbs2/bulkmail.c b/src/sbbs2/bulkmail.c
deleted file mode 100644
index 0d6bd83a100ba0873163380927c9f3b99994b155..0000000000000000000000000000000000000000
--- a/src/sbbs2/bulkmail.c
+++ /dev/null
@@ -1,219 +0,0 @@
-#line 1 "BULKMAIL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-int bulkmailhdr(int usernum, smbmsg_t *msg, ushort msgattr, ulong offset
-    , ulong length, char *title)
-{
-    char str[256];
-    int i,j;
-    node_t node;
-
-memset(msg,0,sizeof(smbmsg_t));
-memcpy(msg->hdr.id,"SHD\x1a",4);
-msg->hdr.version=smb_ver();
-msg->hdr.attr=msg->idx.attr=msgattr;
-msg->hdr.when_written.time=msg->hdr.when_imported.time=time(NULL);
-msg->hdr.when_written.zone=msg->hdr.when_imported.zone=sys_timezone;
-msg->hdr.offset=msg->idx.offset=offset;
-
-username(usernum,str);
-smb_hfield(msg,RECIPIENT,strlen(str),str);
-strlwr(str);
-
-sprintf(str,"%u",usernum);
-smb_hfield(msg,RECIPIENTEXT,strlen(str),str);
-msg->idx.to=usernum;
-
-strcpy(str,useron.alias);
-smb_hfield(msg,SENDER,strlen(str),str);
-strlwr(str);
-
-sprintf(str,"%u",useron.number);
-smb_hfield(msg,SENDEREXT,strlen(str),str);
-msg->idx.from=useron.number;
-
-strcpy(str,title);
-smb_hfield(msg,SUBJECT,strlen(str),str);
-strlwr(str);
-msg->idx.subj=crc16(str);
-
-smb_dfield(msg,TEXT_BODY,length);
-
-j=smb_addmsghdr(&smb,msg,SMB_SELFPACK);
-if(j)
-    return(j);
-
-// smb_incdat(&smb,offset,length,1); Remove 04/15/96
-lncntr=0;
-bprintf("Bulk Mailed %s #%d\r\n",username(usernum,tmp),usernum);
-sprintf(str,"Bulk Mailed %s #%d",username(usernum,tmp),usernum);
-logline("E+",str);
-useron.emails++;
-logon_emails++;
-useron.etoday++;
-for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
-    getnodedat(i,&node,0);
-    if(node.useron==usernum && !(node.misc&NODE_POFF)
-        && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
-        sprintf(str,text[EmailNodeMsg],node_num,useron.alias);
-        putnmsg(i,str);
-        break; } }
-if(i>sys_nodes) {   /* User wasn't online, so leave short msg */
-    sprintf(str,text[UserSentYouMail],useron.alias);
-    putsmsg(usernum,str); }
-return(0);
-}
-
-void bulkmail(uchar *ar)
-{
-	char	str[256],str2[256],msgpath[256],title[LEN_TITLE+1],ch
-			,buf[SDT_BLOCK_LEN],found=0;
-	ushort	xlat=XLAT_NONE,msgattr=0;
-	int 	i,j,k,x,file;
-	long	l,msgs=0;
-	ulong	length,offset;
-	FILE	*instream;
-	user_t	user;
-	smbmsg_t msg;
-
-memset(&msg,0,sizeof(smbmsg_t));
-
-title[0]=0;
-action=NODE_SMAL;
-nodesync();
-
-if(sys_misc&SM_ANON_EM && (SYSOP || useron.exempt&FLAG('A'))
-    && !noyes(text[AnonymousQ]))
-	msgattr|=MSG_ANONYMOUS;
-
-sprintf(msgpath,"%sINPUT.MSG",node_dir);
-sprintf(str2,"Bulk Mailing");
-if(!writemsg(msgpath,nulstr,title,WM_EMAIL,0,str2)) {
-    bputs(text[Aborted]);
-    return; }
-
-bputs(text[WritingIndx]);
-CRLF;
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=mail_maxcrcs;
-	smb.status.max_msgs=MAX_SYSMAIL;
-	smb.status.max_age=mail_maxage;
-	smb.status.attr=SMB_EMAIL;
-	if((i=smb_create(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return; } }
-
-length=flength(msgpath)+2;	 /* +2 for translation string */
-
-if(length&0xfff00000UL) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LEN,smb.file,length);
-    return; }
-
-if((i=smb_open_da(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if(sys_misc&SM_FASTMAIL)
-	offset=smb_fallocdat(&smb,length,1);
-else
-	offset=smb_allocdat(&smb,length,1);
-smb_close_da(&smb);
-
-if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_freemsgdat(&smb,offset,length,1);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
-	return; }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-
-j=lastuser();
-x=0;
-
-if(*ar)
-	for(i=1;i<=j;i++) {
-		user.number=i;
-		getuserdat(&user);
-		if(user.misc&(DELETED|INACTIVE))
-			continue;
-		if(chk_ar(ar,user)) {
-			if(found)
-				smb_freemsgmem(&msg);
-			x=bulkmailhdr(i,&msg,msgattr,offset,length,title);
-			if(x)
-				break;
-			msgs++;
-			found=1; } }
-else
-	while(1) {
-		bputs(text[EnterAfterLastDestUser]);
-		if(!getstr(str,LEN_ALIAS,K_UPRLWR))
-			break;
-		if((i=finduser(str))!=0) {
-			if(found)
-				smb_freemsgmem(&msg);
-			x=bulkmailhdr(i,&msg,msgattr,offset,length,title);
-			if(x)
-				break;
-			msgs++; }
-		found=1; }
-
-if((i=smb_open_da(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if(!msgs)
-	smb_freemsgdat(&smb,offset,length,1);
-else if(msgs>1)
-	smb_incdat(&smb,offset,length,msgs-1);
-smb_close_da(&smb);
-
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-smb_freemsgmem(&msg);
-if(x) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,x);
-	return; }
-
-putuserrec(useron.number,U_EMAILS,5,itoa(useron.emails,tmp,10));
-putuserrec(useron.number,U_ETODAY,5,itoa(useron.etoday,tmp,10));
-}
-
-
diff --git a/src/sbbs2/chat.c b/src/sbbs2/chat.c
deleted file mode 100644
index 1621dd79550f4c3e35c6f611a19da0dc4feb0b8f..0000000000000000000000000000000000000000
--- a/src/sbbs2/chat.c
+++ /dev/null
@@ -1,1715 +0,0 @@
-#line 1 "CHAT.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************/
-/* Local and Node-to-Node Chat routines */
-/****************************************/
-
-#include "sbbs.h"
-
-#define PCHAT_LEN 1000		/* Size of Private chat file */
-
-int getnodetopage(int all, int telegram);
-
-
-char *weekday[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"
-				,"Saturday"};
-char *month[]={"January","February","March","April","May","June"
-			,"July","August","September","October","November","December"};
-
-
-/****************************************************************************/
-/* Chat between local keyboard and remote user on current node.				*/
-/* Called from inkey (inkey is then re-entrant)								*/
-/****************************************************************************/
-void localchat()
-{
-	uchar	str[256],act;
-	int con=console;	/* save console state */
-	time_t 	beg=time(NULL);
-
-console&=~(CON_L_ECHOX|CON_R_ECHOX);	/* turn off X's */
-console|=(CON_L_ECHO|CON_R_ECHO);		/* make sure echo is enabled */
-nosound();
-sys_status&=~SS_SYSPAGE;
-act=action;					/* save the user's current action */
-action=NODE_LCHT;
-bprintf(text[SysopIsHere],sys_op);
-while(sys_status&SS_LCHAT && online) {
-	SYNC;
-	getstr(str,78,K_WRAP|K_MSG); }
-bputs(text[EndOfChat]);
-now=time(NULL);
-if(!(sys_status&SS_USERON))
-	answertime=now;
-starttime+=now-beg;   /* credit user for time in chat */
-RESTORELINE;
-action=act;
-console=con;					/* restore console */
-}
-
-void sysop_page(void)
-{
-	int i;
-
-for(i=0;i<total_pages;i++)
-	if(chk_ar(page[i]->ar,useron))
-		break;
-if(i<total_pages) {
-	bprintf(text[PagingGuru],sys_op);
-	external(cmdstr(page[i]->cmd,nulstr,nulstr,NULL)
-		,page[i]->misc&IO_INTS ? EX_OUTL|EX_OUTR|EX_INR
-			: EX_OUTL); }
-else if(sys_misc&SM_SHRTPAGE) {
-	bprintf(text[PagingGuru],sys_op);
-	for(i=0;i<10 && !lkbrd(1);i++) {
-		beep(1000,200);
-		mswait(200);
-		outchar('.'); }
-	CRLF; }
-else {
-	sys_status^=SS_SYSPAGE;
-	bprintf(text[SysopPageIsNow]
-		,sys_status&SS_SYSPAGE ? text[ON] : text[OFF]);
-	nosound();	}
-}
-
-/****************************************************************************/
-/* Returns 1 if user online has access to channel "channum"                 */
-/****************************************************************************/
-char chan_access(uint cnum)
-{
-
-if(!total_chans || cnum>=total_chans || !chk_ar(chan[cnum]->ar,useron)) {
-	bputs(text[CantAccessThatChannel]);
-	return(0); }
-if(!(useron.exempt&FLAG('J')) && chan[cnum]->cost>useron.cdt+useron.freecdt) {
-	bputs(text[NotEnoughCredits]);
-	return(0); }
-return(1);
-}
-
-void privchat(void)
-{
-	uchar	str[128],ch,c,*p,localbuf[5][81],remotebuf[5][81]
-			,localline=0,remoteline=0,localchar=0,remotechar=0
-			,*sep="\1w\1h�����[\1i\1r%c\1n\1h]���Ĵ "
-				"\1yPrivate Chat - \1rCtrl-C to Quit \1y- "
-				"Time Left: \1g%-8s\1w"
-				" �����[\1i\1b%c\1n\1h]�����";
-	int 	in,out,i,j,n,done,echo=1,x,y,activity;
-	node_t	node;
-
-n=getnodetopage(0,0);
-if(!n)
-	return;
-if(n==node_num) {
-	bputs(text[NoNeedToPageSelf]);
-	return; }
-getnodedat(n,&node,0);
-if(node.action==NODE_PCHT && node.aux!=node_num) {
-	bprintf(text[NodeNAlreadyInPChat],n);
-	return; }
-if((node.action!=NODE_PAGE || node.aux!=node_num)
-	&& node.misc&NODE_POFF && !SYSOP) {
-	bprintf(text[CantPageNode],node.misc&NODE_ANON
-		? text[UNKNOWN_USER] : username(node.useron,tmp));
-	return; }
-if(node.action!=NODE_PAGE) {
-	bprintf("\r\n\1n\1mPaging \1h%s #%u\1n\1m for private chat\r\n"
-		,node.misc&NODE_ANON ? text[UNKNOWN_USER] : username(node.useron,tmp)
-		,node.useron);
-	sprintf(str,text[NodePChatPageMsg]
-		,node_num,thisnode.misc&NODE_ANON
-			? text[UNKNOWN_USER] : useron.alias);
-	putnmsg(n,str);
-	sprintf(str,"Paged %s on node %d to private chat"
-		,username(node.useron,tmp),n);
-	logline("C",str); }
-
-getnodedat(node_num,&thisnode,1);
-thisnode.action=action=NODE_PAGE;
-thisnode.aux=n;
-putnodedat(node_num,thisnode);
-
-if(node.action!=NODE_PAGE || node.aux!=node_num) {
-	bprintf(text[WaitingForNodeInPChat],n);
-	while(online && !(sys_status&SS_ABORT)) {
-		getnodedat(n,&node,0);
-		if((node.action==NODE_PAGE || node.action==NODE_PCHT)
-			&& node.aux==node_num) {
-			bprintf(text[NodeJoinedPrivateChat]
-				,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
-					: username(node.useron,tmp));
-			break; }
-		if(!inkey(0))
-			mswait(1);
-		action=NODE_PAGE;
-		checkline();
-		gettimeleft();
-		SYNC; } }
-
-getnodedat(node_num,&thisnode,1);
-thisnode.action=action=NODE_PCHT;
-putnodedat(node_num,thisnode);
-
-if(!online || sys_status&SS_ABORT)
-	return;
-
-if(useron.chat&CHAT_SPLITP && useron.misc&ANSI && rows>=24)
-	sys_status|=SS_SPLITP;
-/*
-if(!(useron.misc&EXPERT))
-	menu("PRIVCHAT");
-*/
-
-if(!(sys_status&SS_SPLITP))
-	bputs(text[WelcomeToPrivateChat]);
-
-sprintf(str,"%sCHAT.DAB",node_dir);
-if((out=open(str,O_RDWR|O_DENYNONE|O_CREAT|O_BINARY
-	,S_IREAD|S_IWRITE))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE|O_CREAT);
-	return; }
-
-sprintf(str,"%sCHAT.DAB",node_path[n-1]);
-if(!fexist(str))		/* Wait while it's created for the first time */
-	mswait(2000);
-if((in=open(str,O_RDWR|O_DENYNONE|O_CREAT|O_BINARY
-	,S_IREAD|S_IWRITE))==-1) {
-	close(out);
-	errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE|O_CREAT);
-	return; }
-
-if((p=(char *)MALLOC(PCHAT_LEN))==NULL) {
-	close(in);
-	close(out);
-	errormsg(WHERE,ERR_ALLOC,str,PCHAT_LEN);
-	return; }
-memset(p,0,PCHAT_LEN);
-write(in,p,PCHAT_LEN);
-write(out,p,PCHAT_LEN);
-FREE(p);
-lseek(in,0L,SEEK_SET);
-lseek(out,0L,SEEK_SET);
-
-getnodedat(node_num,&thisnode,1);
-thisnode.misc&=~NODE_RPCHT; 		/* Clear "reset pchat flag" */
-putnodedat(node_num,thisnode);
-
-getnodedat(n,&node,1);
-node.misc|=NODE_RPCHT;				/* Set "reset pchat flag" */
-putnodedat(n,node); 				/* on other node */
-
-									/* Wait for other node */
-									/* to acknowledge and reset */
-while(online && !(sys_status&SS_ABORT)) {
-	getnodedat(n,&node,0);
-	if(!(node.misc&NODE_RPCHT))
-		break;
-	getnodedat(node_num,&thisnode,0);
-	if(thisnode.misc&NODE_RPCHT)
-		break;
-	checkline();
-	gettimeleft();
-	SYNC;
-	inkey(0);
-	mswait(1); }
-
-
-action=NODE_PCHT;
-SYNC;
-
-if(sys_status&SS_SPLITP) {
-	lncntr=0;
-	CLS;
-	ANSI_SAVE();
-	GOTOXY(1,13);
-	bprintf(sep
-		,thisnode.misc&NODE_MSGW ? 'T':SP
-		,sectostr(timeleft,tmp)
-		,thisnode.misc&NODE_NMSG ? 'M':SP);
-	CRLF; }
-
-done=0;
-
-while(online && !(sys_status&SS_ABORT) && !done) {
-	RIOSYNC(0);
-	lncntr=0;
-	if(sys_status&SS_SPLITP)
-		lbuflen=0;
-	action=NODE_PCHT;
-	if(!localchar) {
-		if(sys_status&SS_SPLITP) {
-			getnodedat(node_num,&thisnode,0);
-			if(thisnode.misc&NODE_INTR)
-				break;
-			if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) {
-				getuserdat(&useron);
-				getnodedat(node_num,&thisnode,1);
-				thisnode.misc&=~NODE_UDAT;
-				putnodedat(node_num,thisnode); } }
-		else
-			nodesync(); }
-	activity=0;
-	if((ch=inkey(K_GETSTR))!=0) {
-		activity=1;
-		if(echo)
-			attr(color[clr_chatlocal]);
-		else
-			lclatr(color[clr_chatlocal]);
-		if(ch==BS) {
-			if(localchar) {
-				if(echo)
-					bputs("\b \b");
-				else
-					lputs("\b \b");
-				localchar--;
-				localbuf[localline][localchar]=0; } }
-		else if(ch==TAB) {
-			if(echo)
-				outchar(SP);
-			else
-				lputc(SP);
-			localbuf[localline][localchar]=SP;
-			localchar++;
-			while(localchar<78 && localchar%8) {
-				if(echo)
-					outchar(SP);
-				else
-					lputc(SP);
-				localbuf[localline][localchar++]=SP; } }
-		else if(ch>=SP || ch==CR) {
-			if(ch!=CR) {
-				if(echo)
-					outchar(ch);
-				else
-					lputc(ch);
-				localbuf[localline][localchar]=ch; }
-
-			if(ch==CR || (localchar>68 && ch==SP) || ++localchar>78) {
-
-				localbuf[localline][localchar]=0;
-				localchar=0;
-
-				if(sys_status&SS_SPLITP && lclwy()==24) {
-					GOTOXY(1,13);
-					bprintf(sep
-						,thisnode.misc&NODE_MSGW ? 'T':SP
-						,sectostr(timeleft,tmp)
-						,thisnode.misc&NODE_NMSG ? 'M':SP);
-					attr(color[clr_chatlocal]);
-					for(x=13,y=0;x<rows;x++,y++) {
-						bprintf("\x1b[%d;1H\x1b[K",x+1);
-						if(y<=localline)
-							bprintf("%s\r\n",localbuf[y]); }
-					GOTOXY(1,15+localline);
-					localline=0; }
-				else {
-					if(localline>=4)
-						for(i=0;i<4;i++)
-							memcpy(localbuf[i],localbuf[i+1],81);
-					else
-						localline++;
-					if(echo) {
-						CRLF;
-						if(sys_status&SS_SPLITP)
-							bputs("\x1b[K"); }
-					else
-						lputs(crlf); }
-				// SYNC;
-				} }
-
-		read(out,&c,1);
-		lseek(out,-1L,SEEK_CUR);
-		if(!c)		/* hasn't wrapped */
-			write(out,&ch,1);
-		else {
-			if(!tell(out))
-				lseek(out,0L,SEEK_END);
-			lseek(out,-1L,SEEK_CUR);
-			ch=0;
-			write(out,&ch,1);
-			lseek(out,-1L,SEEK_CUR); }
-		if(tell(out)>=PCHAT_LEN)
-			lseek(out,0L,SEEK_SET);
-		}
-	else while(online) {
-		if(!(sys_status&SS_SPLITP))
-			remotechar=localchar;
-		if(tell(in)>=PCHAT_LEN)
-			lseek(in,0L,SEEK_SET);
-		ch=0;
-		read(in,&ch,1);
-		lseek(in,-1L,SEEK_CUR);
-		if(!ch) break;					  /* char from other node */
-		activity=1;
-		x=lclwx();
-		y=lclwy();
-		if(sys_status&SS_SPLITP)
-			ANSI_RESTORE();
-		attr(color[clr_chatremote]);
-		if(sys_status&SS_SPLITP)
-			bputs("\b \b");             /* Delete fake cursor */
-		if(ch==BS) {
-			if(remotechar) {
-				bputs("\b \b");
-				remotechar--;
-				remotebuf[remoteline][remotechar]=0; } }
-		else if(ch==TAB) {
-			outchar(SP);
-			remotebuf[remoteline][remotechar]=SP;
-			remotechar++;
-			while(remotechar<78 && remotechar%8) {
-				outchar(SP);
-				remotebuf[remoteline][remotechar++]=SP; } }
-		else if(ch>=SP || ch==CR) {
-			if(ch!=CR) {
-				outchar(ch);
-				remotebuf[remoteline][remotechar]=ch; }
-
-			if(ch==CR || (remotechar>68 && ch==SP) || ++remotechar>78) {
-
-				remotebuf[remoteline][remotechar]=0;
-				remotechar=0;
-
-				if(sys_status&SS_SPLITP && lclwy()==12) {
-					CRLF;
-					bprintf(sep
-						,thisnode.misc&NODE_MSGW ? 'T':SP
-						,sectostr(timeleft,tmp)
-						,thisnode.misc&NODE_NMSG ? 'M':SP);
-					attr(color[clr_chatremote]);
-					for(i=0;i<12;i++) {
-						bprintf("\x1b[%d;1H\x1b[K",i+1);
-						if(i<=remoteline)
-							bprintf("%s\r\n",remotebuf[i]); }
-					remoteline=0;
-					GOTOXY(1,6); }
-				else {
-					if(remoteline>=4)
-						for(i=0;i<4;i++)
-							memcpy(remotebuf[i],remotebuf[i+1],81);
-					else
-						remoteline++;
-					if(echo) {
-						CRLF;
-						if(sys_status&SS_SPLITP)
-							bputs("\x1b[K"); }
-					else
-						lputs(crlf); } } }
-		if(sys_status&SS_SPLITP) {
-			bputs("\1i_\1n");  /* Fake cursor */
-			ANSI_SAVE();
-			GOTOXY(x,y); }
-		ch=0;
-		write(in,&ch,1);
-
-		if(!(sys_status&SS_SPLITP))
-			localchar=remotechar;
-		}
-	if(!activity) { 						/* no activity so chk node.dab */
-		getnodedat(n,&node,0);
-		if((node.action!=NODE_PCHT && node.action!=NODE_PAGE)
-			|| node.aux!=node_num) {
-			bprintf(text[NodeLeftPrivateChat]
-				,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
-				: username(node.useron,tmp));
-			break; }
-		getnodedat(node_num,&thisnode,0);
-		if(thisnode.misc&NODE_RPCHT) {		/* pchat has been reset */
-			lseek(in,0L,SEEK_SET);			/* so seek to beginning */
-			lseek(out,0L,SEEK_SET);
-			getnodedat(node_num,&thisnode,1);
-			thisnode.misc&=~NODE_RPCHT;
-			putnodedat(node_num,thisnode); }
-		mswait(0); }
-	checkline();
-	gettimeleft(); }
-if(sys_status&SS_SPLITP)
-	CLS;
-sys_status&=~SS_SPLITP;
-close(in);
-close(out);
-}
-
-/****************************************************************************/
-/* The chat section                                                         */
-/****************************************************************************/
-void chatsection()
-{
-	uchar	line[256],str[256],ch,c,done,no_rip_menu
-			,usrs,preusrs,qusrs,*gurubuf=NULL,channel,savch,*p
-			,pgraph[400],buf[400]
-			,usr[MAX_NODES],preusr[MAX_NODES],qusr[MAX_NODES];
-	int 	file,in,out;
-	long	i,j,k,n;
-	node_t 	node;
-
-action=NODE_CHAT;
-if(useron.misc&(RIP|WIP) || !(useron.misc&EXPERT))
-    menu("CHAT");
-ASYNC;
-bputs(text[ChatPrompt]);
-while(online) {
-	no_rip_menu=0;
-	ch=getkeys("ACDJPQST?\r",0);
-	if(ch>SP)
-		logch(ch,0);
-	switch(ch) {
-		case 'S':
-			useron.chat^=CHAT_SPLITP;
-			putuserrec(useron.number,U_CHAT,8
-                ,ltoa(useron.chat,str,16));
-			bprintf("\r\nPrivate split-screen chat is now: %s\r\n"
-				,useron.chat&CHAT_SPLITP ? text[ON]:text[OFF]);
-			break;
-		case 'A':
-			CRLF;
-			useron.chat^=CHAT_NOACT;
-			putuserrec(useron.number,U_CHAT,8
-				,ltoa(useron.chat,str,16));
-			getnodedat(node_num,&thisnode,1);
-			thisnode.misc^=NODE_AOFF;
-			printnodedat(node_num,thisnode);
-			putnodedat(node_num,thisnode);
-			no_rip_menu=1;
-			break;
-		case 'D':
-			CRLF;
-			useron.chat^=CHAT_NOPAGE;
-			putuserrec(useron.number,U_CHAT,8
-                ,ltoa(useron.chat,str,16));
-			getnodedat(node_num,&thisnode,1);
-			thisnode.misc^=NODE_POFF;
-			printnodedat(node_num,thisnode);
-			putnodedat(node_num,thisnode);
-			no_rip_menu=1;
-			break;
-		case 'J':
-			if(!chan_access(0))
-				break;
-			if(useron.misc&(RIP|WIP) ||!(useron.misc&EXPERT))
-				menu("MULTCHAT");
-			getnodedat(node_num,&thisnode,1);
-			bputs(text[WelcomeToMultiChat]);
-			channel=thisnode.aux=1;		/* default channel 1 */
-			putnodedat(node_num,thisnode);
-			bprintf(text[WelcomeToChannelN],channel,chan[0]->name);
-			if(gurubuf) {
-				FREE(gurubuf);
-				gurubuf=NULL; }
-			if(chan[0]->misc&CHAN_GURU && chan[0]->guru<total_gurus
-				&& chk_ar(guru[chan[0]->guru]->ar,useron)) {
-				sprintf(str,"%s%s.DAT",ctrl_dir,guru[chan[0]->guru]->code);
-				if((file=nopen(str,O_RDONLY))==-1) {
-					errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-					break; }
-				if((gurubuf=MALLOC(filelength(file)+1))==NULL) {
-					close(file);
-					errormsg(WHERE,ERR_ALLOC,str,filelength(file)+1);
-					break; }
-				read(file,gurubuf,filelength(file));
-				gurubuf[filelength(file)]=0;
-				close(file); }
-			usrs=0;
-			for(i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-				if(i==node_num)
-					continue;
-				getnodedat(i,&node,0);
-				if(node.action!=NODE_MCHT || node.status!=NODE_INUSE)
-					continue;
-				if(node.aux && (node.aux&0xff)!=channel)
-					continue;
-				printnodedat(i,node);
-				preusr[usrs]=usr[usrs++]=i; }
-			preusrs=usrs;
-			if(gurubuf)
-				bprintf(text[NodeInMultiChatLocally]
-					,sys_nodes+1,guru[chan[channel-1]->guru]->name,channel);
-			bputs(text[YoureOnTheAir]);
-			done=0;
-			while(online && !done) {
-				checkline();
-				gettimeleft();
-				action=NODE_MCHT;
-				qusrs=usrs=0;
-            	for(i=1;i<=sys_nodes;i++) {
-					if(i==node_num)
-						continue;
-					getnodedat(i,&node,0);
-					if(node.action!=NODE_MCHT
-						|| (node.aux && channel && (node.aux&0xff)!=channel))
-						continue;
-					if(node.status==NODE_QUIET)
-						qusr[qusrs++]=i;
-					else if(node.status==NODE_INUSE)
-						usr[usrs++]=i; }
-				if(preusrs>usrs) {
-					if(!usrs && channel && chan[channel-1]->misc&CHAN_GURU
-						&& chan[channel-1]->guru<total_gurus)
-						bprintf(text[NodeJoinedMultiChat]
-							,sys_nodes+1,guru[chan[channel-1]->guru]->name
-							,channel);
-					outchar(7);
-					for(i=0;i<preusrs;i++) {
-						for(j=0;j<usrs;j++)
-							if(preusr[i]==usr[j])
-								break;
-						if(j==usrs) {
-							getnodedat(preusr[i],&node,0);
-							if(node.misc&NODE_ANON)
-								sprintf(str,"%.80s",text[UNKNOWN_USER]);
-							else
-								username(node.useron,str);
-							bprintf(text[NodeLeftMultiChat]
-								,preusr[i],str,channel); } } }
-				else if(preusrs<usrs) {
-					if(!preusrs && channel && chan[channel-1]->misc&CHAN_GURU
-						&& chan[channel-1]->guru<total_gurus)
-						bprintf(text[NodeLeftMultiChat]
-							,sys_nodes+1,guru[chan[channel-1]->guru]->name
-							,channel);
-					outchar(7);
-					for(i=0;i<usrs;i++) {
-						for(j=0;j<preusrs;j++)
-							if(usr[i]==preusr[j])
-								break;
-						if(j==preusrs) {
-							getnodedat(usr[i],&node,0);
-                            if(node.misc&NODE_ANON)
-								sprintf(str,"%.80s",text[UNKNOWN_USER]);
-							else
-								username(node.useron,str);
-							bprintf(text[NodeJoinedMultiChat]
-								,usr[i],str,channel); } } }
-                preusrs=usrs;
-				for(i=0;i<usrs;i++)
-					preusr[i]=usr[i];
-				attr(color[clr_multichat]);
-				SYNC;
-				sys_status&=~SS_ABORT;
-				if((ch=inkey(0))!=0 || wordwrap[0]) {
-					if(ch=='/') {
-						bputs(text[MultiChatCommandPrompt]);
-						strcpy(str,"ACELWQ?*");
-						if(SYSOP)
-							strcat(str,"0");
-						i=getkeys(str,total_chans);
-						if(i&0x80000000L) {  /* change channel */
-							savch=i&~0x80000000L;
-							if(savch==channel)
-								continue;
-							if(!chan_access(savch-1))
-								continue;
-							bprintf(text[WelcomeToChannelN]
-								,savch,chan[savch-1]->name);
-
-							usrs=0;
-							for(i=1;i<=sys_nodes;i++) {
-								if(i==node_num)
-									continue;
-								getnodedat(i,&node,0);
-								if(node.action!=NODE_MCHT
-									|| node.status!=NODE_INUSE)
-									continue;
-								if(node.aux && (node.aux&0xff)!=savch)
-									continue;
-								printnodedat(i,node);
-								if(node.aux&0x1f00) {	/* password */
-									bprintf(text[PasswordProtected]
-										,node.misc&NODE_ANON
-										? text[UNKNOWN_USER]
-										: username(node.useron,tmp));
-									if(!getstr(str,8,K_UPPER|K_ALPHA|K_LINE))
-										break;
-									if(strcmp(str,unpackchatpass(tmp,node)))
-										break;
-										bputs(text[CorrectPassword]);  }
-								preusr[usrs]=usr[usrs++]=i; }
-							if(i<=sys_nodes) {	/* failed password */
-								bputs(text[WrongPassword]);
-								continue; }
-							if(gurubuf) {
-								FREE(gurubuf);
-								gurubuf=NULL; }
-							if(chan[savch-1]->misc&CHAN_GURU
-								&& chan[savch-1]->guru<total_gurus
-								&& chk_ar(guru[chan[savch-1]->guru]->ar,useron
-								)) {
-								sprintf(str,"%s%s.DAT",ctrl_dir
-									,guru[chan[savch-1]->guru]->code);
-                                if((file=nopen(str,O_RDONLY))==-1) {
-                                    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-                                    break; }
-                                if((gurubuf=MALLOC(filelength(file)+1))==NULL) {
-                                    close(file);
-									errormsg(WHERE,ERR_ALLOC,str
-										,filelength(file)+1);
-                                    break; }
-                                read(file,gurubuf,filelength(file));
-                                gurubuf[filelength(file)]=0;
-                                close(file); }
-							preusrs=usrs;
-							if(gurubuf)
-								bprintf(text[NodeInMultiChatLocally]
-									,sys_nodes+1
-									,guru[chan[savch-1]->guru]->name
-									,savch);
-							channel=savch;
-							if(!usrs && chan[savch-1]->misc&CHAN_PW
-								&& !noyes(text[PasswordProtectChanQ])) {
-								bputs(text[PasswordPrompt]);
-								if(getstr(str,8,K_UPPER|K_ALPHA|K_LINE)) {
-									getnodedat(node_num,&thisnode,1);
-									thisnode.aux=channel;
-									packchatpass(str,&thisnode); }
-								else {
-									getnodedat(node_num,&thisnode,1);
-									thisnode.aux=channel; } }
-							else {
-								getnodedat(node_num,&thisnode,1);
-								thisnode.aux=channel; }
-							putnodedat(node_num,thisnode);
-							bputs(text[YoureOnTheAir]);
-							if(chan[channel-1]->cost
-								&& !(useron.exempt&FLAG('J')))
-								subtract_cdt(chan[channel-1]->cost); }
-						else switch(i) {	/* other command */
-							case '0':	/* Global channel */
-								if(!SYSOP)
-									break;
-                            	usrs=0;
-								for(i=1;i<=sys_nodes;i++) {
-									if(i==node_num)
-										continue;
-									getnodedat(i,&node,0);
-									if(node.action!=NODE_MCHT
-										|| node.status!=NODE_INUSE)
-										continue;
-									printnodedat(i,node);
-									preusr[usrs]=usr[usrs++]=i; }
-								preusrs=usrs;
-								getnodedat(node_num,&thisnode,1);
-								thisnode.aux=channel=0;
-								putnodedat(node_num,thisnode);
-								break;
-							case 'A':   /* Action commands */
-								useron.chat^=CHAT_ACTION;
-								bprintf("\r\nAction commands are now %s\r\n"
-									,useron.chat&CHAT_ACTION
-									? text[ON]:text[OFF]);
-								putuserrec(useron.number,U_CHAT,8
-                                    ,ltoa(useron.chat,str,16));
-								break;
-							case 'C':   /* List of action commands */
-								CRLF;
-								for(i=0;i<total_chatacts;i++) {
-									if(chatact[i]->actset
-										!=chan[channel-1]->actset)
-										continue;
-									bprintf("%-*.*s",LEN_CHATACTCMD
-										,LEN_CHATACTCMD,chatact[i]->cmd);
-									if(!((i+1)%8)) {
-										CRLF; }
-									else
-										bputs(" "); }
-								CRLF;
-								break;
-							case 'E':   /* Toggle echo */
-								useron.chat^=CHAT_ECHO;
-								bprintf(text[EchoIsNow]
-									,useron.chat&CHAT_ECHO
-									? text[ON]:text[OFF]);
-								putuserrec(useron.number,U_CHAT,8
-                                    ,ltoa(useron.chat,str,16));
-								break;
-							case 'L':	/* list nodes */
-								CRLF;
-								for(i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-									getnodedat(i,&node,0);
-									printnodedat(i,node); }
-								CRLF;
-								break;
-							case 'W':   /* page node(s) */
-								j=getnodetopage(0,0);
-								if(!j)
-									break;
-								for(i=0;i<usrs;i++)
-									if(usr[i]==j)
-										break;
-								if(i>=usrs) {
-									bputs(text[UserNotFound]);
-									break; }
-
-								bputs(text[NodeMsgPrompt]);
-								if(!getstr(line,66,K_LINE|K_MSG))
-									break;
-
-								sprintf(buf,text[ChatLineFmt]
-									,thisnode.misc&NODE_ANON
-									? text[AnonUserChatHandle]
-									: useron.handle
-									,node_num,'*',line);
-								strcat(buf,crlf);
-								if(useron.chat&CHAT_ECHO)
-									bputs(buf);
-								putnmsg(j,buf);
-								break;
-							case 'Q':	/* quit */
-								done=1;
-								break;
-							case '*':
-								sprintf(str,"%sMENU\\CHAN.*",text_dir);
-								if(fexist(str))
-									menu("CHAN");
-								else {
-									bputs(text[ChatChanLstHdr]);
-									bputs(text[ChatChanLstTitles]);
-									if(total_chans>=10) {
-										bputs("     ");
-										bputs(text[ChatChanLstTitles]); }
-									CRLF;
-									bputs(text[ChatChanLstUnderline]);
-									if(total_chans>=10) {
-										bputs("     ");
-										bputs(text[ChatChanLstUnderline]); }
-									CRLF;
-									if(total_chans>=10)
-										j=(total_chans/2)+(total_chans&1);
-									else
-										j=total_chans;
-									for(i=0;i<j && !msgabort();i++) {
-										bprintf(text[ChatChanLstFmt],i+1
-											,chan[i]->name
-											,chan[i]->cost);
-										if(total_chans>=10) {
-											k=(total_chans/2)
-												+i+(total_chans&1);
-											if(k<total_chans) {
-												bputs("     ");
-												bprintf(text[ChatChanLstFmt]
-													,k+1
-													,chan[k]->name
-													,chan[k]->cost); } }
-										CRLF; }
-									CRLF; }
-								break;
-							case '?':	/* menu */
-								menu("MULTCHAT");
-								break;	} }
-					else {
-						ungetkey(ch);
-						j=0;
-						pgraph[0]=0;
-						while(j<5) {
-							if(!getstr(line,66,K_WRAP|K_MSG|K_CHAT))
-								break;
-							if(j) {
-								sprintf(str,text[ChatLineFmt]
-									,thisnode.misc&NODE_ANON
-									? text[AnonUserChatHandle]
-									: useron.handle
-									,node_num,':',nulstr);
-								sprintf(tmp,"%*s",bstrlen(str),nulstr);
-								strcat(pgraph,tmp); }
-							strcat(pgraph,line);
-							strcat(pgraph,crlf);
-							if(!wordwrap[0])
-								break;
-							j++; }
-						if(pgraph[0]) {
-							if(useron.chat&CHAT_ACTION) {
-								for(i=0;i<total_chatacts;i++) {
-									if(chatact[i]->actset
-										!=chan[channel-1]->actset)
-                                        continue;
-									sprintf(str,"%s ",chatact[i]->cmd);
-									if(!strnicmp(str,pgraph,strlen(str)))
-										break;
-									sprintf(str,"%.*s"
-										,LEN_CHATACTCMD+2,pgraph);
-									str[strlen(str)-2]=0;
-									if(!stricmp(chatact[i]->cmd,str))
-										break; }
-
-								if(i<total_chatacts) {
-									p=pgraph+strlen(str);
-									n=atoi(p);
-									for(j=0;j<usrs;j++) {
-										getnodedat(usr[j],&node,0);
-										if(usrs==1) /* no need to search */
-											break;
-										if(n) {
-											if(usr[j]==n)
-												break;
-											continue; }
-										username(node.useron,str);
-										if(!strnicmp(str,p,strlen(str)))
-											break;
-										getuserrec(node.useron,U_HANDLE
-											,LEN_HANDLE,str);
-										if(!strnicmp(str,p,strlen(str)))
-											break; }
-									if(!usrs
-										&& chan[channel-1]->guru<total_gurus)
-										strcpy(str
-										,guru[chan[channel-1]->guru]->name);
-									else if(j>=usrs)
-										strcpy(str,"everyone");
-									else if(node.misc&NODE_ANON)
-										strcpy(str,text[UNKNOWN_USER]);
-									else
-										username(node.useron,str);
-
-									/* Display on same node */
-									bprintf(chatact[i]->out
-										,thisnode.misc&NODE_ANON
-										? text[UNKNOWN_USER] : useron.alias
-										,str);
-									CRLF;
-
-									if(usrs && j<usrs) {
-										/* Display to dest user */
-										sprintf(buf,chatact[i]->out
-											,thisnode.misc&NODE_ANON
-											? text[UNKNOWN_USER] : useron.alias
-											,"you");
-										strcat(buf,crlf);
-										putnmsg(usr[j],buf); }
-
-
-									/* Display to all other users */
-									sprintf(buf,chatact[i]->out
-										,thisnode.misc&NODE_ANON
-										? text[UNKNOWN_USER] : useron.alias
-										,str);
-									strcat(buf,crlf);
-
-									for(i=0;i<usrs;i++) {
-										if(i==j)
-											continue;
-										getnodedat(usr[i],&node,0);
-										putnmsg(usr[i],buf); }
-									for(i=0;i<qusrs;i++) {
-										getnodedat(qusr[i],&node,0);
-										putnmsg(qusr[i],buf); }
-									continue; } }
-
-							sprintf(buf,text[ChatLineFmt]
-								,thisnode.misc&NODE_ANON
-								? text[AnonUserChatHandle]
-								: useron.handle
-								,node_num,':',pgraph);
-							if(useron.chat&CHAT_ECHO)
-								bputs(buf);
-							for(i=0;i<usrs;i++) {
-								getnodedat(usr[i],&node,0);
-								putnmsg(usr[i],buf); }
-							for(i=0;i<qusrs;i++) {
-								getnodedat(qusr[i],&node,0);
-								putnmsg(qusr[i],buf); }
-							if(!usrs && channel && gurubuf
-								&& chan[channel-1]->misc&CHAN_GURU)
-								guruchat(pgraph,gurubuf,chan[channel-1]->guru);
-								} } }
-				else
-					mswait(1);
-				if(sys_status&SS_ABORT)
-					break; }
-			lncntr=0;
-			break;
-		case 'P':   /* private node-to-node chat */
-            privchat();
-            break;
-		case 'C':
-			no_rip_menu=1;
-			ch=kbd_state(); 	 /* Check scroll lock */
-			if(ch&16 || (sys_chat_ar[0] && chk_ar(sys_chat_ar,useron))
-				|| useron.exempt&FLAG('C')) {
-				sysop_page();
-				break; }
-			bprintf(text[SysopIsNotAvailable],sys_op);
-			if(total_gurus && chk_ar(guru[0]->ar,useron)) {
-				sprintf(str,text[ChatWithGuruInsteadQ],guru[0]->name);
-				if(!yesno(str))
-					break; }
-			else
-				break;
-		case 'T':
-			if(!total_gurus) {
-				bprintf(text[SysopIsNotAvailable],"The Guru");
-				break; }
-			if(total_gurus==1 && chk_ar(guru[0]->ar,useron))
-				i=0;
-			else {
-				for(i=0;i<total_gurus;i++)
-					uselect(1,i,nulstr,guru[i]->name,guru[i]->ar);
-				i=uselect(0,0,0,0,0);
-				if(i<0)
-					break; }
-			if(gurubuf)
-				FREE(gurubuf);
-			sprintf(str,"%s%s.DAT",ctrl_dir,guru[i]->code);
-			if((file=nopen(str,O_RDONLY))==-1) {
-				errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-				return; }
-			if((gurubuf=MALLOC(filelength(file)+1))==NULL) {
-				close(file);
-				errormsg(WHERE,ERR_ALLOC,str,filelength(file)+1);
-				return; }
-			read(file,gurubuf,filelength(file));
-			gurubuf[filelength(file)]=0;
-			close(file);
-			localguru(gurubuf,i);
-			no_rip_menu=1;
-			FREE(gurubuf);
-			gurubuf=NULL;
-			break;
-		case '?':
-			if(useron.misc&EXPERT)
-				menu("CHAT");
-			break;
-		default:	/* 'Q' or <CR> */
-			lncntr=0;
-			if(gurubuf)
-				FREE(gurubuf);
-			return; }
-	action=NODE_CHAT;
-	if(!(useron.misc&EXPERT) || useron.misc&WIP
-		|| (useron.misc&RIP && !no_rip_menu)) {
-#if 0
-		sys_status&=~SS_ABORT;
-		if(lncntr) {
-			SYNC;
-			CRLF;
-			if(lncntr)			/* CRLF or SYNC can cause pause */
-				pause(); }
-#endif
-		menu("CHAT"); }
-	ASYNC;
-	bputs(text[ChatPrompt]); }
-if(gurubuf)
-	FREE(gurubuf);
-}
-
-int getnodetopage(int all, int telegram)
-{
-	static	uchar last[26];
-	char	str[128];
-	int 	i,j;
-	ulong	l;
-	node_t	node;
-
-if(!lastnodemsg)
-	last[0]=0;
-if(lastnodemsg) {
-	getnodedat(lastnodemsg,&node,0);
-    if(node.status!=NODE_INUSE && !SYSOP)
-		lastnodemsg=1; }
-for(j=0,i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-	getnodedat(i,&node,0);
-	if(i==node_num)
-		continue;
-	if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
-		if(!lastnodemsg)
-			lastnodemsg=i;
-		j++; } }
-
-if(!last[0])
-	sprintf(last,"%u",lastnodemsg);
-
-if(!j && !telegram) {
-    bputs(text[NoOtherActiveNodes]);
-	return(0); }
-
-if(all)
-	sprintf(str,text[NodeToSendMsgTo],lastnodemsg);
-else
-	sprintf(str,text[NodeToPrivateChat],lastnodemsg);
-mnemonics(str);
-
-strcpy(str,last);
-getstr(str,25,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
-if(sys_status&SS_ABORT)
-	return(0);
-if(!str[0])
-	return(0);
-
-j=atoi(str);
-if(j && j<=sys_lastnode && j<=sys_nodes) {
-	getnodedat(j,&node,0);
-	if(node.status!=NODE_INUSE && !SYSOP) {
-		bprintf(text[NodeNIsNotInUse],j);
-		return(0); }
-	if(telegram && node.misc&(NODE_POFF|NODE_ANON) && !SYSOP) {
-		bprintf(text[CantPageNode],node.misc&NODE_ANON
-			? text[UNKNOWN_USER] : username(node.useron,tmp));
-		return(0); }
-	strcpy(last,str);
-	if(telegram)
-		return(node.useron);
-	return(j); }
-if(all && !stricmp(str,"ALL"))
-	return(-1);
-
-if(str[0]=='\'') {
-	j=userdatdupe(0,U_HANDLE,LEN_HANDLE,str+1,0);
-	if(!j) {
-		bputs(text[UnknownUser]);
-		return(0); } }
-else if(str[0]=='#')
-    j=atoi(str+1);
-else
-	j=finduser(str);
-if(!j)
-	return(0);
-if(j>lastuser())
-	return(0);
-getuserrec(j,U_MISC,8,tmp);
-l=ahtoul(tmp);
-if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
-    bputs(text[UnknownUser]);
-	return(0); }
-
-for(i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-	getnodedat(i,&node,0);
-	if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
-		&& node.useron==j) {
-		if(telegram && node.misc&NODE_POFF && !SYSOP) {
-			bprintf(text[CantPageNode],node.misc&NODE_ANON
-				? text[UNKNOWN_USER] : username(node.useron,tmp));
-			return(0); }
-		if(telegram)
-			return(j);
-		strcpy(last,str);
-		return(i); } }
-if(telegram) {
-	strcpy(last,str);
-	return(j); }
-bputs(text[UserNotFound]);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Sending single line messages between nodes                               */
-/****************************************************************************/
-void nodemsg()
-{
-	static	inside;
-	char	str[256],line[256],buf[512],logbuf[512],ch;
-	int 	i,j,usernumber,done=0;
-	node_t	node,savenode;
-
-if(inside>1)	/* nested once only */
-	return;
-sys_status|=SS_IN_CTRLP;
-getnodedat(node_num,&savenode,0);
-inside++;
-wordwrap[0]=0;
-while(online && !done) {
-	if(useron.rest&FLAG('C')) {
-		bputs(text[R_SendMessages]);
-		break; }
-	SYNC;
-	mnemonics(text[PrivateMsgPrompt]);
-	sys_status&=~SS_ABORT;
-	while(online) { 	 /* Watch for incoming messages */
-		ch=toupper(inkey(0));
-		if(ch && strchr("TMCQ\r",ch))
-			break;
-		if(sys_status&SS_ABORT)
-			break;
-		if(online==ON_REMOTE && rioctl(IOSTATE)&ABORT) {
-			sys_status|=SS_ABORT;
-			break; }
-		getnodedat(node_num,&thisnode,0);
-		if(thisnode.misc&(NODE_MSGW|NODE_NMSG)) {
-			SAVELINE;
-			CRLF;
-			if(thisnode.misc&NODE_NMSG)
-				getnmsg();
-			if(thisnode.misc&NODE_MSGW)
-				getsmsg(useron.number);
-			CRLF;
-			RESTORELINE; }
-		else
-			nodesync();
-		gettimeleft();
-		checkline(); }
-
-	if(!online || sys_status&SS_ABORT) {
-		sys_status&=~SS_ABORT;
-		CRLF;
-		break; }
-
-	switch(toupper(ch)) {
-		case 'T':   /* Telegram */
-			bputs("Telegram\r\n");
-			usernumber=getnodetopage(0,1);
-			if(!usernumber)
-				break;
-
-			if(usernumber==1 && useron.rest&FLAG('S')) { /* ! val fback */
-				bprintf(text[R_Feedback],sys_op);
-				break; }
-			if(usernumber!=1 && useron.rest&FLAG('E')) {
-				bputs(text[R_Email]);
-				break; }
-			now=time(NULL);
-			bprintf("\1n\r\n\1mSending telegram to \1h%s #%u\1n\1m (Max 5 "
-				"lines, Blank line ends):\r\n\r\n\1g\1h"
-				,username(usernumber,tmp),usernumber);
-			sprintf(buf,"\1n\1g\7Telegram from \1n\1h%s\1n\1g on %s:\r\n\1h"
-				,thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias
-				,timestr(&now));
-			i=0;
-			logbuf[0]=0;
-			while(online && i<5) {
-				bprintf("%4s",nulstr);
-				if(!getstr(line,70,K_WRAP|K_MSG))
-					break;
-				sprintf(str,"%4s%s\r\n",nulstr,line);
-				strcat(buf,str);
-				if(line[0])
-					strcat(logbuf,line);
-				i++; }
-			if(!i)
-				break;
-			if(sys_status&SS_ABORT) {
-				CRLF;
-				break; }
-			putsmsg(usernumber,buf);
-			sprintf(str,"Sent telegram to %s #%u"
-				,username(usernumber,tmp),usernumber);
-			logline("C",str);
-			logline(nulstr,logbuf);
-			bprintf("\1n\1mTelegram sent to \1h%s\r\n"
-				,username(usernumber,tmp));
-			break;
-		case 'M':   /* Message */
-			bputs("Message\r\n");
-			i=getnodetopage(1,0);
-			if(!i)
-				break;
-			if(i!=-1) {
-				getnodedat(i,&node,0);
-				usernumber=node.useron;
-				if(node.misc&NODE_POFF && !SYSOP)
-					bprintf(text[CantPageNode],node.misc&NODE_ANON
-						? text[UNKNOWN_USER] : username(node.useron,tmp));
-				else {
-					bprintf("\r\n\1n\1mSending message to \1h%s\r\n"
-						,node.misc&NODE_ANON ? text[UNKNOWN_USER]
-						: username(node.useron,tmp));
-					bputs(text[NodeMsgPrompt]);
-					if(!getstr(line,69,K_LINE))
-						break;
-					sprintf(buf,text[NodeMsgFmt],node_num
-						,thisnode.misc&NODE_ANON
-							? text[UNKNOWN_USER] : useron.alias,line);
-					putnmsg(i,buf);
-					if(!(node.misc&NODE_ANON))
-						bprintf("\r\n\1n\1mMessage sent to \1h%s #%u\r\n"
-							,username(usernumber,tmp),usernumber);
-					sprintf(str,"Sent message to %s on node %d:"
-						,username(usernumber,tmp),i);
-					logline("C",str);
-					logline(nulstr,line); } }
-			else {	/* ALL */
-				bputs(text[NodeMsgPrompt]);
-				if(!getstr(line,70,K_LINE))
-					break;
-				sprintf(buf,text[AllNodeMsgFmt],node_num
-					,thisnode.misc&NODE_ANON
-						? text[UNKNOWN_USER] : useron.alias,line);
-				for(i=1;i<=sys_nodes;i++) {
-					if(i==node_num)
-						continue;
-					getnodedat(i,&node,0);
-					if((node.status==NODE_INUSE
-						|| (SYSOP && node.status==NODE_QUIET))
-						&& (SYSOP || !(node.misc&NODE_POFF)))
-						putnmsg(i,buf); }
-				logline("C","Sent message to all nodes");
-				logline(nulstr,line); }
-			break;
-		case 'C':   /* Chat */
-			bputs("Chat\r\n");
-			if(action==NODE_PCHT) { /* already in pchat */
-				done=1;
-				break; }
-			privchat();
-			action=savenode.action;
-			break;
-		default:
-			bputs("Quit\r\n");
-			done=1;
-			break; } }
-inside--;
-if(!inside)
-	sys_status&=~SS_IN_CTRLP;
-getnodedat(node_num,&thisnode,1);
-thisnode.action=action=savenode.action;
-thisnode.aux=savenode.aux;
-thisnode.extaux=savenode.extaux;
-putnodedat(node_num,thisnode);
-}
-
-/****************************************************************************/
-/* The guru will respond from the 'guru' buffer to 'line'                   */
-/****************************************************************************/
-void guruchat(char *line, char *gurubuf, int gurunum)
-{
-	char	str[256],cstr[256],*ptr,c,*answer[100],answers,theanswer[769]
-			,mistakes=1,hu=0;
-	int 	i,j,k,file;
-	long 	len;
-	struct	tm *tm;
-
-now=time(NULL);
-tm=localtime(&now);
-
-for(i=0;i<100;i++) {
-	if((answer[i]=MALLOC(513))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,nulstr,513);
-		while(i) {
-			i--;
-			FREE(answer[i]); }
-		sys_status&=~SS_GURUCHAT;
-		return; } }
-ptr=gurubuf;
-len=strlen(gurubuf);
-strupr(line);
-j=strlen(line);
-k=0;
-for(i=0;i<j;i++) {
-	if(!isalnum(line[i]) && !k)	/* beginning non-alphanumeric */
-		continue;
-	if(!isalnum(line[i]) && line[i]==line[i+1])	/* redundant non-alnum */
-		continue;
-	if(!isalnum(line[i]) && line[i+1]=='?')	/* fix "WHAT ?" */
-		continue;
-	cstr[k++]=line[i]; }
-cstr[k]=0;
-while(--k) {
-	if(!isalnum(cstr[k]))
-		continue;
-	break; }
-if(k<1) {
-	for(i=0;i<100;i++)
-		FREE(answer[i]);
-	return; }
-if(cstr[k+1]=='?')
-	k++;
-cstr[k+1]=0;
-while(*ptr && ptr<gurubuf+len) {
-	if(*ptr=='(') {
-		ptr++;
-		if(!guruexp(&ptr,cstr)) {
-			while(*ptr && *ptr!='(' && ptr<gurubuf+len)
-				ptr++;
-			continue; } }
-	else {
-		while(*ptr && *ptr!=LF && ptr<gurubuf+len) /* skip LF after ')' */
-			ptr++;
-		ptr++;
-		answers=0;
-		while(*ptr && answers<100 && ptr<gurubuf+len) {
-			i=0;
-			while(*ptr && *ptr!=CR && i<512 && ptr<gurubuf+len) {
-				answer[answers][i]=*ptr;
-				ptr++;
-				i++;
-				if(*ptr=='\\' && *(ptr+1)==CR) {	/* multi-line answer */
-					ptr+=3;	/* skip \CRLF */
-					answer[answers][i++]=CR;
-					answer[answers][i++]=LF; } }
-			answer[answers][i]=0;
-			if(!strlen(answer[answers]) || answer[answers][0]=='(') {
-				ptr-=strlen(answer[answers]);
-				break; }
-			ptr+=2;	/* skip CRLF */
-			answers++; }
-		if(answers==100)
-			while(*ptr && *ptr!='(' && ptr<gurubuf+len)
-				ptr++;
-		i=random(answers);
-		for(j=0,k=0;j<strlen(answer[i]);j++) {
-			if(answer[i][j]=='`') {
-				j++;
-				theanswer[k]=0;
-				switch(toupper(answer[i][j])) {
-					case 'A':
-						if(sys_status&SS_USERON)
-							strcat(theanswer,useron.alias);
-						else
-							strcat(theanswer,text[UNKNOWN_USER]);
-						break;
-					case 'B':
-						if(sys_status&SS_USERON)
-							strcat(theanswer,useron.birth);
-						else
-							strcat(theanswer,"00/00/00");
-						break;
-					case 'C':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,useron.comp);
-						else
-							strcat(theanswer,"PC Jr.");
-						break;
-					case 'D':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,ultoac(useron.dlb,tmp));
-						else
-							strcat(theanswer,"0");
-						break;
-					case 'G':
-						strcat(theanswer,guru[gurunum]->name);
-						break;
-					case 'H':
-						hu=1;
-						break;
-					case 'I':
-						strcat(theanswer,sys_id);
-						break;
-					case 'J':
-						sprintf(tmp,"%u",tm->tm_mday);
-						break;
-					case 'L':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,itoa(useron.level,tmp,10));
-						else
-							strcat(theanswer,"0");
-						break;
-					case 'M':
-						strcat(theanswer,month[tm->tm_mon]);
-						break;
-					case 'N':   /* Note */
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,useron.note);
-						else
-							strcat(theanswer,text[UNKNOWN_USER]);
-						break;
-					case 'O':
-						strcat(theanswer,sys_op);
-						break;
-					case 'P':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,useron.phone);
-						else
-							strcat(theanswer,"000-000-0000");
-						break;
-					case 'Q':
-							sys_status&=~SS_GURUCHAT;
-						break;
-					case 'R':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,useron.name);
-						else
-							strcat(theanswer,text[UNKNOWN_USER]);
-						break;
-					case 'S':
-						strcat(theanswer,sys_name);
-						break;
-					case 'T':
-						sprintf(tmp,"%u:%02u",tm->tm_hour>12 ? tm->tm_hour-12
-							: tm->tm_hour,tm->tm_min);
-						strcat(theanswer,tmp);
-						break;
-					case 'U':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,ultoac(useron.ulb,tmp));
-						else
-							strcat(theanswer,"0");
-						break;
-					case 'W':
-						strcat(theanswer,weekday[tm->tm_wday]);
-						break;
-					case 'Y':   /* Current year */
-						sprintf(tmp,"%u",1900+tm->tm_year);
-						strcat(theanswer,tmp);
-						break;
-					case 'Z':
-						if(sys_status&SS_USERON)
-							strcat(theanswer,useron.zipcode);
-                        else
-							strcat(theanswer,"90210");
-						break;
-					case '$':   /* Credits */
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,ultoac(useron.cdt,tmp));
-						else
-							strcat(theanswer,"0");
-						break;
-					case '#':
-                    	if(sys_status&SS_USERON)
-							strcat(theanswer,itoa(getage(useron.birth)
-								,tmp,10));
-						else
-							strcat(theanswer,"0");
-						break;
-					case '!':
-						mistakes=!mistakes;
-						break;
-					case '_':
-						mswait(500);
-						break; }
-				k=strlen(theanswer); }
-			else
-				theanswer[k++]=answer[i][j]; }
-		theanswer[k]=0;
-		mswait(500+random(1000));	 /* thinking time */
-		if(action!=NODE_MCHT) {
-			for(i=0;i<k;i++) {
-				if(mistakes && theanswer[i]!=theanswer[i-1] &&
-					((!isalnum(theanswer[i]) && !random(100))
-					|| (isalnum(theanswer[i]) && !random(30)))) {
-					c=j=random(3)+1;	/* 1 to 3 chars */
-					if(c<strcspn(theanswer+(i+1),"\0., "))
-						c=j=1;
-					while(j) {
-						outchar(97+random(26));
-						mswait(25+random(150));
-						j--; }
-					if(random(100)) {
-						mswait(100+random(300));
-						while(c) {
-							bputs("\b \b");
-							mswait(50+random(50));
-							c--; } } }
-				outchar(theanswer[i]);
-				if(theanswer[i]==theanswer[i+1])
-					mswait(25+random(50));
-				else
-					mswait(25+random(150));
-				if(theanswer[i]==SP)
-					mswait(random(50)); } }
-		else {
-			mswait(strlen(theanswer)*100);
-			bprintf(text[ChatLineFmt],guru[gurunum]->name
-				,sys_nodes+1,':',theanswer); }
-		CRLF;
-		sprintf(str,"%sGURU.LOG",data_dir);
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1)
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-		else {
-			if(action==NODE_MCHT) {
-				sprintf(str,"[Multi] ");
-				write(file,str,strlen(str)); }
-			sprintf(str,"%s:\r\n",sys_status&SS_USERON
-				? useron.alias : "UNKNOWN");
-			write(file,str,strlen(str));
-			write(file,line,strlen(line));
-			if(action!=NODE_MCHT)
-				write(file,crlf,2);
-			sprintf(str,"%s:\r\n",guru[gurunum]->name);
-			write(file,str,strlen(str));
-			write(file,theanswer,strlen(theanswer));
-			write(file,crlf,2);
-			close(file); }
-		if(hu)
-			hangup();
-		break; } }
-for(i=0;i<100;i++)
-	FREE(answer[i]);
-}
-
-/****************************************************************************/
-/* An expression from the guru's buffer 'ptrptr' is evaluated and true or   */
-/* false is returned.                                                       */
-/****************************************************************************/
-char guruexp(char **ptrptr, char *line)
-{
-	char	c,*cp,str[256],true=0,and=0,or=0,nest,*ar;
-
-if((**ptrptr)==')') {	/* expressions of () are always true */
-	(*ptrptr)++;
-	return(1); }
-while((**ptrptr)!=')' && (**ptrptr)) {
-	if((**ptrptr)=='[') {
-		(*ptrptr)++;
-		sprintf(str,"%.128s",*ptrptr);
-		while(**ptrptr && (**ptrptr)!=']')
-            (*ptrptr)++;
-        (*ptrptr)++;
-		cp=strchr(str,']');
-		if(cp) *cp=0;
-		ar=arstr(NULL,str);
-		c=chk_ar(ar,useron);
-		if(ar[0]!=AR_NULL)
-			FREE(ar);
-		if(!c && and) {
-			true=0;
-            break; }
-		if(c && or) {
-			true=1;
-			break; }
-		if(c)
-			true=1;
-		continue; }
-	if((**ptrptr)=='(') {
-		(*ptrptr)++;
-		c=guruexp(&(*ptrptr),line);
-		if(!c && and) {
-			true=0;
-			break; }
-		if(c && or) {
-			true=1;
-			break; }
-		if(c)
-			true=1;	}
-	if((**ptrptr)==')')
-		break;
-	c=0;
-	while((**ptrptr) && isspace(**ptrptr))
-		(*ptrptr)++;
-	while((**ptrptr)!='|' && (**ptrptr)!='&' && (**ptrptr)!=')' &&(**ptrptr)) {
-		str[c++]=(**ptrptr);
-		(*ptrptr)++; }
-	str[c]=0;
-	if((**ptrptr)=='|') {
-		if(!c && true)
-			break;
-		and=0;
-		or=1; }
-	else if((**ptrptr)=='&') {
-		if(!c && !true)
-			break;
-		and=1;
-		or=0; }
-	if(!c) {				/* support ((exp)op(exp)) */
-		(*ptrptr)++;
-		continue; }
-	if((**ptrptr)!=')')
-		(*ptrptr)++;
-	c=0;					/* c now used for start line flag */
-	if(str[strlen(str)-1]=='^') {	/* ^signifies start of line only */
-		str[strlen(str)-1]=0;
-		c=1; }
-	if(str[strlen(str)-1]=='~') {	/* ~signifies non-isolated word */
-		str[strlen(str)-1]=0;
-		cp=strstr(line,str);
-		if(c && cp!=line)
-			cp=0; }
-	else {
-		cp=strstr(line,str);
-		if(cp && c) {
-			if(cp!=line || isalnum(*(cp+strlen(str))))
-				cp=0; }
-		else {	/* must be isolated word */
-			while(cp)
-				if((cp!=line && isalnum(*(cp-1)))
-					|| isalnum(*(cp+strlen(str))))
-					cp=strstr(cp+strlen(str),str);
-				else
-					break; } }
-	if(!cp && and) {
-		true=0;
-		break; }
-	if(cp && or) {
-		true=1;
-		break; }
-	if(cp)
-		true=1; }
-nest=0;
-while((**ptrptr)!=')' && (**ptrptr)) {		/* handle nested exp */
-	if((**ptrptr)=='(')						/* (TRUE|(IGNORE)) */
-		nest++;
-	(*ptrptr)++;
-	while((**ptrptr)==')' && nest && (**ptrptr)) {
-		nest--;
-		(*ptrptr)++; } }
-(*ptrptr)++;	/* skip over ')' */
-return(true);
-}
-
-/****************************************************************************/
-/* Guru chat with the appearance of Local chat with sysop.                  */
-/****************************************************************************/
-void localguru(char *gurubuf, int gurunum)
-{
-	char	ch,str[256];
-	int 	con=console;		 /* save console state */
-
-if(sys_status&SS_GURUCHAT || !total_gurus)
-	return;
-sys_status|=SS_GURUCHAT;
-console&=~(CON_L_ECHOX|CON_R_ECHOX);	/* turn off X's */
-console|=(CON_L_ECHO|CON_R_ECHO);					/* make sure echo is on */
-if(action==NODE_CHAT) {	/* only page if from chat section */
-	bprintf(text[PagingGuru],guru[gurunum]->name);
-	ch=random(25)+25;
-	while(ch--) {
-		mswait(200);
-		outchar('.'); } }
-bprintf(text[SysopIsHere],guru[gurunum]->name);
-getnodedat(node_num,&thisnode,1);
-thisnode.aux=gurunum;
-putnodedat(node_num,thisnode);
-attr(color[clr_chatlocal]);
-guruchat("HELLO",gurubuf,gurunum);
-while(online && (sys_status&SS_GURUCHAT)) {
-	checkline();
-	action=NODE_GCHT;
-	SYNC;
-	if((ch=inkey(0))!=0) {
-		ungetkey(ch);
-		attr(color[clr_chatremote]);
-		if(getstr(str,78,K_WRAP|K_CHAT)) {
-			attr(color[clr_chatlocal]);
-			guruchat(str,gurubuf,gurunum); } }
-	else
-		mswait(1); }
-bputs(text[EndOfChat]);
-sys_status&=~SS_GURUCHAT;
-console=con;				/* restore console state */
-}
-
-/****************************************************************************/
-/* Packs the password 'pass' into 5bit ASCII inside node_t. 32bits in 		*/
-/* node.extaux, and the other 8bits in the upper byte of node.aux			*/
-/****************************************************************************/
-void packchatpass(char *pass, node_t *node)
-{
-	char	bits;
-	int		i,j;
-
-node->aux&=~0xff00;		/* clear the password */
-node->extaux=0L;
-if((j=strlen(pass))==0) /* there isn't a password */
-	return;
-node->aux|=(int)((pass[0]-64)<<8);  /* 1st char goes in low 5bits of aux */
-if(j==1)	/* password is only one char, we're done */
-	return;
-node->aux|=(int)((pass[1]-64)<<13); /* low 3bits of 2nd char go in aux */
-node->extaux|=(long)((pass[1]-64)>>3); /* high 2bits of 2nd char go extaux */
-bits=2;
-for(i=2;i<j;i++) {	/* now process the 3rd char through the last */
-	node->extaux|=(long)((long)(pass[i]-64)<<bits);
-	bits+=5; }
-}
-
-/****************************************************************************/
-/* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
-/* node.extaux, and the other 8bits in the upper byte of node.aux			*/
-/****************************************************************************/
-char *unpackchatpass(char *pass, node_t node)
-{
-	char 	bits;
-	int 	i;
-
-pass[0]=(node.aux&0x1f00)>>8;
-pass[1]=((node.aux&0xe000)>>13)|((node.extaux&0x3)<<3);
-bits=2;
-for(i=2;i<8;i++) {
-	pass[i]=(node.extaux>>bits)&0x1f;
-	bits+=5; }
-pass[8]=0;
-for(i=0;i<8;i++)
-	if(pass[i])
-		pass[i]+=64;
-return(pass);
-}
diff --git a/src/sbbs2/chk_ar.c b/src/sbbs2/chk_ar.c
deleted file mode 100644
index ee82da2a0146d1bb94fe265b240d36cf305e7e2f..0000000000000000000000000000000000000000
--- a/src/sbbs2/chk_ar.c
+++ /dev/null
@@ -1,509 +0,0 @@
-#line 1 "CHK_AR.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-int ar_exp(char **ptrptr, user_t user)
-{
-	uint len,true=1,not,or,equal,artype=AR_LEVEL,n,i,age;
-	ulong l;
-	struct tm *gm;
-
-for(;(**ptrptr);(*ptrptr)++) {
-
-	if((**ptrptr)==AR_ENDNEST)
-		break;
-
-	not=or=equal=0;
-
-	if((**ptrptr)==AR_OR) {
-        or=1;
-		(*ptrptr)++; }
-	
-	if((**ptrptr)==AR_NOT) {
-		not=1;
-		(*ptrptr)++; }
-
-	if((**ptrptr)==AR_EQUAL) {
-        equal=1;
-        (*ptrptr)++; }
-
-	if((true && or) || (!true && !or))
-		break;
-
-	if((**ptrptr)==AR_BEGNEST) {
-		(*ptrptr)++;
-		if(ar_exp(ptrptr,user))
-			true=!not;
-		else
-			true=not;
-		while((**ptrptr)!=AR_ENDNEST && (**ptrptr)) /* in case of early exit */
-			(*ptrptr)++;
-		if(!(**ptrptr))
-			break;
-		continue; }
-
-	artype=(**ptrptr);
-	switch(artype) {
-		case AR_ANSI:				/* No arguments */
-		case AR_RIP:
-		case AR_WIP:
-		case AR_LOCAL:
-		case AR_EXPERT:
-		case AR_SYSOP:
-		case AR_QUIET:
-		case AR_OS2:
-		case AR_DOS:
-			break;
-		default:
-			(*ptrptr)++;
-			break; }
-
-	n=(**ptrptr);
-	i=(*(short *)*ptrptr);
-	switch(artype) {
-		case AR_LEVEL:
-			if((equal && user.level!=n) || (!equal && user.level<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessLevel];
-				noaccess_val=n; }
-			break;
-		case AR_AGE:
-			age=getage(user.birth);
-			if((equal && age!=n) || (!equal && age<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessAge];
-                noaccess_val=n; }
-			break;
-		case AR_BPS:
-			if((equal && cur_rate!=i) || (!equal && cur_rate<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessBPS];
-				noaccess_val=i; }
-			break;
-		case AR_ANSI:
-			if(!(user.misc&ANSI))
-				true=not;
-			else true=!not;
-			break;
-		case AR_RIP:
-			if(!(user.misc&RIP))
-				true=not;
-			else true=!not;
-            break;
-		case AR_WIP:
-			if(!(user.misc&WIP))
-				true=not;
-			else true=!not;
-            break;
-		case AR_OS2:
-			#ifndef __OS2__
-				true=not;
-			#else
-				true=!not;
-			#endif
-			break;
-		case AR_DOS:
-			#ifdef __FLAT__
-				true=not;
-			#else
-				true=!not;
-			#endif
-			break;
-		case AR_EXPERT:
-			if(!(user.misc&EXPERT))
-				true=not;
-			else true=!not;
-            break;
-		case AR_SYSOP:
-			if(!SYSOP)
-				true=not;
-			else true=!not;
-            break;
-		case AR_QUIET:
-			if(thisnode.status!=NODE_QUIET)
-				true=not;
-			else true=!not;
-            break;
-		case AR_LOCAL:
-			if(online!=ON_LOCAL)
-				true=not;
-			else true=!not;
-            break;
-		case AR_DAY:
-			now=time(NULL);
-			gm=localtime(&now); 	  /* Qnet call out based on time */
-			if((equal && gm->tm_wday!=n) || (!equal && gm->tm_wday<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessDay];
-				noaccess_val=n; }
-			break;
-		case AR_CREDIT:
-			l=(ulong)i*1024UL;
-			if((equal && user.cdt+user.freecdt!=l)
-				|| (!equal && user.cdt+user.freecdt<l))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessCredit];
-				noaccess_val=l; }
-			break;
-		case AR_NODE:
-			if((equal && node_num!=n) || (!equal && node_num<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessNode];
-                noaccess_val=n; }
-			break;
-		case AR_USER:
-			if((equal && user.number!=i) || (!equal && user.number<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessUser];
-				noaccess_val=i; }
-			break;
-		case AR_GROUP:
-			if((equal
-				&& (cursubnum<0 || cursubnum>=total_subs
-					|| sub[cursubnum]->grp!=i))
-				|| (!equal && cursubnum>=0 && cursubnum<total_subs
-					&& sub[cursubnum]->grp<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessGroup];
-				noaccess_val=i+1; }
-            break;
-		case AR_SUB:
-			if((equal && cursubnum!=i) || (!equal && cursubnum<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessSub];
-				noaccess_val=i+1; }
-            break;
-		case AR_SUBCODE:
-			if(cursubnum<0 || cursubnum>=total_subs
-				|| strcmp(sub[cursubnum]->code,*ptrptr))
-				true=not;
-			else
-				true=!not;
-			while(*(*ptrptr))
-				(*ptrptr)++;
-			if(!true)
-				noaccess_str=text[NoAccessSub];
-			break;
-		case AR_LIB:
-			if((equal
-				&& (curdirnum<0 || curdirnum>=total_dirs
-					|| dir[curdirnum]->lib!=i))
-				|| (!equal && curdirnum>=0 && curdirnum<total_dirs
-					&& dir[curdirnum]->lib<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessLib];
-				noaccess_val=i+1; }
-            break;
-		case AR_DIR:
-			if((equal && curdirnum!=i) || (!equal && curdirnum<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessDir];
-				noaccess_val=i+1; }
-            break;
-		case AR_DIRCODE:
-			if(curdirnum<0 || curdirnum>=total_dirs
-				|| strcmp(dir[curdirnum]->code,*ptrptr))
-				true=not;
-			else
-				true=!not;
-			while(*(*ptrptr))
-				(*ptrptr)++;
-			if(!true)
-				noaccess_str=text[NoAccessSub];
-            break;
-		case AR_EXPIRE:
-			now=time(NULL);
-			if(!user.expire || now+((long)i*24L*60L*60L)>user.expire)
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessExpire];
-				noaccess_val=i; }
-			break;
-		case AR_RANDOM:
-			n=random(i+1);
-			if((equal && n!=i) || (!equal && n<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			break;
-		case AR_LASTON:
-			now=time(NULL);
-			if((now-user.laston)/(24L*60L*60L)<i)
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			break;
-		case AR_LOGONS:
-			if((equal && user.logons!=i) || (!equal && user.logons<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			break;
-		case AR_MAIN_CMDS:
-			if((equal && main_cmds!=i) || (!equal && main_cmds<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-            break;
-		case AR_FILE_CMDS:
-			if((equal && xfer_cmds!=i) || (!equal && xfer_cmds<i))
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-            break;
-		case AR_TLEFT:
-			if(timeleft/60<n)
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessTimeLeft];
-                noaccess_val=n; }
-			break;
-		case AR_TUSED:
-			if((time(NULL)-logontime)/60<n)
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessTimeUsed];
-                noaccess_val=n; }
-			break;
-		case AR_TIME:
-			now=time(NULL);
-			unixtodos(now,&date,&curtime);
-			if((curtime.ti_hour*60)+curtime.ti_min<i)
-				true=not;
-			else
-				true=!not;
-			(*ptrptr)++;
-			if(!true) {
-				noaccess_str=text[NoAccessTime];
-				noaccess_val=i; }
-			break;
-		case AR_PCR:
-			if(user.logons>user.posts
-				&& (!user.posts || 100/(user.logons/user.posts)<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessPCR];
-                noaccess_val=n; }
-			break;
-		case AR_UDR:	/* up/download byte ratio */
-			l=user.dlb;
-			if(!l) l=1;
-			if(user.dlb>user.ulb
-				&& (!user.ulb || 100/(l/user.ulb)<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessUDR];
-                noaccess_val=n; }
-			break;
-		case AR_UDFR:	/* up/download file ratio */
-			i=user.dls;
-			if(!i) i=1;
-			if(user.dls>user.uls
-				&& (!user.uls || 100/(i/user.uls)<n))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessUDFR];
-                noaccess_val=n; }
-            break;
-		case AR_FLAG1:
-			if((!equal && !(user.flags1&FLAG(n)))
-				|| (equal && user.flags1!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessFlag1];
-                noaccess_val=n; }
-			break;
-		case AR_FLAG2:
-			if((!equal && !(user.flags2&FLAG(n)))
-				|| (equal && user.flags2!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessFlag2];
-                noaccess_val=n; }
-            break;
-		case AR_FLAG3:
-			if((!equal && !(user.flags3&FLAG(n)))
-				|| (equal && user.flags3!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessFlag3];
-                noaccess_val=n; }
-            break;
-		case AR_FLAG4:
-			if((!equal && !(user.flags4&FLAG(n)))
-				|| (equal && user.flags4!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessFlag4];
-                noaccess_val=n; }
-            break;
-		case AR_REST:
-			if((!equal && !(user.rest&FLAG(n)))
-				|| (equal && user.rest!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessRest];
-                noaccess_val=n; }
-            break;
-		case AR_EXEMPT:
-			if((!equal && !(user.exempt&FLAG(n)))
-				|| (equal && user.exempt!=FLAG(n)))
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessExempt];
-                noaccess_val=n; }
-            break;
-		case AR_SEX:
-			if(user.sex!=n)
-				true=not;
-			else
-				true=!not;
-			if(!true) {
-				noaccess_str=text[NoAccessSex];
-                noaccess_val=n; }
-			break; } }
-return(true);
-}
-
-int chk_ar(char *str, user_t user)
-{
-	char *p;
-
-if(str==NULL)
-	return(1);
-p=str;
-return(ar_exp(&p,user));
-}
-
-
-/****************************************************************************/
-/* This function fills the usrsub, usrsubs, usrgrps, curgrp, and cursub     */
-/* variables based on the security clearance of the current user (useron)   */
-/****************************************************************************/
-void getusrsubs()
-{
-    uint i,j,k,l;
-
-for(j=0,i=0;i<total_grps;i++) {
-    if(!chk_ar(grp[i]->ar,useron))
-        continue;
-    for(k=0,l=0;l<total_subs;l++) {
-        if(sub[l]->grp!=i) continue;
-        if(!chk_ar(sub[l]->ar,useron))
-            continue;
-        usrsub[j][k++]=l; }
-    usrsubs[j]=k;
-    if(!k)          /* No subs accessible in group */
-        continue;
-    usrgrp[j++]=i; }
-usrgrps=j;
-while((curgrp>=usrgrps || !usrsubs[curgrp]) && curgrp) curgrp--;
-while(cursub[curgrp]>=usrsubs[curgrp] && cursub[curgrp]) cursub[curgrp]--;
-}
-
-/****************************************************************************/
-/* This function fills the usrdir, usrdirs, usrlibs, curlib, and curdir     */
-/* variables based on the security clearance of the current user (useron)   */
-/****************************************************************************/
-void getusrdirs()
-{
-    uint i,j,k,l;
-
-if(useron.rest&FLAG('T')) {
-    usrlibs=0;
-    return; }
-for(j=0,i=0;i<total_libs;i++) {
-    if(!chk_ar(lib[i]->ar,useron))
-        continue;
-    for(k=0,l=0;l<total_dirs;l++) {
-        if(dir[l]->lib!=i) continue;
-        if(!chk_ar(dir[l]->ar,useron))
-            continue;
-        usrdir[j][k++]=l; }
-    usrdirs[j]=k;
-    if(!k)          /* No dirs accessible in lib */
-        continue;
-    usrlib[j++]=i; }
-usrlibs=j;
-while((curlib>=usrlibs || !usrdirs[curlib]) && curlib) curlib--;
-while(curdir[curlib]>=usrdirs[curlib] && curdir[curlib]) curdir[curlib]--;
-}
-
-int dir_op(uint dirnum)
-{
-return(SYSOP || (dir[dirnum]->op_ar[0] && chk_ar(dir[dirnum]->op_ar,useron)));
-}
-
-
diff --git a/src/sbbs2/cmdshell.h b/src/sbbs2/cmdshell.h
deleted file mode 100644
index 8ec3c4e29973b4a8a3596a2ac2316b88b09590f7..0000000000000000000000000000000000000000
--- a/src/sbbs2/cmdshell.h
+++ /dev/null
@@ -1,586 +0,0 @@
-/* CMDSHELL.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "gen_defs.h"
-
-/******************************/
-/* Instructions and Functions */
-/******************************/
-enum {
-
-/* Single byte instructions */
-
-	 CS_IF_TRUE=0			// Same as IF_EQUAL
-	,CS_IF_FALSE			// Same as IF_NOT_EQUAL
-	,CS_ELSE
-	,CS_ENDIF
-	,CS_CMD_HOME
-	,CS_CMD_POP
-	,CS_END_CMD
-	,CS_RETURN
-	,CS_GETKEY
-	,CS_GETKEYE
-	,CS_UNGETKEY
-	,CS_UNGETSTR
-	,CS_PRINTKEY
-	,CS_PRINTSTR
-	,CS_HANGUP
-	,CS_SYNC
-	,CS_ASYNC
-	,CS_CHKSYSPASS
-	,CS_LOGKEY
-	,CS_LOGKEY_COMMA
-	,CS_LOGSTR
-	,CS_CLS
-	,CS_CRLF
-	,CS_PAUSE
-	,CS_PAUSE_RESET
-	,CS_GETLINES
-	,CS_GETFILESPEC
-	,CS_FINDUSER
-	,CS_CLEAR_ABORT
-	,CS_SELECT_SHELL
-	,CS_SET_SHELL
-	,CS_SELECT_EDITOR
-	,CS_SET_EDITOR			// 0x20
-	,CS_INKEY
-	,CS_RIOSYNC
-	,CS_GETTIMELEFT
-	,CS_SAVELINE
-	,CS_RESTORELINE
-	,CS_IF_GREATER
-	,CS_IF_GREATER_OR_EQUAL
-	,CS_IF_LESS
-	,CS_IF_LESS_OR_EQUAL
-	,CS_DEFAULT 			// 0x2a
-	,CS_END_SWITCH
-	,CS_END_CASE
-	,CS_PUT_NODE
-	,CS_ONE_MORE_BYTE=0x2f
-
-/* Two byte instructions */
-
-	,CS_CMDKEY=0x30
-	,CS_NODE_ACTION
-	,CS_GETSTR
-	,CS_GETNAME
-	,CS_GETSTRUPR
-	,CS_SHIFT_STR
-	,CS_COMPARE_KEY
-	,CS_SETLOGIC
-	,CS_SET_USER_LEVEL
-	,CS_SET_USER_STRING
-	,CS_GETLINE 			// 0x3a
-	,CS_NODE_STATUS
-	,CS_TWO_MORE_BYTES=0x3f
-
-/* Three byte instructions */
-
-	,CS_GOTO=0x40
-	,CS_CALL
-	,CS_TOGGLE_NODE_MISC
-	,CS_ADJUST_USER_CREDITS
-	,CS_TOGGLE_USER_FLAG
-	,CS_GETNUM
-	,CS_COMPARE_NODE_MISC
-	,CS_MSWAIT
-	,CS_ADJUST_USER_MINUTES
-	,CS_REVERT_TEXT
-	,CS_THREE_MORE_BYTES=0x4f
-
-/* String arg instructions */
-
-	,CS_MENU=0x50
-	,CS_PRINT
-	,CS_PRINT_LOCAL
-	,CS_PRINT_REMOTE
-	,CS_PRINTFILE
-	,CS_PRINTFILE_LOCAL
-	,CS_PRINTFILE_REMOTE
-	,CS_YES_NO
-    ,CS_NO_YES
-	,CS_COMPARE_STR
-	,CS_COMPARE_WORD		// 0x5a
-	,CS_EXEC
-	,CS_EXEC_INT
-	,CS_EXEC_BIN
-	,CS_EXEC_XTRN
-	,CS_GETCMD
-	,CS_LOG 				// 0x60
-	,CS_MNEMONICS
-	,CS_SETSTR
-	,CS_SET_MENU_DIR
-	,CS_SET_MENU_FILE
-	,CS_CMDSTR
-	,CS_CHKFILE
-	,CS_GET_TEMPLATE
-	,CS_TRASHCAN
-	,CS_CREATE_SIF
-	,CS_READ_SIF			// 0x6a
-	,CS_CMDKEYS
-	,CS_COMPARE_KEYS
-	,CS_STR_FUNCTION=0x6f
-
-/* Var length instructions */
-
-	,CS_COMPARE_ARS=0x70
-	,CS_TOGGLE_USER_MISC
-	,CS_COMPARE_USER_MISC
-	,CS_REPLACE_TEXT
-	,CS_TOGGLE_USER_CHAT
-	,CS_COMPARE_USER_CHAT
-	,CS_TOGGLE_USER_QWK
-	,CS_COMPARE_USER_QWK
-	,CS_SWITCH
-	,CS_CASE
-	,CS_USE_INT_VAR 		// 0x7a
-
-/* File I/O Functions */
-
-	,CS_FIO_FUNCTION=0x7e
-
-/* Variable instruction sub-ops */
-
-	,CS_VAR_INSTRUCTION=0x7f
-
-/* Functions */
-
-	,CS_MAIL_READ=0x80
-	,CS_MAIL_READ_SENT
-	,CS_MAIL_READ_ALL
-	,CS_MAIL_SEND
-	,CS_MAIL_SEND_BULK
-	,CS_MAIL_SEND_FILE
-	,CS_MAIL_SEND_FEEDBACK
-	,CS_MAIL_SEND_NETMAIL
-	,CS_MAIL_SEND_NETFILE
-	,CS_LOGOFF
-    ,CS_LOGOFF_FAST
-	,CS_AUTO_MESSAGE
-	,CS_MSG_SET_AREA
-	,CS_MSG_SELECT_AREA
-	,CS_MSG_SHOW_GROUPS
-    ,CS_MSG_SHOW_SUBBOARDS
-	,CS_MSG_GROUP_UP			// 0x90
-    ,CS_MSG_GROUP_DOWN
-    ,CS_MSG_SUBBOARD_UP
-    ,CS_MSG_SUBBOARD_DOWN
-	,CS_MSG_GET_SUB_NUM
-	,CS_MSG_GET_GRP_NUM
-	,CS_MSG_READ
-	,CS_MSG_POST
-	,CS_MSG_QWK
-	,CS_MSG_PTRS_CFG
-	,CS_MSG_PTRS_REINIT
-	,CS_MSG_NEW_SCAN_CFG
-	,CS_MSG_NEW_SCAN
-	,CS_MSG_NEW_SCAN_ALL
-	,CS_MSG_CONT_SCAN
-	,CS_MSG_CONT_SCAN_ALL
-	,CS_MSG_BROWSE_SCAN 		// 0xA0
-	,CS_MSG_BROWSE_SCAN_ALL
-	,CS_MSG_FIND_TEXT
-	,CS_MSG_FIND_TEXT_ALL
-	,CS_MSG_YOUR_SCAN_CFG
-	,CS_MSG_YOUR_SCAN
-	,CS_MSG_YOUR_SCAN_ALL
-	,CS_MSG_NEW_SCAN_SUB
-	,CS_MSG_SET_GROUP
-	,CS_MSG_UNUSED4
-	,CS_MSG_UNUSED3
-	,CS_MSG_UNUSED2
-	,CS_MSG_UNUSED1
-	,CS_FILE_SET_AREA
-	,CS_FILE_SELECT_AREA
-	,CS_FILE_SHOW_LIBRARIES
-	,CS_FILE_SHOW_DIRECTORIES	// 0xB0
-	,CS_FILE_LIBRARY_UP
-	,CS_FILE_LIBRARY_DOWN
-	,CS_FILE_DIRECTORY_UP
-	,CS_FILE_DIRECTORY_DOWN
-	,CS_FILE_GET_DIR_NUM
-	,CS_FILE_GET_LIB_NUM
-	,CS_FILE_LIST
-	,CS_FILE_LIST_EXTENDED
-	,CS_FILE_VIEW
-	,CS_FILE_UPLOAD
-	,CS_FILE_UPLOAD_USER
-	,CS_FILE_UPLOAD_SYSOP
-	,CS_FILE_DOWNLOAD
-	,CS_FILE_DOWNLOAD_USER
-	,CS_FILE_DOWNLOAD_BATCH
-	,CS_FILE_REMOVE 			//0xC0
-	,CS_FILE_BATCH_SECTION
-	,CS_FILE_TEMP_SECTION
-	,CS_FILE_NEW_SCAN_CFG
-	,CS_FILE_NEW_SCAN
-	,CS_FILE_NEW_SCAN_ALL
-	,CS_FILE_FIND_TEXT
-	,CS_FILE_FIND_TEXT_ALL
-	,CS_FILE_FIND_NAME
-	,CS_FILE_FIND_NAME_ALL
-	,CS_FILE_PTRS_CFG
-	,CS_FILE_BATCH_ADD
-	,CS_FILE_BATCH_CLEAR
-	,CS_FILE_SET_LIBRARY
-	,CS_FILE_SEND				//Like file_get, but no password needed
-	,CS_FILE_BATCH_ADD_LIST
-	,CS_FILE_UNUSED1			//0xD0
-	,CS_NODELIST_ALL
-	,CS_NODELIST_USERS
-	,CS_CHAT_SECTION
-	,CS_USER_DEFAULTS
-	,CS_USER_EDIT
-	,CS_TEXT_FILE_SECTION
-	,CS_INFO_SYSTEM
-	,CS_INFO_SUBBOARD
-	,CS_INFO_DIRECTORY
-	,CS_INFO_USER
-	,CS_INFO_VERSION
-	,CS_INFO_XFER_POLICY
-	,CS_XTRN_EXEC
-	,CS_XTRN_SECTION
-	,CS_USERLIST_SUB
-	,CS_USERLIST_DIR			//0xE0
-	,CS_USERLIST_ALL
-    ,CS_USERLIST_LOGONS
-	,CS_PAGE_SYSOP
-    ,CS_PRIVATE_CHAT
-    ,CS_PRIVATE_MESSAGE
-	,CS_MINUTE_BANK
-	,CS_GURU_LOG
-	,CS_ERROR_LOG
-	,CS_SYSTEM_LOG
-	,CS_SYSTEM_YLOG
-	,CS_SYSTEM_STATS
-	,CS_NODE_STATS
-	,CS_SHOW_MEM
-	,CS_CHANGE_USER
-	,CS_ANSI_CAPTURE
-	,CS_LIST_TEXT_FILE			//0xF0
-	,CS_EDIT_TEXT_FILE
-	,CS_FILE_SET_ALT_PATH
-	,CS_FILE_RESORT_DIRECTORY
-	,CS_FILE_GET
-	,CS_FILE_PUT
-	,CS_FILE_UPLOAD_BULK
-	,CS_FILE_FIND_OLD
-	,CS_FILE_FIND_OPEN
-	,CS_FILE_FIND_OFFLINE
-	,CS_FILE_FIND_OLD_UPLOADS
-	,CS_INC_MAIN_CMDS
-	,CS_INC_FILE_CMDS
-	,CS_PRINTFILE_STR
-	,CS_PAGE_GURU				//0xFE
-	
-	};
-
-	/* Variable instructions (sub-op-code) */
-
-enum {
-
-	 SHOW_VARS						// Show all variables
-	,PRINT_VAR						// Print a single variable
-	,VAR_PRINTF 					// Print a formated line of text
-	,VAR_RESERVED_4
-	,VAR_RESERVED_3
-	,VAR_RESERVED_2
-	,VAR_RESERVED_1
-	,DEFINE_STR_VAR 				// Define Local Variable
-	,DEFINE_INT_VAR
-	,VAR_RESERVED_A4
-	,VAR_RESERVED_A3
-	,VAR_RESERVED_A2
-	,VAR_RESERVED_A1
-	,DEFINE_GLOBAL_STR_VAR			// Define Global Variable
-	,DEFINE_GLOBAL_INT_VAR
-	,VAR_RESERVED_B4
-	,VAR_RESERVED_B3	// 0x10
-	,VAR_RESERVED_B2
-	,VAR_RESERVED_B1
-	,SET_STR_VAR					// Set string variable
-	,SET_INT_VAR					// Set integer variable
-	,VAR_RESERVED_C4
-	,VAR_RESERVED_C3
-	,VAR_RESERVED_C2
-	,VAR_RESERVED_C1
-	,COMPARE_STR_VAR				// Compare string variable (static)
-	,COMPARE_INT_VAR				// Compare integer variable (static)
-	,STRNCMP_VAR					// Compare n chars of str var (static)
-	,STRSTR_VAR 					// Sub-string compare of str var (static)
-	,VAR_RESERVED_D2
-	,VAR_RESERVED_D1
-	,COMPARE_VARS					// Compare two variables
-	,STRNCMP_VARS		// 0x20 	// Compare n chars of str vars (dynamic)
-	,STRSTR_VARS					// Sub-string compare between two str vars
-	,VAR_RESERVED_E2
-	,VAR_RESERVED_E1
-	,COPY_VAR						// Copy from one variable to another
-	,VAR_RESERVED_F4
-	,VAR_RESERVED_F3
-	,VAR_RESERVED_F2
-	,VAR_RESERVED_F1
-	,SWAP_VARS						// Swap two variables
-	,VAR_RESERVED_G4
-	,VAR_RESERVED_G3
-	,VAR_RESERVED_G2
-	,VAR_RESERVED_G1
-	,CAT_STR_VAR					// Concatenate string variable (static)
-    ,CAT_STR_VARS                   // Concatenate strint variable (dynamic)
-	,FORMAT_STR_VAR 	// 0x30 	// Format string variable
-	,TIME_STR						// Write formated date/time to string
-	,DATE_STR						// Write MM/DD/YY to string
-	,FORMAT_TIME_STR				// Create custom date/time string
-	,SECOND_STR 					// Create a string in format hh:mm:ss
-	,STRUPR_VAR 					// Convert string to upper case
-	,STRLWR_VAR 					// Convert string to lower case
-	,ADD_INT_VAR					// Add to int variable (static)
-	,ADD_INT_VARS					// Add to int variable (dynamic)
-	,VAR_RESERVED_I4
-	,VAR_RESERVED_I3
-	,VAR_RESERVED_I2
-	,VAR_RESERVED_I1
-	,SUB_INT_VAR					// Subtract from int variable (static)
-	,SUB_INT_VARS					// Subtract from int variable (dynamic)
-	,VAR_RESERVED_J4
-	,VAR_RESERVED_J3	// 0x40
-	,VAR_RESERVED_J2
-	,VAR_RESERVED_J1
-	,MUL_INT_VAR					// Multiply int variable (static)
-	,MUL_INT_VARS					// Multiply int variable (dynamic)
-	,VAR_RESERVED_K4
-	,VAR_RESERVED_K3
-	,VAR_RESERVED_K2
-	,VAR_RESERVED_K1
-	,DIV_INT_VAR					// Divide int variable (static)
-	,DIV_INT_VARS					// Divide int variable (dynamic)
-	,MOD_INT_VAR
-	,MOD_INT_VARS
-	,VAR_RESERVED_L2
-	,VAR_RESERVED_L1
-	,AND_INT_VAR					// Bit-wise AND int variable (static)
-	,AND_INT_VARS		// 0x50 	// Bit-wise AND int variable (dynamic)
-	,VAR_RESERVED_M4
-	,VAR_RESERVED_M3
-	,VAR_RESERVED_M2
-	,VAR_RESERVED_M1
-	,OR_INT_VAR 					// Bit-wise OR int variable (static)
-	,OR_INT_VARS					// Bit-wise OR int variable (dynamic)
-	,VAR_RESERVED_N4
-	,VAR_RESERVED_N3
-	,VAR_RESERVED_N2
-	,VAR_RESERVED_N1
-	,NOT_INT_VAR					// Bit-wise NOT int variable (static)
-	,NOT_INT_VARS					// Bit-wise NOT int variable (dynamic)
-	,VAR_RESERVED_O4
-	,VAR_RESERVED_O3
-	,VAR_RESERVED_O2
-	,VAR_RESERVED_O1	// 0x60
-	,XOR_INT_VAR					// XOR int variable (static)
-	,XOR_INT_VARS					// XOR int variable (dynamic)
-	,VAR_RESERVED_P4
-	,VAR_RESERVED_P3
-	,VAR_RESERVED_P2
-	,VAR_RESERVED_P1
-	,RANDOM_INT_VAR 				// Set integer to random number
-	,TIME_INT_VAR					// Set integer to current time/date
-	,DATE_STR_TO_INT				// Convert a date string to integer
-	,STRLEN_INT_VAR 				// Set integer to length of str
-	,CRC16_TO_INT					// Get CRC-16 of str var
-	,CRC32_TO_INT					// Get CRC-32 of str var
-	,FLENGTH_TO_INT 				// Put length of str var file into int
-	,CHARVAL_TO_INT 				// Put character val of str var into int
-	,GETNUM_VAR 					// Get number
-	,GETSTR_VAR 		// 0x70 	// Get string
-	,GETNAME_VAR					// Get string (upper/lower)
-	,GETSTRUPR_VAR					// Get string (upper)
-	,GETLINE_VAR					// Get string (input bar/line)
-	,SHIFT_STR_VAR					// Shift str in variable
-	,GETSTR_MODE					// Get string with various modes
-	,TRUNCSP_STR_VAR				// Truncate space off end of str var
-	,CHKFILE_VAR
-	,PRINTFILE_VAR_MODE 			// Printfile str var with mode
-	,PRINTTAIL_VAR_MODE 			// Print tail-end of str var with mode
-	,CHKSUM_TO_INT					// Get CHKSUM of str var
-	,STRIP_CTRL_STR_VAR 			// Strip ctrl chars from str var
-	,SEND_FILE_VIA					// Send file (static) via protocol
-	,SEND_FILE_VIA_VAR				// Send file (dynamic) via protocol
-	,FTIME_TO_INT					// Put time of str var file into int
-	,RECEIVE_FILE_VIA				// Receive file (static) via protocol
-	,RECEIVE_FILE_VIA_VAR			// Receive file (dynamic) via protocol
-	};
-
-									// More string arg functions
-enum {
-	 CS_LOGIN						// Login/password prompt
-	,CS_LOAD_TEXT					// Load alternative TEXT.DAT
-	};
-
-enum {								// More single byte instructions
-	 CS_ONLINE						// Online execution only
-	,CS_OFFLINE 					// Offline execution allowed
-	,CS_NEWUSER 					// New user procedure
-	,CS_LOGON						// Logon procedure
-	,CS_LOGOUT						// Logout procedure
-	,CS_EXIT						// Exit current module immediately
-	};
-
-enum {								// More two byte instructions
-	 CS_USER_EVENT					// External user event
-	};
-
-enum {
-	 FIO_OPEN						// Open file (static filename)
-	,FIO_CLOSE						// Close file
-	,FIO_READ						// Read from file
-	,FIO_READ_VAR					// Read from file, variable # of bytes
-	,FIO_WRITE						// Write to file
-	,FIO_WRITE_VAR					// Write to file, variable # of bytes
-	,FIO_GET_LENGTH 				// Get length
-	,FIO_EOF						// Set logic to TRUE if eof
-	,FIO_GET_POS					// Get current file position
-	,FIO_SEEK						// Seek within file
-	,FIO_SEEK_VAR					// Seek within file, variable offset
-	,FIO_LOCK						// Lock a region
-	,FIO_LOCK_VAR					// Lock a region, variable length
-	,FIO_UNLOCK 					// Unlock a region
-	,FIO_UNLOCK_VAR 				// Unlock a region, variable length
-	,FIO_SET_LENGTH 				// Change size
-	,FIO_SET_LENGTH_VAR 			// Change size, variable length
-	,FIO_PRINTF 					// Write formated string to file
-	,FIO_SET_ETX					// Set end-of-text character
-	,FIO_GET_TIME					// Gets the current date/time of file
-	,FIO_SET_TIME					// Sets the current date/time of file
-	,FIO_OPEN_VAR					// Open a file (dynamic filename)
-	,FIO_READ_LINE					// Read a single line from file
-	,FIO_FLUSH						// Flush buffered output to disk
-	,FIO_UNUSED8
-	,FIO_UNUSED7
-	,FIO_UNUSED6
-	,FIO_UNUSED5
-	,FIO_UNUSED4
-	,FIO_UNUSED3
-	,FIO_UNUSED2
-	,FIO_UNUSED1
-	,REMOVE_FILE					// Remove a file
-	,RENAME_FILE					// Rename a file
-	,COPY_FILE						// Copy a file to another file
-	,MOVE_FILE						// Move a file to another file
-	,GET_FILE_ATTRIB				// Get file attributes
-	,SET_FILE_ATTRIB				// Set file attributes
-	,MAKE_DIR						// Make directory
-	,CHANGE_DIR 					// Change current directory
-	,REMOVE_DIR 					// Remove directory
-	,OPEN_DIR						// Open a directory
-	,READ_DIR						// Read a directory entry
-	,REWIND_DIR 					// Rewind an open directory
-	,CLOSE_DIR						// Close an open directory
-	};
-
-enum {
-	 USER_STRING_ALIAS
-	,USER_STRING_REALNAME
-	,USER_STRING_HANDLE
-	,USER_STRING_COMPUTER
-	,USER_STRING_NOTE
-	,USER_STRING_ADDRESS
-	,USER_STRING_LOCATION
-	,USER_STRING_ZIPCODE
-	,USER_STRING_PASSWORD
-	,USER_STRING_BIRTHDAY
-	,USER_STRING_PHONE
-	,USER_STRING_MODEM
-	,USER_STRING_COMMENT
-
-	};
-
-#define CS_ONE_BYTE 	CS_IF_TRUE
-#define CS_TWO_BYTE 	CS_CMDKEY
-#define CS_THREE_BYTE	CS_GOTO
-#define CS_ASCIIZ		CS_MENU
-#define CS_MISC 		CS_COMPARE_ARS
-#define CS_FUNCTIONS	CS_MAIL_READ
-#define CS_ELSEORENDIF	0xff
-#define CS_NEXTCASE 	0xfe
-
-#define CS_DIGIT		0xff
-#define CS_EDIGIT		0xfe
-
-									/* Bits for csi_t.misc */
-#define CS_IN_SWITCH	(1L<<0) 	/* Inside active switch statement */
-#define CS_OFFLINE_EXEC (1L<<1) 	/* Offline execution */
-
-#define MAX_RETS	50	/* maximum nested call depth */
-#define MAX_CMDRETS 50	/* maximum nested cmd depth */
-#define MAX_STRVARS 26
-#define MAX_INTVARS 26
-#define MAX_STRLEN	81
-#define MAX_FOPENS	10	/* maximum open files */
-#define MAX_SYSVARS 16	/* maximum system variable saves */
-
-#define LOGIC_LESS		-1
-#define LOGIC_EQUAL 	0
-#define LOGIC_GREATER	1
-#define LOGIC_TRUE		LOGIC_EQUAL
-#define LOGIC_FALSE 	LOGIC_LESS
-
-typedef struct {					/* Command shell image */
-
-	uchar	*cs,					/* Command shell image */
-			*ip,					/* Instruction pointer */
-			cmd,					/* Current command key */
-			etx,					/* End-of-text character */
-			*str,					/* Current string */
-			*ret[MAX_RETS], 		/* Return address stack */
-			rets,					/* Returns on stack */
-			*cmdret[MAX_CMDRETS],	/* Command return address stack */
-			cmdrets,				/* Command returns on stack */
-			**str_var;				/* String variables */
-
-
-	int 	logic,					/* Current logic */
-			files;					/* Open files */
-
-	FILE	*file[MAX_FOPENS];		/* Each file ptr */
-
-	uint	str_vars,				/* Total number of string variables */
-			int_vars;				/* Total number of integer variables */
-
-	long	retval, 				/* Return value */
-			misc,					/* Misc bits */
-			switch_val, 			/* Current switch value */
-			*int_var,				/* Integer variables */
-			*str_var_name,			/* String variable names (CRC-32) */
-			*int_var_name;			/* Integer variable names (CRC-32) */
-
-	ulong	length; 				/* Length of image */
-
-	} csi_t;
-
-extern uint global_str_vars;
-extern char **global_str_var;
-extern long *global_str_var_name;
-extern uint global_int_vars;
-extern long *global_int_var;
-extern long *global_int_var_name;
-extern csi_t main_csi;
-extern char *sysvar_p[MAX_SYSVARS];
-extern int sysvar_pi;
-extern long sysvar_l[MAX_SYSVARS];
-extern int sysvar_li;
-
-int exec(csi_t *csi);
-int exec_function(csi_t *csi);
-int exec_misc(csi_t *csi, uchar *path);
-int execmsg(csi_t *csi);
-int execfile(csi_t *csi);
-long exec_bin(uchar *mod, csi_t *csi);
-void clearvars(csi_t *bin);
-void freevars(csi_t *bin);
-char **getstrvar(csi_t *bin, long name);
-long *getintvar(csi_t *bin, long name);
-char *copystrvar(csi_t *csi, char *p, char *str);
-void skipto(csi_t *csi, uchar inst);
-
-/* End of CMDSHELL.H */
diff --git a/src/sbbs2/comio.c b/src/sbbs2/comio.c
deleted file mode 100644
index 510a415ddffdb680b8c9588e1083483a4f9cc83f..0000000000000000000000000000000000000000
--- a/src/sbbs2/comio.c
+++ /dev/null
@@ -1,354 +0,0 @@
-#line 1 "COMIO.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/***********************************/
-/* COM port and modem i/o routines */
-/***********************************/
-
-#include "sbbs.h"
-
-#ifndef __FLAT__
-extern mswtyp;
-#endif
-
-extern char term_ret;
-extern uint addrio;
-
-/****************************************************************************/
-/* Outputs a NULL terminated string to the COM port verbatim				*/
-/* Called from functions putmsg, getstr and color							*/
-/****************************************************************************/
-void putcom(char *str)
-{
-	ulong	l=0;
-
-while(str[l])
-	putcomch(str[l++]);
-}
-
-/****************************************************************************/
-/* Outputs a single character to the COM port								*/
-/****************************************************************************/
-void putcomch(char ch)
-{
-	char 	lch;
-	int 	i=0;
-
-if(!com_port)
-	return;
-while(outcom(ch)&TXBOF && i<1440) {	/* 3 minute pause delay */
-    if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==3) {
-			lputs("local abort (putcomch)\r\n");
-			i=1440;
-			break; }
-		ungetkey(lch); }
-	if(!DCDHIGH)
-		break;
-	i++;
-	if(sys_status&SS_SYSPAGE)
-		beep(i,80);
-	else
-		mswait(80); }
-if(i==1440) {						/* timeout - beep flush outbuf */
-	i=rioctl(TXBC);
-	lprintf("timeout(putcomch) %04X %04X\r\n",i,rioctl(IOFO));
-	outcom(7);
-	lputc(7);
-	rioctl(IOCS|PAUSE); }
-}
-
-/****************************************************************************/
-/* Sends string of characters to COM port. Interprets ^M and ~ (pause)		*/
-/* Called from functions waitforcall and offhook							*/
-/****************************************************************************/
-void mdmcmd(char *str)
-{
-	int 	i=0;
-	uint	lch;
-
-if(mdm_misc&MDM_DUMB)
-	return;
-if(sys_status&SS_MDMDEBUG)
-	lputs("\r\nModem command  : ");
-while(str[i]) {
-	if(str[i]=='~')
-		mswait(DELAY_MDMTLD);
-	else {
-		if(i && str[i-1]=='^' && str[i]!='^')  /* control character */
-			putcomch(toupper(str[i])-64);
-		else if(str[i]!='^' || (i && str[i-1]=='^'))
-			putcomch(str[i]);
-		if(sys_status&SS_MDMDEBUG)
-			lputc(str[i]); }
-	i++; }
-putcomch(CR);
-i=0;
-while(rioctl(TXSYNC|(1<<8)) && i<10) { /* wait for modem to receive all chars */
-	if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==0x2e03) {
-			lputs("local abort (mdmcmd)\r\n");
-			break; }
-		if(lch==0xff00)
-			bail(1);
-		ungetkey(lch); }
-	i++; }
-if(i==10) {
-	i=rioctl(TXBC);
-	lprintf("\r\ntimeout(mdmcmd) %04X %04X\r\n",i,rioctl(IOFO)); }
-if(sys_status&SS_MDMDEBUG)
-	lputs(crlf);
-}
-
-/****************************************************************************/
-/* Returns CR terminated string from the COM port. 							*/
-/* Called from function waitforcall 										*/
-/****************************************************************************/
-char getmdmstr(char *str, int sec)
-{
-	uchar	j=0,ch;
-	uint	lch;
-	time_t	start;
-
-if(sys_status&SS_MDMDEBUG)
-	lputs("Modem response : ");
-start=time(NULL);
-while(time(NULL)-start<sec && j<81) {
-	if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==0x2e03 || lch==3) {
-			lputs("local abort (getmdmstr)\r\n");
-			break; }
-		if(lch==0xff00)
-			bail(1);
-		ungetkey(lch); }
-	if((ch=incom())==CR && j) {
-		if(mdm_misc&MDM_VERBAL)
-			incom();	/* LF */
-		break; }
-	if(ch && (ch<0x20 || ch>0x7f)) { /* ignore ctrl characters and ex-ascii */
-		if(sys_status&SS_MDMDEBUG)
-			lprintf("[%02X]",ch);
-		continue; }
-	if(ch) {
-		str[j++]=ch;
-		if(sys_status&SS_MDMDEBUG)
-			lputc(ch); }
-	else mswait(0); }
-mswait(500);
-str[j]=0;
-if(sys_status&SS_MDMDEBUG)
-	lputs(crlf);
-return(j);
-}
-
-/****************************************************************************/
-/* Drops DTR (if COM port used), clears KEY and COM Buffers and other vars	*/
-/* Called from functions checkline, getkey, inkey, main, waitforcall,		*/
-/* main_sec, xfer_sec, gettimeleft and newuser								*/
-/****************************************************************************/
-void hangup()
-{
-	char	str1[256],str2[256],c;
-	uint	i;
-
-rioctl(MSR);
-if(!term_ret && com_port && (rioctl(IOSTATE)&DCD)) {  /* if carrier detect */
-	riosync(0);
-	mswait(DELAY_HANGUP);		 /* wait for modem buffer to clear */
-	if(mdm_misc&MDM_NODTR)
-		mdmcmd(mdm_hang);
-	else {
-		lputs("\r\nDropping DTR...");
-		if(dtr(15))  {			/* drop dtr, wait 15 seconds for dcd to drop */
-			lputs("\rDropping DTR Failed");
-			logline("@!","Dropping DTR Failed");
-			mdmcmd(mdm_hang); } }
-	mswait(110);
-	rioctl(MSR);
-	if(rioctl(IOSTATE)&DCD) {
-		mswait(5000);
-		rioctl(MSR);
-		if(rioctl(IOSTATE)&DCD) {
-			lputs("\r\nDCD high after hang up");
-			logline("@!","DCD high after hang up");
-			mswait(5000); } } }
-if(sys_status&SS_CAP) {	/* Close capture if open */
-	fclose(capfile);
-#ifdef __MSDOS__
-	freedosmem=farcoreleft(); /* fnopen allocates memory and fclose frees */
-#endif
-	sys_status^=SS_CAP; }
-if(sys_status&SS_FINPUT) { /* Close file input if open */
-	close(inputfile);
-	sys_status^=SS_FINPUT; }
-
-keybufbot=keybuftop=online=console=0;
-sys_status&=~(SS_TMPSYSOP|SS_LCHAT|SS_SYSPAGE|SS_ABORT);
-nosound();
-if(com_port)
-	dtr(1);
-}
-
-/****************************************************************************/
-/* Sends 'off-hook' string to modem to pick up phone (if COM port used)		*/
-/* Called from function waitforcall											*/
-/****************************************************************************/
-void offhook()
-{
-if(com_port && !(mdm_misc&MDM_DUMB)) {
-	mdmcmd(mdm_offh);
-	rioctl(TXSYNC|(2<<8));	/* wait up 2 seconds for modem to receive */
-	}
-}
-
-/****************************************************************************/
-/* Checks to see if remote user has hung up.								*/
-/* Called from function getkey												*/
-/****************************************************************************/
-void checkline()
-{
-if(online!=ON_REMOTE) return;
-if(!DCDHIGH) {
-	lprintf("\r\nHung up");
-	logline(nulstr,"Hung up");
-	hangup(); }
-}
-
-/****************************************************************************/
-/* Syncronizes the remote and local machines before command prompts         */
-/****************************************************************************/
-void riosync(char abortable)
-{
-	int 	i=0;
-
-if(useron.misc&(RIP|WIP))	/* don't allow abort with RIP or WIP */
-	abortable=0;		/* mainly because of ANSI cursor posistion response */
-if(sys_status&SS_ABORT)	/* no need to sync if already aborting */
-	return;
-if(online==ON_REMOTE && console&CON_R_ECHO) {
-	while(rioctl(TXSYNC|(1<<8)) && i<180) { /* three minutes till tx buf empty */
-		if(sys_status&SS_SYSPAGE)
-			beep(i,10);
-		if(lkbrd(1))
-			break;
-		if(abortable && rioctl(RXBC)) { 	/* incoming characer */
-			rioctl(IOFO);					/* flush output */
-			sys_status|=SS_ABORT;			/* set abort flag so no pause */
-			break; }						/* abort sync */
-		if(!DCDHIGH)
-			break;
-		mswait(0);
-		i++; }
-	if(i==180) {
-		i=rioctl(TXBC);
-		lprintf("timeout(sync) %04X %04X\r\n",i,rioctl(IOFO));
-		outcom(7);
-		lputc(7);
-		rioctl(IOCS|PAUSE); }
-	if(rioctl(IOSTATE)&ABORT)
-		sys_status|=SS_ABORT;
-	rioctl(IOCS|ABORT); }
-}
-
-/*****************************************************************************/
-/* Initializes com i/o routines and sets baud rate                           */
-/*****************************************************************************/
-void comini()
-{
-	int 	i;
-#ifndef __FLAT__
-	uint	base=0xffff;
-#endif
-
-if(sys_status&SS_COMISR)	/* Already installed */
-	return;
-lprintf("\r\nInitializing COM port %u: ",com_port);
-#ifndef __FLAT__
-switch(com_base) {
-	case 0xb:
-		lputs("PC BIOS");
-		break;
-	case 0xd:
-		lputs("DigiBoard");
-		break;
-	case 0xe:
-		lputs("PS/2 BIOS");
-		break;
-	case 0xf:
-		lputs("FOSSIL");
-		break;
-	case 0:
-		base=com_port;
-		lputs("UART I/O (BIOS), ");
-		if(com_irq)
-            lprintf("IRQ %d",com_irq);
-        else lputs("default IRQ");
-		break;
-	default:
-		base=com_base;
-		lprintf("UART I/O %Xh, ",com_base);
-		if(com_irq)
-            lprintf("IRQ %d",com_irq);
-        else lputs("default IRQ");
-        break; }
-
-if(base==0xffff)
-	lprintf(" channel %u",com_irq);
-i=rioini(base,com_irq);
-#else
-#ifdef __OS2__
-if(rio_handle!=-1)	// Already opened, prolly passed to SBBS4OS2 via cmd line
-	lprintf("handle %d",rio_handle);
-#endif
-i=rioini(com_port,0);
-#endif
-if(i) {
-	lprintf(" - Failed! (%d)\r\n",i);
-	bail(1); }
-i=0;
-if(mdm_misc&MDM_CTS)
-	i=CTSCK;
-if(mdm_misc&MDM_RTS)
-	i|=RTSCK;
-if(i)
-	rioctl(IOSM|i); /* set cts checking if hardware flow control */
-
-#ifndef __FLAT__
-rioctl(TSTYPE|mswtyp);	 /* set time-slice API type */
-#endif
-
-rioctl(CPTON);			/* ctrl-p translation */
-
-if(addrio) {
-	lprintf("\r\nAdditional rioctl: %04Xh",addrio);
-	rioctl(addrio); }
-
-sys_status|=SS_COMISR;
-}
-
-/****************************************************************************/
-/* Sets the current baud rate to either the current connect rate or the 	*/
-/* DTE rate 																*/
-/****************************************************************************/
-void setrate()
-{
-	int i;
-
-if(online==ON_REMOTE && !(mdm_misc&MDM_STAYHIGH))
-	dte_rate=cur_rate;
-else
-	dte_rate=com_rate;
-lprintf("\r\nSetting DTE rate: %lu baud",dte_rate);
-#ifdef __FLAT__
-if((i=setbaud(dte_rate))!=0) {
-#else
-if((i=setbaud((uint)(dte_rate&0xffffL)))!=0) {
-#endif
-	lprintf(" - Failed! (%d)\r\n",i);
-	bail(1); }
-lputs(crlf);
-}
diff --git a/src/sbbs2/con_hi.c b/src/sbbs2/con_hi.c
deleted file mode 100644
index be01d3b7f33941dbf49985a9a4d8c9898595ae32..0000000000000000000000000000000000000000
--- a/src/sbbs2/con_hi.c
+++ /dev/null
@@ -1,796 +0,0 @@
-#line 1 "CON_HI.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-extern char question[128];
-
-char *mnestr;
-
-/****************************************************************************/
-/* Waits for remote or local user to input a CR terminated string. 'length' */
-/* is the maximum number of characters that getstr will allow the user to   */
-/* input into the string. 'mode' specifies upper case characters are echoed */
-/* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */
-/* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */
-/* ^N non-destructive BS, ^V center line. Valid keys are echoed.            */
-/****************************************************************************/
-int getstr(char *strout, int maxlen, long mode)
-{
-    int i,l,x,z;    /* i=current position, l=length, j=printed chars */
-                    /* x&z=misc */
-    uchar ch,str1[256],str2[256],ins=0,atr;
-
-console&=~CON_UPARROW;
-sys_status&=~SS_ABORT;
-if(mode&K_LINE && useron.misc&ANSI && !(mode&K_NOECHO)) {
-    attr(color[clr_inputline]);
-    for(i=0;i<maxlen;i++)
-        outchar(SP);
-    bprintf("\x1b[%dD",maxlen); }
-if(wordwrap[0]) {
-    strcpy(str1,wordwrap);
-    wordwrap[0]=0; }
-else str1[0]=0;
-if(mode&K_EDIT)
-    strcat(str1,strout);
-if(strlen(str1)>maxlen)
-    str1[maxlen]=0;
-atr=curatr;
-if(!(mode&K_NOECHO)) {
-	if(mode&K_AUTODEL && str1[0]) {
-		i=(color[clr_inputline]&0x77)<<4;
-		i|=(color[clr_inputline]&0x77)>>4;
-		attr(i); }
-	rputs(str1);
-	if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && useron.misc&ANSI)
-		bputs("\x1b[K");  /* destroy to eol */ }
-
-i=l=strlen(str1);
-if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) {
-	ch=getkey(mode|K_GETSTR);
-    attr(atr);
-    if(isprint(ch) || ch==0x7f) {
-        for(i=0;i<l;i++)
-            bputs("\b \b");
-        i=l=0; }
-    else {
-        for(i=0;i<l;i++)
-            outchar(BS);
-        rputs(str1);
-        i=l; }
-	if(ch!=SP && ch!=TAB)
-		ungetkey(ch); }
-
-while(!(sys_status&SS_ABORT) && (ch=getkey(mode|K_GETSTR))!=CR && online) {
-	if(sys_status&SS_ABORT)
-		break;
-	if(ch==LF) /* Ctrl-J same as CR */
-		break;
-	if(ch==TAB && !(mode&K_WRAP))	/* TAB same as CR */
-		break;
-	if(!i && mode&K_UPRLWR && (ch==SP || ch==TAB))
-		continue;	/* ignore beginning white space if upper/lower */
-    if(mode&K_E71DETECT && ch==(CR|0x80) && l>1) {
-        if(strstr(str1,"��")) {
-            bputs("\r\n\r\nYou must set your terminal to NO PARITY, "
-                "8 DATA BITS, and 1 STOP BIT (N-8-1).\7\r\n");
-            return(0); } }
-    switch(ch) {
-        case 1: /* Ctrl-A for ANSI */
-            if(!(mode&K_MSG) || useron.rest&FLAG('A') || i>maxlen-3)
-                break;
-            if(ins) {
-                if(l<maxlen)
-                    l++;
-                for(x=l;x>i;x--)
-                    str1[x]=str1[x-1];
-                rprintf("%.*s",l-i,str1+i);
-                rprintf("\x1b[%dD",l-i);
-                if(i==maxlen-1)
-                    ins=0; }
-            outchar(str1[i++]=1);
-            break;
-        case 2: /* Ctrl-B Beginning of Line */
-			if(useron.misc&ANSI && i && !(mode&K_NOECHO)) {
-                bprintf("\x1b[%dD",i);
-                i=0; }
-            break;
-        case 4: /* Ctrl-D Delete word right */
-            if(i<l) {
-                x=i;
-                while(x<l && str1[x]!=SP) {
-                    outchar(SP);
-                    x++; }
-                while(x<l && str1[x]==SP) {
-                    outchar(SP);
-                    x++; }
-                bprintf("\x1b[%dD",x-i);   /* move cursor back */
-                z=i;
-                while(z<l-(x-i))  {             /* move chars in string */
-                    outchar(str1[z]=str1[z+(x-i)]);
-                    z++; }
-                while(z<l) {                    /* write over extra chars */
-                    outchar(SP);
-                    z++; }
-                bprintf("\x1b[%dD",z-i);
-                l-=x-i; }                       /* l=new length */
-            break;
-        case 5: /* Ctrl-E End of line */
-			if(useron.misc&ANSI && i<l) {
-                bprintf("\x1b[%dC",l-i);  /* move cursor to eol */
-                i=l; }
-            break;
-        case 6: /* Ctrl-F move cursor forewards */
-            if(i<l && (useron.misc&ANSI)) {
-                bputs("\x1b[C");   /* move cursor right one */
-                i++; }
-            break;
-        case 7:
-            if(!(mode&K_MSG))
-                break;
-            if(useron.rest&FLAG('B')) {
-                if (i+6<maxlen) {
-                    if(ins) {
-                        for(x=l+6;x>i;x--)
-                            str1[x]=str1[x-6];
-                        if(l+5<maxlen)
-                            l+=6;
-                        if(i==maxlen-1)
-                            ins=0; }
-                    str1[i++]='(';
-                    str1[i++]='b';
-                    str1[i++]='e';
-                    str1[i++]='e';
-                    str1[i++]='p';
-                    str1[i++]=')';
-					if(!(mode&K_NOECHO))
-						bputs("(beep)"); }
-                if(ins)
-                    redrwstr(str1,i,l,0);
-                break; }
-             if(ins) {
-                if(l<maxlen)
-                    l++;
-                for(x=l;x>i;x--)
-                    str1[x]=str1[x-1];
-                if(i==maxlen-1)
-                    ins=0; }
-             if(i<maxlen) {
-                str1[i++]=7;
-				if(!(mode&K_NOECHO))
-					outchar(7); }
-             break;
-        case 14:    /* Ctrl-N Next word */
-            if(i<l && (useron.misc&ANSI)) {
-                x=i;
-                while(str1[i]!=SP && i<l)
-                    i++;
-                while(str1[i]==SP && i<l)
-                    i++;
-                bprintf("\x1b[%dC",i-x); }
-            break;
-        case 0x1c:    /* Ctrl-\ Previous word */
-			if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
-                x=i;
-                while(str1[i-1]==SP && i)
-                    i--;
-                while(str1[i-1]!=SP && i)
-                    i--;
-                bprintf("\x1b[%dD",x-i); }
-            break;
-        case 18:    /* Ctrl-R Redraw Line */
-			if(!(mode&K_NOECHO))
-				redrwstr(str1,i,l,0);
-            break;
-        case TAB:
-            if(!(i%TABSIZE)) {
-                if(ins) {
-                    if(l<maxlen)
-                        l++;
-                    for(x=l;x>i;x--)
-                        str1[x]=str1[x-1];
-                    if(i==maxlen-1)
-                        ins=0; }
-                str1[i++]=SP;
-				if(!(mode&K_NOECHO))
-					outchar(SP); }
-            while(i<maxlen && i%TABSIZE) {
-                if(ins) {
-                    if(l<maxlen)
-                        l++;
-                    for(x=l;x>i;x--)
-                        str1[x]=str1[x-1];
-                    if(i==maxlen-1)
-                        ins=0; }
-                str1[i++]=SP;
-				if(!(mode&K_NOECHO))
-					outchar(SP); }
-			if(ins && !(mode&K_NOECHO))
-                redrwstr(str1,i,l,0);
-            break;
-        case BS:
-            if(!i)
-                break;
-            i--;
-            l--;
-            if(i!=l) {              /* Deleting char in middle of line */
-                outchar(BS);
-                z=i;
-                while(z<l)  {       /* move the characters in the line */
-                    outchar(str1[z]=str1[z+1]);
-                    z++; }
-                outchar(SP);        /* write over the last char */
-                bprintf("\x1b[%dD",(l-i)+1); }
-			else if(!(mode&K_NOECHO))
-                bputs("\b \b");
-            break;
-        case 22:    /* Ctrl-V   Center line */
-            str1[l]=0;
-            l=bstrlen(str1);
-            if(!l) break;
-            for(x=0;x<(maxlen-l)/2;x++)
-                str2[x]=SP;
-            str2[x]=0;
-            strcat(str2,str1);
-            strcpy(strout,str2);
-            l=strlen(strout);
-			if(mode&K_NOECHO)
-				return(l);
-            if(mode&K_MSG)
-                redrwstr(strout,i,l,K_MSG);
-            else {
-                while(i--)
-                    bputs("\b");
-                bputs(strout);
-                if(mode&K_LINE)
-                    attr(LIGHTGRAY); }
-            CRLF;
-            return(l);
-        case 23:    /* Ctrl-W   Delete word left */
-            if(i<l) {
-                x=i;                            /* x=original offset */
-                while(i && str1[i-1]==SP) {
-                    outchar(BS);
-                    i--; }
-                while(i && str1[i-1]!=SP) {
-                    outchar(BS);
-                    i--; }
-                z=i;                            /* i=z=new offset */
-                while(z<l-(x-i))  {             /* move chars in string */
-                    outchar(str1[z]=str1[z+(x-i)]);
-                    z++; }
-                while(z<l) {                    /* write over extra chars */
-                    outchar(SP);
-                    z++; }
-                bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
-                l-=x-i; }                       /* l=new length */
-            else {
-                while(i && str1[i-1]==SP) {
-                    i--;
-                    l--;
-					if(!(mode&K_NOECHO))
-						bputs("\b \b"); }
-                while(i && str1[i-1]!=SP) {
-                    i--;
-                    l--;
-					if(!(mode&K_NOECHO))
-						bputs("\b \b"); } }
-            break;
-        case 24:    /* Ctrl-X   Delete entire line */
-			if(mode&K_NOECHO)
-				l=0;
-			else {
-				while(i<l) {
-					outchar(SP);
-					i++; }
-				while(l) {
-					l--;
-					bputs("\b \b"); } }
-            i=0;
-            break;
-        case 25:    /* Ctrl-Y   Delete to end of line */
-			if(useron.misc&ANSI && !(mode&K_NOECHO)) {
-                bputs("\x1b[K");
-                l=i; }
-            break;
-        case 31:    /* Ctrl-Minus       Toggles Insert/Overwrite */
-			if(!(useron.misc&ANSI) || mode&K_NOECHO)
-                break;
-            if(ins) {
-                ins=0;
-                redrwstr(str1,i,l,0); }
-            else if(i<l) {
-                ins=1;
-				bprintf("\x1b[s\x1b[%dC",79-lclwx());    /* save pos  */
-                z=curatr;                                /* and got to EOL */
-                attr(z|BLINK|HIGH);
-                outchar('�');
-                attr(z);
-                bputs("\x1b[u"); }  /* restore pos */
-            break;
-        case 0x1e:  /* Ctrl-^ */
-            if(!(mode&K_EDIT))
-                break;
-            if(i>l)
-                l=i;
-            str1[l]=0;
-            strcpy(strout,str1);
-			if((stripattr(strout) || ins) && !(mode&K_NOECHO))
-                redrwstr(strout,i,l,K_MSG);
-			if(mode&K_LINE && !(mode&K_NOECHO))
-				attr(LIGHTGRAY);
-            console|=CON_UPARROW;
-            return(l);
-        case 0x1d:  /* Ctrl-]  Reverse Cursor Movement */
-			if(i && (useron.misc&ANSI) && !(mode&K_NOECHO)) {
-                bputs("\x1b[D");   /* move cursor left one */
-                i--; }
-            break;
-        case 0x7f:  /* Ctrl-BkSpc (DEL) Delete current char */
-            if(i==l)
-                break;
-            l--;
-            z=i;
-            while(z<l)  {       /* move the characters in the line */
-                outchar(str1[z]=str1[z+1]);
-                z++; }
-            outchar(SP);        /* write over the last char */
-            bprintf("\x1b[%dD",(l-i)+1);
-            break;
-        default:
-            if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
-                str1[i]=0;
-				if(ch==SP && !(mode&K_CHAT)) { /* don't wrap a space */ 
-					strcpy(strout,str1);	   /* as last char */
-					if(stripattr(strout) && !(mode&K_NOECHO))
-                        redrwstr(strout,i,l,K_MSG);
-					if(!(mode&K_NOECHO))
-						CRLF;
-                    return(i); }
-                x=i-1;
-                z=1;
-                wordwrap[0]=ch;
-                while(str1[x]!=SP && x)
-                    wordwrap[z++]=str1[x--];
-                if(x<(maxlen/2)) {
-                    wordwrap[1]=0;  /* only wrap one character */
-                    strcpy(strout,str1);
-					if(stripattr(strout) && !(mode&K_NOECHO))
-                        redrwstr(strout,i,l,K_MSG);
-					if(!(mode&K_NOECHO))
-						CRLF;
-                    return(i); }
-                wordwrap[z]=0;
-				if(!(mode&K_NOECHO))
-					while(z--) {
-						bputs("\b \b");
-						i--; }
-                strrev(wordwrap);
-                str1[x]=0;
-                strcpy(strout,str1);
-				if(stripattr(strout) && !(mode&K_NOECHO))
-					redrwstr(strout,i,x,mode);
-				if(!(mode&K_NOECHO))
-					CRLF;
-                return(x); }
-            if(i<maxlen && ch>=SP) {
-                if(mode&K_UPRLWR)
-                    if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
-                        || str1[i-1]=='.' || str1[i-1]=='_')))
-                        ch=toupper(ch);
-                    else
-                        ch=tolower(ch);
-                if(ins) {
-                    if(l<maxlen)    /* l<maxlen */
-                        l++;
-                    for(x=l;x>i;x--)
-                        str1[x]=str1[x-1];
-					rprintf("%.*s",l-i,str1+i);
-					rprintf("\x1b[%dD",l-i);
-					if(i==maxlen-1) {
-						bputs("  \b\b");
-						ins=0; } }
-                str1[i++]=ch;
-				if(!(mode&K_NOECHO))
-					outchar(ch); } }
-    if(i>l)
-        l=i;
-    if(mode&K_CHAT && !l)
-        return(0); }
-if(!online)
-    return(0);
-if(i>l)
-    l=i;
-str1[l]=0;
-if(!(sys_status&SS_ABORT)) {
-    strcpy(strout,str1);
-	if((stripattr(strout) || ins) && !(mode&K_NOECHO))
-        redrwstr(strout,i,l,K_MSG); }
-else
-    l=0;
-if(mode&K_LINE && !(mode&K_NOECHO)) attr(LIGHTGRAY);
-if(!(mode&(K_NOCRLF|K_NOECHO))) {
-    outchar(CR);
-    if(!(mode&K_MSG && sys_status&SS_ABORT))
-        outchar(LF);
-    lncntr=0; }
-return(l);
-}
-
-/****************************************************************************/
-/* Hot keyed number input routine.                                          */
-/* Returns a valid number between 1 and max, 0 if no number entered, or -1  */
-/* if the user hit 'Q' or ctrl-c                                            */
-/****************************************************************************/
-long getnum(ulong max)
-{
-    uchar ch,n=0;
-	long i=0;
-
-while(online) {
-	ch=getkey(K_UPPER);
-    if(ch>0x7f)
-        continue;
-	if(ch=='Q') {
-		outchar('Q');
-		if(useron.misc&COLDKEYS)
-			ch=getkey(K_UPPER);
-		if(ch==BS) {
-			bputs("\b \b");
-			continue; }
-        CRLF;
-        lncntr=0;
-        return(-1); }
-    else if(sys_status&SS_ABORT) {
-        CRLF;
-        lncntr=0;
-        return(-1); }
-    else if(ch==CR) {
-        CRLF;
-        lncntr=0;
-        return(i); }
-    else if(ch==BS && n) {
-        bputs("\b \b");
-        i/=10;
-        n--; }
-	else if(isdigit(ch) && (i*10L)+(ch&0xf)<=max && (ch!='0' || n)) {
-		i*=10L;
-        n++;
-        i+=ch&0xf;
-        outchar(ch);
-		if(i*10L>max && !(useron.misc&COLDKEYS)) {
-            CRLF;
-            lncntr=0;
-            return(i); } } }
-return(0);
-}
-
-/*****************************************************************************/
-/* Displays or erases [WAIT] message                                         */
-/*****************************************************************************/
-void waitforsysop(char on)
-{
-    static saveatr;
-    int i,j;
-
-if(on) {
-	saveatr=curatr;
-    bputs(text[Wait]);
-    lclatr(LIGHTGRAY);
-    return; }
-j=bstrlen(text[Wait]);
-attr(saveatr);
-for(i=0;i<j;i++)
-    bputs("\b \b");
-}
-
-/****************************************************************************/
-/* Returns 1 if a is a valid ctrl-a code, 0 if it isn't.                    */
-/****************************************************************************/
-char validattr(char a)
-{
-
-switch(toupper(a)) {
-    case '-':   /* clear        */
-    case '_':   /* clear        */
-    case 'B':   /* blue     fg  */
-    case 'C':   /* cyan     fg  */
-    case 'G':   /* green    fg  */
-    case 'H':   /* high     fg  */
-    case 'I':   /* blink        */
-    case 'K':   /* black    fg  */
-    case 'L':   /* cls          */
-    case 'M':   /* magenta  fg  */
-    case 'N':   /* normal       */
-    case 'P':   /* pause        */
-    case 'R':   /* red      fg  */
-    case 'W':   /* white    fg  */
-    case 'Y':   /* yellow   fg  */
-    case '0':   /* black    bg  */
-    case '1':   /* red      bg  */
-    case '2':   /* green    bg  */
-    case '3':   /* brown    bg  */
-    case '4':   /* blue     bg  */
-    case '5':   /* magenta  bg  */
-    case '6':   /* cyan     bg  */
-    case '7':   /* white    bg  */
-		return(1); }
-return(0);
-}
-
-/****************************************************************************/
-/* Strips invalid Ctrl-Ax sequences from str                                */
-/* Returns number of ^A's in line                                           */
-/****************************************************************************/
-char stripattr(char *strin)
-{
-    uchar str[256];
-    uchar a,c,d,e;
-
-e=strlen(strin);
-for(a=c=d=0;c<e;c++) {
-    if(strin[c]==1) {
-        a++;
-        if(!validattr(strin[c+1])) {
-            c++;
-            continue; } }
-    str[d++]=strin[c]; }
-str[d]=0;
-strcpy(strin,str);
-return(a);
-}
-
-/****************************************************************************/
-/* Redraws str using i as current cursor position and l as length           */
-/****************************************************************************/
-void redrwstr(char *strin, int i, int l, char mode)
-{
-    char str[256],c;
-
-sprintf(str,"%-*.*s",l,l,strin);
-c=i;
-while(c--)
-    outchar(BS);
-if(mode&K_MSG)
-    bputs(str);
-else
-    rputs(str);
-if(useron.misc&ANSI) {
-    bputs("\x1b[K");
-    if(i<l)
-        bprintf("\x1b[%dD",l-i); }
-else {
-    while(c<79) { /* clear to end of line */
-        outchar(SP);
-        c++; }
-    while(c>l) { /* back space to end of string */
-        outchar(BS);
-        c--; } }
-}
-
-/****************************************************************************/
-/* Outputs a string highlighting characters preceeded by a tilde            */
-/****************************************************************************/
-void mnemonics(char *str)
-{
-    char *ctrl_a_codes;
-    long l;
-
-if(!strchr(str,'~')) {
-	mnestr=str;
-	bputs(str);
-	return; }
-ctrl_a_codes=strchr(str,1);
-if(!ctrl_a_codes) {
-	if(str[0]=='@' && str[strlen(str)-1]=='@' && !strchr(str,SP)) {
-		mnestr=str;
-		bputs(str);
-		return; }
-	attr(color[clr_mnelow]); }
-l=0L;
-while(str[l]) {
-    if(str[l]=='~' && str[l+1]) {
-        if(!(useron.misc&ANSI))
-            outchar('(');
-        l++;
-        if(!ctrl_a_codes)
-            attr(color[clr_mnehigh]);
-        outchar(str[l]);
-        l++;
-        if(!(useron.misc&ANSI))
-            outchar(')');
-        if(!ctrl_a_codes)
-            attr(color[clr_mnelow]); }
-    else {
-        if(str[l]==1) {             /* ctrl-a */
-            ctrl_a(str[++l]);       /* skip the ctrl-a */
-            l++; }                  /* skip the attribute code */
-        else
-            outchar(str[l++]); } }
-if(!ctrl_a_codes)
-    attr(color[clr_mnecmd]);
-}
-
-/****************************************************************************/
-/* Prompts user for Y or N (yes or no) and CR is interpreted as a Y         */
-/* Returns 1 for Y or 0 for N                                               */
-/* Called from quite a few places                                           */
-/****************************************************************************/
-char yesno(char *str)
-{
-    char ch;
-
-strcpy(question,str);
-SYNC;
-if(useron.misc&WIP) {
-	strip_ctrl(question);
-	menu("YESNO"); }
-else
-	bprintf(text[YesNoQuestion],str);
-while(online) {
-	if(sys_status&SS_ABORT)
-		ch=text[YN][1];
-	else
-		ch=getkey(K_UPPER|K_COLD);
-	if(ch==text[YN][0] || ch==CR) {
-		if(bputs(text[Yes]))
-			CRLF;
-        lncntr=0;
-        return(1); }
-	if(ch==text[YN][1]) {
-		if(bputs(text[No]))
-			CRLF;
-        lncntr=0;
-        return(0); } }
-return(1);
-}
-
-/****************************************************************************/
-/* Prompts user for N or Y (no or yes) and CR is interpreted as a N         */
-/* Returns 1 for N or 0 for Y                                               */
-/* Called from quite a few places                                           */
-/****************************************************************************/
-char noyes(char *str)
-{
-    char ch;
-
-strcpy(question,str);
-SYNC;
-if(useron.misc&WIP) {
-	strip_ctrl(question);
-	menu("NOYES"); }
-else
-	bprintf(text[NoYesQuestion],str);
-while(online) {
-	if(sys_status&SS_ABORT)
-		ch=text[YN][1];
-	else
-		ch=getkey(K_UPPER|K_COLD);
-	if(ch==text[YN][1] || ch==CR) {
-		if(bputs(text[No]))
-			CRLF;
-        lncntr=0;
-        return(1); }
-	if(ch==text[YN][0]) {
-		if(bputs(text[Yes]))
-			CRLF;
-        lncntr=0;
-        return(0); } }
-return(1);
-}
-
-/****************************************************************************/
-/* Waits for remote or local user to hit a key that is contained inside str.*/
-/* 'str' should contain uppercase characters only. When a valid key is hit, */
-/* it is echoed (upper case) and is the return value.                       */
-/* Called from quite a few functions                                        */
-/****************************************************************************/
-long getkeys(char *str, ulong max)
-{
-	uchar ch,n=0,c;
-	ulong i=0;
-
-strupr(str);
-while(online) {
-	ch=getkey(K_UPPER);
-    if(max && ch>0x7f)  /* extended ascii chars are digits to isdigit() */
-        continue;
-    if(sys_status&SS_ABORT) {   /* return -1 if Ctrl-C hit */
-        attr(LIGHTGRAY);
-        CRLF;
-        lncntr=0;
-        return(-1); }
-    if(ch && !n && (strchr(str,ch))) {  /* return character if in string */
-		outchar(ch);
-		if(useron.misc&COLDKEYS && ch>SP) {
-			while(online && !(sys_status&SS_ABORT)) {
-				c=getkey(0);
-				if(c==CR || c==BS)
-					break; }
-			if(sys_status&SS_ABORT) {
-				CRLF;
-				return(-1); }
-			if(c==BS) {
-				bputs("\b \b");
-				continue; } }
-		attr(LIGHTGRAY);
-        CRLF;
-        lncntr=0;
-        return(ch); }
-    if(ch==CR && max) {             /* return 0 if no number */
-        attr(LIGHTGRAY);
-        CRLF;
-        lncntr=0;
-        if(n)
-			return(i|0x80000000L);		 /* return number plus high bit */
-        return(0); }
-    if(ch==BS && n) {
-        bputs("\b \b");
-        i/=10;
-        n--; }
-    else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
-        i*=10;
-        n++;
-        i+=ch&0xf;
-        outchar(ch);
-		if(i*10>max && !(useron.misc&COLDKEYS)) {
-            attr(LIGHTGRAY);
-            CRLF;
-            lncntr=0;
-			return(i|0x80000000L); } } }
-return(-1);
-}
-
-void center(char *str)
-{
-	 int i,j;
-
-j=bstrlen(str);
-for(i=0;i<(80-j)/2;i++)
-	outchar(SP);
-bputs(str);
-CRLF;
-}
-
-
-int uselect(int add, int n, char *title, char *item, char *ar)
-{
-	static uint total,num[500];
-	char str[128];
-	int i,t;
-
-if(add) {
-	if(ar && !chk_ar(ar,useron))
-		return(0);
-	if(!total)
-		bprintf(text[SelectItemHdr],title);
-	num[total++]=n;
-	bprintf(text[SelectItemFmt],total,item);
-	return(0); }
-
-if(!total)
-	return(-1);
-
-for(i=0;i<total;i++)
-	if(num[i]==n)
-		break;
-if(i==total)
-	i=0;
-sprintf(str,text[SelectItemWhich],i+1);
-mnemonics(str);
-i=getnum(total);
-t=total;
-total=0;
-if(i<0)
-	return(-1);
-if(!i) {					/* User hit ENTER, use default */
-	for(i=0;i<t;i++)
-		if(num[i]==n)
-			return(num[i]);
-	if(n<t)
-		return(num[n]);
-	return(-1); }
-return(num[i-1]);
-}
diff --git a/src/sbbs2/con_in.c b/src/sbbs2/con_in.c
deleted file mode 100644
index 8458335ccdd0f522764bf493cd40cc2bdc110b37..0000000000000000000000000000000000000000
--- a/src/sbbs2/con_in.c
+++ /dev/null
@@ -1,663 +0,0 @@
-#line 1 "CON_IN.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-#define LAST_STAT_LINE 16
-
-#ifdef __WIN32__
-
-#include <windows.h>
-
-uint lkbrd(int mode)
-{
-	uint c;
-
-if(mode)
-	return(kbhit());
-c=getch();
-if(!c)
-	c=(getch()<<8);
-return(c);
-}
-
-int  lclaes(void)
-{
-return(0);
-}
-
-#elif defined(__OS2__)
-
-void fixkbdmode(void)
-{
-	KBDINFO 	kbd;
-
-/* Disable Ctrl-C/Ctrl-P processing by OS/2 */
-KbdGetStatus(&kbd,0);
-if(kbd.fsMask&KEYBOARD_ASCII_MODE) {
-    kbd.fsMask|=KEYBOARD_BINARY_MODE;
-    kbd.fsMask&=~KEYBOARD_ASCII_MODE;
-    KbdSetStatus(&kbd,0); }
-}
-
-uint lkbrd(int leave)
-{
-	KBDKEYINFO	key;
-
-if(leave)
-	KbdPeek(&key,0);
-else
-	KbdCharIn(&key,IO_NOWAIT,0);
-if(!(key.fbStatus&KBDTRF_FINAL_CHAR_IN))
-	return(0);
-if(!(key.fbStatus&0x02) || key.chScan==0xE0)
-	return(key.chChar);
-return(key.chScan<<8);
-}
-
-#endif
-
-/****************************************************************************/
-/* Returns character if a key has been hit locally or remotely and responds */
-/* to local ctrl/function keys. Does not print character. 					*/
-/* Called from functions getkey, msgabort and main_sec						*/
-/****************************************************************************/
-char inkey(int mode)
-{
-	static inside;
-	uchar str[512],*scrnbuf,x,y,c,atr,*gurubuf,ch=0,*helpbuf;
-	int file,con=console;
-	uint i,j;
-	long l,length;
-
-if(!(node_misc&NM_NO_LKBRD) && (lkbrd(1) || sys_status&SS_FINPUT)) {
-	if(sys_status&SS_FINPUT) {
-		if(lkbrd(1)==0xff00) {
-			close(inputfile);
-			sys_status^=SS_FINPUT;
-			return(0); }
-		if(read(inputfile,&c,1)!=1) {
-            close(inputfile);
-			sys_status^=SS_FINPUT;
-			return(0); }
-		if(c)	/* Regular character */
-		   i=c;
-		else {	/* Scan code */
-			if(read(inputfile,&c,1)!=1) {
-				close(inputfile);
-				sys_status^=SS_FINPUT;
-				return(0); }
-			i=c<<8; } }
-	else
-		i=lkbrd(0);
-	if(sys_status&SS_LCHAT && curatr!=color[clr_chatlocal])
-		attr(color[clr_chatlocal]);
-	if(i&0xff)
-		ch=i&0xff;
-	else {				 /* Alt or Function key hit */
-		i>>=8;
-		/*		 F1 - F10			Shift-F1 - Alt-F10			F11 - Alt-F12	*/
-		if((i>=0x3b &&i<=0x44) || (i>=0x54 &&i<=0x71) || (i>=0x85 &&i<=0x8c)) {
-			if(sys_status&SS_FINPUT)
-				return(0);							/* MACROS */
-			sprintf(str,"%s%sF%d.MAC",text_dir
-				,i<0x45 || (i>=0x85 && i<=0x86) ? nulstr
-				:i<0x5e || (i>=0x87 && i<=0x88) ? "SHFT-"
-				:i<0x68 || (i>=0x89 && i<=0x8a) ? "CTRL-" : "ALT-"
-				,i<0x45 ? i-0x3a : i<0x5e ? i-0x53 : i<0x68 ? i-0x5d
-				:i<0x72 ? i-0x67 : i<0x87 ? i-0x7a : i<0x89 ? i-0x7c
-				:i<0x8b ? i-0x7e : i-0x80);
-			if((inputfile=nopen(str,O_RDONLY))!=-1)
-				sys_status|=SS_FINPUT;
-			return(0); }
-		if(i>=0x78 && i<=0x81) {			/* Alt-# Quick Validation */
-			if(!(sys_status&SS_USERON)		/* can't quick-validate if not */
-				|| !useron.number
-				|| !(sys_misc&SM_QVALKEYS)) { /* or not valid user number */
-				beep(100,500);					 /* online yet */
-				nosound();
-				return(0); }
-			if((node_misc&NM_SYSPW || SYSOP) && !chksyspass(1))
-				return(0);
-			beep(1000,100);
-			beep(1500,100);
-			nosound();
-			if(i==0x81)
-				i=0;
-			else
-				i-=0x77;
-			useron.level=val_level[i];
-			useron.flags1=val_flags1[i];
-			useron.flags2=val_flags2[i];
-			useron.flags3=val_flags3[i];
-			useron.flags4=val_flags4[i];
-			useron.exempt=val_exempt[i];
-			useron.rest=val_rest[i];
-			now=time(NULL);
-			if(useron.expire<now && val_expire[i])
-				useron.expire=now+((long)val_expire[i]*24L*60L*60L);
-			else
-				useron.expire+=((long)val_expire[i]*24L*60L*60L);
-			putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,str,10));
-			putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,str,16));
-			putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,str,16));
-			putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,str,16));
-			putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,str,16));
-			putuserrec(useron.number,U_EXEMPT,8
-				,ultoa(useron.exempt,str,16));
-			putuserrec(useron.number,U_REST,8
-				,ultoa(useron.rest,str,16));
-			putuserrec(useron.number,U_EXPIRE,8
-				,ultoa(useron.expire,str,16));
-			useron.cdt=adjustuserrec(useron.number,U_CDT,10,val_cdt[i]);
-			statusline();
-			return(0); }
-		switch(i) {
-			case 0x16:	  /* Alt-U	- Runs Uedit local only with user online */
-				sprintf(str,"%.*s",lbuflen,lbuf);
-				waitforsysop(1);
-				if((scrnbuf=MALLOC((node_scrnlen*80L)*2L))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,nulstr,(node_scrnlen*80L)*2L);
-					return(CR); }
-				gettext(1,1,80,node_scrnlen-1,scrnbuf);
-				x=lclwx();
-				y=lclwy();
-				console&=~(CON_R_ECHO|CON_R_INPUT);
-				i=(sys_status&SS_TMPSYSOP);
-				if(!SYSOP) sys_status|=SS_TMPSYSOP;
-				useredit(0,1);
-				if(!i) sys_status&=~SS_TMPSYSOP;
-				lputc(FF);
-				puttext(1,1,80,node_scrnlen-1,scrnbuf);
-				FREE(scrnbuf);
-				lclxy(x,y);
-				statusline();
-				if(online==ON_REMOTE)
-					rioctl(IOFI);					/* flush input buffer */
-				console=con;
-				waitforsysop(0);
-				strcpy(lbuf,str);
-				lbuflen=strlen(lbuf);
-				return(0);
-			case 0x1f:	  /* Alt-S	- Toggles Spinning Cursor */
-				useron.misc^=SPIN;
-				return(0);
-			case 0x12:	  /* Alt-E	 - Toggle Remote echo and input */
-				if(online!=ON_REMOTE) return(0);
-				if(console&CON_R_ECHO) {
-					beep(500,50);
-					beep(1000,50);
-                    nosound();
-					waitforsysop(1);
-					console&=~(CON_R_ECHO|CON_R_INPUT);
-					j=bstrlen(text[Wait]);
-					for(i=0;i<j;i++)
-						bputs("\b \b"); }
-				else {
-					beep(1000,50);
-					beep(500,50);
-                    nosound();
-					j=bstrlen(text[Wait]);
-					for(i=0;i<j;i++)
-						outchar(SP);
-					console|=(CON_R_ECHO|CON_R_INPUT);
-					rioctl(IOFI);				/* flush input buffer */
-					waitforsysop(0); }
-				return(0);
-			case 0x10:	  /* Alt-Q	 - Toggles remote input */
-				if(online!=ON_REMOTE)
-					return(0);
-				console^=CON_R_INPUT;
-				if(console&CON_R_INPUT) {
-					beep(1000,50);
-					beep(500,50);
-                    nosound();
-					rioctl(IOSM|PAUSE|ABORT); }
-				else {
-					beep(500,50);
-					beep(1000,50);
-					nosound();
-					rioctl(IOCM|PAUSE|ABORT); }
-				rioctl(IOFI);			/* flush input buffer */
-				return(0);
-			case 0x19:		/* Alt-P   - Turns off sysop page */
-				nosound();
-				sys_status&=~SS_SYSPAGE;
-				return(0);
-			case 0x23:		/* Alt-H   - Hangs up on user */
-				hangup();
-				return(0);
-			case 0x1e:		/* Alt-A   - Alert Sysop when User's done */
-				sys_status^=SS_SYSALERT;
-				statusline();
-				return(0);
-			case 0x82:		/* Alt--   - Sub Time (5 min) */
-				starttime-=300;
-				return(0);
-			case 0x83:		/* Alt-+   - Add time (5 min)*/
-				starttime+=300;
-				return(0);
-			case 0x14:		/* Alt-T   - Temp SysOp */
-				if(!(sys_status&SS_TMPSYSOP) && node_misc&NM_SYSPW
-					&& !chksyspass(1))
-					return(0);
-				if(sys_misc&SM_L_SYSOP)
-					sys_status^=SS_TMPSYSOP;
-				statusline();
-				return(0);
-			case 0x2c:		/* Alt-Z	- Menu of local keys */
-				if((scrnbuf=MALLOC((node_scrnlen*80L)*2L))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,nulstr,(node_scrnlen*80L)*2L);
-					return(CR); }
-				gettext(1,1,80,node_scrnlen,scrnbuf);
-				sprintf(str,"%sSBBSHELP.DAB",exec_dir);
-				if((file=nopen(str,O_RDONLY))==-1)
-					lputs("\7Can't open SBBSHELP");
-				else {
-					length=filelength(file);
-					if((helpbuf=MALLOC(length))==NULL)
-						lputs("\7Can't allocate for SBBSHELP");
-					else {
-						read(file,helpbuf,length);
-						close(file);
-						puttext(13,1,66,24,helpbuf);
-						FREE(helpbuf); } }
-				while(!lkbrd(1)) mswait(1);
-				if(lkbrd(1)==0x2c00)	/* suck up the alt-z */
-					lkbrd(0);
-				puttext(1,1,80,node_scrnlen,scrnbuf);
-				FREE(scrnbuf);
-                return(0);
-			case 0x2e:		/* Alt-C	- Sysop Chat */
-				if(sys_status&SS_LCHAT) {
-					sys_status^=SS_LCHAT;
-					return(CR); }
-				else {
-					sys_status|=SS_LCHAT;
-					SAVELINE;
-					localchat();
-					return(0); }
-			case 0x2d:	/* Alt-X exit after logoff */
-				getnodedat(node_num,&thisnode,1);
-				thisnode.misc^=NODE_DOWN;
-				putnodedat(node_num,thisnode);
-				statusline();
-				return(0);
-			case 0x47:	/* Home - Same as Ctrl-B */
-				return(2);	/* ctrl-b beginning of line */
-			case 0x8d:	/* Ctrl-Up Arrow - decrement statusline */
-				if(statline) {
-					statline--;
-					statusline(); }
-				return(0);
-			case 0x77:	/* Ctrl-Home up - top of status line info */
-				statline=1;
-				statusline();
-				return(0);
-			case 0x4b:		/* Left Arrow - same as ctrl-] */
-				return(0x1d);
-			case 0x4d:		/* Right Arrow - same as ctrl-f */
-				return(6);
-			case 0x48:		/* Up arrow - same as ctrl-^ */
-				return(0x1e);
-			case 0x50:		/* Down arrow - same as Ctrl-J */
-				return(LF);
-			case 0x4f:	  /* End	  - same as Ctrl-E */
-				return(5);	/* ctrl-e - end of line */
-			case 0x91:	  /* Ctrl-Dn Arrow - increment statusline */
-				if(statline<LAST_STAT_LINE) {
-					statline++;
-					statusline(); }
-				return(0);
-			case 0x75:	/* Ctrl-End - end of status line info */
-				statline=LAST_STAT_LINE;
-				statusline();
-				return(0);
-			case 0x52:	/* Insert */
-				return(0x1f);	/* ctrl-minus - insert mode */
-			case 0x53:	/* Delete */
-				return(0x7f);	/* ctrl-bkspc - del cur char */
-			case 0x26:	/* Alt-L  - Capture to cap_fname */
-				if(lclaes())
-					return(0);
-				if(sys_status&SS_CAP) {
-					sys_status^=SS_CAP;
-					fclose(capfile);
-#ifdef __MSDOS__
-					freedosmem=farcoreleft();	/* fclose frees memory */
-#endif
-					statusline();
-					return(0); }
-				x=lclwx();
-				y=lclwy();
-				atr=lclatr(LIGHTGRAY<<4);
-				STATUSLINE;
-				lclxy(1,node_scrnlen);
-				lputs("  Filename: ");
-				lputc(CLREOL);
-				console&=~(CON_R_INPUT|CON_R_ECHO);
-				getstr(cap_fname,40,K_UPPER|K_EDIT);
-				TEXTWINDOW;
-				lclxy(x,y);
-				lclatr(atr);
-                console=con;
-				if(cap_fname[0] &&
-					(capfile=fopen(cap_fname,"a"))==NULL)
-					bprintf("Couldn't open %s.\r\n",cap_fname);
-				else if(cap_fname[0]) {
-#ifdef __MSDOS__
-					freedosmem=farcoreleft();	/* fnopen allocates memory */
-#endif
-					sys_status|=SS_CAP; }
-				statusline();
-				return(0);
-			case 0x17:	/* Alt-I  - Interrupt node now */
-				getnodedat(node_num,&thisnode,1);
-				thisnode.misc^=NODE_INTR;
-				putnodedat(node_num,thisnode);
-				return(0);
-			case 0x13:	/* Alt-R  - Rerun node when caller hangs up */
-				getnodedat(node_num,&thisnode,1);
-				thisnode.misc^=NODE_RRUN;
-				putnodedat(node_num,thisnode);
-				statusline();
-				return(0);
-			case 0x31:	/* Alt-N  - Lock this node */
-				getnodedat(node_num,&thisnode,1);
-				thisnode.misc^=NODE_LOCK;
-				putnodedat(node_num,thisnode);
-				statusline();
-				return(0);
-			case 0x22:	/* Alt-G  - Guru Chat */
-				if(sys_status&SS_GURUCHAT) {
-					sys_status&=~SS_GURUCHAT;
-					return(CR); }
-				if(!total_gurus)
-					break;
-				for(i=0;i<total_gurus;i++)
-					if(chk_ar(guru[i]->ar,useron))
-						break;
-				if(i>=total_gurus)
-					i=0;
-				sprintf(str,"%s%s.DAT",ctrl_dir,guru[i]->code);
-				if((file=nopen(str,O_RDONLY))==-1) {
-					errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-					return(0); }
-				if((gurubuf=MALLOC(filelength(file)+1L))==NULL) {
-					close(file);
-					errormsg(WHERE,ERR_ALLOC,str,filelength(file)+1L);
-					return(0); }
-				read(file,gurubuf,filelength(file));
-				gurubuf[filelength(file)]=0;
-				close(file);
-				localguru(gurubuf,i);
-				FREE(gurubuf);
-				return(CR);
-			case 0x20:	/* Alt-D - Shell to DOS */
-				sprintf(str,"%.*s",lbuflen,lbuf);
-				waitforsysop(1);
-				if((scrnbuf=MALLOC((node_scrnlen*80L)*2L))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,nulstr,(node_scrnlen*80L)*2L);
-					return(CR); }
-				gettext(1,1,80,node_scrnlen,scrnbuf);
-				lclatr(LIGHTGRAY);
-				x=lclwx();
-				y=lclwy();
-				lclini(node_scrnlen);
-				lputc(FF);
-				if(!(node_misc&NM_SYSPW) || chksyspass(1))
-					external(comspec,0);
-				lclini(node_scrnlen-1);
-				puttext(1,1,80,node_scrnlen,scrnbuf);
-				FREE(scrnbuf);
-				lclxy(x,y);
-				if(online==ON_REMOTE)
-					rioctl(IOFI);	/* flush input buffer */
-				waitforsysop(0);
-				strcpy(lbuf,str);
-				lbuflen=strlen(lbuf);
-				timeout=time(NULL);
-				return(0);
-			case 0x49:	/* PgUp - local ASCII upload */
-				if(sys_status&SS_FINPUT || lclaes() || inside)
-					return(0);
-				inside=1;
-				x=lclwx();
-				y=lclwy();
-				atr=lclatr(LIGHTGRAY<<4);
-				STATUSLINE;
-				lclxy(1,node_scrnlen);
-				lputs("  Filename: ");
-				lputc(CLREOL);
-				console&=~(CON_R_INPUT|CON_R_ECHO);
-				getstr(str,60,K_UPPER);
-				if(str[0] && (inputfile=nopen(str,O_RDONLY))!=-1)
-					sys_status|=SS_FINPUT;
-				statusline();
-				lclxy(x,y);
-				lclatr(atr);
-				console=con;
-				inside=0;
-				return(0);
-			case 0xff:	/* ctrl-break - bail immediately */
-				lputs("\r\nTerminate BBS (y/N) ? ");
-				while((i=lkbrd(0))==0);
-				if(toupper(i&0xff)=='Y') {  /* Ctrl-brk yes/no */
-					lputs("Yes\r\n");
-					bail(0); }
-				lputs("No\r\n");
-				sys_status|=SS_ABORT;
-				return(0); }
-		return(0); } }
-
-if(!ch && console&CON_R_INPUT && rioctl(RXBC)) {
-	if(sys_status&SS_LCHAT && curatr!=color[clr_chatremote])
-		attr(color[clr_chatremote]);
-	ch=incom();
-	if(node_misc&NM_7BITONLY
-		&& (!(sys_status&SS_USERON) || useron.misc&NO_EXASCII))
-		ch&=0x7f; }
-if(ch)
-	timeout=time(NULL);
-if(ch==3) {  /* Ctrl-C Abort */
-	sys_status|=SS_ABORT;
-	if(mode&K_SPIN) /* back space once if on spinning cursor */
-		bputs("\b \b");
-	return(0); }
-if(ch==26 && action!=NODE_PCHT) {	 /* Ctrl-Z toggle raw input mode */
-    if(mode&K_SPIN)
-        bputs("\b ");
-    SAVELINE;
-	attr(LIGHTGRAY);
-    CRLF;
-    bputs(text[RawMsgInputModeIsNow]);
-    if(console&CON_RAW_IN)
-        bputs(text[OFF]);
-    else
-        bputs(text[ON]);
-    console^=CON_RAW_IN;
-    CRLF;
-	CRLF;
-    RESTORELINE;
-    lncntr=0;
-	if(action!=NODE_MAIN && action!=NODE_XFER)
-		return(26);
-	return(0); }
-if(console&CON_RAW_IN)	{ /* ignore ctrl-key commands if in raw mode */
-	if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO || node_misc&NM_LOWPRIO))
-		mswait(0);
-	return(ch);
-}
-if(ch<SP) { 				/* Control chars */
-	if(ch==LF)				/* ignore LF's in not in raw mode */
-		return(0);
-	if(ch==15) {	/* Ctrl-O toggles pause temporarily */
-		useron.misc^=UPAUSE;
-		return(0); }
-	if(ch==0x10) {	/* Ctrl-P Private node-node comm */
-		if(!(sys_status&SS_USERON))
-			return(0);			 /* keep from being recursive */
-		if(mode&K_SPIN)
-			bputs("\b ");
-		if(sys_status&SS_SPLITP) {
-			if((scrnbuf=MALLOC((24L*80L)*2L))==NULL) {
-				errormsg(WHERE,ERR_ALLOC,nulstr,(24L*80L)*2L);
-				return(CR); }
-			gettext(1,1,80,24,scrnbuf);
-			x=lclwx();
-			y=lclwy();
-			CLS; }
-		else {
-			SAVELINE;
-			attr(LIGHTGRAY);
-			CRLF; }
-		nodesync(); 	/* read any waiting messages */
-		nodemsg();		/* send a message */
-		SYNC;
-		if(sys_status&SS_SPLITP) {
-			lncntr=0;
-			CLS;
-			for(i=0;i<((24*80)-1)*2;i+=2) {
-				if(scrnbuf[i+1]!=curatr)
-					attr(scrnbuf[i+1]);
-				outchar(scrnbuf[i]); }
-			FREE(scrnbuf);
-			GOTOXY(x,y); }
-		else {
-			CRLF;
-			RESTORELINE; }
-		lncntr=0;
-		return(0); }
-
-	if(ch==21) { /* Ctrl-U Users online */
-		if(!(sys_status&SS_USERON))
-			return(0);
-		if(mode&K_SPIN)
-			bputs("\b ");
-		if(sys_status&SS_SPLITP) {
-			if((scrnbuf=MALLOC((24L*80L)*2L))==NULL) {
-				errormsg(WHERE,ERR_ALLOC,nulstr,(24L*80L)*2L);
-				return(CR); }
-			gettext(1,1,80,24,scrnbuf);
-			x=lclwx();
-			y=lclwy();
-			CLS; }
-        else {
-			SAVELINE;
-			attr(LIGHTGRAY);
-			CRLF; }
-		whos_online(1); 	/* list users */
-		ASYNC;
-		if(sys_status&SS_SPLITP) {
-			CRLF;
-			nodesync();
-			pause();
-			CLS;
-			for(i=0;i<((24*80)-1)*2;i+=2) {
-				if(scrnbuf[i+1]!=curatr)
-					attr(scrnbuf[i+1]);
-				outchar(scrnbuf[i]); }
-			FREE(scrnbuf);
-			GOTOXY(x,y); }
-		else {
-			CRLF;
-            RESTORELINE; }
-		lncntr=0;
-		return(0); }
-	if(ch==20 && !(sys_status&SS_SPLITP)) { /* Ctrl-T Time information */
-		if(!(sys_status&SS_USERON))
-			return(0);
-		if(mode&K_SPIN)
-			bputs("\b ");
-		SAVELINE;
-		attr(LIGHTGRAY);
-		now=time(NULL);
-		bprintf(text[TiLogon],timestr(&logontime));
-		bprintf(text[TiNow],timestr(&now));
-		bprintf(text[TiTimeon]
-			,sectostr(now-logontime,tmp));
-		bprintf(text[TiTimeLeft]
-			,sectostr(timeleft,tmp));
-		SYNC;
-		RESTORELINE;
-		lncntr=0;
-		return(0); }
-	if(ch==11 && !(sys_status&SS_SPLITP)) {  /*  Ctrl-k Control key menu */
-		if(!(sys_status&SS_USERON))
-			return(0);
-		if(mode&K_SPIN)
-			bputs("\b ");
-		SAVELINE;
-		attr(LIGHTGRAY);
-		lncntr=0;
-		bputs(text[ControlKeyMenu]);
-		ASYNC;
-		RESTORELINE;
-		lncntr=0;
-		return(0); }
-
-	if(ch==ESC && console&CON_R_INPUT) {
-		for(i=0;i<20 && !rioctl(RXBC);i++)
-			mswait(1);
-		if(i==20)
-			return(ESC);
-		ch=incom();
-		if(ch!='[') {
-			ungetkey(ESC);
-			ungetkey(ch);
-			return(0); }
-		i=j=0;
-		autoterm|=ANSI; 			/* <ESC>[x means they have ANSI */
-		if(!(useron.misc&ANSI) && useron.misc&AUTOTERM && sys_status&SS_USERON
-			&& useron.number) {
-			useron.misc|=ANSI;
-			putuserrec(useron.number,U_MISC,8,ultoa(useron.misc,str,16)); }
-		while(i<10 && j<30) {		/* up to 3 seconds */
-			if(rioctl(RXBC)) {
-				ch=incom();
-				if(ch!=';' && !isdigit(ch) && ch!='R') {    /* other ANSI */
-					switch(ch) {
-						case 'A':
-							return(0x1e);	/* ctrl-^ (up arrow) */
-						case 'B':
-							return(LF); 	/* ctrl-j (dn arrow) */
-						case 'C':
-							return(0x6);	/* ctrl-f (rt arrow) */
-						case 'D':
-							return(0x1d);	/* ctrl-] (lf arrow) */
-						case 'H':
-							return(0x2);	/* ctrl-b (beg line) */
-						case 'K':
-							return(0x5);	/* ctrl-e (end line) */
-						}
-					ungetkey(ESC);
-					ungetkey('[');
-					for(j=0;j<i;j++)
-						ungetkey(str[j]);
-					ungetkey(ch);
-					return(0); }
-				if(ch=='R') {       /* cursor position report */
-					if(i && !(useron.rows)) {	/* auto-detect rows */
-						str[i]=0;
-						rows=atoi(str);
-						if(rows<5 || rows>99) rows=24; }
-					return(0); }
-				str[i++]=ch; }
-			else {
-				mswait(100);
-				j++; } }
-
-		ungetkey(ESC);		/* should only get here if time-out */
-		ungetkey('[');
-		for(j=0;j<i;j++)
-			ungetkey(str[j]);
-		return(0); }
-
-		}	/* end of control chars */
-
-if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO || node_misc&NM_LOWPRIO))
-	mswait(0);
-return(ch);
-}
-
diff --git a/src/sbbs2/con_mid.c b/src/sbbs2/con_mid.c
deleted file mode 100644
index 1925c4d173685f6db3e8d6b59783d61d3e0d9aa6..0000000000000000000000000000000000000000
--- a/src/sbbs2/con_mid.c
+++ /dev/null
@@ -1,813 +0,0 @@
-#line 1 "CON_MID.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-extern char *wday[];	/* 3 char days of week */
-
-/****************************************************************************/
-/* Waits for remote or local user to hit a key. Inactivity timer is checked */
-/* and hangs up if inactive for 4 minutes. Returns key hit, or uppercase of */
-/* key hit if mode&K_UPPER or key out of KEY BUFFER. Does not print key.    */
-/* Called from functions all over the place.                                */
-/****************************************************************************/
-char getkey(long mode)
-{
-	char ch,coldkey,c=0,spin=random(5);
-
-if(!online)
-    return(0);
-sys_status&=~SS_ABORT;
-if((sys_status&SS_USERON || action==NODE_DFLT) && !(mode&K_GETSTR))
-    mode|=(useron.misc&SPIN);
-lncntr=0;
-timeout=time(NULL);
-if(mode&K_SPIN)
-    outchar(' ');
-do {
-    checkline();    /* check to make sure remote user is still online */
-	if(online==ON_REMOTE && console&CON_R_INPUT && rioctl(IOSTATE)&ABORT) {
-        rioctl(IOCS|ABORT);
-        sys_status|=SS_ABORT;
-        if(mode&K_SPIN) /* back space once if on spinning cursor */
-            bputs("\b \b");
-        return(0); }
-	if(sys_status&SS_SYSPAGE)
-		beep(random(800),100);
-    if(mode&K_SPIN)
-        switch(spin) {
-            case 0:
-                switch(c++) {
-                    case 0:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 10:
-                        outchar(BS);
-                        outchar('/');
-                        break;
-                    case 20:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 30:
-                        outchar(BS);
-                        outchar('\\');
-                        break;
-                    case 40:
-                        c=0;
-                        break;
-                    default:
-                        if(!inDV && !(node_misc&NM_WINOS2))
-							mswait(DELAY_SPIN);
-                        break;  }
-                break;
-            case 1:
-                switch(c++) {
-                    case 0:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 10:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 20:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 30:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 40:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 50:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 60:
-                        c=0;
-                        break;
-                    default:
-                        if(!inDV && !(node_misc&NM_WINOS2))
-							mswait(DELAY_SPIN);
-                        break;  }
-                break;
-            case 2:
-                switch(c++) {
-                    case 0:
-                        outchar(BS);
-                        outchar('-');
-                        break;
-                    case 10:
-                        outchar(BS);
-                        outchar('=');
-                        break;
-                    case 20:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 30:
-                        outchar(BS);
-                        outchar('=');
-                        break;
-                    case 40:
-                        c=0;
-                        break;
-                    default:
-                        if(!inDV && !(node_misc&NM_WINOS2))
-							mswait(DELAY_SPIN);
-                        break;  }
-                break;
-            case 3:
-                switch(c++) {
-                    case 0:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 10:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 20:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 30:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 40:
-                        c=0;
-                        break;
-                    default:
-                        if(!inDV && !(node_misc&NM_WINOS2))
-							mswait(DELAY_SPIN);
-                        break;  }
-                break;
-            case 4:
-                switch(c++) {
-                    case 0:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 10:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 20:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 30:
-                        outchar(BS);
-                        outchar('�');
-                        break;
-                    case 40:
-                        c=0;
-                        break;
-                    default:
-                        if(!inDV && !(node_misc&NM_WINOS2))
-							mswait(DELAY_SPIN);
-                        break;  }
-                break; }
-    if(keybuftop!=keybufbot) {
-        ch=keybuf[keybufbot++];
-        if(keybufbot==KEY_BUFSIZE)
-            keybufbot=0; }
-    else
-        ch=inkey(mode);
-    if(sys_status&SS_ABORT)
-        return(0);
-    now=time(NULL);
-    if(ch) {
-        if(mode&K_NUMBER && isprint(ch) && !isdigit(ch))
-            continue;
-        if(mode&K_ALPHA && isprint(ch) && !isalpha(ch))
-            continue;
-        if(mode&K_NOEXASC && ch&0x80)
-            continue;
-        if(mode&K_SPIN)
-            bputs("\b \b");
-		if(mode&K_COLD && ch>SP && useron.misc&COLDKEYS) {
-			if(mode&K_UPPER)
-				outchar(toupper(ch));
-			else
-				outchar(ch);
-			while((coldkey=inkey(mode))==0 && online && !(sys_status&SS_ABORT))
-				checkline();
-			bputs("\b \b");
-			if(coldkey==BS)
-				continue;
-			if(coldkey>SP)
-				ungetkey(coldkey); }
-        if(mode&K_UPPER)
-            return(toupper(ch));
-        return(ch); }
-    if(sys_status&SS_USERON && !(sys_status&SS_LCHAT)) gettimeleft();
-    else if(online &&
-        ((node_dollars_per_call && now-answertime>SEC_BILLING)
-        || (now-answertime>SEC_LOGON && !(sys_status&SS_LCHAT)))) {
-        console&=~(CON_R_ECHOX|CON_L_ECHOX);
-        console|=(CON_R_ECHO|CON_L_ECHO);
-        bputs(text[TakenTooLongToLogon]);
-        hangup(); }
-	if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn)
-		&& !SYSOP && !(sys_status&SS_LCHAT)) {
-        timeleft_warn=5-(timeleft/60);
-        SAVELINE;
-		attr(LIGHTGRAY);
-        bprintf(text[OnlyXminutesLeft]
-			,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr);
-        RESTORELINE; }
-
-	if(online==ON_LOCAL && node_misc&NM_NO_INACT)
-		timeout=now;
-	if(now-timeout>=sec_warn) { 					/* warning */
-        if(sys_status&SS_USERON) {
-            SAVELINE;
-            bputs(text[AreYouThere]); }
-        else
-            bputs("\7\7");
-		while(!inkey(0) && online && now-timeout>=sec_warn) {
-            now=time(NULL);
-			if(now-timeout>=sec_hangup) {
-                if(online==ON_REMOTE) {
-                    console|=CON_R_ECHO;
-                    console&=~CON_R_ECHOX; }
-                bputs(text[CallBackWhenYoureThere]);
-                logline(nulstr,"Inactive");
-                hangup();
-                return(0); }
-            mswait(100); }
-        if(sys_status&SS_USERON) {
-            bputs("\r\1n\1>");
-            RESTORELINE; }
-        timeout=now; }
-
-    } while(online);
-return(0);
-}
-
-/****************************************************************************/
-/* This function lists users that are online.                               */
-/* If listself is true, it will list the current node.                      */
-/* Returns number of active nodes (not including current node).             */
-/****************************************************************************/
-int whos_online(char listself)
-{
-    int i,j;
-    node_t node;
-
-CRLF;
-bputs(text[NodeLstHdr]);
-for(j=0,i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-    getnodedat(i,&node,0);
-    if(i==node_num) {
-        if(listself)
-            printnodedat(i,node);
-        continue; }
-    if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
-        printnodedat(i,node);
-        if(!lastnodemsg)
-            lastnodemsg=i;
-        j++; } }
-if(!j)
-    bputs(text[NoOtherActiveNodes]);
-return(j);
-}
-
-/****************************************************************************/
-/* Displays the information for node number 'number' contained in 'node'    */
-/****************************************************************************/
-void printnodedat(uint number, node_t node)
-{
-    uint i;
-    char hour,mer[3];
-
-attr(color[clr_nodenum]);
-bprintf("%3d  ",number);
-attr(color[clr_nodestatus]);
-switch(node.status) {
-    case NODE_WFC:
-        bputs("Waiting for call");
-        break;
-    case NODE_OFFLINE:
-        bputs("Offline");
-        break;
-    case NODE_NETTING:
-        bputs("Networking");
-        break;
-    case NODE_LOGON:
-        bputs("At logon prompt");
-        break;
-    case NODE_EVENT_WAITING:
-        bputs("Waiting for all nodes to become inactive");
-        break;
-    case NODE_EVENT_LIMBO:
-        bprintf("Waiting for node %d to finish external event",node.aux);
-        break;
-    case NODE_EVENT_RUNNING:
-        bputs("Running external event");
-        break;
-    case NODE_NEWUSER:
-        attr(color[clr_nodeuser]);
-        bputs("New user");
-        attr(color[clr_nodestatus]);
-        bputs(" applying for access ");
-        if(!node.connection)
-            bputs("Locally");
-        else
-            bprintf("at %ubps",node.connection);
-        break;
-    case NODE_QUIET:
-        if(!SYSOP) {
-            bputs("Waiting for call");
-            break; }
-    case NODE_INUSE:
-		if(node.misc&NODE_EXT) {
-			getnodeext(number,tmp);
-			bputs(tmp);
-			break; }
-        attr(color[clr_nodeuser]);
-        if(node.misc&NODE_ANON && !SYSOP)
-            bputs("UNKNOWN USER");
-        else
-            bputs(username(node.useron,tmp));
-        attr(color[clr_nodestatus]);
-        bputs(" ");
-        switch(node.action) {
-            case NODE_MAIN:
-                bputs("at main menu");
-                break;
-            case NODE_RMSG:
-                bputs("reading messages");
-                break;
-            case NODE_RMAL:
-                bputs("reading mail");
-                break;
-            case NODE_RSML:
-                bputs("reading sent mail");
-                break;
-            case NODE_RTXT:
-                bputs("reading text files");
-                break;
-            case NODE_PMSG:
-                bputs("posting message");
-                break;
-            case NODE_SMAL:
-                bputs("sending mail");
-                break;
-            case NODE_AMSG:
-                bputs("posting auto-message");
-                break;
-            case NODE_XTRN:
-                if(!node.aux)
-                    bputs("at external program menu");
-                else {
-                    bputs("running ");
-                    i=node.aux-1;
-					if(SYSOP || chk_ar(xtrn[i]->ar,useron))
-                        bputs(xtrn[node.aux-1]->name);
-                    else
-                        bputs("external program"); }
-                break;
-            case NODE_DFLT:
-                bputs("changing defaults");
-                break;
-            case NODE_XFER:
-                bputs("at transfer menu");
-                break;
-            case NODE_RFSD:
-                bprintf("retrieving from device #%d",node.aux);
-                break;
-            case NODE_DLNG:
-                bprintf("downloading");
-                break;
-            case NODE_ULNG:
-                bputs("uploading");
-                break;
-            case NODE_BXFR:
-                bputs("transferring bidirectional");
-                break;
-            case NODE_LFIL:
-                bputs("listing files");
-                break;
-            case NODE_LOGN:
-                bputs("logging on");
-                break;
-            case NODE_LCHT:
-                bprintf("in local chat with %s",sys_op);
-                break;
-            case NODE_MCHT:
-                if(node.aux) {
-                    bprintf("in multinode chat channel %d",node.aux&0xff);
-                    if(node.aux&0x1f00) { /* password */
-                        outchar('*');
-                        if(SYSOP)
-                            bprintf(" %s",unpackchatpass(tmp,node)); } }
-                else
-                    bputs("in multinode global chat channel");
-                break;
-            case NODE_PAGE:
-                bprintf("paging node %u for private chat",node.aux);
-                break;
-            case NODE_PCHT:
-                bprintf("in private chat with node %u",node.aux);
-                break;
-            case NODE_GCHT:
-				i=node.aux;
-				if(i>=total_gurus)
-					i=0;
-				bprintf("chatting with %s",guru[i]->name);
-                break;
-            case NODE_CHAT:
-                bputs("in chat section");
-                break;
-            case NODE_TQWK:
-                bputs("transferring QWK packet");
-                break;
-            case NODE_SYSP:
-                bputs("performing sysop activities");
-                break;
-            default:
-                bputs(itoa(node.action,tmp,10));
-                break;  }
-        if(!node.connection)
-            bputs(" locally");
-        else
-            bprintf(" at %ubps",node.connection);
-        if(node.action==NODE_DLNG) {
-            if(sys_misc&SM_MILITARY) {
-                hour=node.aux/60;
-                mer[0]=0; }
-            else if((node.aux/60)>=12) {
-                if(node.aux/60==12)
-                    hour=12;
-                else
-                    hour=(node.aux/60)-12;
-                strcpy(mer,"pm"); }
-            else {
-                if((node.aux/60)==0)    /* 12 midnite */
-                    hour=12;
-                else hour=node.aux/60;
-                strcpy(mer,"am"); }
-            bprintf(" ETA %02d:%02d %s"
-                ,hour,node.aux%60,mer); }
-        break; }
-i=NODE_LOCK;
-if(node.status==NODE_INUSE || SYSOP)
-	i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
-if(node.misc&i) {
-    bputs(" (");
-	if(node.misc&(i&NODE_AOFF))
-        outchar('A');
-    if(node.misc&NODE_LOCK)
-        outchar('L');
-	if(node.misc&(i&(NODE_MSGW|NODE_NMSG)))
-        outchar('M');
-	if(node.misc&(i&NODE_POFF))
-        outchar('P');
-    outchar(')'); }
-if(SYSOP && ((node.misc
-    &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
-    || node.status==NODE_QUIET)) {
-    bputs(" [");
-    if(node.misc&NODE_ANON)
-        outchar('A');
-    if(node.misc&NODE_INTR)
-        outchar('I');
-    if(node.misc&NODE_RRUN)
-        outchar('R');
-    if(node.misc&NODE_UDAT)
-        outchar('U');
-    if(node.status==NODE_QUIET)
-        outchar('Q');
-    if(node.misc&NODE_EVENT)
-        outchar('E');
-    if(node.misc&NODE_DOWN)
-        outchar('D');
-    outchar(']'); }
-if(node.errors && SYSOP) {
-    attr(color[clr_err]);
-	bprintf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' ); }
-attr(LIGHTGRAY);
-CRLF;
-}
-
-/****************************************************************************/
-/* Prints/updates the local status line (line #25) with the user/system     */
-/* information. Which info depends on value of statline.                    */
-/* Called from several functions                                            */
-/****************************************************************************/
-void statusline()
-{
-    int row,col,atr;
-    char tmp1[128],tmp2[256],tmp3[256],age;
-
-#ifndef __OS2__
-if(lclaes())
-    return;
-#endif
-col=lclwx();
-row=lclwy();
-STATUSLINE;
-lclxy(1,node_scrnlen);
-age=getage(useron.birth);
-if(sys_status&(SS_CAP|SS_TMPSYSOP)) {
-    atr=lclatr((LIGHTGRAY<<4)|BLINK);
-    sys_status&SS_CAP ? lputc('C') : lputc(SP);
-    sys_status&SS_TMPSYSOP ? lputc('*') : lputc(SP);
-    lclatr(LIGHTGRAY<<4); }
-else {
-    atr=lclatr(LIGHTGRAY<<4);
-    lputs("  "); }
-switch(statline) {
-    case -1:
-        lputs("Terminal:  Alt-X Exit  Alt-D DOS  Alt-H Hangup  "
-            "Alt-L Logon  Alt-U User Edit");
-        break;
-    case 0:     /* Alias ML Password Modem Birthday Age Sex Phone */
-        lprintf("%-24.24s %02d %-8.8s %-8.8s %-8.8s %02d %c %s"
-            ,useron.alias,useron.level,sys_misc&SM_ECHO_PW ? useron.pass:"XXXX"
-            ,useron.modem,useron.birth,age,useron.sex,useron.phone);
-        break;
-    case 1:     /* Alias ML RealName Alt-Z for Help */
-        lprintf("%-24.24s %02d %-25.25s  "
-            ,useron.alias,useron.level,useron.name);
-        lputs("Alt-Z for Help");
-        break;
-    case 2:     /* Alias ML RealName Age Sex Phone */
-        lprintf("%-24.24s %02d %-25.25s  %02d %c %s"
-            ,useron.alias,useron.level,useron.name,age,useron.sex,useron.phone);
-        break;
-    case 3:     /* Alias ML Location Phone */
-        lprintf("%-24.24s %02d %-30.30s  %s"
-            ,useron.alias,useron.level,useron.location,useron.phone);
-        break;
-    case 4:     /* Alias ML Note Phone */
-        lprintf("%-24.24s %02d %-30.30s  %s"
-            ,useron.alias,useron.level,useron.note,useron.phone);
-        break;
-    case 5:     /* Alias ML MF Age Sex Phone */
-        lprintf("%-24.24s %02d %-26.26s %02d %c %s"
-            ,useron.alias,useron.level,ltoaf(useron.flags1,tmp1)
-            ,age,useron.sex,useron.phone);
-        break;
-    case 6:     /* Alias ML MF Expiration */
-        lprintf("%-24.24s %02d %-26.26s Exp: %s"
-            ,useron.alias,useron.level,ltoaf(useron.flags1,tmp1)
-            ,unixtodstr(useron.expire,tmp2));
-        break;
-    case 7:     /* Alias ML Firston Laston Expire */
-        lprintf("%-24.24s %02d First: %s Last: %s Exp: %s"
-            ,useron.alias,useron.level,unixtodstr(useron.firston,tmp1)
-            ,unixtodstr(useron.laston,tmp2),unixtodstr(useron.expire,tmp3));
-        break;
-    case 8:     /* Alias Credits Minutes Expire */
-        lprintf("%-24.24s Cdt: %-13.13s Min: %-10luExp: %s"
-            ,useron.alias,ultoac(useron.cdt,tmp1),useron.min
-            ,unixtodstr(useron.expire,tmp2));
-        break;
-    case 9:    /* Exemptions Restrictions */
-        lprintf("  Exempt:%-26.26s   Restrict:%s"
-            ,ltoaf(useron.exempt,tmp1),ltoaf(useron.rest,tmp2));
-        break;
-    case 10:    /* Computer Modem Handle*/
-        lprintf("Comp: %-30.30s  Modem: %-8.8s  Handle: %s"
-            ,useron.comp,connection,useron.handle);
-        break;
-    case 11:    /* StreetAddress Location Zip */
-        lprintf("%-30.30s %-30.30s %s"
-            ,useron.address,useron.location,useron.zipcode);
-        break;
-    case 12:    /* UploadBytes Uploads DownloadBytes Downloads Leeches */
-        lprintf("Uloads: %-13.13s / %-5u Dloads: %-13.13s / %-5u Leech: %u"
-            ,ultoac(useron.ulb,tmp1),useron.uls
-            ,ultoac(useron.dlb,tmp2),useron.dls,useron.leech);
-        break;
-    case 13:    /* Posts Emails Fbacks Waiting Logons Timeon */
-        lprintf("P: %-5u E: %-5u F: %-5u W: %-5u L: %-5u T: %-5u"
-            ,useron.posts,useron.emails,useron.fbacks,getmail(useron.number,0)
-            ,useron.logons,useron.timeon);
-        break;
-    case 14:    /* NetMail forwarding address */
-        lprintf("NetMail: %s",useron.netmail);
-        break;
-    case 15:    /* Comment */
-        lprintf("Comment: %s",useron.comment);
-        break;
-        }
-lputc(CLREOL);
-lclxy(75,lclwy());
-getnodedat(node_num,&thisnode,0);
-if(sys_status&SS_SYSALERT
-    || thisnode.misc&(NODE_RRUN|NODE_DOWN|NODE_LOCK|NODE_EVENT)) {
-    lclatr((LIGHTGRAY<<4)|BLINK);
-    sys_status&SS_SYSALERT ? lputc('A'):lputc(SP);
-    thisnode.misc&NODE_RRUN ? lputc('R'):lputc(SP);
-    thisnode.misc&NODE_DOWN ? lputc('D'):lputc(SP);
-    thisnode.misc&NODE_LOCK ? lputc('L'):lputc(SP);
-    thisnode.misc&NODE_EVENT ? lputc('E'):lputc(SP); }
-TEXTWINDOW;
-lclxy(col,row);
-lclatr(atr);
-}
-
-/****************************************************************************/
-/* Prints PAUSE message and waits for a key stoke                           */
-/****************************************************************************/
-void pause()
-{
-	char	ch;
-	uchar	tempattrs=curatr; /* was lclatr(-1) */
-	int 	i,j;
-	long	l=K_UPPER;
-
-RIOSYNC(0);
-if(sys_status&SS_ABORT)
-    return;
-lncntr=0;
-if(online==ON_REMOTE)
-    rioctl(IOFI);
-bputs(text[Pause]);
-j=bstrlen(text[Pause]);
-if(sys_status&SS_USERON && !(useron.misc&NO_EXASCII) && !(useron.misc&WIP))
-	l|=K_SPIN;
-
-ch=getkey(l);
-if(ch==text[YN][1] || ch=='Q')
-	sys_status|=SS_ABORT;
-else if(ch==LF)
-	lncntr=rows-2;	/* down arrow == display one more line */
-if(text[Pause][0]!='@')
-	for(i=0;i<j;i++)
-		bputs("\b \b");
-getnodedat(node_num,&thisnode,0);
-nodesync();
-attr(tempattrs);
-}
-
-void getlines()
-{
-if(useron.misc&ANSI && !useron.rows         /* Auto-detect rows */
-    && online==ON_REMOTE) {                 /* Remote */
-    SYNC;   
-    putcom("\x1b[s\x1b[99B\x1b[6n\x1b[u");
-    while(online && !rioctl(RXBC) && !lkbrd(1))
-        checkline();
-    inkey(0); }
-
-}
-
-
-/****************************************************************************/
-/* Prints a file remotely and locally, interpreting ^A sequences, checks    */
-/* for pauses, aborts and ANSI. 'str' is the path of the file to print      */
-/* Called from functions menu and text_sec                                  */
-/****************************************************************************/
-void printfile(char *str, int mode)
-{
-	char HUGE16 *buf;
-	int file,wip=0,rip=0;
-	long length,savcon=console;
-	FILE *stream;
-
-if(strstr(str,".WIP"))
-	wip=1;
-if(strstr(str,".RIP"))
-	rip=1;
-
-if(mode&P_NOABORT || wip || rip) {
-	if(online==ON_REMOTE && console&CON_R_ECHO) {
-        rioctl(IOCM|ABORT);
-        rioctl(IOCS|ABORT); }
-    sys_status&=~SS_ABORT; }
-
-if(!tos && !wip && !rip)
-	CRLF;
-
-if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-    bputs(text[FileNotFound]);
-    if(SYSOP) bputs(str);
-    CRLF;
-	return; }
-
-if(wip || rip || !(console&CON_L_ECHO)) {
-	if(online!=ON_REMOTE || !(console&CON_R_ECHO)) {
-		fclose(stream);
-		return; }
-	console&=~CON_L_ECHO;
-	lprintf("PRINTFILE (Remote Only): %s\r\n",str);  }
-if(mode&P_OPENCLOSE) {
-	length=filelength(file);
-	if((buf=MALLOC(length+1L))==NULL) {
-		close(file);
-		console=savcon;
-		errormsg(WHERE,ERR_ALLOC,str,length+1L);
-		return; }
-	buf[lread(file,buf,length)]=0;
-	fclose(stream);
-	putmsg(buf,mode);
-	FREE((char *)buf); }
-else {
-	putmsg_fp(stream,filelength(file),mode);
-	fclose(stream); }
-if((mode&P_NOABORT || wip || rip) && online==ON_REMOTE) {
-    SYNC;
-    rioctl(IOSM|ABORT); }
-if(rip)
-	getlines();
-console=savcon;
-}
-
-void printtail(char *str, int lines, int mode)
-{
-	char HUGE16 *buf,HUGE16 *p;
-	int file,cur=0;
-	ulong length,l;
-
-if(mode&P_NOABORT) {
-    if(online==ON_REMOTE) {
-        rioctl(IOCM|ABORT);
-        rioctl(IOCS|ABORT); }
-    sys_status&=~SS_ABORT; }
-strupr(str);
-if(!tos) {
-    CRLF; }
-if((file=nopen(str,O_RDONLY))==-1) {
-    bputs(text[FileNotFound]);
-    if(SYSOP) bputs(str);
-    CRLF;
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length+1L))==NULL) {
-    close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length+1L);
-	return; }
-l=lread(file,buf,length);
-buf[l]=0;
-close(file);
-p=(buf+l)-1;
-if(*p==LF) p--;
-while(*p && p>buf) {
-	if(*p==LF)
-		cur++;
-	if(cur>=lines) {
-		p++;
-		break; }
-	p--; }
-putmsg(p,mode);
-if(mode&P_NOABORT && online==ON_REMOTE) {
-    SYNC;
-    rioctl(IOSM|ABORT); }
-FREE((char *)buf);
-}
-
-/****************************************************************************/
-/* Prints the menu number 'menunum' from the text directory. Checks for ^A  */
-/* ,ANSI sequences, pauses and aborts. Usually accessed by user inputing '?'*/
-/* Called from every function that has an available menu.                   */
-/* The code definitions are as follows:                                     */
-/****************************************************************************/
-void menu(char *code)
-{
-    char str[256],path[256];
-    int c,i,l;
-
-sys_status&=~SS_ABORT;
-if(menu_file[0])
-	strcpy(path,menu_file);
-else {
-	sprintf(str,"%sMENU\\",text_dir);
-	if(menu_dir[0]) {
-		strcat(str,menu_dir);
-		strcat(str,"\\"); }
-	strcat(str,code);
-	strcat(str,".");
-	sprintf(path,"%s%s",str,useron.misc&WIP ? "WIP":"RIP");
-	if(!(useron.misc&(RIP|WIP)) || !fexist(path)) {
-		sprintf(path,"%sMON",str);
-		if((useron.misc&(COLOR|ANSI))!=ANSI || !fexist(path)) {
-			sprintf(path,"%sANS",str);
-			if(!(useron.misc&ANSI) || !fexist(path))
-				sprintf(path,"%sASC",str); } } }
-
-printfile(path,P_OPENCLOSE);
-}
-
-/****************************************************************************/
-/* Puts a character into the input buffer                                   */
-/****************************************************************************/
-void ungetkey(char ch)
-{
-
-keybuf[keybuftop++]=ch;
-if(keybuftop==KEY_BUFSIZE)
-    keybuftop=0;
-}
-
diff --git a/src/sbbs2/con_out.c b/src/sbbs2/con_out.c
deleted file mode 100644
index 6384088dd9635331b83e15178a9efd491ff76aab..0000000000000000000000000000000000000000
--- a/src/sbbs2/con_out.c
+++ /dev/null
@@ -1,1043 +0,0 @@
-#line 1 "CON_OUT.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/**********************************************************************/
-/* Functions that pertain to console i/o - color, strings, chars etc. */
-/* Called from functions everywhere                                   */
-/**********************************************************************/
-
-#include "sbbs.h"
-
-extern char *mnestr;
-
-/***************************************************/
-/* Seven bit table for EXASCII to ASCII conversion */
-/***************************************************/
-char *sbtbl="CUeaaaaceeeiiiAAEaAooouuyOUcLYRfaiounNao?--24!<>"
-			"###||||++||++++++--|-+||++--|-+----++++++++##[]#"
-			"abrpEout*ono%0ENE+><rj%=o..+n2* ";
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-
-uchar outchar_esc=0;
-
-#ifdef __WIN32__
-
-int lclatr(int atr)
-{
-
-textattr(atr);
-return(curatr);
-}
-
-void lputc(ch)
-{
-switch(ch) {
-    case CLREOL:
-		clreol();
-        break;
-    case FF:
-		clrscr();
-        break;
-    case TAB:
-		if(!(wherex()%8))
-			putchar(SP);
-		while(wherex()%8)
-			putchar(SP);
-        break;
-    default:
-		putchar(ch);
-		break; }
-}
-
-#endif
-
-#ifdef __OS2__
-
-HEV con_out_sem;					/* Console command semaphore */
-
-#define CON_OUT_BUFLEN		8192	/* Console output (ANSI) buffer */
-#define CON_BLK_BUFLEN		4096	/* Console block (all same atr) buffer */
-
-uchar conoutbuf[CON_OUT_BUFLEN];
-uchar conblkbuf[CON_BLK_BUFLEN];
-volatile uint  conblkcnt=0;
-volatile uint  conoutbot=0;
-volatile uint  conouttop=0;
-
-uchar lcl_curatr=LIGHTGRAY;
-
-/****************************************************************************/
-/* Prints one block of text (all same attribute) at current cursor position */
-/****************************************************************************/
-void print_conblkbuf()
-{
-conblkbuf[conblkcnt]=0;
-cputs(conblkbuf);
-conblkcnt=0;
-}
-
-void con_outch(int ch)
-{
-	static uchar ansi_esc;
-	static uchar ansi_curval;
-	static uchar ansi_val[3];
-	static uchar ansi_x;
-	static uchar ansi_y;
-    int x,y;
-
-if(ch==ESC) {
-    ansi_esc=1;
-	ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0;
-    return; }
-
-if(ansi_esc==1) {           /* Received ESC already */
-    if(ch=='[') {
-        ansi_esc++;
-        return; }
-	ansi_esc=ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0; }
-
-if(ansi_esc==2) {           /* Received ESC[ already */
-
-    if(isdigit(ch)) {
-		if(ansi_curval>2) ansi_curval=0;
-        ansi_val[ansi_curval]*=10;
-        ansi_val[ansi_curval]+=ch&0xf;
-        return; }
-
-    if(ch==';') {
-        ansi_curval++;
-        return; }
-
-    /* looks like valid ANSI, so purge the output block */
-    if(conblkcnt)
-        print_conblkbuf();
-    switch(ch) {
-        case 'A': // Move cursor up
-            y=wherey();
-            if(ansi_val[0])
-                y-=ansi_val[0];
-            else
-                y--;
-            if(y<1) y=1;
-            gotoxy(wherex(),y);
-            break;
-        case 'B': // Move cursor down
-            y=wherey();
-            if(ansi_val[0])
-                y+=ansi_val[0];
-            else
-                y++;
-            if(y>node_scrnlen) y=node_scrnlen;
-            gotoxy(wherex(),y);
-            break;
-        case 'C': // Move cursor right
-            x=wherex();
-            if(ansi_val[0])
-                x+=ansi_val[0];
-            else
-                x++;
-            if(x>80) x=80;
-            gotoxy(x,wherey());
-            break;
-        case 'D': // Move cursor left
-            x=wherex();
-            if(ansi_val[0])
-                x-=ansi_val[0];
-            else
-                x--;
-            if(x<1) x=1;
-            gotoxy(x,wherey());
-            break;
-        case 'J': // clear screen
-            if(ansi_val[0]==2)
-                clrscr();
-            break;
-        case 'K': // clearn from cursor to end of line
-            clreol();
-            break;
-        case 'H': // Position cursor
-        case 'f':
-            y=ansi_val[0];
-            x=ansi_val[1];
-            if(x<1) x=1;
-            if(x>80) x=80;
-            if(y<1) y=1;
-            if(y>node_scrnlen) y=node_scrnlen;
-            gotoxy(x,y);
-            break;
-		case 's': // Save cursor position
-			ansi_x=wherex();
-			ansi_y=wherey();
-			break;
-		case 'u': // Restore cursor position
-			if(ansi_x)
-				gotoxy(ansi_x,ansi_y);
-			break;
-        case 'm': // Select character attributes
-            for(x=0;x<=ansi_curval;x++)
-                switch(ansi_val[x]) {
-                    case 0: // no special attributes
-                    case 8: // concealed text (no display)
-                        lcl_curatr=LIGHTGRAY;
-                        break;
-                    case 1: // high intensity
-                    case 3: // italic
-                    case 4: // underline
-                        lcl_curatr|=HIGH;
-                        break;
-                    case 2: // low intensity
-                        lcl_curatr&=~HIGH;
-                        break;
-                    case 5: // blink
-                    case 6: // rapid blink
-                    case 7: // reverse video
-                        lcl_curatr|=BLINK;
-                        break;
-                    case 30: // foreground black
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=BLACK;
-                        break;
-                    case 31: // foreground red
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=RED;
-                        break;
-                    case 32: // foreground green
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=GREEN;
-                        break;
-                    case 33: // foreground yellow
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=BROWN;
-                        break;
-                    case 34: // foreground blue
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=BLUE;
-                        break;
-                    case 35: // foreground magenta
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=MAGENTA;
-                        break;
-                    case 36: // foreground cyan
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=CYAN;
-                        break;
-                    case 37: // foreground white
-                        lcl_curatr&=0xf8;
-                        lcl_curatr|=LIGHTGRAY;
-                        break;
-                    case 40: // background black
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(BLACK<<4);
-                        break;
-                    case 41: // background red
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(RED<<4);
-                        break;
-                    case 42: // background green
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(GREEN<<4);
-                        break;
-                    case 43: // background yellow
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(BROWN<<4);
-                        break;
-                    case 44: // background blue
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(BLUE<<4);
-                        break;
-                    case 45: // background magenta
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(MAGENTA<<4);
-                        break;
-                    case 46: // background cyan
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(CYAN<<4);
-                        break;
-                    case 47: // background white
-                        lcl_curatr&=0x8f;
-                        lcl_curatr|=(LIGHTGRAY<<4);
-                        break; }
-			textattr(lcl_curatr);
-            break; }
-
-	ansi_esc=ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0;
-    return; }
-
-if(conblkcnt+1>=CON_BLK_BUFLEN)
-    print_conblkbuf();
-switch(ch) {
-    case CLREOL:
-		if(conblkcnt) print_conblkbuf();
-		clreol();
-        break;
-    case FF:
-		if(conblkcnt) print_conblkbuf();
-        clrscr();
-        break;
-    case TAB:
-		if(conblkcnt) print_conblkbuf();
-		if(!(wherex()%8))
-			putch(SP);
-		while(wherex()%8)
-			putch(SP);
-        break;
-    default:
-		conblkbuf[conblkcnt++]=ch;
-        break; }
-}
-
-
-/****************************************************************************/
-/* Thread that services the console output buffer (conoutbuf) which 		*/
-/* contains ANSI escape sequences											*/
-/* All output is for the text window (mirroring the remote console) 		*/
-/****************************************************************************/
-void con_out_thread(void *unused)
-{
-	int i,top,cnt;
-	ulong l;
-
-while(1) {
-	/* mswait(1);	Removed 12/99 via Enigma */
-	if(conoutbot==conouttop) {
-		DosWaitEventSem(con_out_sem,10000);  /* every 10 seconds */
-		DosResetEventSem(con_out_sem,&l);
-        continue; }
-	top=conouttop;
-	if(top<conoutbot)
-		cnt=CON_OUT_BUFLEN-conoutbot;
-	else
-		cnt=top-conoutbot;
-	for(i=conoutbot;i<conoutbot+cnt;i++)
-		con_outch(conoutbuf[i]);
-	conoutbot=i;
-	if(conblkcnt)
-		print_conblkbuf();
-	if(conoutbot==CON_OUT_BUFLEN)
-		conoutbot=0; }
-}
-
-
-
-void outcon(char ch)
-{
-	int i=conouttop+1;
-
-if(i==CON_OUT_BUFLEN)
-	i=0;
-while(conoutbot==i) // Wait for thread to service queue
-	mswait(1);
-conoutbuf[conouttop++]=ch;
-if(conouttop==CON_OUT_BUFLEN)
-	conouttop=0;
-DosPostEventSem(con_out_sem);	 // Enable output
-}
-
-int outcon_pending()
-{
-if(conoutbot!=conouttop)
-	return(1);
-if(conblkcnt) {
-	print_conblkbuf();
-	return(1); }
-return(0);
-}
-
-int conaes()
-{
-return(outchar_esc==2);
-}
-
-void lputc(int ch)
-{
-
-while(outcon_pending())
-	mswait(1);
-switch(ch) {
-    case CLREOL:
-		clreol();
-        break;
-    case FF:
-		clrscr();
-        break;
-    case TAB:
-		if(!(wherex()%8))
-			putch(SP);
-		while(wherex()%8)
-			putch(SP);
-        break;
-    default:
-		putch(ch);
-		break; }
-}
-
-long lputs(char *str)
-{
-while(outcon_pending())
-	mswait(1);
-return(cputs(str));
-}
-
-int lclwx(void)
-{
-while(outcon_pending())
-	mswait(1);
-return(wherex());
-}
-
-int lclwy(void)
-{
-while(outcon_pending())
-	mswait(1);
-return(wherey());
-}
-
-void lclxy(int x, int y)
-{
-while(outcon_pending())
-	mswait(1);
-gotoxy(x,y);
-}
-
-int lclatr(int x)
-{
-	int i;
-
-while(conoutbot!=conouttop) 	/* wait for output buf to empty */
-	mswait(1);
-if(x==-1)
-	return(lcl_curatr);
-
-textattr(x);
-i=lcl_curatr;
-lcl_curatr=x;
-return(i);		/* Return previous attribute */
-}
-
-#endif
-
-/****************************************************************************/
-/* Outputs a NULL terminated string locally and remotely (if applicable)    */
-/* Handles ctrl-a characters                                                */
-/****************************************************************************/
-int bputs(char *str)
-{
-	int i;
-    ulong l=0;
-
-while(str[l]) {
-    if(str[l]==1) {             /* ctrl-a */
-        ctrl_a(str[++l]);       /* skip the ctrl-a */
-		l++;					/* skip the attribute code */
-		continue; }
-	if(str[l]=='@') {           /* '@' */
-		if(str==mnestr			/* Mnemonic string or */
-			|| (str>=text[0]	/* Straight out of TEXT.DAT */
-				&& str<=text[TOTAL_TEXT-1])) {
-			i=atcodes(str+l);		/* return 0 if not valid @ code */
-			l+=i;					/* i is length of code string */
-			if(i)					/* if valid string, go to top */
-				continue; }
-		for(i=0;i<TOTAL_TEXT;i++)
-			if(str==text[i])
-				break;
-		if(i<TOTAL_TEXT) {		/* Replacement text */
-			//lputc(7);
-			i=atcodes(str+l);
-			l+=i;
-			if(i)
-				continue; } }
-	outchar(str[l++]); }
-return(l);
-}
-
-/****************************************************************************/
-/* Outputs a NULL terminated string locally and remotely (if applicable)    */
-/* Does not expand ctrl-a characters (raw)                                  */
-/* Max length of str is 64 kbytes                                           */
-/****************************************************************************/
-int rputs(char *str)
-{
-    ulong l=0;
-
-while(str[l])
-    outchar(str[l++]);
-return(l);
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Performs printf() using bbs bputs function								*/
-/****************************************************************************/
-int bprintf(char *fmt, ...)
-{
-	va_list argptr;
-	char sbuf[1024];
-
-if(!strchr(fmt,'%'))
-	return(bputs(fmt));
-va_start(argptr,fmt);
-vsprintf(sbuf,fmt,argptr);
-va_end(argptr);
-return(bputs(sbuf));
-}
-
-/****************************************************************************/
-/* Performs printf() using bbs rputs function								*/
-/****************************************************************************/
-int rprintf(char *fmt, ...)
-{
-	va_list argptr;
-	char sbuf[1024];
-
-va_start(argptr,fmt);
-vsprintf(sbuf,fmt,argptr);
-va_end(argptr);
-return(rputs(sbuf));
-}
-
-/****************************************************************************/
-/* Outputs character locally and remotely (if applicable), preforming echo  */
-/* translations (X's and r0dent emulation) if applicable.					*/
-/****************************************************************************/
-void outchar(char ch)
-{
-	char lch;
-	int i;
-
-if(console&CON_ECHO_OFF)
-	return;
-if(ch==ESC)
-	outchar_esc=1;
-else if(outchar_esc==1) {
-	if(ch=='[')
-		outchar_esc++;
-	else
-		outchar_esc=0; }
-else
-	outchar_esc=0;
-if(useron.misc&NO_EXASCII && ch&0x80)
-	ch=sbtbl[(uchar)ch^0x80];  /* seven bit table */
-if(ch==FF && lncntr>1 && !tos) {
-	lncntr=0;
-	CRLF;
-	pause();
-	while(lncntr && online && !(sys_status&SS_ABORT))
-		pause(); }
-if(sys_status&SS_CAP	/* Writes to Capture File */
-	&& (sys_status&SS_ANSCAP || (ch!=ESC && !lclaes())))
-	fwrite(&ch,1,1,capfile);
-if(console&CON_L_ECHO) {
-	if(console&CON_L_ECHOX && (uchar)ch>=SP)
-		outcon('X');
-	else if(node_misc&NM_NOBEEP && ch==7);	 /* Do nothing if beep */
-	else if(ch==7) {
-			beep(2000,110);
-			nosound(); }
-	else outcon(ch); }
-if(online==ON_REMOTE && console&CON_R_ECHO) {
-	if(console&CON_R_ECHOX && (uchar)ch>=SP)
-		ch='X';
-	i=0;
-	while(outcom(ch)&TXBOF && i<1440) { /* 3 minute pause delay */
-
-        if(lkbrd(1)) {
-			lch=lkbrd(0);	/* ctrl-c */
-			if(lch==3) {
-				lputs("local abort (outchar)\r\n");
-				i=1440;
-				break; }
-			ungetkey(lch); }
-		if(!DCDHIGH)
-			break;
-		i++;
-		if(sys_status&SS_SYSPAGE)
-			beep(i,80);
-		else
-			mswait(80); }
-	if(i==1440) {							/* timeout - beep flush outbuf */
-		i=rioctl(TXBC);
-		lprintf("timeout(outchar) %04X %04X\r\n",i,rioctl(IOFO));
-		outcom(7);
-		lputc(7);
-		rioctl(IOCS|PAUSE); } }
-if(ch==LF) {
-	lncntr++;
-	lbuflen=0;
-	tos=0; }
-else if(ch==FF) {
-	lncntr=0;
-	lbuflen=0;
-	tos=1; }
-
-else {
-	if(!lbuflen)
-		latr=curatr;
-	if(lbuflen<LINE_BUFSIZE)
-		lbuf[lbuflen++]=ch; }
-
-if(lncntr==rows-1 && ((useron.misc&UPAUSE && !(sys_status&SS_PAUSEOFF))
-	|| sys_status&SS_PAUSEON)) {
-	lncntr=0;
-	pause(); }
-
-}
-
-
-/****************************************************************************/
-/* performs the correct attribute modifications for the Ctrl-A code			*/
-/****************************************************************************/
-void ctrl_a(char x)
-{
-	int i,j;
-	char tmp1[128],atr=curatr;
-
-if(x && (uchar)x<ESC) {    /* Ctrl-A through Ctrl-Z for users with MF only */
-	if(!(useron.flags1&FLAG(x+64)))
-		console^=(CON_ECHO_OFF);
-	return; }
-if((uchar)x>=0x7f) {
-	if(useron.misc&ANSI)
-		bprintf("\x1b[%uC",(uchar)x-0x7f);
-	else
-		for(i=0;i<(uchar)x-0x7f;i++)
-			outchar(SP);
-	return; }
-switch(toupper(x)) {
-	case '!':   /* level 10 or higher */
-		if(useron.level<10)
-			console^=CON_ECHO_OFF;
-		break;
-	case '@':   /* level 20 or higher */
-		if(useron.level<20)
-			console^=CON_ECHO_OFF;
-        break;
-	case '#':   /* level 30 or higher */
-		if(useron.level<30)
-			console^=CON_ECHO_OFF;
-        break;
-	case '$':   /* level 40 or higher */
-		if(useron.level<40)
-			console^=CON_ECHO_OFF;
-        break;
-	case '%':   /* level 50 or higher */
-		if(useron.level<50)
-			console^=CON_ECHO_OFF;
-        break;
-	case '^':   /* level 60 or higher */
-		if(useron.level<60)
-			console^=CON_ECHO_OFF;
-        break;
-	case '&':   /* level 70 or higher */
-		if(useron.level<70)
-			console^=CON_ECHO_OFF;
-        break;
-	case '*':   /* level 80 or higher */
-		if(useron.level<80)
-			console^=CON_ECHO_OFF;
-        break;
-	case '(':   /* level 90 or higher */
-		if(useron.level<90)
-			console^=CON_ECHO_OFF;
-        break;
-	case ')':   /* turn echo back on */
-		console&=~CON_ECHO_OFF;
-		break;
-	case '-':								/* turn off all attributes if */
-		if(atr&(HIGH|BLINK|(LIGHTGRAY<<4)))	/* high intensity, blink or */
-			attr(LIGHTGRAY);				/* background bits are set */
-		break;
-	case '_':								/* turn off all attributes if */
-		if(atr&(BLINK|(LIGHTGRAY<<4)))		/* blink or background is set */
-			attr(LIGHTGRAY);
-		break;
-	case 'P':	/* Pause */
-		pause();
-		break;
-	case 'Q':   /* Pause reset */
-		lncntr=0;
-		break;
-	case 'T':   /* Time */
-		now=time(NULL);
-		unixtodos(now,&date,&curtime);
-		bprintf("%02d:%02d %s"
-			,curtime.ti_hour==0 ? 12
-			: curtime.ti_hour>12 ? curtime.ti_hour-12
-			: curtime.ti_hour, curtime.ti_min, curtime.ti_hour>11 ? "pm":"am");
-		break;
-	case 'D':   /* Date */
-		now=time(NULL);
-		bputs(unixtodstr(now,tmp1));
-		break;
-	case ',':   /* Delay 1/10 sec */
-		mswait(100);
-		break;
-	case ';':   /* Delay 1/2 sec */
-		mswait(500);
-		break;
-	case '.':   /* Delay 2 secs */
-		mswait(2000);
-		break;
-	case 'S':   /* Synchronize */
-		ASYNC;
-		break;
-	case 'L':	/* CLS (form feed) */
-		CLS;
-		break;
-	case '>':   /* CLREOL */
-		if(useron.misc&ANSI)
-			bputs("\x1b[K");
-		else {
-			i=j=lclwx();
-			while(i++<79)
-				outchar(SP);
-			while(j++<79)
-				outchar(BS); }
-		break;
-	case '<':   /* Non-destructive backspace */
-		outchar(BS);
-		break;
-	case '[':   /* Carriage return */
-		outchar(CR);
-		break;
-	case ']':   /* Line feed */
-		outchar(LF);
-		break;
-	case 'A':   /* Ctrl-A */
-		outchar(1);
-		break;
-	case 'H': 	/* High intensity */
-		atr|=HIGH;
-		attr(atr);
-		break;
-	case 'I':	/* Blink */
-		atr|=BLINK;
-		attr(atr);
-		break;
-	case 'N': 	/* Normal */
-		attr(LIGHTGRAY);
-		break;
-	case 'R':
-		atr=(atr&0xf8)|RED;
-		attr(atr);
-		break;
-	case 'G':
-		atr=(atr&0xf8)|GREEN;
-		attr(atr);
-		break;
-	case 'B':
-		atr=(atr&0xf8)|BLUE;
-		attr(atr);
-		break;
-    case 'W':	/* White */
-		atr=(atr&0xf8)|LIGHTGRAY;
-		attr(atr);
-		break;
-    case 'C':
-		atr=(atr&0xf8)|CYAN;
-		attr(atr);
-		break;
-	case 'M':
-		atr=(atr&0xf8)|MAGENTA;
-		attr(atr);
-		break;
-	case 'Y':   /* Yellow */
-		atr=(atr&0xf8)|BROWN;
-		attr(atr);
-		break;
-    case 'K':	/* Black */
-		atr=(atr&0xf8)|BLACK;
-		attr(atr);
-		break;
-    case '0':	/* Black Background */
-		atr=(atr&0x8f)|(BLACK<<4);
-		attr(atr);
-		break;
-	case '1':	/* Red Background */
-		atr=(atr&0x8f)|(RED<<4);
-		attr(atr);
-		break;
-	case '2':	/* Green Background */
-		atr=(atr&0x8f)|(GREEN<<4);
-		attr(atr);
-		break;
-	case '3':	/* Yellow Background */
-		atr=(atr&0x8f)|(BROWN<<4);
-		attr(atr);
-		break;
-	case '4':	/* Blue Background */
-		atr=(atr&0x8f)|(BLUE<<4);
-		attr(atr);
-		break;
-	case '5':	/* Magenta Background */
-		atr=(atr&0x8f)|(MAGENTA<<4);
-		attr(atr);
-		break;
-	case '6':	/* Cyan Background */
-		atr=(atr&0x8f)|(CYAN<<4);
-		attr(atr);
-		break;
-	case '7':	/* White Background */
-		atr=(atr&0x8f)|(LIGHTGRAY<<4);
-		attr(atr);
-		break; }
-}
-
-/***************************************************************************/
-/* Changes local and remote text attributes accounting for monochrome      */
-/***************************************************************************/
-/****************************************************************************/
-/* Sends ansi codes to change remote ansi terminal's colors                 */
-/* Only sends necessary codes - tracks remote terminal's current attributes */
-/* through the 'curatr' variable                                            */
-/****************************************************************************/
-void attr(int atr)
-{
-
-if(!(useron.misc&ANSI))
-    return;
-if(!(useron.misc&COLOR)) {  /* eliminate colors if user doesn't have them */
-    if(atr&LIGHTGRAY)       /* if any foreground bits set, set all */
-        atr|=LIGHTGRAY;
-    if(atr&(LIGHTGRAY<<4))  /* if any background bits set, set all */
-        atr|=(LIGHTGRAY<<4);
-    if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4))
-        atr&=~LIGHTGRAY;    /* if background is solid, foreground is black */
-    if(!atr)
-        atr|=LIGHTGRAY; }   /* don't allow black on black */
-if(curatr==atr) /* text hasn't changed. don't send codes */
-    return;
-
-if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
-    || atr==LIGHTGRAY) {
-    bputs("\x1b[0m");
-    curatr=LIGHTGRAY; }
-
-if(atr==LIGHTGRAY)                  /* no attributes */
-    return;
-
-if(atr&BLINK) {                     /* special attributes */
-    if(!(curatr&BLINK))
-        bputs(ansi(BLINK)); }
-if(atr&HIGH) {
-    if(!(curatr&HIGH))
-        bputs(ansi(HIGH)); }
-
-if((atr&0x7)==BLACK) {              /* foreground colors */
-    if((curatr&0x7)!=BLACK)
-        bputs(ansi(BLACK)); }
-else if((atr&0x7)==RED) {
-    if((curatr&0x7)!=RED)
-        bputs(ansi(RED)); }
-else if((atr&0x7)==GREEN) {
-    if((curatr&0x7)!=GREEN)
-        bputs(ansi(GREEN)); }
-else if((atr&0x7)==BROWN) {
-    if((curatr&0x7)!=BROWN)
-        bputs(ansi(BROWN)); }
-else if((atr&0x7)==BLUE) {
-    if((curatr&0x7)!=BLUE)
-        bputs(ansi(BLUE)); }
-else if((atr&0x7)==MAGENTA) {
-    if((curatr&0x7)!=MAGENTA)
-        bputs(ansi(MAGENTA)); }
-else if((atr&0x7)==CYAN) {
-    if((curatr&0x7)!=CYAN)
-        bputs(ansi(CYAN)); }
-else if((atr&0x7)==LIGHTGRAY) {
-    if((curatr&0x7)!=LIGHTGRAY)
-        bputs(ansi(LIGHTGRAY)); }
-
-if((atr&0x70)==(BLACK<<4)) {        /* background colors */
-    if((curatr&0x70)!=(BLACK<<4))
-        bputs("\x1b[40m"); }
-else if((atr&0x70)==(RED<<4)) {
-    if((curatr&0x70)!=(RED<<4))
-        bputs(ansi(RED<<4)); }
-else if((atr&0x70)==(GREEN<<4)) {
-    if((curatr&0x70)!=(GREEN<<4))
-        bputs(ansi(GREEN<<4)); }
-else if((atr&0x70)==(BROWN<<4)) {
-    if((curatr&0x70)!=(BROWN<<4))
-        bputs(ansi(BROWN<<4)); }
-else if((atr&0x70)==(BLUE<<4)) {
-    if((curatr&0x70)!=(BLUE<<4))
-        bputs(ansi(BLUE<<4)); }
-else if((atr&0x70)==(MAGENTA<<4)) {
-    if((curatr&0x70)!=(MAGENTA<<4))
-        bputs(ansi(MAGENTA<<4)); }
-else if((atr&0x70)==(CYAN<<4)) {
-    if((curatr&0x70)!=(CYAN<<4))
-        bputs(ansi(CYAN<<4)); }
-else if((atr&0x70)==(LIGHTGRAY<<4)) {
-    if((curatr&0x70)!=(LIGHTGRAY<<4))
-        bputs(ansi(LIGHTGRAY<<4)); }
-
-curatr=atr;
-}
-
-/****************************************************************************/
-/* Returns the ANSI code to obtain the value of atr. Mixed attributes		*/
-/* high intensity colors, or background/forground cobinations don't work.   */
-/* A call to attr is more appropriate, being it is intelligent				*/
-/****************************************************************************/
-char *ansi(char atr)
-{
-
-switch(atr) {
-	case (char)BLINK:
-		return("\x1b[5m");
-	case HIGH:
-		return("\x1b[1m");
-	case BLACK:
-		return("\x1b[30m");
-	case RED:
-		return("\x1b[31m");
-	case GREEN:
-		return("\x1b[32m");
-	case BROWN:
-		return("\x1b[33m");
-	case BLUE:
-		return("\x1b[34m");
-	case MAGENTA:
-		return("\x1b[35m");
-	case CYAN:
-		return("\x1b[36m");
-	case LIGHTGRAY:
-		return("\x1b[37m");
-	case (RED<<4):
-		return("\x1b[41m");
-	case (GREEN<<4):
-		return("\x1b[42m");
-	case (BROWN<<4):
-		return("\x1b[43m");
-	case (BLUE<<4):
-		return("\x1b[44m");
-	case (MAGENTA<<4):
-		return("\x1b[45m");
-	case (CYAN<<4):
-		return("\x1b[46m");
-	case (LIGHTGRAY<<4):
-		return("\x1b[47m"); }
-
-return("-Invalid use of ansi()-");
-}
-
-
-/****************************************************************************/
-/* Checks to see if user has hit Pause or Abort. Returns 1 if user aborted. */
-/* If the user hit Pause, waits for a key to be hit.                        */
-/* Emulates remote XON/XOFF flow control on local console                   */
-/* Preserves SS_ABORT flag state, if already set.                           */
-/* Called from various listing procedures that wish to check for abort      */
-/****************************************************************************/
-char msgabort()
-{
-    char ch;
-
-if(sys_status&SS_SYSPAGE)
-	beep(random(800),1);
-if(lkbrd(1)) {
-    ch=inkey(0);
-    if(sys_status&SS_ABORT) {                   /* ^c */
-        keybufbot=keybuftop=0;
-        return(1); }
-    else if(ch==17 && online==ON_REMOTE)    /* ^q */
-        rioctl(IOCS|PAUSE);
-    else if(ch==19)                         /* ^s */
-        while(online) {
-            if((ch=inkey(0))!=0) {
-                if(ch==17)  /* ^q */
-                    return(0);
-                ungetkey(ch); }
-             if(sys_status&SS_ABORT) { /* ^c */
-                keybufbot=keybuftop=0;
-                return(1); }
-             checkline(); }
-    else if(ch)
-        ungetkey(ch); }
-checkline();
-if(sys_status&SS_ABORT)
-    return(1);
-if(online==ON_REMOTE && rioctl(IOSTATE)&ABORT) {
-    rioctl(IOCS|ABORT);
-    sys_status|=SS_ABORT;
-    return(1); }
-if(!online)
-    return(1);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Takes the value 'sec' and makes a string the format HH:MM:SS             */
-/****************************************************************************/
-char *sectostr(uint sec,char *str)
-{
-    uchar hour,min,sec2;
-
-hour=(sec/60)/60;
-min=(sec/60)-(hour*60);
-sec2=sec-((min+(hour*60))*60);
-sprintf(str,"%2.2d:%2.2d:%2.2d",hour,min,sec2);
-return(str);
-}
-
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()                                        */
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-    static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-gm=localtime(intime);
-if(gm==NULL) {
-	strcpy(str,"Invalid Time");
-	return(str); }
-if(sys_misc&SM_MILITARY) {
-    sprintf(str,"%s %s %02d %4d %02d:%02d:%02d"
-        ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-        ,gm->tm_hour,gm->tm_min,gm->tm_sec);
-    return(str); }
-if(gm->tm_hour>=12) {
-    if(gm->tm_hour==12)
-        hour=12;
-    else
-        hour=gm->tm_hour-12;
-    strcpy(mer,"pm"); }
-else {
-    if(gm->tm_hour==0)
-        hour=12;
-    else
-        hour=gm->tm_hour;
-    strcpy(mer,"am"); }
-sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-    ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-    ,hour,gm->tm_min,mer);
-return(str);
-}
-
diff --git a/src/sbbs2/data.c b/src/sbbs2/data.c
deleted file mode 100644
index 537358a8bf04d98cb76284c4e155e054f39de433..0000000000000000000000000000000000000000
--- a/src/sbbs2/data.c
+++ /dev/null
@@ -1,177 +0,0 @@
-#line 1 "DATA.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/**************************************************************/
-/* Functions that store and retrieve data from disk or memory */
-/**************************************************************/
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Looks for a perfect match amoung all usernames (not deleted users)		*/
-/* Returns the number of the perfect matched username or 0 if no match		*/
-/* Called from functions waitforcall and newuser							*/
-/****************************************************************************/
-uint matchuser(char *str)
-{
-	int file;
-	char str2[256],c;
-	ulong l,length;
-	FILE *stream;
-
-sprintf(str2,"%sUSER\\NAME.DAT",data_dir);
-if((stream=fnopen(&file,str2,O_RDONLY))==NULL)
-	return(0);
-length=filelength(file);
-for(l=0;l<length;l+=LEN_ALIAS+2) {
-	fread(str2,LEN_ALIAS+2,1,stream);
-	for(c=0;c<LEN_ALIAS;c++)
-		if(str2[c]==ETX) break;
-	str2[c]=0;
-	if(!stricmp(str,str2)) {
-		fclose(stream);
-		return((l/(LEN_ALIAS+2))+1); } }
-fclose(stream);
-return(0);
-}
-
-/****************************************************************************/
-/* Looks for close or perfect matches between str and valid usernames and  	*/
-/* numbers and prompts user for near perfect matches in names.				*/
-/* Returns the number of the matched user or 0 if unsuccessful				*/
-/* Called from functions main_sec, useredit and readmailw					*/
-/****************************************************************************/
-uint finduser(char *instr)
-{
-	int file,i;
-	char str[128],str2[256],str3[256],ynq[25],c,pass=1;
-	ulong l,length;
-	FILE *stream;
-
-i=atoi(instr);
-if(i>0) {
-	username(i,str2);
-	if(str2[0] && strcmp(str2,"DELETED USER"))
-		return(i); }
-strcpy(str,instr);
-strupr(str);
-sprintf(str3,"%sUSER\\NAME.DAT",data_dir);
-if(flength(str3)<1L)
-	return(0);
-if((stream=fnopen(&file,str3,O_RDONLY))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str3,O_RDONLY);
-	return(0); }
-sprintf(ynq,"%.2s",text[YN]);
-ynq[2]='Q';
-ynq[3]=0;
-length=filelength(file);
-while(pass<3) {
-	fseek(stream,0L,SEEK_SET);	/* seek to beginning for each pass */
-	for(l=0;l<length;l+=LEN_ALIAS+2) {
-		if(!online) break;
-		fread(str2,LEN_ALIAS+2,1,stream);
-		for(c=0;c<LEN_ALIAS;c++)
-			if(str2[c]==ETX) break;
-		str2[c]=0;
-		if(!c)		/* deleted user */
-			continue;
-		strcpy(str3,str2);
-		strupr(str2);
-		if(pass==1 && !strcmp(str,str2)) {
-			fclose(stream);
-			return((l/(LEN_ALIAS+2))+1); }
-		if(pass==2 && strstr(str2,str)) {
-			bprintf(text[DoYouMeanThisUserQ],str3
-				,(uint)(l/(LEN_ALIAS+2))+1);
-			c=getkeys(ynq,0);
-			if(sys_status&SS_ABORT) {
-				fclose(stream);
-				return(0); }
-			if(c==text[YN][0]) {
-				fclose(stream);
-				return((l/(LEN_ALIAS+2))+1); }
-			if(c=='Q') {
-				fclose(stream);
-				return(0); } } }
-	pass++; }
-bputs(text[UnknownUser]);
-fclose(stream);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the number of files in the directory 'dirnum'                    */
-/****************************************************************************/
-int getfiles(uint dirnum)
-{
-	char str[256];
-	long l;
-
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-l=flength(str);
-if(l>0L)
-	return(l/F_IXBSIZE);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the number of user transfers in XFER.IXT for either a dest user  */
-/* source user, or filename.												*/
-/****************************************************************************/
-int getuserxfers(int fromuser, int destuser, char *fname)
-{
-	char str[256];
-	int file,found=0;
-	FILE *stream;
-
-sprintf(str,"%sXFER.IXT",data_dir);
-if(!fexist(str))
-	return(0);
-if(!flength(str)) {
-	remove(str);
-	return(0); }
-if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return(0); }
-while(!ferror(stream)) {
-	if(!fgets(str,81,stream))
-		break;
-	str[22]=0;
-	if(fname!=NULL && fname[0] && !strncmp(str+5,fname,12))
-			found++;
-	else if(fromuser && atoi(str+18)==fromuser)
-			found++;
-	else if(destuser && atoi(str)==destuser)
-			found++; }
-fclose(stream);
-return(found);
-}
-
-/****************************************************************************/
-/* Returns the number of the last user in USER.DAT (deleted ones too)		*/
-/* Called from function useredit											*/
-/****************************************************************************/
-uint lastuser()
-{
-	char str[256];
-	long length;
-
-sprintf(str,"%sUSER\\USER.DAT",data_dir);
-if((length=flength(str))>0)
-	return((uint)(length/U_LEN));
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the number of files in the database for 'dir'					*/
-/****************************************************************************/
-uint gettotalfiles(uint dirnum)
-{
-	char str[81];
-
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-return((uint)(flength(str)/F_IXBSIZE));
-}
-
-
diff --git a/src/sbbs2/data_ovl.c b/src/sbbs2/data_ovl.c
deleted file mode 100644
index 95f81f1d470aa9d43ba939119fd84f0e9b725c65..0000000000000000000000000000000000000000
--- a/src/sbbs2/data_ovl.c
+++ /dev/null
@@ -1,439 +0,0 @@
-#line 1 "DATA_OVL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Writes into user.number's slot in USER.DAT data in structure 'user'      */
-/* Called from functions newuser, useredit and main                         */
-/****************************************************************************/
-void putuserdat(user_t user)
-{
-    int i,file;
-    char userdat[U_LEN+1],str[U_LEN+1];
-    node_t node;
-
-if(!user.number) {
-    errormsg(WHERE,ERR_CHK,"user number",0);
-    return; }
-memset(userdat,ETX,U_LEN);
-putrec(userdat,U_ALIAS,LEN_ALIAS+5,user.alias);
-putrec(userdat,U_NAME,LEN_NAME,user.name);
-putrec(userdat,U_HANDLE,LEN_HANDLE,user.handle);
-putrec(userdat,U_HANDLE+LEN_HANDLE,2,crlf);
-
-putrec(userdat,U_NOTE,LEN_NOTE,user.note);
-putrec(userdat,U_COMP,LEN_COMP,user.comp);
-putrec(userdat,U_COMP+LEN_COMP,2,crlf);
-
-putrec(userdat,U_COMMENT,LEN_COMMENT,user.comment);
-putrec(userdat,U_COMMENT+LEN_COMMENT,2,crlf);
-
-putrec(userdat,U_NETMAIL,LEN_NETMAIL,user.netmail);
-putrec(userdat,U_NETMAIL+LEN_NETMAIL,2,crlf);
-
-putrec(userdat,U_ADDRESS,LEN_ADDRESS,user.address);
-putrec(userdat,U_LOCATION,LEN_LOCATION,user.location);
-putrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user.zipcode);
-putrec(userdat,U_ZIPCODE+LEN_ZIPCODE,2,crlf);
-
-putrec(userdat,U_PASS,LEN_PASS,user.pass);
-putrec(userdat,U_PHONE,LEN_PHONE,user.phone);
-putrec(userdat,U_BIRTH,LEN_BIRTH,user.birth);
-putrec(userdat,U_MODEM,LEN_MODEM,user.modem);
-putrec(userdat,U_LASTON,8,ultoa(user.laston,str,16));
-putrec(userdat,U_FIRSTON,8,ultoa(user.firston,str,16));
-putrec(userdat,U_EXPIRE,8,ultoa(user.expire,str,16));
-putrec(userdat,U_PWMOD,8,ultoa(user.pwmod,str,16));
-putrec(userdat,U_PWMOD+8,2,crlf);
-
-putrec(userdat,U_LOGONS,5,itoa(user.logons,str,10));
-putrec(userdat,U_LTODAY,5,itoa(user.ltoday,str,10));
-putrec(userdat,U_TIMEON,5,itoa(user.timeon,str,10));
-putrec(userdat,U_TEXTRA,5,itoa(user.textra,str,10));
-putrec(userdat,U_TTODAY,5,itoa(user.ttoday,str,10));
-putrec(userdat,U_TLAST,5,itoa(user.tlast,str,10));
-putrec(userdat,U_POSTS,5,itoa(user.posts,str,10));
-putrec(userdat,U_EMAILS,5,itoa(user.emails,str,10));
-putrec(userdat,U_FBACKS,5,itoa(user.fbacks,str,10));
-putrec(userdat,U_ETODAY,5,itoa(user.etoday,str,10));
-putrec(userdat,U_PTODAY,5,itoa(user.ptoday,str,10));
-putrec(userdat,U_PTODAY+5,2,crlf);
-
-putrec(userdat,U_ULB,10,ultoa(user.ulb,str,10));
-putrec(userdat,U_ULS,5,itoa(user.uls,str,10));
-putrec(userdat,U_DLB,10,ultoa(user.dlb,str,10));
-putrec(userdat,U_DLS,5,itoa(user.dls,str,10));
-putrec(userdat,U_CDT,10,ultoa(user.cdt,str,10));
-putrec(userdat,U_MIN,10,ultoa(user.min,str,10));
-putrec(userdat,U_MIN+10,2,crlf);
-
-putrec(userdat,U_LEVEL,2,itoa(user.level,str,10));
-putrec(userdat,U_FLAGS1,8,ultoa(user.flags1,str,16));
-putrec(userdat,U_TL,2,nulstr);	/* unused */
-putrec(userdat,U_FLAGS2,8,ultoa(user.flags2,str,16));
-putrec(userdat,U_EXEMPT,8,ultoa(user.exempt,str,16));
-putrec(userdat,U_REST,8,ultoa(user.rest,str,16));
-putrec(userdat,U_REST+8,2,crlf);
-
-putrec(userdat,U_ROWS,2,itoa(user.rows,str,10));
-userdat[U_SEX]=user.sex;
-userdat[U_PROT]=user.prot;
-putrec(userdat,U_MISC,8,ultoa(user.misc,str,16));
-putrec(userdat,U_LEECH,2,itoa(user.leech,str,16));
-
-putrec(userdat,U_CURSUB,8,user.cursub);
-putrec(userdat,U_CURDIR,8,user.curdir);
-
-// putrec(userdat,U_CMDSET,2,itoa(user.cmdset,str,16)); /* Unused */
-putrec(userdat,U_CMDSET+2,2,crlf);
-
-putrec(userdat,U_XFER_CMD+LEN_XFER_CMD,2,crlf);
-
-putrec(userdat,U_MAIL_CMD+LEN_MAIL_CMD,2,crlf);
-
-putrec(userdat,U_FREECDT,10,ultoa(user.freecdt,str,10));
-
-putrec(userdat,U_FLAGS3,8,ultoa(user.flags3,str,16));
-putrec(userdat,U_FLAGS4,8,ultoa(user.flags4,str,16));
-
-if(user.xedit)
-	putrec(userdat,U_XEDIT,8,xedit[user.xedit-1]->code);
-else
-	putrec(userdat,U_XEDIT,8,nulstr);
-
-putrec(userdat,U_SHELL,8,shell[user.shell]->code);
-
-putrec(userdat,U_QWK,8,ultoa(user.qwk,str,16));
-putrec(userdat,U_TMPEXT,3,user.tmpext);
-putrec(userdat,U_CHAT,8,ultoa(user.chat,str,16));
-putrec(userdat,U_NS_TIME,8,ultoa(user.ns_time,str,16));
-
-putrec(userdat,U_UNUSED,29,crlf);
-putrec(userdat,U_UNUSED+29,2,crlf);
-
-sprintf(str,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_DENYNONE))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_DENYNONE);
-	return; }
-
-/***		This shouldn't be necessary
-if(filelength(file)<(long)((long)user.number*U_LEN))
-    lseek(file,0L,SEEK_END);
-else
-***/
-
-lseek(file,(long)((long)((long)user.number-1)*U_LEN),SEEK_SET);
-
-i=0;
-while(i<LOOP_NODEDAB
-	&& lock(file,(long)((long)(user.number-1)*U_LEN),U_LEN)==-1) {
-	if(i>10)
-		mswait(55);
-	i++; }
-
-if(i>=LOOP_NODEDAB) {
-	close(file);
-	errormsg(WHERE,ERR_LOCK,"USER.DAT",user.number);
-    return; }
-
-if(write(file,userdat,U_LEN)!=U_LEN) {
-	unlock(file,(long)((long)(user.number-1)*U_LEN),U_LEN);
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,U_LEN);
-    return; }
-unlock(file,(long)((long)(user.number-1)*U_LEN),U_LEN);
-close(file);
-for(i=1;i<=sys_nodes;i++) { /* instant user data update */
-    if(i==node_num)
-        continue;
-    getnodedat(i,&node,0);
-    if(node.useron==user.number && (node.status==NODE_INUSE
-        || node.status==NODE_QUIET)) {
-        getnodedat(i,&node,1);
-        node.misc|=NODE_UDAT;
-        putnodedat(i,node);
-        break; } }
-}
-
-
-/****************************************************************************/
-/* Puts 'name' into slot 'number' in USER\\NAME.DAT							*/
-/****************************************************************************/
-void putusername(int number, char *name)
-{
-	char str[256];
-	int file;
-	long length,l;
-
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_CREAT);
-	return; }
-length=filelength(file);
-if(length && length%(LEN_ALIAS+2)) {
-	close(file);
-	errormsg(WHERE,ERR_LEN,str,length);
-	return; }
-if(length<(((long)number-1)*(LEN_ALIAS+2))) {
-	sprintf(str,"%*s",LEN_ALIAS,nulstr);
-	strset(str,ETX);
-	strcat(str,crlf);
-	lseek(file,0L,SEEK_END);
-	while(filelength(file)<((long)number*(LEN_ALIAS+2)))
-		write(file,str,(LEN_ALIAS+2)); }
-lseek(file,(long)(((long)number-1)*(LEN_ALIAS+2)),SEEK_SET);
-putrec(str,0,LEN_ALIAS,name);
-putrec(str,LEN_ALIAS,2,crlf);
-write(file,str,LEN_ALIAS+2);
-close(file);
-}
-
-/****************************************************************************/
-/* Fills the 'ptr' element of the each element of the sub[] array of sub_t  */
-/* and the sub_misc and sub_ptr global variables                            */
-/* Called from function main                                                */
-/****************************************************************************/
-void getmsgptrs()
-{
-	char	str[256];
-	ushort	ch;
-	uint	i;
-	int 	file;
-	long	length;
-	FILE	*stream;
-
-now=time(NULL);
-if(!useron.number)
-    return;
-bputs(text[LoadingMsgPtrs]);
-sprintf(str,"%sUSER\\PTRS\\%4.4u.IXB",data_dir,useron.number);
-if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-	for(i=0;i<total_subs;i++) {
-		sub_ptr[i]=sub[i]->ptr=sub_last[i]=sub[i]->last=0;
-		if(sub[i]->misc&SUB_NSDEF)
-			sub[i]->misc|=SUB_NSCAN;
-		else
-			sub[i]->misc&=~SUB_NSCAN;
-		if(sub[i]->misc&SUB_SSDEF)
-			sub[i]->misc|=SUB_SSCAN;
-		else
-			sub[i]->misc&=~SUB_SSCAN;
-		sub_misc[i]=sub[i]->misc; }
-	bputs(text[LoadedMsgPtrs]);
-	return; }
-length=filelength(file);
-for(i=0;i<total_subs;i++) {
-	if(length<(sub[i]->ptridx+1)*10L) {
-		sub[i]->ptr=sub[i]->last=0L;
-		if(sub[i]->misc&SUB_NSDEF)
-			sub[i]->misc|=SUB_NSCAN;
-		else
-			sub[i]->misc&=~SUB_NSCAN;
-		if(sub[i]->misc&SUB_SSDEF)
-			sub[i]->misc|=SUB_SSCAN;
-		else
-			sub[i]->misc&=~SUB_SSCAN; }
-	else {
-		fseek(stream,(long)sub[i]->ptridx*10L,SEEK_SET);
-		fread(&sub[i]->ptr,4,1,stream);
-		fread(&sub[i]->last,4,1,stream);
-		fread(&ch,2,1,stream);
-		if(ch&5)	/* Either bit 0 or 2 */
-			sub[i]->misc|=SUB_NSCAN;
-		else
-			sub[i]->misc&=~SUB_NSCAN;
-		if(ch&2)
-			sub[i]->misc|=SUB_SSCAN;
-		else
-			sub[i]->misc&=~SUB_SSCAN;
-		if(ch&0x100)
-			sub[i]->misc|=SUB_YSCAN;
-		else
-			sub[i]->misc&=~SUB_YSCAN; }
-	sub_ptr[i]=sub[i]->ptr;
-	sub_last[i]=sub[i]->last;
-    sub_misc[i]=sub[i]->misc; }
-fclose(stream);
-bputs(text[LoadedMsgPtrs]);
-}
-
-/****************************************************************************/
-/* Writes to DATA\USER\PTRS\xxxx.DAB the msgptr array for the current user	*/
-/* Called from functions main and newuser                                   */
-/****************************************************************************/
-void putmsgptrs()
-{
-	char	str[256];
-	ushort	idx,ch;
-	uint	i,j;
-	int 	file;
-	ulong	l=0L,length;
-
-if(!useron.number)
-    return;
-sprintf(str,"%sUSER\\PTRS\\%4.4u.IXB",data_dir,useron.number);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-	return; }
-length=filelength(file);
-for(i=0;i<total_subs;i++) {
-	if(sub[i]->ptr==sub_ptr[i] && sub[i]->last==sub_last[i]
-		&& length>=((long)(sub[i]->ptridx+1)*10)
-		&& ((sub[i]->misc&(SUB_NSCAN|SUB_SSCAN|SUB_YSCAN))
-			==(sub_misc[i]&(SUB_NSCAN|SUB_SSCAN|SUB_YSCAN))))
-        continue;
-	while(filelength(file)<(long)(sub[i]->ptridx)*10) {
-        lseek(file,0L,SEEK_END);
-		idx=tell(file)/10;
-		for(j=0;j<total_subs;j++)
-			if(sub[j]->ptridx==idx)
-				break;
-        write(file,&l,4);
-        write(file,&l,4);
-		ch=0xff;					/* default to scan ON for new sub */
-		if(j<total_subs) {
-			if(!(sub[j]->misc&SUB_NSCAN))
-				ch&=~5;
-			if(!(sub[j]->misc&SUB_SSCAN))
-				ch&=~2;
-			if(sub[j]->misc&SUB_YSCAN)
-				ch|=0x100; }
-		write(file,&ch,2); }
-	lseek(file,(long)((long)(sub[i]->ptridx)*10),SEEK_SET);
-    write(file,&(sub[i]->ptr),4);
-	write(file,&(sub[i]->last),4);
-	ch=0xff;
-	if(!(sub[i]->misc&SUB_NSCAN))
-		ch&=~5;
-	if(!(sub[i]->misc&SUB_SSCAN))
-		ch&=~2;
-	if(sub[i]->misc&SUB_YSCAN)
-		ch|=0x100;
-	write(file,&ch,2); }
-close(file);
-if(!flength(str))				/* Don't leave 0 byte files */
-	remove(str);
-}
-
-/****************************************************************************/
-/* Checks for a duplicate user filed starting at user record offset         */
-/* 'offset', reading in 'datlen' chars, comparing to 'str' for each user    */
-/* except 'usernumber' if it is non-zero. Comparison is NOT case sensitive. */
-/* del is 1 if the search is to included deleted/inactive users 0 otherwise */
-/* Returns the usernumber of the dupe if found, 0 if not                    */
-/****************************************************************************/
-uint userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
-    , char del)
-{
-    char str[256];
-    int i,file;
-    long l,length;
-
-truncsp(dat);
-sprintf(str,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1)
-    return(0);
-length=filelength(file);
-bputs(text[SearchingForDupes]);
-for(l=0;l<length && online;l+=U_LEN) {
-	checkline();
-    if(usernumber && l/U_LEN==usernumber-1)
-        continue;
-    lseek(file,l+offset,SEEK_SET);
-	i=0;
-	while(i<LOOP_NODEDAB && lock(file,l,U_LEN)==-1) {
-		if(i>10)
-			mswait(55);
-		i++; }
-
-	if(i>=LOOP_NODEDAB) {
-		close(file);
-		errormsg(WHERE,ERR_LOCK,"USER.DAT",l);
-		return(0); }
-
-    read(file,str,datlen);
-    for(i=0;i<datlen;i++)
-        if(str[i]==ETX) break;
-    str[i]=0;
-    truncsp(str);
-    if(!stricmp(str,dat)) {
-        if(!del) {      /* Don't include deleted users in search */
-            lseek(file,l+U_MISC,SEEK_SET);
-            read(file,str,8);
-            getrec(str,0,8,str);
-			if(ahtoul(str)&(DELETED|INACTIVE)) {
-				unlock(file,l,U_LEN);
-				continue; } }
-		unlock(file,l,U_LEN);
-        close(file);
-        bputs(text[SearchedForDupes]);
-		return((l/U_LEN)+1); }
-	else
-		unlock(file,l,U_LEN); }
-close(file);
-bputs(text[SearchedForDupes]);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Removes any files in the user transfer index (XFER.IXT) that match the   */
-/* specifications of dest, or source user, or filename or any combination.  */
-/****************************************************************************/
-void rmuserxfers(int fromuser, int destuser, char *fname)
-{
-    char str[256],*ixtbuf;
-    int file;
-    long l,length;
-
-sprintf(str,"%sXFER.IXT",data_dir);
-if(!fexist(str))
-    return;
-if(!flength(str)) {
-    remove(str);
-    return; }
-if((file=nopen(str,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    return; }
-length=filelength(file);
-if((ixtbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length);
-    return; }
-if(read(file,ixtbuf,length)!=length) {
-    close(file);
-	FREE(ixtbuf);
-    errormsg(WHERE,ERR_READ,str,length);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-	FREE(ixtbuf);
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
-    return; }
-for(l=0;l<length;l+=24) {
-    if(fname!=NULL && fname[0]) {               /* fname specified */
-        if(!strncmp(ixtbuf+l+5,fname,12)) {     /* this is the file */
-            if(destuser && fromuser) {          /* both dest and from user */
-                if(atoi(ixtbuf+l)==destuser && atoi(ixtbuf+l+18)==fromuser)
-                    continue; }                 /* both match */
-            else if(fromuser) {                 /* from user */
-                if(atoi(ixtbuf+l+18)==fromuser) /* matches */
-                    continue; }
-            else if(destuser) {                 /* dest user */
-                if(atoi(ixtbuf+l)==destuser)    /* matches */
-                    continue; }
-            else continue; } }                  /* no users, so match */
-    else if(destuser && fromuser) {
-        if(atoi(ixtbuf+l+18)==fromuser && atoi(ixtbuf+l)==destuser)
-            continue; }
-    else if(destuser && atoi(ixtbuf+l)==destuser)
-        continue;
-    else if(fromuser && atoi(ixtbuf+l+18)==fromuser)
-        continue;
-    write(file,ixtbuf+l,24); }
-close(file);
-FREE(ixtbuf);
-}
-
diff --git a/src/sbbs2/dcdwatch/dcdwatch.c b/src/sbbs2/dcdwatch/dcdwatch.c
deleted file mode 100644
index 6ee6a3fa42000d720896e4f9168af1644cb3d412..0000000000000000000000000000000000000000
--- a/src/sbbs2/dcdwatch/dcdwatch.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* DCDWATCH.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Program to execute another program, but terminate if carrier detect is	*/
-/* lost */
-
-/* Compile small memory model */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <process.h>
-#include <dos.h>
-#include <io.h>
-#include <alloc.h>
-
-extern unsigned _heaplen=2048;
-
-#define uint unsigned int
-
-#pragma warn -par
-
-char hungup=0;
-uint far *msr;
-
-void interrupt (*old_int21)(void);
-
-struct	REGPACK r;
-
-void interrupt new_int21(uint bp, uint di, uint si, uint ds, uint es,
-	uint dx, uint cx, uint bx, uint ax, uint ip, uint cs, uint flags)
-{
-
-r.r_ax=ax;
-r.r_bx=bx;
-r.r_cx=cx;
-r.r_dx=dx;
-r.r_bp=bp;
-r.r_si=si;
-r.r_di=di;
-r.r_flags=flags;
-r.r_ds=ds;
-r.r_es=es;
-
-intr(0xaa,&r);
-
-ax=r.r_ax;
-bx=r.r_bx;
-cx=r.r_cx;
-dx=r.r_dx;
-bp=r.r_bp;
-si=r.r_si;
-di=r.r_di;
-flags=r.r_flags;
-ds=r.r_ds;
-es=r.r_es;
-
-if(!(*(msr)&0x8000) && !hungup) {
-    hungup=1;
-	r.r_ax=0x4c00;
-	intr(0xaa,&r); }					 /* so exit */
-}
-
-#pragma warn +par
-
-
-int main(int argc, char **argv)
-{
-	char str[256],*arg[30],*comspec;
-	int i;
-	FILE *stream;
-
-if(argc<3) {
-	printf("usage: %%!dcdwatch %%& <program> <arguments>\n");
-	exit(1) ;}
-
-msr=(uint far *)atol(argv[1]);
-
-if((stream=fopen("INTRSBBS.DAT","r"))!=NULL) {
-	fgets(str,81,stream);
-	msr=(uint far *)atol(str);
-	fclose(stream);
-	remove("INTRSBBS.DAT"); }
-
-if(msr) {
-	old_int21=getvect(0x21);
-	setvect(0xAA,old_int21);
-	setvect(0x21,new_int21); }
-
-comspec=getenv("COMSPEC");
-
-arg[0]=comspec;
-arg[1]="/c";
-for(i=2;i<30;i++)
-	arg[i]=argv[i];
-
-i=spawnvp(P_WAIT,arg[0],arg);
-
-if(msr)
-	setvect(0x21,old_int21);
-return(i);
-}
diff --git a/src/sbbs2/delfiles/delfiles.c b/src/sbbs2/delfiles/delfiles.c
deleted file mode 100644
index e4f45ffe7d6daab33fe635811b1fa34caf5f0a8f..0000000000000000000000000000000000000000
--- a/src/sbbs2/delfiles/delfiles.c
+++ /dev/null
@@ -1,763 +0,0 @@
-#line 1 "DELFILES.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-#define DELFILES_VER "1.01"
-
-char tmp[256];
-
-#define MAX_NOTS	25
-
-#define ALL 	(1L<<0)
-#define OFFLINE (1L<<1)
-#define NO_LINK (1L<<2)
-#define REPORT	(1L<<3)
-
-void bail(int code)
-{
-exit(code);
-}
-
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-	int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is aREADy open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1) {
-	printf("nopen -1\n");
-	return(NULL); }
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	printf("fdopen NULL mode='%s'\n",mode);
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,_A_NORMAL,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,_A_NORMAL,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-	return(f.size);
-return(-1L);
-}
-
-#ifndef __FLAT__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char HUGE16 *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-
-/****************************************************************************/
-/* This function writes files that are potentially larger than 32767 bytes  */
-/* Up to one megabytes of data can be written with each call.				*/
-/****************************************************************************/
-long lwrite(int file, char HUGE16 *buf, long bytes)
-{
-
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(write(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(write(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-
-/****************************************************************************/
-/* Removes any files in the user transfer index (XFER.IXT) that match the   */
-/* specifications of dest, or source user, or filename or any combination.  */
-/****************************************************************************/
-void rmuserxfers(int fromuser, int destuser, char *fname)
-{
-    char str[256],*ixtbuf;
-    int file;
-    long l,length;
-
-sprintf(str,"%sXFER.IXT",data_dir);
-if(!fexist(str))
-    return;
-if(!flength(str)) {
-    remove(str);
-    return; }
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERROR opening %s\r\n",str);
-    return; }
-length=filelength(file);
-if((ixtbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-	printf("ERROR allocating %lu bytes for %s\r\n",length,str);
-    return; }
-if(read(file,ixtbuf,length)!=length) {
-    close(file);
-	FREE(ixtbuf);
-	printf("ERROR reading %lu bytes from %s\r\n",length,str);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-	FREE(ixtbuf);
-	printf("ERROR opening %s\r\n",str);
-    return; }
-for(l=0;l<length;l+=24) {
-    if(fname!=NULL && fname[0]) {               /* fname specified */
-        if(!strncmp(ixtbuf+l+5,fname,12)) {     /* this is the file */
-            if(destuser && fromuser) {          /* both dest and from user */
-                if(atoi(ixtbuf+l)==destuser && atoi(ixtbuf+l+18)==fromuser)
-                    continue; }                 /* both match */
-            else if(fromuser) {                 /* from user */
-                if(atoi(ixtbuf+l+18)==fromuser) /* matches */
-                    continue; }
-            else if(destuser) {                 /* dest user */
-                if(atoi(ixtbuf+l)==destuser)    /* matches */
-                    continue; }
-            else continue; } }                  /* no users, so match */
-    else if(destuser && fromuser) {
-        if(atoi(ixtbuf+l+18)==fromuser && atoi(ixtbuf+l)==destuser)
-            continue; }
-    else if(destuser && atoi(ixtbuf+l)==destuser)
-        continue;
-    else if(fromuser && atoi(ixtbuf+l+18)==fromuser)
-        continue;
-    write(file,ixtbuf+l,24); }
-close(file);
-FREE(ixtbuf);
-}
-
-/****************************************************************************/
-/* Removes DAT and IXB entries for the file in the struct 'f'               */
-/****************************************************************************/
-void removefiledat(file_t f)
-{
-	char c,str[256],ixbname[12],HUGE16 *ixbbuf,fname[13];
-	int file;
-	ulong l,length;
-
-strcpy(fname,f.name);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERROR opening %s\r\n",str);
-    return; }
-length=filelength(file);
-if(!length) {
-	close(file);
-	return; }
-if((ixbbuf=(char *)MALLOC(length))==0) {
-    close(file);
-	printf("ERROR allocating %lu bytes for %s\r\n",length,str);
-    return; }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-	printf("ERROR reading %lu bytes from %s\r\n",length,str);
-	FREE((char *)ixbbuf);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-	printf("ERROR opening %s\r\n",str);
-    return; }
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        ixbname[c]=ixbbuf[l+c];
-    ixbname[c]=0;
-    if(strcmp(ixbname,fname))
-		if(lwrite(file,&ixbbuf[l],F_IXBSIZE)!=F_IXBSIZE) {
-            close(file);
-			printf("ERROR writing %lu bytes to %s\r\n",F_IXBSIZE,str);
-			FREE((char *)ixbbuf);
-            return; } }
-FREE((char *)ixbbuf);
-close(file);
-sprintf(str,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY))==-1) {
-	printf("ERROR opening %s\r\n",str);
-    return; }
-lseek(file,f.datoffset,SEEK_SET);
-c=ETX;          /* If first char of record is ETX, record is unused */
-if(write(file,&c,1)!=1) { /* So write a D_T on the first byte of the record */
-    close(file);
-	printf("ERROR writing to %s\r\n",str);
-    return; }
-close(file);
-if(f.dir==user_dir)  /* remove file from index */
-    rmuserxfers(0,0,f.name);
-}
-
-/****************************************************************************/
-/* Places into 'strout' CR or ETX terminated string starting at             */
-/* 'start' and ending at 'start'+'length' or terminator from 'strin'        */
-/****************************************************************************/
-void getrec(char *strin,int start,int length,char *strout)
-{
-    int i=0,stop;
-
-stop=start+length;
-while(start<stop) {
-    if(strin[start]==ETX)
-        break;
-    strout[i++]=strin[start++]; }
-strout[i]=0;
-}
-
-/****************************************************************************/
-/* Turns FILE    .EXT into FILE.EXT                                         */
-/****************************************************************************/
-char *unpadfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0,d=0;c<strlen(filename);c++)
-    if(filename[c]!=SP) str[d++]=filename[c];
-str[d]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Returns the time/date of the file in 'filespec' in time_t (unix) format  */
-/****************************************************************************/
-long fdate(char *filespec)
-{
-	int 	file;
-#ifdef __WATCOMC__
-	unsigned short ft,fd;
-#else
-	unsigned ft,fd;
-#endif
-	struct	tm t;
-
-if((file=nopen(filespec,O_RDONLY))==-1)
-	return(0);
-_dos_getftime(file,&fd,&ft);
-close(file);
-memset(&t,0,sizeof(t));
-t.tm_year=((fd&0xfe00)>>9)+80;
-t.tm_mon=((fd&0x01e0)>>5)-1;
-t.tm_mday=fd&0x1f;
-t.tm_hour=(ft&0xf800)>>11;
-t.tm_min=(ft&0x07e0)>>5;
-t.tm_sec=(ft&0x001f)<<1;
-return(mktime(&t));
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                               */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-    ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-    val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-uint hptoi(char *str)
-{
-	char tmp[128];
-	uint i;
-
-if(!str[1] || toupper(str[0])<='F')
-	return(ahtoul(str));
-strcpy(tmp,str);
-tmp[0]='F';
-i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
-return(i);
-}
-
-/****************************************************************************/
-/* Gets filedata from dircode.DAT file										*/
-/* Need fields .name ,.dir and .offset to get other info    				*/
-/* Does not fill .dateuled or .datedled fields.                             */
-/****************************************************************************/
-void getfiledat(file_t *f)
-{
-	char buf[F_LEN+1],str[256],tmp[256];
-	int file;
-	long length;
-
-sprintf(str,"%s%s.DAT",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("ERROR opening %s\r\n",str);
-	return; }
-length=filelength(file);
-if(f->datoffset>length) {
-	close(file);
-	printf("ERROR %s filelength %ld is less than offset\r\n",str,length);
-	return; }
-if(length%F_LEN) {
-	close(file);
-	printf("ERROR %s filelength %ld is not evenly divisible\r\n",str,length);
-	return; }
-lseek(file,f->datoffset,SEEK_SET);
-if(read(file,buf,F_LEN)!=F_LEN) {
-	close(file);
-	printf("ERROR reading %ld bytes from %s\r\n",F_LEN,str);
-	return; }
-close(file);
-getrec(buf,F_ALTPATH,2,str);
-f->altpath=hptoi(str);
-getrec(buf,F_CDT,7,str);
-f->cdt=atol(str);
-
-if(!f->size) {					/* only read disk if this is null */
-	if(dir[f->dir]->misc&DIR_FCHK) {
-		sprintf(str,"%s%s"
-			,f->altpath>0 && f->altpath<=altpaths ? altpath[f->altpath-1]
-			: dir[f->dir]->path,unpadfname(f->name,tmp));
-		f->size=flength(str);
-		f->date=fdate(str); }
-	else {
-		f->size=f->cdt;
-		f->date=0; } }
-//if((f->size>0L) && cur_cps)
-//	  f->timetodl=(f->size/(ulong)cur_cps);
-//else
-	f->timetodl=0;
-
-getrec(buf,F_DESC,LEN_FDESC,f->desc);
-getrec(buf,F_ULER,LEN_ALIAS,f->uler);
-getrec(buf,F_TIMESDLED,5,str);
-f->timesdled=atoi(str);
-getrec(buf,F_OPENCOUNT,3,str);
-f->opencount=atoi(str);
-if(buf[F_MISC]!=ETX)
-	f->misc=buf[F_MISC]-SP;
-else
-	f->misc=0;
-}
-
-/****************************************************************************/
-/* Checks  directory data file for 'filename' (must be padded). If found,   */
-/* it returns the 1, else returns 0.                                        */
-/* Called from upload and bulkupload                                        */
-/****************************************************************************/
-char findfile(uint dirnum, char *filename)
-{
-	char str[256],c,fname[128],HUGE16 *ixbbuf;
-    int file;
-    ulong length,l;
-
-strcpy(fname,filename);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) return(0);
-length=filelength(file);
-if(!length) {
-    close(file);
-    return(0); }
-if((ixbbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-	printf("ERR_ALLOC %s %lu\n",str,length);
-    return(0); }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-	FREE((char *)ixbbuf);
-    return(0); }
-close(file);
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        if(fname[c]!=ixbbuf[l+c]) break;
-    if(c==11) break; }
-FREE((char *)ixbbuf);
-if(l<length)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Turns FILE.EXT into FILE    .EXT                                         */
-/* Called from upload                                                       */
-/****************************************************************************/
-char *padfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0;c<8;c++)
-    if(filename[c]=='.' || !filename[c]) break;
-    else str[c]=filename[c];
-d=c;
-if(filename[c]=='.') c++;
-while(d<8)
-    str[d++]=SP;
-str[d++]='.';
-while(d<12)
-    if(!filename[c]) break;
-    else str[d++]=filename[c++];
-while(d<12)
-    str[d++]=SP;
-str[d]=0;
-return(str);
-}
-
-void main(int argc, char **argv)
-{
-	char str[256],fname[256],not[MAX_NOTS][9],nots=0,*p;
-	uchar HUGE16 *ixbbuf;
-	int i,j,dirnum,libnum,file;
-	ulong l,m,n,length;
-	long misc=0;
-	time_t now;
-	read_cfg_text_t txt;
-	file_t workfile;
-	struct find_t ff;
-
-putenv("TZ=UCT0");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-fprintf(stderr,"\nDELFILES Version %s (%s) - Removes files from Synchronet "
-	"Filebase\n"
-	,DELFILES_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-    ,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	);
-
-if(argc<2) {
-	printf("\n   usage: DELFILES <dir_code or * for ALL> [switches]\n");
-	printf("\nswitches: /LIB name All directories of specified library\n");
-    printf("          /NOT code Exclude specific directory\n");
-	printf("          /OFF      Remove files that are offline "
-		"(don't exist on disk)\n");
-	printf("          /NOL      Remove files with no link "
-		"(don't exist in database)\n");
-	printf("          /RPT      Report findings only "
-		"(don't delete any files)\n");
-	exit(0); }
-
-p=getenv("SBBSNODE");
-if(p==NULL) {
-	printf("\nSBBSNODE environment variable not set.\n");
-	printf("\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-	exit(1); }
-
-putenv("TZ=UCT0");
-
-strcpy(node_dir,p);
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-txt.openerr="\7\nError opening %s for read.\n";
-txt.reading="\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\nError allocating %u bytes of memory\n";
-txt.error="\7\nERROR: Offset %lu in %s\r\n\n";
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str); }
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str); }
-if(temp_dir[1]!=':' && temp_dir[0]!='\\') {
-	strcpy(str,temp_dir);
-	sprintf(temp_dir,"%s%s",node_dir,str); }
-read_file_cfg(txt);
-printf("\n\n");
-
-dirnum=libnum=-1;
-if(argv[1][0]=='*')
-	misc|=ALL;
-else if(argv[1][0]!='/') {
-	strupr(argv[1]);
-	for(i=0;i<total_dirs;i++)
-		if(!stricmp(argv[1],dir[i]->code))
-			break;
-	if(i>=total_dirs) {
-		printf("\nDirectory code '%s' not found.\n",argv[1]);
-		exit(1); }
-	dirnum=i; }
-for(i=1;i<argc;i++) {
-	if(!stricmp(argv[i],"/LIB")) {
-		if(dirnum!=-1) {
-			printf("\nBoth directory code and /LIB parameters were used.\n");
-			exit(1); }
-		i++;
-		if(i>=argc) {
-			printf("\nLibrary short name must follow /LIB parameter.\n");
-			exit(1); }
-		strupr(argv[i]);
-		for(j=0;j<total_libs;j++)
-			if(!stricmp(lib[j]->sname,argv[i]))
-				break;
-		if(j>=total_libs) {
-			printf("\nLibrary short name '%s' not found.\n",argv[i]);
-			exit(1); }
-		libnum=j; }
-	else if(!stricmp(argv[i],"/NOT")) {
-		if(nots>=MAX_NOTS) {
-			printf("\nMaximum number of /NOT options (%u) exceeded.\n"
-				,MAX_NOTS);
-			exit(1); }
-		i++;
-		if(i>=argc) {
-			printf("\nDirectory internal code must follow /NOT parameter.\n");
-            exit(1); }
-		sprintf(not[nots++],"%.8s",argv[i]); }
-	else if(!stricmp(argv[i],"/OFF"))
-		misc|=OFFLINE;
-	else if(!stricmp(argv[i],"/NOL"))
-		misc|=NO_LINK;
-	else if(!stricmp(argv[i],"/RPT"))
-		misc|=REPORT;
-	else if(!stricmp(argv[i],"/ALL")) {
-		if(dirnum!=-1) {
-			printf("\nBoth directory code and /ALL parameters were used.\n");
-            exit(1); }
-		if(libnum!=-1) {
-			printf("\nBoth library name and /ALL parameters were used.\n");
-			exit(1); }
-		misc|=ALL; } }
-
-for(i=0;i<total_dirs;i++) {
-	if(!(misc&ALL) && i!=dirnum && dir[i]->lib!=libnum)
-		continue;
-	for(j=0;j<nots;j++)
-		if(!stricmp(not[j],dir[i]->code))
-			break;
-	if(j<nots)
-        continue;
-
-	if(misc&NO_LINK && dir[i]->misc&DIR_FCHK) {
-		strcpy(tmp,dir[i]->path);
-		if(tmp[0]=='.') {
-			sprintf(str,"%s%s",node_dir,tmp);
-			strcpy(tmp,str); }
-		sprintf(str,"%s*.*",tmp);
-		printf("\nSearching %s for unlinked files\n",str);
-		for(j=_dos_findfirst(str,_A_NORMAL,&ff);!j
-			;j=_dos_findnext(&ff)) {
-			strupr(ff.name);
-			padfname(ff.name,str);
-			if(!findfile(i,str)) {
-				sprintf(str,"%s%s",tmp,ff.name);
-				printf("Removing %s (not in database)\n",ff.name);
-				if(!(misc&REPORT) && remove(str))
-					printf("Error removing %s\n",str); } }
-#ifdef __WATCOMC__
-		_dos_findclose(&ff);
-#endif
-	}
-
-	if(!dir[i]->maxage && !(misc&OFFLINE))
-		continue;
-
-	printf("\nScanning %s %s\n",lib[dir[i]->lib]->sname,dir[i]->lname);
-
-	sprintf(str,"%s%s.IXB",dir[i]->data_dir,dir[i]->code);
-	if((file=nopen(str,O_RDONLY))==-1)
-		continue;
-    l=filelength(file);
-	if(!l) {
-		close(file);
-		continue; }
-	if((ixbbuf=(char *)MALLOC(l))==NULL) {
-		close(file);
-		printf("\7ERR_ALLOC %s %lu\n",str,l);
-        continue; }
-	if(read(file,ixbbuf,l)!=l) {
-		close(file);
-		printf("\7ERR_READ %s %lu\n",str,l);
-		FREE((char *)ixbbuf);
-		continue; }
-    close(file);
-
-	m=0L;
-	now=time(NULL);
-	while(m<l) {
-		memset(&workfile,0,sizeof(file_t));
-		for(j=0;j<12 && m<l;j++)
-			if(j==8)
-				fname[j]='.';
-			else
-				fname[j]=ixbbuf[m++];
-		fname[j]=0;
-		strcpy(workfile.name,fname);
-		unpadfname(workfile.name,fname);
-		workfile.dir=i;
-		sprintf(str,"%s%s"
-			,workfile.altpath>0 && workfile.altpath<=altpaths
-				? altpath[workfile.altpath-1]
-			: dir[workfile.dir]->path,fname);
-		if(str[0]=='.') {
-			sprintf(tmp,"%s%s",node_dir,str);
-			strcpy(str,tmp); }
-		workfile.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)
-			|((long)ixbbuf[m+2]<<16);
-		workfile.dateuled=(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
-			|((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24));
-		workfile.datedled=(ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
-			|((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24));
-		m+=11;
-		if(dir[i]->maxage && dir[i]->misc&DIR_SINCEDL && workfile.datedled
-			&& (now-workfile.datedled)/86400L>dir[i]->maxage) {
-				printf("Deleting %s (%ld days since last download)\n",fname
-					,(now-workfile.datedled)/86400L);
-				getfiledat(&workfile);
-				if(!(misc&REPORT)) {
-					removefiledat(workfile);
-					if(remove(str))
-						printf("Error removing %s\n",str); } }
-		else if(dir[i]->maxage
-			&& !(workfile.datedled && dir[i]->misc&DIR_SINCEDL)
-			&& (now-workfile.dateuled)/86400L>dir[i]->maxage) {
-				printf("Deleting %s (uploaded %ld days ago)\n",fname
-					,(now-workfile.dateuled)/86400L);
-				getfiledat(&workfile);
-				if(!(misc&REPORT)) {
-					removefiledat(workfile);
-					if(remove(str))
-						printf("Error removing %s\n",str); } }
-		else if(misc&OFFLINE && dir[i]->misc&DIR_FCHK && !fexist(str)) {
-				printf("Removing %s (doesn't exist)\n",fname);
-				getfiledat(&workfile);
-				if(!(misc&REPORT))
-					removefiledat(workfile); } }
-
-	FREE((char *)ixbbuf); }
-}
diff --git a/src/sbbs2/delfiles/makeall.bat b/src/sbbs2/delfiles/makeall.bat
deleted file mode 100755
index d68900c3d3397527fe45f8723f77457287880eda..0000000000000000000000000000000000000000
--- a/src/sbbs2/delfiles/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOSX %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/delfiles/makefile b/src/sbbs2/delfiles/makefile
deleted file mode 100644
index 4b9781ebdaf74d7954f67967754057ef997bad55..0000000000000000000000000000000000000000
--- a/src/sbbs2/delfiles/makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-############################################
-# Makefile for Synchronet DELFILES Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..;..\smb;..\rio
-
-
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml
-!else
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-!ifeq OS NT
-SYSTEM	= NT
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\delfiles.exe
-OBJS	= $(OS)\delfiles.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\ars.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
diff --git a/src/sbbs2/delfiles/makefile.bc b/src/sbbs2/delfiles/makefile.bc
deleted file mode 100644
index 2350abeb74336fdc904075cc99654114fe9f2084..0000000000000000000000000000000000000000
--- a/src/sbbs2/delfiles/makefile.bc
+++ /dev/null
@@ -1,77 +0,0 @@
-############################################
-# Makefile for Synchronet ADDFILES Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC	= bcc
-LD	= tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -N -d -C -I$(INCLUDE)
-LFLAGS  = -c
-!else
-OS	= DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -N -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-!endif
-MAIN	= $(OS)\delfiles.exe
-OBJS	= $(OS)\delfiles.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj \
-	  $(OS)\ars.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL).obj $(OBJS)
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_TEXT_CFG
--DNO_XTRN_CFG 
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib2.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_TEXT_CFG
--DNO_XTRN_CFG 
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
diff --git a/src/sbbs2/dos/rciol.obj b/src/sbbs2/dos/rciol.obj
deleted file mode 100644
index 9d4feb5ec5850d5991c8a550c0527ceac20db4a6..0000000000000000000000000000000000000000
Binary files a/src/sbbs2/dos/rciol.obj and /dev/null differ
diff --git a/src/sbbs2/dstsedit/dstsedit.c b/src/sbbs2/dstsedit/dstsedit.c
deleted file mode 100644
index 87cf898f7e09aa98caa968f62c63b90d2cac350a..0000000000000000000000000000000000000000
--- a/src/sbbs2/dstsedit/dstsedit.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/* DSTSEDIT.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <dos.h>
-#include <dir.h>
-#include <stdio.h>
-#include <io.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "..\sbbsdefs.h"
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-	else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN)
-#ifndef __OS2__
-    if(count>10)
-        delay(50);
-#else
-	;
-#endif
-if(file==-1 && errno==EACCES)
-	puts("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	struct time curtime;
-	struct date date;
-
-if(!strcmp(str,"00/00/00"))
-	return(0);
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-if(str[6]<'7')
-	date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
-else
-	date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
-date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
-return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct time curtime;
-	struct date date;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-
-int main(int argc, char **argv)
-{
-	char ch, str[512], path[256]
-		,*lst="%c) %-25s: %13lu\n"
-		,*nv="\nNew value: ";
-	int file;
-	stats_t stats;
-	time_t t;
-
-if(argc>1)
-	strcpy(path,argv[1]);
-else
-	getcwd(path,MAXDIR);
-if(path[strlen(path)-1]!='\\')
-	strcat(path,"\\");
-
-sprintf(str,"%sDSTS.DAB",path);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("Can't open %s\r\n",str);
-	exit(1); }
-read(file,&t,4L);
-if(read(file,&stats,sizeof(stats_t))!=sizeof(stats_t)) {
-	close(file);
-	printf("Error reading %u bytes from %s\r\n",sizeof(stats_t),str);
-	exit(1); }
-close(file);
-while(1) {
-	clrscr();
-	printf("Synchronet Daily Statistics Editor v1.01\r\n\r\n");
-	printf("S) %-25s: %13s\n","Date Stamp",unixtodstr(t,str));
-	printf(lst,'L',"Total Logons",stats.logons);
-	printf(lst,'O',"Logons Today",stats.ltoday);
-	printf(lst,'T',"Total Time on",stats.timeon);
-	printf(lst,'I',"Time on Today",stats.ttoday);
-	printf(lst,'U',"Uploaded Files Today",stats.uls);
-	printf(lst,'B',"Uploaded Bytes Today",stats.ulb);
-	printf(lst,'D',"Downloaded Files Today",stats.dls);
-	printf(lst,'W',"Downloaded Bytes Today",stats.dlb);
-	printf(lst,'P',"Posts Today",stats.ptoday);
-	printf(lst,'E',"E-Mails Today",stats.etoday);
-	printf(lst,'F',"Feedback Today",stats.ftoday);
-	printf("%c) %-25s: %13u\r\n",'N',"New Users Today",stats.nusers);
-
-	printf("Q) Quit and save changes\r\n");
-	printf("X) Quit and don't save changes\r\n");
-
-	printf("\r\nWhich: ");
-
-	ch=toupper(getch());
-	printf("%c\r\n",ch);
-
-	switch(ch) {
-		case 'S':
-			printf("Date stamp (MM/DD/YY): ");
-			gets(str);
-			if(str[0])
-				t=dstrtounix(str);
-			break;
-		case 'L':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.logons=atol(str);
-			break;
-		case 'O':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.ltoday=atol(str);
-			break;
-		case 'T':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.timeon=atol(str);
-			break;
-		case 'I':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.ttoday=atol(str);
-			break;
-		case 'U':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.uls=atol(str);
-			break;
-		case 'B':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.ulb=atol(str);
-			break;
-		case 'D':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.dls=atol(str);
-            break;
-		case 'W':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.dlb=atol(str);
-            break;
-		case 'P':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.ptoday=atol(str);
-            break;
-		case 'E':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.etoday=atol(str);
-            break;
-		case 'F':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.ftoday=atol(str);
-            break;
-		case 'N':
-			printf(nv);
-			gets(str);
-			if(str[0])
-				stats.nusers=atoi(str);
-			break;
-		case 'Q':
-			sprintf(str,"%sDSTS.DAB",path);
-			if((file=nopen(str,O_WRONLY))==-1) {
-				printf("Error opening %s\r\n",str);
-				exit(1); }
-			write(file,&t,4L);
-			write(file,&stats,sizeof(stats_t));
-			close(file);
-		case 'X':
-			exit(0);
-		default:
-			putchar(7);
-			break; } }
-}
diff --git a/src/sbbs2/dstsedit/make.bat b/src/sbbs2/dstsedit/make.bat
deleted file mode 100755
index b2a462a0295bfcd8834a3eeb9c0d4ace913e2a97..0000000000000000000000000000000000000000
--- a/src/sbbs2/dstsedit/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -I.. -w-pro dstsedit.c
diff --git a/src/sbbs2/dupefind/dupefind.c b/src/sbbs2/dupefind/dupefind.c
deleted file mode 100644
index 4d868182183e5d8308e3cfa1ed21af5acd59103c..0000000000000000000000000000000000000000
--- a/src/sbbs2/dupefind/dupefind.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* DUPEFIND.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "crc32.h"
-
-#define DUPEFIND_VER "1.01"
-
-void bail(int code)
-{
-exit(code);
-}
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stderr));
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(access&O_WRONLY) access|=O_RDWR; 	/* fdopen can't open WRONLY */
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&(O_RDONLY|O_RDWR))
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&(O_WRONLY|O_RDWR))
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-char *display_filename(ushort dir_num,ushort fil_off)
-{
-	static char str[256];
-	char fname[13];
-    int file;
-
-    sprintf(str,"%s%s.IXB",dir[dir_num]->data_dir,dir[dir_num]->code);
-    if((file=nopen(str,O_RDONLY))==-1)
-        return("UNKNOWN");
-	lseek(file,(long)(22*(fil_off-1)),SEEK_SET);
-    read(file,fname,11);
-    close(file);
-
-    sprintf(str,"%-8.8s.%c%c%c",fname,fname[8],fname[9],fname[10]);
-    return(str);
-}
-
-void main(int argc,char **argv)
-{
-	char str[256],*ixbbuf,*p;
-	ulong **fcrc,*foundcrc,total_found=0L;
-	ushort i,j,k,h,g,start_lib=0,end_lib=0,found=-1;
-	int file;
-    long l,m;
-    read_cfg_text_t txt;
-
-putenv("TZ=UCT0");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-fprintf(stderr,"\nDUPEFIND Version %s (%s) - Synchronet Duplicate File "
-	"Finder\n"
-	,DUPEFIND_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-    ,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	);
-
-    p=getenv("SBBSNODE");
-    if(p==NULL) {
-		fprintf(stderr,"\nSBBSNODE environment variable must be set.\n");
-		fprintf(stderr,"\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-        exit(1); }
-
-	if(!stricmp(argv[1],"/?") || !stricmp(argv[1],"?")) {
-		fprintf(stderr,"\n");
-		fprintf(stderr,"usage: DUPEFIND [start] [end]\n");
-		fprintf(stderr,"where: [start] is the starting library number to check\n");
-		fprintf(stderr,"       [end]   is the final library number to check\n");
-		return; }
-
-
-    strcpy(node_dir,p);
-    if(node_dir[strlen(node_dir)-1]!='\\')
-        strcat(node_dir,"\\");
-
-    txt.openerr="\7\nError opening %s for read.\n";
-    txt.reading="\nReading %s...";
-    txt.readit="\rRead %s       ";
-    txt.allocerr="\7\nError allocating %u bytes of memory\n";
-    txt.error="\7\nERROR: Offset %lu in %s\r\n\n";
-
-    read_node_cfg(txt);
-    if(ctrl_dir[0]=='.') {
-        strcpy(str,ctrl_dir);
-		sprintf(ctrl_dir,"%s%s",node_dir,str);
-		if(_fullpath(str,ctrl_dir,40))
-            strcpy(ctrl_dir,str); }
-	backslash(ctrl_dir);
-    read_main_cfg(txt);
-    if(data_dir[0]=='.') {
-        strcpy(str,data_dir);
-		sprintf(data_dir,"%s%s",node_dir,str);
-		if(_fullpath(str,data_dir,40))
-			strcpy(data_dir,str); }
-    backslash(data_dir);
-    read_file_cfg(txt);
-	lputs("\n");
-
-	start_lib=0;
-	end_lib=total_libs-1;
-	if(argc>1)
-		start_lib=end_lib=atoi(argv[1])-1;
-	if(argc>2)
-        end_lib=atoi(argv[2])-1;
-
-	if((fcrc=(ulong **)MALLOC(total_dirs*sizeof(ulong *)))==NULL) {
-		printf("Not enough memory for CRCs.\r\n");
-		exit(1); }
-
-	for(i=0;i<total_dirs;i++) {
-		fprintf(stderr,"Reading directory index %u of %u\r",i+1,total_dirs);
-        sprintf(str,"%s%s.IXB",dir[i]->data_dir,dir[i]->code);
-		if((file=nopen(str,O_RDONLY))==-1) {
-			fcrc[i]=(ulong *)MALLOC(1*sizeof(ulong));
-            fcrc[i][0]=0;
-			continue; }
-        l=filelength(file);
-		if(!l || (dir[i]->lib<start_lib || dir[i]->lib>end_lib)) {
-            close(file);
-			fcrc[i]=(ulong *)MALLOC(1*sizeof(ulong));
-			fcrc[i][0]=0;
-            continue; }
-		if((fcrc[i]=(ulong *)MALLOC((l/22+2)*sizeof(ulong)))==NULL) {
-            printf("Not enough memory for CRCs.\r\n");
-            exit(1); }
-		fcrc[i][0]=(ulong)(l/22);
-        if((ixbbuf=(char *)MALLOC(l))==NULL) {
-            close(file);
-            printf("\7Error allocating memory for index %s.\r\n",str);
-            continue; }
-        if(read(file,ixbbuf,l)!=l) {
-            close(file);
-            printf("\7Error reading %s.\r\n",str);
-			FREE(ixbbuf);
-            continue; }
-        close(file);
-		j=1;
-		m=0L;
-		while(m<l) {
-			sprintf(str,"%-11.11s",(ixbbuf+m));
-			strupr(str);
-			fcrc[i][j++]=crc32(str);
-			m+=22; }
-		FREE(ixbbuf); }
-	lputs("\n");
-
-	foundcrc=0L;
-	for(i=0;i<total_dirs;i++) {
-		if(dir[i]->lib<start_lib || dir[i]->lib>end_lib)
-			continue;
-		lprintf("Scanning %s %s\n",lib[dir[i]->lib]->sname,dir[i]->sname);
-		for(k=1;k<fcrc[i][0];k++) {
-			for(j=i+1;j<total_dirs;j++) {
-				if(dir[j]->lib<start_lib || dir[j]->lib>end_lib)
-					continue;
-				for(h=1;h<fcrc[j][0];h++) {
-					if(fcrc[i][k]==fcrc[j][h]) {
-						if(found!=k) {
-							found=k;
-							for(g=0;g<total_found;g++) {
-								if(foundcrc[g]==fcrc[i][k])
-									g=total_found+1; }
-							if(g==total_found) {
-								++total_found;
-								if((foundcrc=(ulong *)REALLOC(foundcrc
-									,total_found*sizeof(ulong)))==NULL) {
-								printf("Out of memory reallocating\r\n");
-								exit(1); } }
-							else
-								found=0;
-							printf("\n%-12s is located in : %-*s  %s\n"
-								   "%-12s           and : %-*s  %s\n"
-								,display_filename(i,k)
-								,LEN_GSNAME
-								,lib[dir[i]->lib]->sname
-								,dir[i]->sname
-								,""
-								,LEN_GSNAME
-								,lib[dir[j]->lib]->sname
-								,dir[j]->sname
-								); }
-						else
-							printf("%-12s           and : %-*s  %s\n"
-								,""
-								,LEN_GSNAME
-								,lib[dir[j]->lib]->sname
-								,dir[j]->sname
-								); } } } } }
-}
-
diff --git a/src/sbbs2/dupefind/makeall.bat b/src/sbbs2/dupefind/makeall.bat
deleted file mode 100755
index d68900c3d3397527fe45f8723f77457287880eda..0000000000000000000000000000000000000000
--- a/src/sbbs2/dupefind/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOSX %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/dupefind/makefile b/src/sbbs2/dupefind/makefile
deleted file mode 100644
index 9af7a2f85ff375e04410028f3813f3a9c129e78c..0000000000000000000000000000000000000000
--- a/src/sbbs2/dupefind/makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-############################################
-# Makefile for Synchronet DUPEFIND Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..;..\smb;..\rio
-
-
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml
-!else
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-!ifeq OS NT
-SYSTEM	= NT
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\dupefind.exe
-OBJS	= $(OS)\dupefind.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\ars.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
diff --git a/src/sbbs2/dupefind/makefile.bc b/src/sbbs2/dupefind/makefile.bc
deleted file mode 100644
index 22b00d8a8e687772c9f8254b3db29bd3a60860b8..0000000000000000000000000000000000000000
--- a/src/sbbs2/dupefind/makefile.bc
+++ /dev/null
@@ -1,74 +0,0 @@
-############################################
-# Makefile for Synchronet FILELIST Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC      = bcc
-LD      = tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE)
-LFLAGS  = -c
-!else
-OS	= DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL   = l
-CFLAGS	= -d -N -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS  = -n -c
-!endif
-MAIN	= $(OS)\dupefind.exe
-OBJS	= $(OS)\dupefind.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj \
-	  $(OS)\scfglib2.obj $(OS)\ars.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-        @echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $< 
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL).obj $(OBJS)   
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Global Variables
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_XTRN_CFG 
--DNO_TEXT_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib2.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_XTRN_CFG 
--DNO_TEXT_CFG
--DNO_CHAT_CFG
-! ..\$&.c
diff --git a/src/sbbs2/echo/docs/fidostep.doc b/src/sbbs2/echo/docs/fidostep.doc
deleted file mode 100644
index c6bf69e6dfda09cd92d4eaaa15cc37f201c9feed..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/docs/fidostep.doc
+++ /dev/null
@@ -1,321 +0,0 @@
-Step-by-Step instructions for setting up FidoNet using SBBSecho and InterMail
-=============================================================================
-
-One of the most difficult tasks that the novice sysop will encounter is the
-setting up of FidoNet.	These instructions will take you step by step through
-the process of setting up FidoNet on your BBS.	Be warned that these steps are
-very basic, just enough to get FidoNet up and running on your system, but it
-may still be necessary for you to refer to the documentation which accompanies
-the programs referred to in these steps.  For any advanced operations you will
-definitely need to refer to the documentation of programs referred to in these
-steps.	If you know of anyone who is already on FidoNet that is willing to help
-you out, by all means ask them for their help!
-
-NOTE that while it doesn't cost anything to have a node number (for sending
-and receiving netmail) or to receive local conferences, there is usually a
-nominal fee (called "cost recovery") to receive conferences from the FidoNet
-backbone or files from the FidoNet filebone.
-
- 1) First of all you will need to obtain a copy of FidoNet's Policy 4 document
-    (the filename is usually POLICY4.ZIP or POLICY4.TXT), a recent nodelist
-    (usually named NODELIST.???), AND a front-end mailer program.  All three of
-    these can normally be downloaded from any local BBS which carries FidoNet
-    (if not, an e-mail to the sysop of a FidoNet BBS can usually point you in
-    the right direction).  There are several front-end mailers available such
-    as FrontDoor, InterMail, D'Bridge, SEAdog, Dutchie, BinkleyTerm, and Portal
-    of Power to name a few (the latter two are referred to as "FLO-Style"
-    mailers and the others are referred to as "Attach-Style" mailers).  Most
-    front-end mailers offer a limited evaluation version which you can try out
-    before you decide to purchase the program.
-
- 2) Read the Policy 4 document, it will give you information about FidoNet as
-    well as some specifics on how to obtain a node number for your system.
-
- 3) If you do not plan to run InterMail (or FrontDoor which is very similar)
-    you must set up the front-end mailer you plan to use by following the
-    directions which accompany the program and then skip to step number 9.
-    The documentation will also tell you how to "compile" the nodelist file
-    you've downloaded so that your front-end mailer can use it.  Use the
-    temporary address specified in Policy 4 when specifying your node address
-    in the front-end mailer.
-
-Setting up InterMail v2.xx or FrontDoor v2.xx
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 4) Install InterMail per IM.DOC (included with InterMail).
-
-    a) If using FrontDoor, follow the FD.DOC file and substitute the letters FD
-       where ever you see an IM in this section.
-
- 5) Copy the MAILER.BAT included with SBBSecho and the EXEBBS.BAT from the
-    Synchronet DOCS directory into the InterMail directory (C:\IM).
-
- 6) Change into the InterMail directory, run IMSETUP, and perform the
-    following:
-
-    a) Under Global->Address->Main, enter your FidoNet address (or the
-       temporary address specified in Policy 4 until such time as you have
-       received your own address).
-
-    b) Under Global->Filenames, verify that the paths are set similar to the
-       following:
-
-  ������������������������������������������������������� Filenames and paths �
-  �									      �
-  � System    C:\IM\SYSTEM\	  (or C:\FD\ for FrontDoor)		      �
-  � Netmail   C:\IM\MAIL\						      �
-  � Files     C:\IM\INBOUND\						      �
-  � Sec Files C:\IM\INBOUND\						      �
-  �*Packets   C:\IM\PACKETS\						      �
-  �*Log file  C:\IM\IM.LOG						      �
-  � Banner								      �
-  � Nodelist  C:\IM\NODELIST\						      �
-  � In-event								      �
-  � Hudsonfmt								      �
-  � Wildcat!								      �
-  � Swapping  C:\IM\							      �
-  � Semaphore C:\IM\							      �
-  �									      �
-  � * = Must be unique for each Mail Server				      �
-  ���������������������������������������������������������������������������ͼ
-
-    c) Under Modem->Advanced Setup->Connect Strings set ALL "BBSexit" levels
-       to 100.	(For FrontDoor under Mailer->Errorlevels set all baud rates to
-       100, Received Mail to 50, and Create .BAT file to Yes).
-
-    d) Under Manager->Events, make sure all your events are set to exit when
-       mail is received (under Event Behavior). This allows for the immediate
-       importation of new messages into the BBS.
-
-    e) Under Manager->Events, add the following event:
-
-  ���������������������������������������������������������������������� Edit �
-  � Tag 	X							      �
-  � Days	-------A						      �
-  � Modifier	Ignore eventbase (*)					      �
-  � Start time	04:30							      �
-  � Length	00:01							      �
-  � Errorlevel	75							      �
-  � Not used								      �
-  � Behavior								      �
-  � Use alias	1:103/705						      �
-  � Retry delay 0							      �
-  � Comment	Synchronet exclusive event				      �
-  ���������������������������������������������������������������������������ĺ
-  � Event tag A..YZ - eXternal event, errorlevel is required		      �
-  ���������������������������������������������������������������������������ͼ
-
-    f) Under Mailer->Misc, set "Trigger exit upon receipt of netmail" and
-       "Upon receipt of ANY file" to Yes. This will allow for the immediate
-       importation of NetMail and any File Distribution Echoes you may carry.
-
-    g) Under Modem->Hardware, set "Lower DTR when busy" to "No".
-
-    h) Under Modem->Command strings, set the "Down" string to "ATM0H1|".
-
-    i) Exit IMSETUP.
-
- 7) Unarc the nodelist file (NODELIST.???) that you downloaded previously
-    into your nodelist directory.
-
- 8) Now run IMNC to compile the nodelist.
-
-Settup up FidoNet in SCFG
-~~~~~~~~~~~~~~~~~~~~~~~~~
- 9) Run SCFG from one of your node directories, or hit 'C' from the waiting for
-    caller screen.  Then select Networks->FidoNet EchoMail and NetMail.
-    You'll then be brought to a menu that should be set up similar to this:
-
-	  �[�][?]���������������������������������������������������ͻ
-	  �		  FidoNet EchoMail and NetMail		     �
-	  ����������������������������������������������������������͹
-	  � �System Addresses		1:103/705		     �
-	  � �Default Outbound Address	No			     �
-	  � �Default Origin Line				     �
-	  � �NetMail Semaphore		C:\IM\IMRESCAN.NOW	     �
-	  � �EchoMail Semaphore 	C:\IM\IMEXIT.025	     �
-	  � �Inbound File Directory	C:\IM\INBOUND\		     �
-	  � �EchoMail Base Directory				     �
-	  � �NetMail Directory		C:\IM\MAIL\		     �
-	  � �Allow Sending of NetMail	Yes			     �
-	  � �Allow File Attachments	Yes			     �
-	  � �Send NetMail Using Alias	No			     �
-	  � �NetMail Defaults to Crash	No			     �
-	  � �NetMail Defaults to Direct No			     �
-	  � �NetMail Defaults to Hold	No			     �
-	  � �Kill NetMail After Sent	Yes			     �
-	  � �Cost to Send NetMail	102400			     �
-	  ����������������������������������������������������������ͼ
-
-    a) For FrontDoor the NetMail Semaphore file should be set to
-       C:\FD\FDRESCAN.NOW and the EchoMail Semaphore file should be set
-       to C:\FD\FDEXIT.025.
-
-    b) For FrontDoor version 2.11, the EchoMail Semaphore file should be
-       set to C:\FD\FDXIT.025.
-
-    c) For FrontDoor version 2.20 (commercial, multinode), the EchoMail
-       Semaphore file should be set to C:\FD\FDXIT#.025, where # is the
-       node number (0 based).
-
-10) Set your address to your system's FidoNet address (or the temporary address
-    specified in Policy 4 until such time as you have received your own
-    address).  This is the address used for sending and receiving NetMail. It
-    will also be used as the default address for message sub-boards.
-
-11) Create an origin line for your system that most likely contains your BBS
-    name and phone number.
-
-12) Following is an overview of the remaining options available on this menu:
-
-    a) System Addresses:
-       This option will bring you to a sub-menu to allow you to configure
-       different addresses (AKAs) for your system. Following is an example
-       for a BBS configured for two fido type networks.
-
-			 �[�][?]���������������������ͻ
-			 �	System Addresses      �
-			 ����������������������������͹
-			 � �Main     1:103/705	      �
-			 � �AKA 1    1:103/706	      �
-			 � �AKA 2    85:805/205       �
-			 � �			      �
-			 ����������������������������ͼ
-
-    b) Default Outbound Address:
-       When a user sends netmail, this is the 'send to' address that is used
-       as a default (useful for FidoNet<->Internet gateways).
-
-    c) NetMail Semaphore:
-       This is the name of the trigger file which will cause your front-end
-       mailer to exit and scan for outgoing netmail.
-
-    d) EchoMail Semaphore:
-       This is the name of the trigger file which will cause your front-end
-       mailer to exit and scan for outgoing echomail.
-
-    e) Inbound File Directory:
-       This is the name of the directory where your front-end mailer stores
-       incoming files.
-
-    f) EchoMail Base Directory:
-       This is the base directory for your echomail subdirectories
-
-    g) NetMail Directory:
-       This is the name of the directory where your front-end mailer looks for
-       and places netmail.
-
-    h) Allow Sending of NetMail:
-       When set to 'Yes' users can send netmail from your system.
-
-    i) Allow File Attachments:
-       When set to 'Yes' users can send netmail file attachments from your
-       system.
-
-    j) Send NetMail Using Alias:
-       When set to 'Yes' the user alias will be used (rather than their
-       real name) on outgoing netmail.
-
-    k) NetMail Defaults to Crash:
-       If set to 'Yes' netmail sent from your system will default to crash
-       status (send immediately and directly).
-
-    l) NetMail Defaults to Direct:
-       If set to 'Yes' netmail sent from your system will default to direct
-       status (send directly).
-
-    m) NetMail Defaults to Hold:
-       If set to 'Yes', netmail sent from your system will default to hold
-       status.
-
-    n) Kill NetMail After Sent:
-       Setting this to 'Yes' will delete outgoing netmail after it has been
-       sent.
-
-    o) Cost to Send NetMail:
-       This is the cost (in credits) that a user will be charged when sending
-       netmail.
-
-13) Setup SBBSecho by running the ECHOCFG program and reading the documentation
-    for information on the available options.
-
-    a) Under Paths...->Outbound Directory be sure to enter the path where
-       outgoing mail packets and bundles should be placed (ie: C:\IM\OUTBOUND).
-
-    b) Select the appropriate Mailer Type.
-
-    c) Enter your registration number (if you are a registered owner of the
-       SBBSecho program).
-
-14) Once you have done this you must now run the file MAILER.BAT (if using an
-    Attach-Style mailer) to use Synchronet with your front-end mailer.
-    MAILER.BAT must be run from your front-end mailer's directory (e.g. C:\IM).
-    You will no longer run the file SBBS.BAT to start this node (if you run a
-    multi-node system, you will still use SBBS.BAT to start those nodes which
-    are not using a front-end mailer).
-
-    a) If you are NOT using InterMail as your front-end mailer, be sure to
-       modify your MAILER.BAT file to reflect the front-end mailer that you
-       are using.
-
-15) Follow the instructions given in the Policy 4 document to determine who
-    you should send netmail to in order to obtain your own node number.
-
-16) Now, from your front end mailer, send a netmail to this person following
-    the instructions contained in the Policy 4 document.  Once you have done
-    this and the netmail has been sent, you should patiently await a netmail
-    reply containing your node number and the node number of your hub (where
-    you will send/receive your echomail and netmail to/from).
-
-17) Once you have received your node number, you'll want to replace the
-    temporary node number you used in your front-end mailer as well as in
-    SCFG->Networks->FidoNet Echomail and Netmail->System Addresses to it.
-
-18) Send your hub a message with the Area Manager (for the backbone <echomail>)
-    and Areafix (for the filebone <files>) passwords you wish to use on their
-    systems.  You will need to remember these passwords as you will be using
-    them to do remote maintenance (such as adding and removing conferences and
-    file areas that you wish to receive).
-
-19) Your hub should respond with Area Manager instructions and a list of areas
-    available for you to connect to.  If not, contact your hub for more
-    information.
-
-20) Look through the list of areas available to you and determine which
-    conferences you'd like to carry.  In SCFG->Message Areas create a
-    message group(s) for the conferences you'd like to carry.  When setting
-    up a sub-board for a conference, be sure to use the "Area Tag" name
-    given in the area list as the sub-board Short Name.
-
-    a) Under Network Options... for each sub-board toggle the FidoNet
-       Echomail option toggled to YES.
-
-    b) If the conference requires a different address, configure the address
-       under Network Options...
-
-    c) If you allow aliases on your system, under Toggle Options... set Use
-       Real Names to YES.
-
-    d) If you are unfamiliar with adding message groups and/or sub-boards,
-       consult that section of the Synchronet System Operator's Manual.
-
-    e) For a more complete list of conferences available on the FidoNet
-       backbone you may wish to download the file FIDONET.NA from either your
-       hub or a local FidoNet BBS.  This file contains a list of ALL
-       conferences carried on the backbone.
-
-21) Once you have set up all of the conferences you'd like to carry, you'll
-    need to go to SCFG->Message Areas-><group>->Export Areas...->AREAS.BBS
-    (SBBSecho) to create an AREAS.BBS file for SBBSecho to use.
-
-22) Now following the Area Manager instructions, send a message to your hub's
-    Area Manager and turn on all of the conferences you wish to carry.	Note
-    that there are some administrative conferences for FidoNet that your
-    users shouldn't be able to read or post on, and some that even you
-    shouldn't post on, there is also usually a "test" conference which you may
-    want to set up to post messages on and insure that echomail is being sent
-    and received properly.
-
-23) That's about all there is to it.  You are now set up on FidoNet and should
-    be able to send and receive FidoNet echomail and netmail.
-
-
diff --git a/src/sbbs2/echo/docs/man.c b/src/sbbs2/echo/docs/man.c
deleted file mode 100644
index f87fa9b3c9e0c49f4bb456cb0661bca56464faa9..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/docs/man.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* MAN.C */
-
-/* Synchronet docs convert to paged format for printing */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dos.h>
-#include <io.h>
-#include <alloc.h>
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (unsigned char)str[c-1]<=32) c--;
-str[c]=0;
-}
-
-int main(int argc, char **argv)
-{
-	char str[256],str2[256],infile[128],outfile[128],idxfile[128]
-		,*invbuf,*outvbuf,*idxvbuf,*tempvbuf,*p,*p2
-		,chap[128]="SBBSecho"
-		,pagetag[250][9]
-		,idxtag[512][9];
-	int i,j,page=1,line=0,pagetags=0,idxtags=0;
-	long pageidx[250],idx[512],l;
-	FILE *in, *out, *index, *tempfile;
-
-if(argc<3) {
-	printf("usage: man infile outfile indexfile\r\n");
-	exit(1); }
-
-strcpy(infile,argv[1]);
-strcpy(outfile,argv[2]);
-strcpy(idxfile,argv[3]);
-
-if((in=fopen(infile,"rb"))==NULL) {
-	printf("error opening %s\r\n",infile);
-	exit(1); }
-
-if((out=fopen(outfile,"wb"))==NULL) {
-	printf("error opening %s\r\n",outfile);
-    exit(1); }
-
-//if((index=fopen(idxfile,"rb"))==NULL) {
-//	  printf("error opening %s\r\n",idxfile);
-//	  exit(1); }
-
-//if((tempfile=fopen("TEMPFILE","w+b"))==NULL) {
-//	  printf("error opening TEMPFILE\r\n");
-//	  exit(1); }
-
-if((invbuf=(char *)malloc(8*1024))==NULL) {
-	printf("error allocating input buffer\n");
-	exit(1); }
-
-if((outvbuf=(char *)malloc(8*1024))==NULL) {
-	printf("error allocating output buffer\n");
-    exit(1); }
-
-//if((idxvbuf=(char *)malloc(8*1024))==NULL) {
-//	  printf("error allocating index buffer\n");
-//	  exit(1); }
-
-//if((tempvbuf=(char *)malloc(8*1024))==NULL) {
-//	  printf("error allocating temp buffer\n");
-//	  exit(1); }
-
-setvbuf(in,invbuf,_IOFBF,8*1024);
-setvbuf(out,outvbuf,_IOFBF,8*1024);
-//setvbuf(index,idxvbuf,_IOFBF,8*1024);
-//setvbuf(tempfile,tempvbuf,_IOFBF,8*1024);
-
-//while(!ferror(index) && !feof(index)) {
-//	  p=fgets(str,128,index);
-//	  fputs(str,tempfile);
-//	  while((p2=strstr(str,"@@"))!=NULL) {
-//		  p2[0]=32;
-//		  p2[1]=32;
-//		  sprintf(idxtag[idxtags],"%-.8s",p2+2);
-//		  idx[idxtags++]=ftell(index)-strlen(p2); } }
-
-while(!ferror(in) && !feof(in)) {
-	p=fgets(str,128,in);
-	if(str[0]=='&' && str[1]=='&') {
-		truncsp(str+2);
-		strcpy(chap,str+2);
-		continue; }
-	if(str[0]=='$' && str[1]=='$') {
-		truncsp(str+2);
-
-//		  for(i=0;i<idxtags;i++) {
-//			  if(!stricmp(str+2,idxtag[i])) {
-//				  fseek(tempfile,idx[i],SEEK_SET);
-//				  sprintf(str2,"%-10d",page);
-//				  fprintf(tempfile,"%s",str2); } }
-
-		for(i=0;i<pagetags;i++)
-			if(!stricmp(str+2,pagetag[i]))
-				break;
-		if(i<pagetags) {
-			l=ftell(out);
-			fseek(out,pageidx[i]-1,SEEK_SET);
-			sprintf(str,"%10d",page);
-			for(i=0;i<10;i++)
-				if(str[i]==0x20)
-					str[i]='.';
-			fprintf(out,"%s",str);
-			fseek(out,l,SEEK_SET); }
-		continue; }
-
-	line++;
-	if(!p)
-		break;
-	if(!p || str[0]==0xc || line==55) {
-		while(line<55) {
-			fprintf(out,"\r\n");
-			line++; }
-		line=1;
-		if(page!=1) 	/* no tag on page 1 */
-			fprintf(out,"\r\n___________________________________________"
-				"____________________________________\r\n"
-				"%-35s %3u %39s"
-				,"SBBSecho",page,chap);
-		fprintf(out,"\r\n\xc\r\n\r\n");
-		page++; }
-
-	if((p2=strstr(str,"@@"))!=NULL) {
-        sprintf(pagetag[pagetags],"%-.8s",p2+2);
-        pageidx[pagetags++]=ftell(out)+(p2-str)+1; }
-
-	if(!p)
-		break;
-	if(str[0]!=0xc)
-		fprintf(out,"%s",str);
-	else
-		line=0;
-		}
-
-//fseek(tempfile,0L,SEEK_SET);
-//while(!ferror(tempfile) && !feof(tempfile)) {
-//	  j=0;
-//	  p=fgets(str2,128,tempfile);
-//	  for(i=0;i<strlen(str2);i++) {
-//		  str[j++]=str2[i];
-//		  if(str2[i]==',') {
-//			  i++;
-//			  str[j++]=str2[i++];
-//			  while(1) {
-//				  if(str2[i]>32 && isdigit(str2[i]))
-//					  str[j++]=str2[i++];
-//				  else
-//					  break; }
-//			  while(str2[i++]==32);
-//			  i-=2; } }
-//	  str[j]=0;
-
-//	  line++;
-//	  if(!p || str[0]==0xc || line==55) {
-//		  while(line<55) {
-//			  fprintf(out,"\r\n");
-//			  line++; }
-//		  line=1;
-//		  if(page!=1)	  /* no tag on page 1 */
-//			  fprintf(out,"\r\n\t___________________________________________"
-//				  "____________________________________\r\n"
-//				  "\t%-35s %3u %39s"
-//				  ,"Synchronet",page,"Index");
-//		  fprintf(out,"\r\n\xc\r\n\r\n");
-//		  page++; }
-
-//	  if(!p)
-//		  break;
-//	  if(str[0]!=0xc)
-//		  fprintf(out,"\t%s",str);
-//	else
-//		  line=0;
-//		  }
-return(0);
-}
-
-
diff --git a/src/sbbs2/echo/docs/sbbsecho.src b/src/sbbs2/echo/docs/sbbsecho.src
deleted file mode 100644
index 61366df30d078ba12ab1eeebf20bed1fb7259d52..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/docs/sbbsecho.src
+++ /dev/null
@@ -1,838 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-				    SBBSecho
-				  Version 1.22
-				Updated 02/15/96
-
-	       FidoNet Packet Tosser for Synchronet BBS Version 2
-
-			Copyright 1995 Digital Dynamics
-
-                                  PO Box 501
-                             Yorba Linda, CA 92686
-
-		 Voice: 714-529-6328   BBS: 714-529-9525 V.32/V.32bis
-		   FAX: 714-529-9721	    714-529-9547 V.FC
-                  Fido: 1:103/705      ftp: netcom.com /pub/sb/sbbs
-
-
-Table of Contents
-=================
-&&Contents
-
-Introduction....................................................@@INTRO___
-Terminology.....................................................@@TERMS___
-Installation....................................................@@INSTALL_
-AREAS.BBS Format................................................@@AREASBBS
-Configuration...................................................@@CONFIG__
-Running SBBSecho................................................@@EXECUTE_
-Command Line Switches...........................................@@SWITCHES
-Area Manager Remote Commands....................................@@AREAFIX_
-
-Introduction
-============
-&&Introduction
-$$INTRO___
-
-SBBSecho is a full-blown FTN echomail program (tosser/scanner) for Synchronet
-BBS version 2. SBBSecho is level III implementation of the SMB v2.00
-specification including support for HyperAllocated and LZH compressed message
-bases.
-
-It is intended to replace FTSC-1 (*.MSG) compatible echomail programs (GEcho,
-Squish, FastEcho, Alexi/Mail, etc.) and SBBSFIDO with a single program
-incorporating the standard features of echomail programs without the .MSG
-phase (consuming disk space and time).
-
-You will not need to use SBBSFIDO (*.MSG import/export utility for Synchronet)
-or any echomail programs after you have installed SBBSecho.
-
-Terminology
-============
-&&Terminology
-$$TERMS___
-
-FTN
-~~~
-FidoNet Technology Network: Any network using FidoNet standards for addressing,
-mail packets, mail sessions, node lists, etc.
-
-Zones, Nets, Nodes, and Points?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-FTN node addresses are like phone numbers, they are made up of multiple
-components (four to be exact). The components are: zone, net, node, and point.
-Each component is specified by a decimal (base-10) number, separated by symbols
-(no spaces):
-
-	Zone:Net/Node.Point
-
-The zone represents the continent (if FidoNet) or the network number (if other
-FTN network). All FidoNet nodes in North America have a zone 1 address. When
-the zone is specified in an address, it is the first component and must be
-followed by a colon. If the zone is not present in an address, the local
-system's zone is assumed.
-
-The net represents the network number of the FTN node. Duplicate net numbers
-may exist between zones. If the net number is not present, the local system's
-net is assumed.
-
-The node number specifies an exact FTN node within a network. The node number
-is the only required element of an FTN node address.
-
-The point is an optional component which specifies a sub-node that does not
-directly receive mail and is also not listed in the main FTN node list, but
-instead gets all its mail from its boss-node (zone:net/node.0). When the point
-is not specified, 0 (zero) is assumed (i.e. 1:2/3 and 1:2/3.0 are identical)
-which indicates the system is not a point node address.
-
-A 2D (2 dimensional) address refers to an FTN address containing just the
-net and node numbers (i.e. 103/705).
-
-A 3D (3 dimensional) address refers to an FTN address containing the zone,
-net, and node numbers (i.e. 1:103/705), specifically excluding the point number
-if it exists.
-
-A 4D (4 dimensional) address refers to an FTN address containing the zone,
-net, node, and optional point numbers (i.e. 1:103/705.1).
-
-A 5D (5 dimensional) address refers to an FTN address consisting of a standard
-3D or 4D address with an appended "@domain" (i.e. 1:103/705@fidonet.org).
-
-Attach or FLO Mailer?
-~~~~~~~~~~~~~~~~~~~~~
-If you are using FrontDoor, InterMail, D'bridge, SEAdog, Dutchie, or any other
-ArcMail *.MSG attach-style mailer, you are using what we will refer to as an
-"Attach Mailer".
-
-If you are using BinkleyTerm, Portal of Power, or any other FLO/CLO/HLO/DLO
-style mailer, you are using what we will refer to as a "FLO Mailer".
-
-Both types are supported equally by SBBSecho.
-
-NetMail
-~~~~~~~
-Point-to-point (usually person-to-person) direct or routed messages.
-
-EchoMail
-~~~~~~~~
-Group or conference messages of a particular subject matter. Usually
-distributed on a regional or continental (e.g. FidoNet Zone 1 backbone) scale.
-FTN style echomail areas have a unique area tag (name) associated with them to
-distinguish each area from the others.
-
-Packet
-~~~~~~
-An FTN packet is a group of one or more messages contained in a single
-uncompressed file. Packets may contain echomail and/or netmail messages.
-Packets usually have a .PKT extension, although outbound NetMail packets for
-FLO Mailers will have .?UT extensions (where ? is either O, C, D, or H). The
-first eight characters of the filename may be anything, but are usually decimal
-digits representing the date and time the packet was created. SBBSecho creates
-temporary outbound packet files with a .PK_ extension and then renames them to
-.PKT when they're completed. If you find any .PK_ files in your outbound
-directory, don't worry. SBBSecho will find them the next time it is run and
-continue packing them and sending them on their way.
-
-Bundle
-~~~~~~
-An FTN bundle is a single file archive of one or more (usually compressed)
-packets. Bundles will have file extensions where the first two characters
-represent the day of the week the bundle was created (MO, TU, WE, TH, FR, SA,
-and SU) and the third character of the extension is a number or letter. The
-first eight characters of the filename may be anything, but are usually
-hexadecimal digits representing the FTN node address (or relative address) of
-the system that created the bundle. SBBSecho changes the file extension of bad
-inbound bundles to .MO_, .MO-, or .MO.
-
-Areafix/Area Manager
-~~~~~~~~~~~~~~~~~~~~
-Areafix is a synonym for area manager (the very first FTN area manager
-program was called AreaFix). Area manager capabilities (remote adding/removing
-of areas, changing compression type, etc) are built into SBBSecho, so therefore
-no external area manager program is required. If you are not an FTN hub, then
-the area manager portion of SBBSecho will probably not get any use on your
-system.
-
-Installation
-============
-&&Installing SBBSecho
-$$INSTALL_
-
-To begin, copy the SBBSECHO.EXE, ECHOCFG.EXE, and AREAMGR.HLP files into your
-Synchronet EXEC directory (usually C:\SBBS\EXEC), copy the SBBSECHO.CFG file
-into your Synchronet CTRL directory (usually C:\SBBS\CTRL), and copy the
-SBBSECHO.DOC file into your Synchronet DOCS directory (usually C:\SBBS\DOCS).
-
-If you plan on using the 32-bit DOS, OS/2, or Windows 95/NT version of
-SBBSecho, you will need to put the appropriate SBBSECHO.EXE file into your
-Synchronet EXEC directory (unzip OS2.ZIP for the OS/2 version, DOS4G.ZIP for
-the 32-bit DOS version, or WIN32.ZIP for the Windows 95/NT version). If
-you get memory allocation errors running the 16-bit DOS version or desire
-improved performance, you will want to run one of the 32-bit versions.
-
-Add the SBBSCTRL and SBBSNODE environment variables to your AUTOEXEC.BAT.
-Example:
-
-SET SBBSCTRL=C:\SBBS\CTRL
-SET SBBSNODE=C:\SBBS\NODE1
-
-Note: The node number used for the SBBSNODE environment variable is not
-      important, use your NODE1 directory.
-
-These environment variables must be present for SBBSECHO and ECHOCFG to
-function correctly. Type "SET" at the DOS prompt to be sure they are listed
-correctly.
-
-You will also need to modify your existing MAILER.BAT (or FDRUN.BAT, IMRUN.BAT,
-etc) file to accomodate the use of SBBSecho, or replace it with the MAILER.BAT
-included with SBBSecho. If this is your first time setting up FidoNet, you will
-not currently have a MAILER.BAT file set up, so use the one that is included
-and modify it so that it reflects the proper drive letters and directories.
-
-Next, SBBSecho expects to find the file AREAS.BBS in your Synchronet DATA
-directory (usually C:\SBBS\DATA) unless you have overridden the default name
-and/or location using the ECHOCFG program.  The format of this file is very
-similar to the standard AREAS.BBS (which many echomail programs use, or can
-at least export their native area file to this format - i.e. GEcho's GSETUP).
-
-SCFG can also export your sub-boards to AREAS.BBS, but you're probably better
-off modifying the AREAS.BBS file you're already using (if you are) or
-converting your current echomail program's area file to AREAS.BBS. This is
-because SCFG assumes the sub-board short name will be the same as the area's
-tag (as shown in your echo list), but this may not always be the case - unless
-you imported an AREAS.BBS or FIDONET.NA file into SCFG to begin with).
-
-AREAS.BBS Format
-================
-&&AREAS.BBS Format
-$$AREASBBS
-
-Lines beginning with a semicolon (;) are considered comments, and are ignored.
-
-Each line is in the following format:
-
-CODE	TAG	UPLINKS
-
-Where:
-	CODE is the internal code of the sub-board. Any unrecognized internal
-		codes are considered "Passthru" (not imported to your BBS).
-
-	TAG is the FidoNet tag as shown in your echo list (i.e. FIDONET.NA).
-		If this is '*', then it will be considered a "badecho" area
-		and will receive all messages for areas not otherwise specified
-		in this file.
-
-	UPLINKS is a list of FidoNet addresses which you wish to export mail
-		to. At the very least, your hub's address should be listed
-		here. Your address should NOT be listed here. If multiple
-		addresses are specified, you should specify the full 3D address
-		for each.
-
-AREAS.BBS Example:
-
-SBBS		SYNCHRONET	1:3615/50
-SYNCDATA	SYNCDATA	1:3615/50
-SYNC_SYS	SYNC_SYSOPS	1:3615/50
-
-The amount of spacing between each element in the line is not important. Each
-line can be up to 1000 characters in length.
-
-So if your OLD AREAS.BBS file is in .MSG format (for example):
-
-C:\FD\ECHO\SBBS 	SYNCHRONET	1:3615/50
-
-It must be changed to match the example given above!
-
-Configuration
-=============
-&&Configuring SBBSecho
-$$CONFIG__
-
-In order to set up SBBSecho for your system you must run the included ECHOCFG
-program. It should already be located in your EXEC directory. You may want to
-put your EXEC directory in your DOS search path so you can execute SBBSECHO and
-ECHOCFG from any drive and directory on your system.
-
-Multiple configuration files can be used (but isn't usually required) for
-multi-mailer systems. The default configuration filename is SBBSECHO.CFG
-located in your Synchronet CTRL directory. You can override this by specifying
-the name and location of the configuration file on the SBBSECHO and ECHOCFG
-command lines. Example:
-
-ECHOCFG D:\ECHO1.CFG
-SBBSECHO D:\ECHO1.CFG
-
-If you do not specify a configuration file, ECHOCFG and SBBSECHO will use
-SBBSECHO.CFG located in your Synchronet CTRL directory.
-
-Upon running ECHOCFG you will be brought to the main menu of the configuration
-program. The path and filename of the configuration file being modified will
-appear at the top of the menu. Following are screen captures of available menus
-within the configuration program and an explanation of the options contained on
-each of them.
-
-	      �[�][?]�������������������������������������������ͻ
-	      � 	   C:\SBBS\CTRL\SBBSECHO.CFG		 �
-	      ��������������������������������������������������͹
-	      � �Mailer Type			FrontDoor/Attach �
-	      � �Maximum Packet Size		250K		 �
-	      � �Maximum Bundle Size		250K		 �
-	      � �Areafix Failure Notification	User #1 	 �
-	      � �Registration Number		UNREGISTERED	 �
-	      � �Nodes...					 �
-	      � �Paths...					 �
-	      � �Log Options... 				 �
-	      � �Toggle Options...				 �
-	      � �Archive Programs...				 �
-	      � �Additional Echo Lists...			 �
-	      ��������������������������������������������������ͼ
-
-Mailer Type:
-	Selecting this option will toggle between the mailer types supported
-	by SBBSecho, either FrontDoor (message attach) type mailers or Binkley
-	(FLO file) type mailers.  Choose the one that matches your front-end
-	mailer type.
-
-Maximum Packet Size:
-	This option allows you to set the maximum size of each outgoing
-	echomail packet.
-
-Maximum Bundle Size:
-	Mail packets are normally packed into what are called "bundles" (unless
-	a node is set up to receive uncompressed mail packets).  This option
-	allows you to specify the maximum size of each outgoing mail bundle.
-
-Areafix Failure Notification:
-	This is the user number of the person where notification of Areafix
-	failures should be sent.  Such failures include nodes which are not
-	configured for areafix, nodes using incorrect areafix passwords, and
-	the like.  Setting this to 0 will disable this option.
-
-Registration Number:
-	Upon registering SBBSecho with Digital Dynamics, you will be given a
-	registration number.  You should select this option and enter the
-	registration number you are given here.  If you have not yet registered
-	the program, this should say "Unregistered".
-
-Nodes...
-	This option allows you to add, remove, and configure nodes that you
-	will be sending mail to.  Selecting this option will bring you to
-	a sub-menu which will look similar to the following:
-
-				 �[�][?]�����ͻ
-				 �    Nodes   �
-				 ������������͹
-				 � �ALL       �
-				 � �1:100/ALL �
-				 � �1:200/300 �
-				 � �2:ALL     �
-				 � �	      �
-				 ������������ͼ
-
-	At the Nodes... sub-menu, pressing the INSert key will allow you to
-	add a new node, pressing the DELete key will remove the currently
-	highlighted node number, and pressing ENTER on the currently
-	highlighted node will allow you to edit the options for that particular
-	node from a menu like the following (note that the node number you are
-	editing appears at the top of the window):
-
-		    �[�][?]�������������������������������ͻ
-		    �		    1:200/300		   �
-		    ��������������������������������������͹
-		    � �Address		    1:200/300	   �
-		    � �Archive Type	    ZIP 	   �
-		    � �Packet Type	    2+		   �
-		    � �Packet Password			   �
-		    � �Areafix Password 		   �
-		    � �Areafix Flags			   �
-		    � �Status		    None	   �
-		    � �Direct		    No		   �
-		    � �Passive		    No		   �
-		    � �Send Notify List     No		   �
-		    ��������������������������������������ͼ
-
-	Address:
-		This is the address of the node you are editing, selecting it
-		will allow you to change this to a different address. Using
-		the "ALL" wildcard in place of one of the address components
-		will allow you to configure settings for all nodes that meet
-		that specication (e.g. all nodes in zone 1 can be specified
-		as 1:ALL or all nodes in zone 1, net 103 can be specified
-		as 1:103/ALL).
-
-	Archive Type:
-		This is the compression type to be used when packing mail
-		bundles for this node.	Selecting this option will allow you
-		to choose from a menu of currently configured archive types,
-		like the following:
-
-			       �[�][?]���������ͻ
-			       �  Archive Type	�
-			       ����������������͹
-			       � �ZIP		�
-			       � �ARC		�
-			       � �LZH		�
-			       � �ARJ		�
-			       � �PAK		�
-			       � �SQZ		�
-			       � �ZOO		�
-			       � �None		�
-			       ����������������ͼ
-
-		Selecting "None" will specify that this node is to receive
-		uncompressed packets (no bundles).
-
-	Packet Type:
-		This is the packet type that will be used when creating mail
-		packets for this node. The default packet type used by SBBSecho
-		is 2+.	If you are a "point" address (e.g. 1:100/100.1) you
-		should use either a type 2+ or 2.2 packet since type 2 packets
-		do not support point numbers. Selecting this option will allow
-		you to choose from a menu of currently supported packet types:
-
-			       �[�][?]��������ͻ
-			       �  Packet Type  �
-			       ���������������͹
-			       � �2+	       �
-			       � �2.2	       �
-			       � �2	       �
-			       ���������������ͼ
-
-	Packet Password:
-		This is a password that will be placed into each outgoing mail
-		packet for this node.  Passwords are normally used for extra
-		security when sending and receiving mail packets.  This node
-		must also have the same packet password defined for your
-		address and SBBSecho must be set up for secure operation (set
-		in the 'Toggle Options' sub-menu) in order for this feature to
-		function properly.
-
-	Areafix Password:
-		This is the password that will be required by this node (in
-		the subject field) when it sends messages to the area manager
-		(AreaFix).
-
-	Areafix Flags:
-		When additional echo lists have been defined (from the
-		'Additional Echo Lists...' sub-menu) these flags determine
-		which echo lists can be used by this node when processing area
-		manager add requests.
-
-	Status:
-		This option determines the netmail status that will be set
-		when SBBSecho sends out an areafix message or a file attach.
-		Selecting this option toggles between None, Crash, and Hold
-		status.
-
-	Direct:
-		When set to 'Yes' this option will add a Direct kludge line
-		to messages that SBBSecho sends out (or create DLO/DUT files
-		for FLO mailers).
-
-	Passive:
-		Setting this option to 'Yes' will prevent messages from being
-		sent to this node without the need for altering the AREAS.BBS
-		file.  This is useful for temporarily shutting off the messages
-		to this node.  This option can be toggled on and off remotely
-		via an area manager request.
-
-	Send Notify List:
-                This determines whether or not this node is sent a Notify List
-                when using that command line option in SBBSecho.
-                A Notify List is a netmail sent to the system operator of the
-                node showing options set for the node as well as connected
-                areas.
-
-Paths...
-	This option allows you to configure the paths and filenames which are
-	used by SBBSecho.  Selecting this option will bring you to the
-	following sub-menu:
-
-	  �[�][?]���������������������������������������������������ͻ
-	  �		       Paths and Filenames		     �
-	  ����������������������������������������������������������͹
-	  � �Inbound Directory		    <Specified in SCFG>      �
-	  � �Secure Inbound (optional)	    None Specified	     �
-	  � �Outbound Directory 	    C:\IM\OUTBOUND\	     �
-	  � �Area File			    SCFG->DATA\AREAS.BBS     �
-	  � �Log File			    SCFG->DATA\SBBSECHO.LOG  �
-	  ����������������������������������������������������������ͼ
-
-	Inbound Directory:
-		This is the directory where SBBSecho should look for inbound
-		mail packets.  This is normally taken from whatever has been
-		set in the SCFG program.
-
-	Secure Inbound (optional):
-		This is an optional directory where SBBSecho should look for
-		secure inbound mail packets.
-
-	Outbound Directory:
-		This is the directory where SBBSecho will place outgoing mail
-		packets and bundles.
-
-	Area File:
-		This is the path and filename of the file that SBBSecho will
-		use as it's AREAS.BBS file.  By default SBBSecho looks for
-		the file AREAS.BBS in the data directory defined in SCFG.
-
-	Log File:
-		This is the path and filename of the file that SBBSecho will
-		use when logging events.  By default SBBSecho uses the file
-		SBBSECHO.LOG in the data directory defined in SCFG.
-
-Log Options...
-	This list allows you to toggle what events SBBSecho should place into
-	the logfile.  Selecting this option will bring you to the following
-	sub-menu:
-
-		  �[�][?]����������������������������������ͻ
-		  �		  Log Options		    �
-		  �����������������������������������������͹
-		  � �ALL				    �
-		  � �NONE				    �
-		  � �DEFAULT				    �
-		  � �Ignored NetMail Messages		No  �
-		  � �NetMail for Unknown Users		No  �
-		  � �Areafix NetMail Messages		Yes �
-		  � �Imported NetMail Messages		Yes �
-		  � �Packing Out-bound NetMail		Yes �
-		  � �Routing Out-bound NetMail		Yes �
-		  � �In-bound Packet Information	Yes �
-		  � �In-bound Security Violations	Yes �
-		  � �In-bound Grunged Messages		Yes �
-		  � �Disallowed Private EchoMail	Yes �
-		  � �Circular EchoMail Messages 	No  �
-		  � �Duplicate EchoMail Messages	No  �
-		  � �Area Totals			Yes �
-		  � �Over-All Totals			Yes �
-		  �����������������������������������������ͼ
-
-	Selecting ALL, NONE, or DEFAULT will toggle all of the options to
-	'Yes', 'No', or to their default states, respectively.
-
-
-Toggle Options...
-	These options allow you to toggle various features in SBBSecho.
-	Selecting this option will bring you to the following sub-menu:
-
-	   �[�][?]�������������������������������������������������ͻ
-	   �			 Toggle Options 		    �
-	   ��������������������������������������������������������͹
-	   � �Secure Operation					Yes �
-	   � �Swap for Executables				Yes �
-	   � �Fuzzy Zone Operation				No  �
-	   � �Store PATH Lines in Message Base			Yes �
-	   � �Store SEEN-BY Lines in Message Base		Yes �
-	   � �Store Unknown Kludge Lines in Message Base	Yes �
-	   � �Allow Nodes to Add Areas in the AREAS.BBS List	Yes �
-	   ��������������������������������������������������������ͼ
-
-	Secure Operation:
-		When set to 'Yes', SBBSecho will compare the origin of any
-		incoming mail packets to the nodes in the AREAS.BBS file
-		as messages are imported.  If a packet password has been
-		defined for that node, it will also be compared to the
-		password contained in the mail packet.	Packets and messages
-		failing this security will not be imported.
-
-	Swap for Executables:
-		SBBSecho relies on external executable programs for extracting
-		and compressing mail bundles.  This option tells SBBSecho to
-		swap out of memory when running any of these executables,
-		giving the executable programs more free memory to run in.
-		This option is only used in the 16-bit DOS flavor of SBBSecho.
-
-	Fuzzy Zone Operation:
-		Some mail programs do not create netmail messages with zone
-		information (INTL kludge line) or may only do so when sending
-		between zones. This is a problem for systems that receive
-		netmail for multiple addresses with different zones (AKAs with
-		different zone numbers). Setting this option to "Yes" allows
-		SBBSecho to guess what the correct originating and destination
-		zone is based on the net and node portions of the destination
-		address in netmail message.
-
-	Store PATH Lines in Message Base:
-		When set to 'Yes', SBBSecho will store the PATH lines from
-		incoming echomail in the Synchronet message base headers (not
-		the body text). This option is useful for troubleshooting
-		routing/duplicate message problems.
-
-	Store SEEN-BY Lines in Message Base:
-		When set to 'Yes', SBBSecho will store the SEEN-BY lines from
-		incoming echomail in the Synchronet message base headers (not
-		the body text).  This option is useful for troubleshooting
-		routing/duplicate message problems.
-
-	Store Unknown Kludge Lines in Message Base:
-		When set to 'Yes', SBBSecho will store any unknown kludge lines
-		from incoming echomail in the Synchronet message base headers.
-		This option is useful for troubleshooting problems.
-
-	Allow Nodes to Add Areas in the AREAS.BBS List:
-		When set to 'Yes', SBBSecho will allow nodes to add areas
-		(via area manager) which are listed in the AREAS.BBS list.
-		When set to 'No', SBBSecho will only allow nodes to add areas
-		from any additionally configured echo lists which they have
-		access to.
-
-Archive Programs...
-	This option allows you to add or remove archive programs from SBBSecho.
-	Selecting this option will bring you to the following menu:
-
-			     �[�][?]�������������ͻ
-			     �	Archive Programs  �
-			     ��������������������͹
-			     � �ZIP		  �
-			     � �ARC		  �
-			     � �LZH		  �
-			     � �ARJ		  �
-			     � �PAK		  �
-			     � �SQZ		  �
-			     � �ZOO		  �
-			     � �		  �
-			     ��������������������ͼ
-
-	At the Archive Programs... sub-menu, pressing the INSert key will allow
-	you to add a new archive program. Pressing the DELete key will remove
-	the currently highlighted archive program. And pressing ENTER on the
-	currently highlighted archive program will allow you to edit the
-	options for that particular prgram from a menu like the following (note
-	that the name of the archive program you are editing appears at the top
-	of the window):
-
-	  �[�][?]���������������������������������������������������ͻ
-	  �			       ZIP			     �
-	  ����������������������������������������������������������͹
-	  � �Packer Name	  ZIP				     �
-	  � �Hexadecimal ID	  504B				     �
-	  � �Offset to Hex ID	  0				     �
-	  � �Pack Command Line	  PKZIP %f %s			     �
-	  � �Unpack Command Line  PKUNZIP %f %s 		     �
-	  ����������������������������������������������������������ͼ
-
-	Packer Name:
-		This is the name that will be used to reference this particular
-		archiving program.  This is also the name that should be used
-		by nodes using areamanger to change their compression type
-		remotely.
-
-	Hexadecimal ID:
-		This is a hexadecimal identifier that SBBSecho should look for
-		when determining the compression type used on incoming bundles.
-		In this example we are looking for the ID 'PK', '50' is the
-		hexadecimal value for the letter 'P' and '4B' is the
-		hexadecimal value for the letter 'K'.
-
-	Offset to Hex ID:
-		This is the byte offset (from the beginning of the file) where
-		the hexadecimal ID for this archive program can be located.
-		In this example we are looking at an offset of 0 bytes from the
-		beginning of the file.
-
-	Pack Command Line:
-		This is the command line used by this archiving program for
-		compressing files.  The '%f' command line specifier will expand
-		to the name of the compressed file, the '%s' command line
-		specifier will expand to the name of the file being compressed.
-
-	Unpack Command Line:
-		This is the command line used by the archiving program for
-		UNcompressing files.  The '%f' command line specifier will
-		expand to the name of the compressed file, the '%s' command
-		line specifier will expand to the path where the file is
-		being extracted to.
-
-Additional Echo Lists...
-	This option allows you to add and remove additional echo lists which
-	can be used by SBBSecho for area manager add requests.	Normally these
-	will be used in addition to your AREAS.BBS file.  If you have the
-	toggle option 'Allow Nodes to Add Areas in the AREAS.BBS List' set to
-	'No', you MUST create at least one additional echo list if you wish
-	to allow other nodes to add areas via area manager requests.
-
-	Selecting this option will bring you to a sub-menu listing any
-	additional echo lists you currently have defined:
-
-			  �[�][?]������������������ͻ
-			  �  Additional Echo Lists  �
-			  �������������������������͹
-			  � �C:\BACKBONE\FIDONET.NA �
-			  � �			    �
-			  �������������������������ͼ
-
-	Pressing the INSert key will allow you to add a new echo list, pressing
-	the DELete key will remove the currently highlighted echo list, and
-	pressing ENTER on the currently highlighted echo list will allow you to
-	edit information about that list:
-
-	  �[�][?]���������������������������������������������������ͻ
-	  �			    Echo List			     �
-	  ����������������������������������������������������������͹
-	  � �Echo List Path/Name  C:\BACKBONE\FIDONET.NA	     �
-	  � �Hub Address	  None				     �
-	  � �Forward Password	  None				     �
-	  � �Forward Requests	  No				     �
-	  � �Echo List Flags	  BACK				     �
-	  ����������������������������������������������������������ͼ
-
-	Echo List Path/Name:
-		This is the full path and filename of the echo list you are
-		defining.  This list should contain the areatag names of areas,
-		one per line, with any comments seperated from the areatag by
-		at least one space.
-
-	Hub Address:
-		This is the address of the hub of the conferences contained
-		in this list.  If an area is remotely added from this list
-		(using Areafix) this address is automatically added to the
-                AREAS.BBS file.
-
-	Forward Password:
-		This is the area manager password to use when forwarding
-		requests.
-
-	Forward Requests:
-		Setting this option to 'Yes' will cause SBBSecho to send a
-		request to the Hub Address specified to turn on an area from
-		this list.  This happens when users remotely add areas using
-		Areafix and is not necessary if you are already receiving the
-		conferences in this list (ie: from Planet Connect).
-
-
-	Echo List Flags:
-		These are the flags required for a node to be able to gain
-		access to this particular echo list.  These flags are defined
-		for each node from the 'Nodes...' sub-menu.
-
-		Selecting this option will bring you to a sub-menu where you
-		may add and remove flags for this echo list.
-
-			     �[�][?]������������ͻ
-			     �	Echo List Flags  �
-			     �������������������͹
-			     � �BACK		 �
-			     � �		 �
-			     �������������������ͼ
-
-Running SBBSecho
-================
-&&Running SBBSecho
-$$EXECUTE_
-
-The command line for executing SBBSECHO is very similar to SBBSFIDO, although
-some command line switches have been eliminated.
-
-We suggest you use the following command lines:
-
-For importing:
-
-	C:\SBBS\EXEC\SBBSECHO /LES!
-
-For exporting (Attach Mailer):
-
-	C:\SBBS\EXEC\SBBSECHO /LIN
-
-For exporting (FLO Mailer):
-
-	C:\SBBS\EXEC\SBBSECHO /LINF
-
-Remove all references to SBBSFIDO from your batch files (if you have any).
-See the included MAILER.BAT as an example.
-
-Command Lines Switches
-======================
-&&Command Lines Switches
-$$SWITCHES
-
-usage: sbbsecho [cfg_file] [/switches] [sub_code]
-
-where: cfg_file is the filename of config file (default is ctrl\sbbsecho.cfg)
-       sub_code is the internal code for a sub-board (default is ALL subs)
-
-SBBSecho will execute normally (for Attach Mailer operation) with NO command
-line switches required. Command lines switches are used to cause SBBSecho to
-_do_ or _not_ do specific operations. When used, command line switches
-are prepended by a slash (/) character. Multiple switches can be specified
-in one grouping (multiple /switch sets are supported, but not required).
-Switch letters are not case sensitive. The available switch letters and their
-descriptions are:
-
-P: Do not import inbound packets or extract inbound bundles
-X: Do not delete inbound packets (*.PKT) after they're imported
-N: Do not import inbound netmail (packetized netmail and *.MSG)
-D: Do not delete inbound netmail (*.MSG) after they're imported
-I: Do not import inbound echomail
-E: Do not export outbound echomail
-M: Ignore echomail pointers (export all locally created echomail messages)
-U: Update echomail pointers only (export no echomail messages)
-T: Do not update echomail pointers (test export)
-H: Export all echomail messages (including messages imported from FidoNet)
-J: Ignore recieved bit on netmail (import even though flagged as received)
-L: Create log file (data\sbbsecho.log)
-R: Create report of import totals (text\sbbsecho.msg)
-B: Import locally created netmail too (ignore the local flag)
-A: Export ASCII characters only (override individual sub-board ex-ASCII strip)
-F: Create packets for outbound netmail (necessary for FLO Mailer operation)
-G: Generate notify lists
-Y: Import netmail for unknown users to sysop (user #1)
-O: Import all netmail regardless of destination address (unless flagged local)
-S: Import private echomail override (strip private flag)
-=: Change existing tear lines to === when exporting
-!: Notify users via telegram of received echomail messages
-
-AREAFIX Commands
-================
-&&Areafix Commands
-$$AREAFIX_
-
-Remote area manager, or areafix, commands are used by uplinks to be able to
-turn echo areas off and on, list currently connected areas, and more.
-
-The following text is from the file AREAMGR.HLP which, after installation of
-SBBSecho, should be located in your Synchronet EXEC directory.	It lists the
-area manager commands available to the nodes which have been configured using
-the ECHOCFG program:
-
-Address all requests to 'SBBSecho' or 'AreaFix' (without quotes).
-Your Area Manager password goes on the subject line.
-
-In the body of the message to Area Manager:
-
-[+]<areaname>         Connect an area
--<areaname>           Disconnect an area
-%HELP                 Request this message
-%LIST                 Request a list of areas available to you
-%QUERY                Request a list of areas to which you are connected
-%UNLINKED             Request a list of areas to which you are not connected
-%COMPRESSION <type>   Change the compression type (ARC/ARJ/LZH/PAK/SQZ/ZIP/ZOO)
-%PASSWORD <password>  Change your AreaMgr password
-%RESCAN 	      Request a rescan of newly added areas
-%ACTIVE 	      Reconnect all temporarily disconnected areas
-%PASSIVE	      Temporarily disconnect all connected areas
-%FROM <address>       Remote maintenance, must be the first command
-%+ALL		      Connect all available areas
-%-ALL		      Disconnect all areas
-[---]                 Everything below the tear line is ignored
-
-NOTE: A compression type of NONE is also supported for uncompressed packets.
-
-
diff --git a/src/sbbs2/echo/echocfg.c b/src/sbbs2/echo/echocfg.c
deleted file mode 100644
index e7f1b3eb31a6d8ea704a2c569a418aa9d857ca68..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/echocfg.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-/* ECHOCFG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Portions written by Allen Christiansen 1994-1996 						*/
-
-#include <uifc.h>
-#include <sys\stat.h>
-#include "gen_defs.h"
-#include "sbbsdefs.h"
-#include "sbbsecho.h"
-
-char **opt;
-
-void bail(int code);
-void main();
-char fexist(char *filespec);
-char *faddrtoa(faddr_t addr);
-
-uchar node_swap=1;
-long misc=0;
-config_t cfg;
-
-unsigned _stklen=16000;
-
-void bail(int code)
-{
-
-if(code)
-	getch();
-uifcbail();
-exit(code);
-}
-
-#define lprintf cprintf
-
-void main(int argc, char **argv)
-{
-	char str[256],*p;
-	int i,j,k,x,file,dflt,nodeop=0;
-	FILE *stream;
-	echolist_t savlistcfg;
-	nodecfg_t savnodecfg;
-	arcdef_t savarcdef;
-
-fprintf(stderr,"\nSBBSecho Configuration  Version %s  Developed 1995-1997 "
-	"Rob Swindell\n\n",SBBSECHO_VER);
-
-memset(&cfg,0,sizeof(config_t));
-if(argc>1)
-	strcpy(str,argv[1]);
-else {
-	p=getenv("SBBSCTRL");
-	if(!p) {
-		p=getenv("SBBSNODE");
-		if(!p) {
-            printf("usage: echocfg [cfg_file]\n");
-			exit(1); }
-		strcpy(str,p);
-        if(str[strlen(str)-1]!='\\')
-            strcat(str,"\\");
-		strcat(str,"..\\CTRL\\SBBSECHO.CFG"); }
-	else {
-		strcpy(str,p);
-		if(str[strlen(str)-1]!='\\')
-			strcat(str,"\\");
-		strcat(str,"SBBSECHO.CFG"); } }
-strcpy(cfg.cfgfile,str);
-strupr(cfg.cfgfile);
-
-read_cfg();
-
-savnum=0;
-if((opt=(char **)MALLOC(sizeof(char *)*300))==NULL) {
-	cputs("memory allocation error\r\n");
-	bail(1); }
-for(i=0;i<300;i++)
-	if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL) {
-		cputs("memory allocation error\r\n");
-        bail(1); }
-uifcini();
-sprintf(str,"SBBSecho Configuration v%s",SBBSECHO_VER);
-uscrn(str);
-
-dflt=0;
-while(1) {
-	helpbuf=
-" SBBSecho Configuration \r\n\r\n"
-"Move through the various options using the arrow keys.  Select the\r\n"
-"highlighted options by pressing ENTER.\r\n\r\n";
-	i=0;
-	sprintf(opt[i++],"%-30.30s %s","Mailer Type"
-		,misc&FLO_MAILER ? "Binkley/FLO":"FrontDoor/Attach");
-	sprintf(opt[i++],"%-30.30s %luK","Maximum Packet Size"
-		,cfg.maxpktsize/1024UL);
-	sprintf(opt[i++],"%-30.30s %luK","Maximum Bundle Size"
-		,cfg.maxbdlsize/1024UL);
-	if(cfg.notify)
-		sprintf(str,"User #%u",cfg.notify);
-	else
-		strcpy(str,"Disabled");
-	sprintf(opt[i++],"%-30.30s %s","Areafix Failure Notification",str);
-	sprintf(opt[i++],"Nodes...");
-	sprintf(opt[i++],"Paths...");
-	sprintf(opt[i++],"Log Options...");
-	sprintf(opt[i++],"Toggle Options...");
-	sprintf(opt[i++],"Archive Programs...");
-	sprintf(opt[i++],"Additional Echo Lists...");
-	opt[i][0]=NULL;
-	switch(ulist(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,52,&dflt,0
-	,cfg.cfgfile,opt)) {
-
-		case 0:
-			misc^=FLO_MAILER;
-			break;
-
-		case 1:
-helpbuf=
-" Maximum Packet Size \r\n\r\n"
-"This is the maximum file size that SBBSecho will create when placing\r\n"
-"outgoing messages into packets.  The default size is 250k.\r\n";
-            sprintf(str,"%lu",cfg.maxpktsize);
-            uinput(WIN_MID|WIN_BOT,0,0,"Maximum Packet Size",str
-                ,9,K_EDIT|K_NUMBER);
-            cfg.maxpktsize=atol(str);
-            break;
-
-		case 2:
-helpbuf=
-" Maximum Bundle Size \r\n\r\n"
-"This is the maximum file size that SBBSecho will create when placing\r\n"
-"outgoing packets into bundles.  The default size is 250k.\r\n";
-            sprintf(str,"%lu",cfg.maxbdlsize);
-            uinput(WIN_MID|WIN_BOT,0,0,"Maximum Bundle Size",str
-                ,9,K_EDIT|K_NUMBER);
-            cfg.maxbdlsize=atol(str);
-            break;
-
-		case 3:
-helpbuf=
-" Areafix Failure Notification \r\n\r\n"
-"Setting this option to a user number (usually #1), enables the\r\n"
-"automatic notification of that user, via e-mail, of failed areafix\r\n"
-"attempts. Setting this option to 0, disables this feature.\r\n";
-			sprintf(str,"%u",cfg.notify);
-			uinput(WIN_MID|WIN_BOT,0,0,"Areafix Notification User Number",str
-				,5,K_EDIT|K_NUMBER);
-			cfg.notify=atoi(str);
-			break;
-
-		case 4:
-helpbuf=
-" Nodes... \r\n\r\n"
-"From this menu you can configure the area manager options for your\r\n"
-"uplink nodes.\r\n";
-			i=0;
-			while(1) {
-				for(j=0;j<cfg.nodecfgs;j++)
-					strcpy(opt[j],faddrtoa(cfg.nodecfg[j].faddr));
-				opt[j][0]=0;
-				i=ulist(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
-					|WIN_INSACT|WIN_DELACT|WIN_XTR
-					,0,0,0,&i,0,"Nodes",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					str[0]=0;
-helpbuf=
-" Address \r\n\r\n"
-"This is the FidoNet style address of the node you wish to add\r\n";
-					if(uinput(WIN_MID,0,0
-						,"Node Address (ALL wildcard allowed)",str
-						,25,K_EDIT)<1)
-						continue;
-					if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-						,sizeof(nodecfg_t)*(cfg.nodecfgs+1)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-                        exit(1); }
-					for(j=cfg.nodecfgs;j>i;j--)
-						memcpy(&cfg.nodecfg[j],&cfg.nodecfg[j-1]
-                            ,sizeof(nodecfg_t));
-					cfg.nodecfgs++;
-					memset(&cfg.nodecfg[i],0,sizeof(nodecfg_t));
-					cfg.nodecfg[i].faddr=atofaddr(str);
-					continue; }
-
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					cfg.nodecfgs--;
-					if(cfg.nodecfgs<=0) {
-						cfg.nodecfgs=0;
-						continue; }
-					for(j=i;j<cfg.nodecfgs;j++)
-						memcpy(&cfg.nodecfg[j],&cfg.nodecfg[j+1]
-							,sizeof(nodecfg_t));
-					if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-						,sizeof(nodecfg_t)*(cfg.nodecfgs)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-						exit(1); }
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					memcpy(&savnodecfg,&cfg.nodecfg[i],sizeof(nodecfg_t));
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					memcpy(&cfg.nodecfg[i],&savnodecfg,sizeof(nodecfg_t));
-					continue; }
-				while(1) {
-helpbuf=
-" Node Options \r\n\r\n"
-"These are the configurable options available for this node.\r\n";
-					j=0;
-					sprintf(opt[j++],"%-20.20s %s","Address"
-						,faddrtoa(cfg.nodecfg[i].faddr));
-					sprintf(opt[j++],"%-20.20s %s","Archive Type"
-						,cfg.nodecfg[i].arctype>cfg.arcdefs ?
-						"None":cfg.arcdef[cfg.nodecfg[i].arctype].name);
-					sprintf(opt[j++],"%-20.20s %s","Packet Type"
-						,cfg.nodecfg[i].pkt_type==PKT_TWO ? "2"
-						:cfg.nodecfg[i].pkt_type==PKT_TWO_TWO ? "2.2":"2+");
-					sprintf(opt[j++],"%-20.20s %s","Packet Password"
-						,cfg.nodecfg[i].pktpwd);
-					sprintf(opt[j++],"%-20.20s %s","Areafix Password"
-						,cfg.nodecfg[i].password);
-					str[0]=0;
-					for(k=0;k<cfg.nodecfg[i].numflags;k++) {
-						strcat(str,cfg.nodecfg[i].flag[k].flag);
-						strcat(str," "); }
-					sprintf(opt[j++],"%-20.20s %s","Areafix Flags",str);
-					sprintf(opt[j++],"%-20.20s %s","Status"
-						,cfg.nodecfg[i].attr&ATTR_CRASH ? "Crash"
-						:cfg.nodecfg[i].attr&ATTR_HOLD ? "Hold" : "None");
-					sprintf(opt[j++],"%-20.20s %s","Direct"
-						,cfg.nodecfg[i].attr&ATTR_DIRECT ? "Yes":"No");
-					sprintf(opt[j++],"%-20.20s %s","Passive"
-						,cfg.nodecfg[i].attr&ATTR_PASSIVE ? "Yes":"No");
-					sprintf(opt[j++],"%-20.20s %s","Send Notify List"
-                        ,cfg.nodecfg[i].attr&SEND_NOTIFY ? "Yes" : "No");
-					if(misc&FLO_MAILER)
-						sprintf(opt[j++],"%-20.20s %s","Route To"
-							,cfg.nodecfg[i].route.zone
-							? faddrtoa(cfg.nodecfg[i].route) : "Disabled");
-					opt[j][0]=0;
-					k=ulist(WIN_MID|WIN_ACT,0,0,40,&nodeop,0
-						,faddrtoa(cfg.nodecfg[i].faddr),opt);
-					if(k==-1)
-						break;
-					switch(k) {
-						case 0:
-helpbuf=
-" Address \r\n\r\n"
-"This is the FidoNet style address of this node.\r\n";
-							strcpy(str,faddrtoa(cfg.nodecfg[i].faddr));
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Node Address (ALL wildcard allowed)",str
-								,25,K_EDIT|K_UPPER);
-							cfg.nodecfg[i].faddr=atofaddr(str);
-							break;
-						case 1:
-helpbuf=
-" Archive Type \r\n\r\n"
-"This is the compression type that will be used for compressing packets\r\n"
-"to and decompressing packets from this node.\r\n";
-							for(j=0;j<cfg.arcdefs;j++)
-								strcpy(opt[j],cfg.arcdef[j].name);
-							strcpy(opt[j++],"None");
-							opt[j][0]=0;
-							if(cfg.nodecfg[i].arctype<j)
-								j=cfg.nodecfg[i].arctype;
-							k=ulist(WIN_RHT|WIN_SAV,0,0,0,&j,0
-								,"Archive Type",opt);
-							if(k==-1)
-								break;
-							if(k>=cfg.arcdefs)
-								cfg.nodecfg[i].arctype=0xffff;
-							else
-								cfg.nodecfg[i].arctype=k;
-							break;
-						case 2:
-helpbuf=
-" Packet Type \r\n\r\n"
-"This is the packet header type that will be used in mail packets to\r\n"
-"this node.  SBBSecho defaults to using type 2.2.\r\n";
-							j=0;
-							strcpy(opt[j++],"2+");
-							strcpy(opt[j++],"2.2");
-							strcpy(opt[j++],"2");
-							opt[j][0]=0;
-							j=cfg.nodecfg[i].pkt_type;
-							k=ulist(WIN_RHT|WIN_SAV,0,0,0,&j,0,"Packet Type"
-								,opt);
-							if(k==-1)
-								break;
-							cfg.nodecfg[i].pkt_type=k;
-							break;
-						case 3:
-helpbuf=
-" Packet Password \r\n\r\n"
-"This is an optional password that SBBSecho will place into packets\r\n"
-"destined for this node.\r\n";
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Packet Password (optional)"
-								,cfg.nodecfg[i].pktpwd,8,K_EDIT|K_UPPER);
-							break;
-						case 4:
-helpbuf=
-" Areafix Password \r\n\r\n"
-"This is the password that will be used by this node when doing remote\r\n"
-"areamanager functions.\r\n";
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Areafix Password"
-								,cfg.nodecfg[i].password,8,K_EDIT|K_UPPER);
-							break;
-						case 5:
-helpbuf=
-" Areafix Flag \r\n\r\n"
-"This is a flag to to be given to this node allowing access to one or\r\n"
-"more of the configured echo lists\r\n";
-							while(1) {
-								for(j=0;j<cfg.nodecfg[i].numflags;j++)
-									strcpy(opt[j],cfg.nodecfg[i].flag[j].flag);
-								opt[j][0]=0;
-								k=ulist(WIN_SAV|WIN_INS|WIN_DEL|WIN_ACT|
-									WIN_XTR|WIN_INSACT|WIN_DELACT|WIN_RHT
-									,0,0,0,&k,0,"Areafix Flags",opt);
-								if(k==-1)
-									break;
-								if((k&MSK_ON)==MSK_INS) {
-									k&=MSK_OFF;
-									str[0]=0;
-									if(uinput(WIN_MID|WIN_SAV,0,0
-										,"Areafix Flag",str,4
-										,K_EDIT|K_UPPER)<1)
-										continue;
-									if((cfg.nodecfg[i].flag=(flag_t *)
-										REALLOC(cfg.nodecfg[i].flag
-										,sizeof(flag_t)*
-										(cfg.nodecfg[i].numflags+1)))==NULL) {
-										printf("\nMemory Allocation Error\n");
-										exit(1); }
-									for(j=cfg.nodecfg[i].numflags;j>i;j--)
-										memcpy(&cfg.nodecfg[i].flag[j]
-											,&cfg.nodecfg[i].flag[j-1]
-											,sizeof(flag_t));
-									cfg.nodecfg[i].numflags++;
-									memset(&cfg.nodecfg[i].flag[k].flag
-										,0,sizeof(flag_t));
-									strcpy(cfg.nodecfg[i].flag[k].flag,str);
-									continue; }
-
-								if((k&MSK_ON)==MSK_DEL) {
-									k&=MSK_OFF;
-									cfg.nodecfg[i].numflags--;
-									if(cfg.nodecfg[i].numflags<=0) {
-										cfg.nodecfg[i].numflags=0;
-										continue; }
-									for(j=k;j<cfg.nodecfg[i].numflags;j++)
-										strcpy(cfg.nodecfg[i].flag[j].flag
-											,cfg.nodecfg[i].flag[j+1].flag);
-									if((cfg.nodecfg[i].flag=(flag_t *)
-										REALLOC(cfg.nodecfg[i].flag
-										,sizeof(flag_t)*
-										(cfg.nodecfg[i].numflags)))==NULL) {
-										printf("\nMemory Allocation Error\n");
-										exit(1); }
-									continue; }
-								strcpy(str,cfg.nodecfg[i].flag[k].flag);
-								uinput(WIN_MID|WIN_SAV,0,0,"Areafix Flag"
-									,str,4,K_EDIT|K_UPPER);
-								strcpy(cfg.nodecfg[i].flag[k].flag,str);
-								continue; }
-							break;
-						case 6:
-							if(cfg.nodecfg[i].attr&ATTR_CRASH) {
-								cfg.nodecfg[i].attr^=ATTR_CRASH;
-								cfg.nodecfg[i].attr|=ATTR_HOLD;
-								break; }
-							if(cfg.nodecfg[i].attr&ATTR_HOLD) {
-								cfg.nodecfg[i].attr^=ATTR_HOLD;
-								break; }
-							cfg.nodecfg[i].attr|=ATTR_CRASH;
-							break;
-						case 7:
-							cfg.nodecfg[i].attr^=ATTR_DIRECT;
-							break;
-						case 8:
-							cfg.nodecfg[i].attr^=ATTR_PASSIVE;
-							break;
-						case 9:
-							cfg.nodecfg[i].attr^=SEND_NOTIFY;
-							break;
-						case 10:
-helpbuf=
-" Route To \r\n\r\n"
-"When using a FLO type mailer, this is the node number of an address\r\n"
-"to route mail to for this node.\r\n";
-							strcpy(str,faddrtoa(cfg.nodecfg[i].route));
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Node Address to Route To",str
-								,25,K_EDIT);
-								if(str[0])
-									cfg.nodecfg[i].route=atofaddr(str);
-                            break;
-							} } }
-			break;
-
-		case 5:
-helpbuf=
-" Paths... \r\n\r\n"
-"From this menu you can configure the paths that SBBSecho will use\r\n"
-"when importing and exporting.\r\n";
-			j=0;
-			while(1) {
-				i=0;
-				sprintf(opt[i++],"%-30.30s %s","Inbound Directory"
-					,cfg.inbound[0] ? cfg.inbound : "<Specified in SCFG>");
-				sprintf(opt[i++],"%-30.30s %s","Secure Inbound (optional)"
-					,cfg.secure[0] ? cfg.secure : "None Specified");
-				sprintf(opt[i++],"%-30.30s %s","Outbound Directory"
-					,cfg.outbound);
-				sprintf(opt[i++],"%-30.30s %s","Area File"
-					,cfg.areafile[0] ? cfg.areafile
-					: "SCFG->DATA\\AREAS.BBS");
-				sprintf(opt[i++],"%-30.30s %s","Log File"
-					,cfg.logfile[0] ? cfg.logfile
-					: "SCFG->DATA\\SBBSECHO.LOG");
-				opt[i][0]=NULL;
-				j=ulist(WIN_MID|WIN_ACT,0,0,60,&j,0
-					,"Paths and Filenames",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-helpbuf=
-" Inbound Directory \r\n\r\n"
-"This is the complete path (drive and directory) where your front\r\n"
-"end mailer stores, and where SBBSecho will look for, incoming message\r\n"
-"bundles and packets.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Inbound",cfg.inbound
-							,50,K_EDIT|K_UPPER);
-						break;
-
-					case 1:
-helpbuf=
-" Secure Inbound Directory \r\n\r\n"
-"This is the complete path (drive and directory) where your front\r\n"
-"end mailer stores, and where SBBSecho will look for, incoming message\r\n"
-"bundles and packets for SECURE sessions.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Secure Inbound",cfg.secure
-							,50,K_EDIT|K_UPPER);
-						break;
-
-					case 2:
-helpbuf=
-" Outbound Directory \r\n\r\n"
-"This is the complete path (drive and directory) where your front\r\n"
-"end mailer will look for, and where SBBSecho will place, outgoing\r\n"
-"message bundles and packets.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Outbound",cfg.outbound
-							,50,K_EDIT|K_UPPER);
-						break;
-
-					case 3:
-helpbuf=
-" Area File \r\n\r\n"
-"This is the complete path (drive, directory, and filename) of the\r\n"
-"file SBBSecho will use as your AREAS.BBS file.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Areafile",cfg.areafile
-							,50,K_EDIT|K_UPPER);
-						break;
-
-					case 4:
-helpbuf=
-" Log File \r\n\r\n"
-"This is the complete path (drive, directory, and filename) of the\r\n"
-"file SBBSecho will use to log information each time it is run.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Logfile",cfg.logfile
-							,50,K_EDIT|K_UPPER);
-						break; } }
-			break;
-		case 6:
-helpbuf=
-" Log Options \r\n"
-"\r\n"
-"Each loggable item can be toggled off or on from this menu. You must run\r\n"
-"SBBSecho with the /L command line option for any of these items to be\r\n"
-"logged.";
-			j=0;
-			while(1) {
-				i=0;
-				strcpy(opt[i++],"ALL");
-				strcpy(opt[i++],"NONE");
-				strcpy(opt[i++],"DEFAULT");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Ignored NetMail Messages"
-					,cfg.log&LOG_IGNORED ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","NetMail for Unknown Users"
-					,cfg.log&LOG_UNKNOWN ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Areafix NetMail Messages"
-					,cfg.log&LOG_AREAFIX ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Imported NetMail Messages"
-					,cfg.log&LOG_IMPORTED ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Packing Out-bound NetMail"
-					,cfg.log&LOG_PACKING ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Routing Out-bound NetMail"
-					,cfg.log&LOG_ROUTING ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Packet Information"
-					,cfg.log&LOG_PACKETS ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Security Violations"
-					,cfg.log&LOG_SECURITY ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","In-bound Grunged Messages"
-					,cfg.log&LOG_GRUNGED ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Disallowed Private EchoMail"
-					,cfg.log&LOG_PRIVATE ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Circular EchoMail Messages"
-                    ,cfg.log&LOG_CIRCULAR ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Duplicate EchoMail Messages"
-					,cfg.log&LOG_DUPES ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Area Totals"
-					,cfg.log&LOG_AREA_TOTALS ? "Yes":"No");
-				sprintf(opt[i++],"%-35.35s%-3.3s","Over-All Totals"
-					,cfg.log&LOG_TOTALS ? "Yes":"No");
-				opt[i][0]=NULL;
-				j=ulist(0,0,0,43,&j,0,"Log Options",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-						cfg.log=~0L;
-						break;
-					case 1:
-						cfg.log=0;
-						break;
-					case 2:
-						cfg.log=LOG_DEFAULTS;
-						break;
-					case 3:
-						cfg.log^=LOG_IGNORED;
-						break;
-					case 4:
-						cfg.log^=LOG_UNKNOWN;
-                        break;
-					case 5:
-						cfg.log^=LOG_AREAFIX;
-                        break;
-					case 6:
-						cfg.log^=LOG_IMPORTED;
-                        break;
-					case 7:
-						cfg.log^=LOG_PACKING;
-                        break;
-					case 8:
-						cfg.log^=LOG_ROUTING;
-                        break;
-					case 9:
-						cfg.log^=LOG_PACKETS;
-                        break;
-					case 10:
-						cfg.log^=LOG_SECURITY;
-                        break;
-					case 11:
-						cfg.log^=LOG_GRUNGED;
-                        break;
-					case 12:
-						cfg.log^=LOG_PRIVATE;
-                        break;
-					case 13:
-						cfg.log^=LOG_CIRCULAR;
-                        break;
-					case 14:
-						cfg.log^=LOG_DUPES;
-                        break;
-					case 15:
-						cfg.log^=LOG_AREA_TOTALS;
-                        break;
-					case 16:
-						cfg.log^=LOG_TOTALS;
-						break; } }
-            break;
-
-
-		case 7:
-helpbuf=
-"Secure Operation tells SBBSecho to check the AREAS.BBS file to insure\r\n"
-"    that the packet origin exists there as well as check the password of\r\n"
-"    that node (if configured).\r\n\r\n"
-"Swap for Executables tells SBBSecho whether or not it should swap\r\n"
-"    out of memory when executing external executables.\r\n\r\n"
-"Fuzzy Zone Operation when set to yes if SBBSecho receives an inbound\r\n"
-"    netmail with no international zone information, it will compare the\r\n"
-"    net/node of the destination to the net/node information in your AKAs\r\n"
-"    and assume the zone of a matching AKA.\r\n\r\n"
-"Store PATH/SEEN-BY/Unkown Kludge Lines in Message Base allows you to\r\n"
-"    determine whether or not SBBSecho will store this information from\r\n"
-"    incoming messages in the Synchronet message base.\r\n\r\n"
-"Allow Nodes to Add Areas in the AREAS.BBS List when set to YES allows\r\n"
-"    uplinks to add areas listed in the AREAS.BBS file\r\n";
-			j=0;
-			while(1) {
-				i=0;
-				sprintf(opt[i++],"%-50.50s%-3.3s","Secure Operation"
-					,misc&SECURE ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Swap for Executables"
-					,node_swap ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Fuzzy Zone Operation"
-					,misc&FUZZY_ZONE ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Store PATH Lines in "
-					"Message Base",misc&STORE_SEENBY ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Store SEEN-BY Lines in "
-					"Message Base",misc&STORE_PATH ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Store Unknown Kludge Lines "
-					"in Message Base",misc&STORE_KLUDGE ? "Yes":"No");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Allow Nodes to Add Areas "
-					"in the AREAS.BBS List",misc&ELIST_ONLY?"No":"Yes");
-				sprintf(opt[i++],"%-50.50s%-3.3s","Kill/Ignore Empty NetMail "
-					"Messages",misc&KILL_EMPTY_MAIL ? "Yes":"No");
-				opt[i][0]=NULL;
-				j=ulist(0,0,0,60,&j,0,"Toggle Options",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-						misc^=SECURE;
-						break;
-					case 1:
-						if(node_swap)
-							node_swap=0;
-						else
-							node_swap=1;
-						break;
-					case 2:
-						misc^=FUZZY_ZONE;
-						break;
-					case 3:
-						misc^=STORE_SEENBY;
-						break;
-					case 4:
-						misc^=STORE_PATH;
-						break;
-					case 5:
-						misc^=STORE_KLUDGE;
-						break;
-					case 6:
-						misc^=ELIST_ONLY;
-						break;
-					case 7:
-						misc^=KILL_EMPTY_MAIL;
-						} }
-            break;
-		case 8:
-helpbuf=
-" Archive Programs \r\n\r\n"
-"These are the archiving programs (types) which are available for\r\n"
-"compressing outgoing packets.\r\n";
-			i=0;
-			while(1) {
-				for(j=0;j<cfg.arcdefs;j++)
-					sprintf(opt[j],"%-30.30s",cfg.arcdef[j].name);
-				opt[j][0]=0;
-				i=ulist(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
-					|WIN_INSACT|WIN_DELACT|WIN_XTR
-					,0,0,0,&i,0,"Archive Programs",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					str[0]=0;
-helpbuf=
-" Packer Name \r\n\r\n"
-"This is the identifying name of the archiving program\r\n";
-					if(uinput(WIN_MID,0,0
-						,"Packer Name",str,25,K_EDIT|K_UPPER)<1)
-						continue;
-					if((cfg.arcdef=(arcdef_t *)REALLOC(cfg.arcdef
-						,sizeof(arcdef_t)*(cfg.arcdefs+1)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-                        exit(1); }
-					for(j=cfg.arcdefs;j>i;j--)
-						memcpy(&cfg.arcdef[j],&cfg.arcdef[j-1]
-							,sizeof(arcdef_t));
-						strcpy(cfg.arcdef[j].name
-							,cfg.arcdef[j-1].name);
-					cfg.arcdefs++;
-					memset(&cfg.arcdef[i],0,sizeof(arcdef_t));
-					strcpy(cfg.arcdef[i].name,str);
-					continue; }
-
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					cfg.arcdefs--;
-					if(cfg.arcdefs<=0) {
-						cfg.arcdefs=0;
-						continue; }
-					for(j=i;j<cfg.arcdefs;j++)
-						memcpy(&cfg.arcdef[j],&cfg.arcdef[j+1]
-							,sizeof(arcdef_t));
-					if((cfg.arcdef=(arcdef_t *)REALLOC(cfg.arcdef
-						,sizeof(arcdef_t)*(cfg.arcdefs)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-						exit(1); }
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					memcpy(&savarcdef,&cfg.arcdef[i],sizeof(arcdef_t));
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					memcpy(&cfg.arcdef[i],&savarcdef,sizeof(arcdef_t));
-					continue; }
-				while(1) {
-					j=0;
-					sprintf(opt[j++],"%-20.20s %s","Packer Name"
-						,cfg.arcdef[i].name);
-					sprintf(opt[j++],"%-20.20s %s","Hexadecimal ID"
-						,cfg.arcdef[i].hexid);
-					sprintf(opt[j++],"%-20.20s %u","Offset to Hex ID"
-						,cfg.arcdef[i].byteloc);
-					sprintf(opt[j++],"%-20.20s %s","Pack Command Line"
-						,cfg.arcdef[i].pack);
-					sprintf(opt[j++],"%-20.20s %s","Unpack Command Line"
-						,cfg.arcdef[i].unpack);
-					opt[j][0]=0;
-					sprintf(str,"%.30s",cfg.arcdef[i].name);
-					k=ulist(WIN_MID|WIN_ACT,0,0,60,&nodeop,0,str,opt);
-					if(k==-1)
-						break;
-					switch(k) {
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Packer Name",cfg.arcdef[i].name,25
-								,K_EDIT|K_UPPER);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Hexadecimal ID",cfg.arcdef[i].hexid,25
-								,K_EDIT|K_UPPER);
-                            break;
-						case 2:
-							sprintf(str,"%u",cfg.arcdef[i].byteloc);
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Offset to Hex ID",str,5
-								,K_NUMBER|K_EDIT);
-							cfg.arcdef[i].byteloc=atoi(str);
-							break;
-						case 3:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Pack Command Line",cfg.arcdef[i].pack,50
-								,K_EDIT);
-                            break;
-						case 4:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Unpack Command Line",cfg.arcdef[i].unpack,50
-								,K_EDIT);
-                            break;
-							} } }
-            break;
-		case 9:
-helpbuf=
-" Additional Echo Lists \r\n\r\n"
-"This feature allows you to specify echo lists (in addition to your\r\n"
-"AREAS.BBS file) for SBBSecho to search for area add requests.\r\n";
-			i=0;
-			while(1) {
-				for(j=0;j<cfg.listcfgs;j++)
-					sprintf(opt[j],"%-50.50s",cfg.listcfg[j].listpath);
-				opt[j][0]=0;
-				i=ulist(WIN_ORG|WIN_INS|WIN_DEL|WIN_ACT|WIN_GET|WIN_PUT
-					|WIN_INSACT|WIN_DELACT|WIN_XTR
-					,0,0,0,&i,0,"Additional Echo Lists",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					str[0]=0;
-helpbuf=
-" Echo List \r\n\r\n"
-"This is the path and filename of the echo list file you wish\r\n"
-"to add.\r\n";
-					if(uinput(WIN_MID|WIN_SAV,0,0
-						,"Echo List Path/Name",str,50,K_EDIT|K_UPPER)<1)
-						continue;
-					if((cfg.listcfg=(echolist_t *)REALLOC(cfg.listcfg
-						,sizeof(echolist_t)*(cfg.listcfgs+1)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-                        exit(1); }
-					for(j=cfg.listcfgs;j>i;j--)
-						memcpy(&cfg.listcfg[j],&cfg.listcfg[j-1]
-							,sizeof(echolist_t));
-					cfg.listcfgs++;
-					memset(&cfg.listcfg[i],0,sizeof(echolist_t));
-					strcpy(cfg.listcfg[i].listpath,str);
-					continue; }
-
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					cfg.listcfgs--;
-					if(cfg.listcfgs<=0) {
-						cfg.listcfgs=0;
-						continue; }
-					for(j=i;j<cfg.listcfgs;j++)
-						memcpy(&cfg.listcfg[j],&cfg.listcfg[j+1]
-							,sizeof(echolist_t));
-					if((cfg.listcfg=(echolist_t *)REALLOC(cfg.listcfg
-						,sizeof(echolist_t)*(cfg.listcfgs)))==NULL) {
-						printf("\nMemory Allocation Error\n");
-						exit(1); }
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					memcpy(&savlistcfg,&cfg.listcfg[i],sizeof(echolist_t));
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					memcpy(&cfg.listcfg[i],&savlistcfg,sizeof(echolist_t));
-					continue; }
-				while(1) {
-					j=0;
-					sprintf(opt[j++],"%-20.20s %.19s","Echo List Path/Name"
-						,cfg.listcfg[i].listpath);
-					sprintf(opt[j++],"%-20.20s %s","Hub Address"
-						,(cfg.listcfg[i].forward.zone) ?
-						 faddrtoa(cfg.listcfg[i].forward) : "None");
-					sprintf(opt[j++],"%-20.20s %s","Forward Password"
-						,(cfg.listcfg[i].password[0]) ?
-						 cfg.listcfg[i].password : "None");
-					sprintf(opt[j++],"%-20.20s %s","Forward Requests"
-						,(cfg.listcfg[i].misc&NOFWD) ? "No" : "Yes");
-					str[0]=0;
-					for(k=0;k<cfg.listcfg[i].numflags;k++) {
-						strcat(str,cfg.listcfg[i].flag[k].flag);
-						strcat(str," "); }
-					sprintf(opt[j++],"%-20.20s %s","Echo List Flags",str);
-					opt[j][0]=0;
-					k=ulist(WIN_MID|WIN_ACT,0,0,60,&nodeop,0,"Echo List",opt);
-					if(k==-1)
-						break;
-					switch(k) {
-						case 0:
-							strcpy(str,cfg.listcfg[i].listpath);
-							if(uinput(WIN_MID|WIN_SAV,0,0
-								,"Echo List Path/Name",str,50
-								,K_EDIT|K_UPPER)<1)
-								continue;
-							strcpy(cfg.listcfg[i].listpath,str);
-							break;
-						case 1:
-							if(cfg.listcfg[i].forward.zone)
-								strcpy(str,faddrtoa(cfg.listcfg[i].forward));
-							else
-								str[0]=0;
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Hub Address",str
-								,25,K_EDIT);
-							if(str[0])
-								cfg.listcfg[i].forward=atofaddr(str);
-							else
-								memset(&cfg.listcfg[i].forward,0
-									,sizeof(faddr_t));
-							break;
-						case 2:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Password to use when forwarding requests"
-								,cfg.listcfg[i].password,25,K_EDIT|K_UPPER);
-							break;
-						case 3:
-                            cfg.listcfg[i].misc^=NOFWD;
-							if(cfg.listcfg[i].misc&NOFWD)
-								cfg.listcfg[i].password[0]=0;
-                            break;
-						case 4:
-							while(1) {
-								for(j=0;j<cfg.listcfg[i].numflags;j++)
-									strcpy(opt[j],cfg.listcfg[i].flag[j].flag);
-								opt[j][0]=0;
-								x=ulist(WIN_SAV|WIN_INS|WIN_DEL|WIN_ACT|
-									WIN_XTR|WIN_INSACT|WIN_DELACT|WIN_RHT
-									,0,0,0,&x,0,"Echo List Flags",opt);
-								if(x==-1)
-									break;
-								if((x&MSK_ON)==MSK_INS) {
-									x&=MSK_OFF;
-									str[0]=0;
-helpbuf=
-" Echo List Flag \r\n\r\n"
-"These flags determine which nodes have access to the current\r\n"
-"echolist file\r\n";
-									if(uinput(WIN_MID|WIN_SAV,0,0
-										,"Echo List Flag",str,4
-										,K_EDIT|K_UPPER)<1)
-										continue;
-									if((cfg.listcfg[i].flag=(flag_t *)
-										REALLOC(cfg.listcfg[i].flag
-										,sizeof(flag_t)*
-										(cfg.listcfg[i].numflags+1)))==NULL) {
-										printf("\nMemory Allocation Error\n");
-										exit(1); }
-									for(j=cfg.listcfg[i].numflags;j>x;j--)
-										memcpy(&cfg.listcfg[i].flag[j]
-											,&cfg.listcfg[i].flag[j-1]
-											,sizeof(flag_t));
-									cfg.listcfg[i].numflags++;
-									memset(&cfg.listcfg[i].flag[x].flag
-										,0,sizeof(flag_t));
-									strcpy(cfg.listcfg[i].flag[x].flag,str);
-									continue; }
-
-								if((x&MSK_ON)==MSK_DEL) {
-									x&=MSK_OFF;
-									cfg.listcfg[i].numflags--;
-									if(cfg.listcfg[i].numflags<=0) {
-										cfg.listcfg[i].numflags=0;
-										continue; }
-									for(j=x;j<cfg.listcfg[i].numflags;j++)
-										strcpy(cfg.listcfg[i].flag[j].flag
-											,cfg.listcfg[i].flag[j+1].flag);
-									if((cfg.listcfg[i].flag=(flag_t *)
-										REALLOC(cfg.listcfg[i].flag
-										,sizeof(flag_t)*
-										(cfg.listcfg[i].numflags)))==NULL) {
-										printf("\nMemory Allocation Error\n");
-										exit(1); }
-									continue; }
-								strcpy(str,cfg.listcfg[i].flag[x].flag);
-helpbuf=
-" Echo List Flag \r\n\r\n"
-"These flags determine which nodes have access to the current\r\n"
-"echolist file\r\n";
-									uinput(WIN_MID|WIN_SAV,0,0,"Echo List Flag"
-										,str,4,K_EDIT|K_UPPER);
-									strcpy(cfg.listcfg[i].flag[x].flag,str);
-									continue; }
-							break;
-							} } }
-            break;
-
-		case -1:
-helpbuf=
-" Save Configuration File \r\n\r\n"
-"Select Yes to save the config file, No to quit without saving,\r\n"
-"or hit  ESC  to go back to the menu.\r\n\r\n";
-			i=0;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			i=ulist(WIN_MID,0,0,0,&i,0,"Save Config File",opt);
-			if(i==-1) break;
-			if(i) bail(0);
-			if((file=open(cfg.cfgfile
-				,O_WRONLY|O_BINARY|O_CREAT|O_DENYALL|O_TRUNC,S_IWRITE))==-1) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error opening %s\r\n",cfg.cfgfile);
-				bail(1); }
-			if((stream=fdopen(file,"wb"))==NULL) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error fdopen %s\r\n",cfg.cfgfile);
-				bail(1); }
-			if(!node_swap)
-				fprintf(stream,"NOSWAP\r\n");
-			if(cfg.notify)
-				fprintf(stream,"NOTIFY %u\r\n",cfg.notify);
-			if(misc&SECURE)
-				fprintf(stream,"SECURE_ECHOMAIL\r\n");
-			if(misc&KILL_EMPTY_MAIL)
-				fprintf(stream,"KILL_EMPTY\r\n");
-			if(misc&STORE_SEENBY)
-				fprintf(stream,"STORE_SEENBY\r\n");
-			if(misc&STORE_PATH)
-				fprintf(stream,"STORE_PATH\r\n");
-			if(misc&STORE_KLUDGE)
-				fprintf(stream,"STORE_KLUDGE\r\n");
-			if(misc&FUZZY_ZONE)
-				fprintf(stream,"FUZZY_ZONE\r\n");
-			if(misc&FLO_MAILER)
-				fprintf(stream,"FLO_MAILER\r\n");
-			if(misc&ELIST_ONLY)
-				fprintf(stream,"ELIST_ONLY\r\n");
-			if(cfg.areafile[0])
-				fprintf(stream,"AREAFILE %s\r\n",cfg.areafile);
-			if(cfg.logfile[0])
-				fprintf(stream,"LOGFILE %s\r\n",cfg.logfile);
-			if(cfg.log!=LOG_DEFAULTS) {
-				if(cfg.log==0xffffffffUL)
-					fprintf(stream,"LOG ALL\r\n");
-				else if(cfg.log==0L)
-					fprintf(stream,"LOG NONE\r\n");
-				else
-					fprintf(stream,"LOG %08lX\r\n",cfg.log); }
-			if(cfg.inbound[0])
-				fprintf(stream,"INBOUND %s\r\n",cfg.inbound);
-			if(cfg.secure[0])
-				fprintf(stream,"SECURE_INBOUND %s\r\n",cfg.secure);
-			if(cfg.outbound[0])
-				fprintf(stream,"OUTBOUND %s\r\n",cfg.outbound);
-			if(cfg.maxbdlsize!=DFLT_BDL_SIZE)
-				fprintf(stream,"ARCSIZE %lu\r\n",cfg.maxbdlsize);
-			if(cfg.maxpktsize!=DFLT_PKT_SIZE)
-				fprintf(stream,"PKTSIZE %lu\r\n",cfg.maxpktsize);
-			for(i=j=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].attr&SEND_NOTIFY) {
-					if(!j) fprintf(stream,"SEND_NOTIFY");
-                    fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr));
-                    j++; }
-			if(j) fprintf(stream,"\r\n");
-			for(i=j=0;i<cfg.nodecfgs;i++)
-                if(cfg.nodecfg[i].attr&ATTR_HOLD) {
-                    if(!j) fprintf(stream,"HOLD");
-                    fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr));
-                    j++; }
-            if(j) fprintf(stream,"\r\n");
-			for(i=j=0;i<cfg.nodecfgs;i++)
-                if(cfg.nodecfg[i].attr&ATTR_DIRECT) {
-                    if(!j) fprintf(stream,"DIRECT");
-                    fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr));
-                    j++; }
-            if(j) fprintf(stream,"\r\n");
-			for(i=j=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].attr&ATTR_CRASH) {
-					if(!j) fprintf(stream,"CRASH");
-					fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr));
-					j++; }
-			if(j) fprintf(stream,"\r\n");
-			for(i=j=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].attr&ATTR_PASSIVE) {
-					if(!j) fprintf(stream,"PASSIVE");
-					fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr));
-                    j++; }
-			if(j) fprintf(stream,"\r\n");
-
-			for(i=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].pktpwd[0])
-					fprintf(stream,"PKTPWD %s %s\r\n"
-						,faddrtoa(cfg.nodecfg[i].faddr),cfg.nodecfg[i].pktpwd);
-
-			for(i=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].pkt_type)
-					fprintf(stream,"PKTTYPE %s %s\r\n"
-						,cfg.nodecfg[i].pkt_type==PKT_TWO_TWO ? "2.2":"2"
-						,faddrtoa(cfg.nodecfg[i].faddr));
-
-			for(i=0;i<cfg.arcdefs;i++)
-				fprintf(stream,"PACKER %s %u %s\r\n  PACK %s\r\n"
-					"  UNPACK %s\r\nEND\r\n"
-					,cfg.arcdef[i].name
-					,cfg.arcdef[i].byteloc
-					,cfg.arcdef[i].hexid
-					,cfg.arcdef[i].pack
-					,cfg.arcdef[i].unpack
-					);
-			for(i=0;i<cfg.arcdefs;i++) {
-				for(j=k=0;j<cfg.nodecfgs;j++)
-					if(cfg.nodecfg[j].arctype==i) {
-						if(!k)
-							fprintf(stream,"%-10s %s","USEPACKER"
-								,cfg.arcdef[i].name);
-						k++;
-						fprintf(stream," %s",faddrtoa(cfg.nodecfg[j].faddr)); }
-				if(k)
-					fprintf(stream,"\r\n"); }
-
-			for(i=j=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].arctype==0xffff) {
-					if(!j)
-						fprintf(stream,"%-10s %s","USEPACKER","NONE");
-					j++;
-					fprintf(stream," %s",faddrtoa(cfg.nodecfg[i].faddr)); }
-			if(j)
-				fprintf(stream,"\r\n");
-
-			for(i=0;i<cfg.listcfgs;i++) {
-				fprintf(stream,"%-10s","ECHOLIST");
-				if(cfg.listcfg[i].password[0])
-					fprintf(stream," FORWARD %s %s"
-						,faddrtoa(cfg.listcfg[i].forward)
-						,cfg.listcfg[i].password);
-				else if(cfg.listcfg[i].misc&NOFWD &&
-					cfg.listcfg[i].forward.zone)
-					fprintf(stream," HUB %s"
-						,faddrtoa(cfg.listcfg[i].forward));
-                fprintf(stream," %s",cfg.listcfg[i].listpath);
-                for(j=0;j<cfg.listcfg[i].numflags;j++)
-                    fprintf(stream," %s",cfg.listcfg[i].flag[j].flag);
-                fprintf(stream,"\r\n"); }
-
-			for(i=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].password[0]) {
-					fprintf(stream,"%-10s %s %s","AREAFIX"
-						,faddrtoa(cfg.nodecfg[i].faddr)
-						,cfg.nodecfg[i].password);
-					for(j=0;j<cfg.nodecfg[i].numflags;j++)
-						fprintf(stream," %s",cfg.nodecfg[i].flag[j].flag);
-					fprintf(stream,"\r\n"); }
-
-			for(i=0;i<cfg.nodecfgs;i++)
-				if(cfg.nodecfg[i].route.zone) {
-					fprintf(stream,"%-10s %s","ROUTE_TO"
-						,faddrtoa(cfg.nodecfg[i].route));
-					fprintf(stream," %s"
-						,faddrtoa(cfg.nodecfg[i].faddr));
-					for(j=i+1;j<cfg.nodecfgs;j++)
-						if(!memcmp(&cfg.nodecfg[j].route,&cfg.nodecfg[i].route
-							,sizeof(faddr_t))) {
-							fprintf(stream," %s"
-								,faddrtoa(cfg.nodecfg[j].faddr));
-							cfg.nodecfg[j].route.zone=0; }
-					fprintf(stream,"\r\n"); }
-
-			fclose(stream);
-			bail(0);
-	}
-}
-}
-/****************************************************************************/
-/* Checks the disk drive for the existance of a file. Returns 1 if it 		*/
-/* exists, 0 if it doesn't.													*/
-/* Called from upload														*/
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-	return(1);
-return(0);
-}
diff --git a/src/sbbs2/echo/echocfg.mak b/src/sbbs2/echo/echocfg.mak
deleted file mode 100644
index 6af1ffce79c091f4cc799555716c321e1811ef34..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/echocfg.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-
-# Macros
-CC	= bcc
-LD	= tlink
-UIFC	= ..\..\uifc
-MSWAIT	= ..\..\mswait
-INCLUDE = \bc45\include;$(UIFC);..;..\smb
-LIB	= \bc45\lib
-MODEL	= l
-CFLAGS  = -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LDFLAGS = /n /c
-OBJS	= $(MSWAIT)\dos\mswait$(MODEL).obj uifc.obj read_cfg.obj
-HEADERS = $(UIFC)\uifc.h sbbsecho.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-echocfg.exe: $(OBJS) echocfg.obj
-    	@echo Linking $< ...
-	$(LD) $(LDFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) echocfg.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-
-# All .obj modules
-echocfg.obj: $(HEADERS)
-
-uifc.obj: $(UIFC)\uifc.h $(UIFC)\uifc.c
-	@echo Compiling $(UIFC)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $(UIFC)\$*.c
-
diff --git a/src/sbbs2/echo/makeall.bat b/src/sbbs2/echo/makeall.bat
deleted file mode 100755
index d6b6d6ff757cec74de667dd842bdb8047fbb72d4..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/makeall.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-make
-if errorlevel 1 goto end
-wmake -f sbbsecho.wat OS=OS2
-if errorlevel 1 goto end
-wmake -f sbbsecho.wat OS=DOS4G
-if errorlevel 1 goto end
-wmake -f sbbsecho.wat OS=NT
-:end
\ No newline at end of file
diff --git a/src/sbbs2/echo/makecfg.bat b/src/sbbs2/echo/makecfg.bat
deleted file mode 100755
index 5f6ed1e474943bdd178bb1e9e8b3d038fd630c7f..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/makecfg.bat
+++ /dev/null
@@ -1 +0,0 @@
-@make -fechocfg %1 %2 %3 %4
diff --git a/src/sbbs2/echo/makefile b/src/sbbs2/echo/makefile
deleted file mode 100644
index 82f3398b8721e3c011fead53f868415f0feb4598..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/makefile
+++ /dev/null
@@ -1,94 +0,0 @@
-############################################
-# Makefile for Synchronet SBBSecho Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-
-!ifdef __OS2__
-OS	= OS2
-CC	= c:\bcos2\bin\bcc
-LD	= c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE) -w-prot
-LFLAGS  = -c
-
-!elif $d(DOSX)
-OS	= DOSX
-CC	= \bc4\bin\bcc32
-LD    	= \bc4\bin\tlink32
-INCLUDE = \bc4\include;..;..\smb;..\rio
-LIB	= \bc4\lib
-CFLAGS	= -w-pro -d -C -WX -I$(INCLUDE) -w-prot
-LFLAGS  = -Tpe -ax -n -c -L$(LIB)
-
-!else
-OS	= DOS
-CC	= \bc45\bin\bcc
-LD	= \bc45\bin\tlink
-INCLUDE = \bc45\include;..\smb;..\rio;..
-LIB	= \bc45\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -DLZH_DYNAMIC_BUF -DSMB_GETMSGTXT -w-pro
-
-LFLAGS	= -c -L$(LIB)
-!endif
-MAIN	= $(OS)\sbbsecho.exe
-OBJS	= $(OS)\sbbsecho.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj \
-	  $(OS)\smblib.obj $(OS)\ars.obj $(OS)\lzh.obj \
-	  $(OS)\read_cfg.obj
-HEADERS = ..\sbbsdefs.h ..\scfgvars.c ..\smb\smbdefs.h ..\smb\smblib.h 
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) $(HEADERS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-c02.obj $(OBJS)
-+, $*, $*, os2.lib c2.lib
-!elif $d(DOSX)
-	$(LD) $(LFLAGS) @&&+
-c0X32.obj $(OBJS)
-+, $*, $*, DPMI32 CW32
-!else
-	$(LD) $(LFLAGS) @&&+
-c0$(MODEL) $(OBJS)
-+, $*, $*, ..\..\spawno\spawnl.lib mathl emu cl
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_FILE_CFG
--DNO_XTRN_CFG
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling SMBLIB ...
-	$(CC) -DSMB_GETMSGTXT $(CFLAGS) -n$(OS) -c ..\smb\smblib.c
-
-$(OS)\lzh.obj: ..\smb\lzh.c ..\smb\lzh.h
-        @echo Compiling LZH ...
-	$(CC) $(CFLAGS) -n$(OS) -c ..\smb\lzh.c
-
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h 
-        @echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -n$(OS) -c ..\ars.c
-
-$(OS)\sbbsecho.obj: sbbsecho.c sbbsecho.h
-	@echo Compiling $&.c to $< ...
-	$(CC) $(CFLAGS) -n$(OS) -c sbbsecho.c
diff --git a/src/sbbs2/echo/read_cfg.c b/src/sbbs2/echo/read_cfg.c
deleted file mode 100644
index 0db669b236e37eb1f9f4a523e67c34e796b6beb3..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/read_cfg.c
+++ /dev/null
@@ -1,681 +0,0 @@
-/* READ_CFG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Portions written by Allen Christiansen 1994-1996 						*/
-
-#include <dos.h>
-#include <mem.h>
-#include <time.h>
-#include <errno.h>
-#include <stdio.h>
-#include <conio.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <share.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <process.h>
-#include <sys\stat.h>
-
-#include "crc32.h"
-#include "sbbsdefs.h"
-#include "sbbsecho.h"
-
-#ifdef __WATCOMC__
-    #define O_DENYNONE SH_DENYNO
-#endif
-
-extern uchar node_swap;
-extern long misc;
-extern config_t cfg;
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.   All files are opened in BINARY mode.            */
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-    char logstr[256];
-    int file,share,count=0;
-
-if(access&O_DENYNONE) {
-	access&=~O_DENYNONE;
-	share=SH_DENYNO; }
-else if(access==O_RDONLY) share=SH_DENYWR;
-else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-    && errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-    printf("\7\nNOPEN: ACCESS DENIED\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.                                                               */
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-    char mode[128];
-    FILE *stream;
-
-if(access&O_WRONLY) {
-	access&=~O_WRONLY;
-	access|=O_RDWR; }	 /* fdopen can't open WRONLY */
-
-if(((*file)=nopen(str,access))==-1)
-    return(NULL);
-
-if(access&O_APPEND) {
-	if(access&(O_RDONLY|O_RDWR))
-        strcpy(mode,"a+");
-    else
-        strcpy(mode,"a"); }
-else {
-	if(access&(O_WRONLY|O_RDWR))
-        strcpy(mode,"r+");
-    else
-        strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	printf("\7\nFDOPEN(%s) FAILED\n",mode);
-    close(*file);
-    return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-/******************************************************************************
- Here we take a string and put a terminator in place of the first TAB or SPACE
-******************************************************************************/
-char *cleanstr(char *instr)
-{
-	int i;
-
-for(i=0;instr[i];i++)
-	if((uchar)instr[i]<=SP)
-		break;
-instr[i]=0;
-return(instr);
-}
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-faddr_t atofaddr(char *instr)
-{
-	char *p,str[51];
-    faddr_t addr;
-
-sprintf(str,"%.50s",instr);
-cleanstr(str);
-if(!stricmp(str,"ALL")) {
-	addr.zone=addr.net=addr.node=addr.point=0xffff;
-	return(addr); }
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-	if(!strnicmp(str,"ALL:",4))
-		addr.zone=0xffff;
-	else
-		addr.zone=atoi(str);
-	p++;
-	if(!strnicmp(p,"ALL",3))
-		addr.net=0xffff;
-	else
-		addr.net=atoi(p); }
-else {
-#ifdef SCFG
-    if(total_faddrs)
-        addr.zone=faddr[0].zone;
-    else
-#endif
-        addr.zone=1;
-    addr.net=atoi(str); }
-if(!addr.zone)              /* no such thing as zone 0 */
-    addr.zone=1;
-if((p=strchr(str,'/'))!=NULL) {
-	p++;
-	if(!strnicmp(p,"ALL",3))
-		addr.node=0xffff;
-	else
-		addr.node=atoi(p); }
-else {
-	if(!addr.net) {
-#ifdef SCFG
-		if(total_faddrs)
-			addr.net=faddr[0].net;
-		else
-#endif
-			addr.net=1; }
-	addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL) {
-	p++;
-	if(!strnicmp(p,"ALL",3))
-		addr.point=0xffff;
-	else
-		addr.point=atoi(p); }
-return(addr);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(faddr_t addr)
-{
-    static char str[25];
-	char tmp[25];
-
-if(addr.zone==0xffff)
-	strcpy(str,"ALL");
-else {
-	sprintf(str,"%u:",addr.zone);
-	if(addr.net==0xffff)
-		strcat(str,"ALL");
-	else {
-		sprintf(tmp,"%u/",addr.net);
-		strcat(str,tmp);
-		if(addr.node==0xffff)
-			strcat(str,"ALL");
-		else {
-			sprintf(tmp,"%u",addr.node);
-			strcat(str,tmp);
-			if(addr.point==0xffff)
-				strcat(str,".ALL");
-			else if(addr.point) {
-				sprintf(tmp,".%u",addr.point);
-				strcat(str,tmp); } } } }
-return(str);
-}
-/******************************************************************************
- This function returns the number of the node in the SBBSECHO.CFG file which
- matches the address passed to it (or cfg.nodecfgs if no match).
- ******************************************************************************/
-int matchnode(faddr_t addr, int exact)
-{
-	int i;
-
-if(exact!=2) {
-	for(i=0;i<cfg.nodecfgs;i++) 				/* Look for exact match */
-		if(!memcmp(&cfg.nodecfg[i].faddr,&addr,sizeof(faddr_t)))
-			break;
-	if(exact || i<cfg.nodecfgs)
-		return(i); }
-
-for(i=0;i<cfg.nodecfgs;i++) 					/* Look for point match */
-	if(cfg.nodecfg[i].faddr.point==0xffff
-		&& addr.zone==cfg.nodecfg[i].faddr.zone
-		&& addr.net==cfg.nodecfg[i].faddr.net
-		&& addr.node==cfg.nodecfg[i].faddr.node)
-		break;
-if(i<cfg.nodecfgs)
-    return(i);
-
-for(i=0;i<cfg.nodecfgs;i++) 					/* Look for node match */
-	if(cfg.nodecfg[i].faddr.node==0xffff
-		&& addr.zone==cfg.nodecfg[i].faddr.zone
-		&& addr.net==cfg.nodecfg[i].faddr.net)
-		break;
-if(i<cfg.nodecfgs)
-    return(i);
-
-for(i=0;i<cfg.nodecfgs;i++) 					/* Look for net match */
-	if(cfg.nodecfg[i].faddr.net==0xffff
-		&& addr.zone==cfg.nodecfg[i].faddr.zone)
-		break;
-if(i<cfg.nodecfgs)
-	return(i);
-
-for(i=0;i<cfg.nodecfgs;i++) 					/* Look for total wild */
-	if(cfg.nodecfg[i].faddr.zone==0xffff)
-        break;
-return(i);
-}
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-void read_cfg()
-{
-	uchar str[1025],tmp[512],*p,*tp;
-	short attr;
-	int i,j,file;
-	FILE *stream;
-	faddr_t addr,route_addr;
-
-
-/****** READ IN SBBSECHO.CFG FILE *******/
-
-printf("\n\nReading %s\n",cfg.cfgfile);
-if((stream=fnopen(&file,cfg.cfgfile,O_RDONLY))==NULL) {
-    printf("Unable to open %s for read.\n",cfg.cfgfile);
-    exit(1); }
-
-cfg.maxpktsize=DFLT_PKT_SIZE;
-cfg.maxbdlsize=DFLT_BDL_SIZE;
-cfg.badecho=-1;
-cfg.log=LOG_DEFAULTS;
-
-while(1) {
-    if(!fgets(str,256,stream))
-        break;
-    truncsp(str);
-    p=str;
-    while(*p && *p<=SP) p++;
-    if(*p==';')
-        continue;
-    sprintf(tmp,"%-.25s",p);
-    tp=strchr(tmp,SP);
-    if(tp)
-        *tp=0;                              /* Chop off at space */
-    strupr(tmp);                            /* Convert code to uppercase */
-    while(*p>SP) p++;                       /* Skip code */
-    while(*p && *p<=SP) p++;                /* Skip white space */
-
-    if(!strcmp(tmp,"PACKER")) {             /* Archive Definition */
-		if((cfg.arcdef=(arcdef_t *)REALLOC(cfg.arcdef
-            ,sizeof(arcdef_t)*(cfg.arcdefs+1)))==NULL) {
-			printf("\nError allocating %u bytes of memory for arcdef #%u.\n"
-                ,sizeof(arcdef_t)*(cfg.arcdefs+1),cfg.arcdefs+1);
-            exit(1); }
-        sprintf(cfg.arcdef[cfg.arcdefs].name,"%-.25s",p);
-        tp=cfg.arcdef[cfg.arcdefs].name;
-        while(*tp && *tp>SP) tp++;
-        *tp=0;
-        while(*p && *p>SP) p++;
-        while(*p && *p<=SP) p++;
-        cfg.arcdef[cfg.arcdefs].byteloc=atoi(p);
-        while(*p && *p>SP) p++;
-        while(*p && *p<=SP) p++;
-        sprintf(cfg.arcdef[cfg.arcdefs].hexid,"%-.25s",p);
-        tp=cfg.arcdef[cfg.arcdefs].hexid;
-        while(*tp && *tp>SP) tp++;
-        *tp=0;
-        while(fgets(str,256,stream) && strnicmp(str,"END",3)) {
-            p=str;
-            while(*p && *p<=SP) p++;
-            if(!strnicmp(p,"PACK ",5)) {
-                p+=5;
-                while(*p && *p<=SP) p++;
-                sprintf(cfg.arcdef[cfg.arcdefs].pack,"%-.80s",p);
-                truncsp(cfg.arcdef[cfg.arcdefs].pack);
-                continue; }
-            if(!strnicmp(p,"UNPACK ",7)) {
-                p+=7;
-                while(*p && *p<=SP) p++;
-                sprintf(cfg.arcdef[cfg.arcdefs].unpack,"%-.80s",p);
-                truncsp(cfg.arcdef[cfg.arcdefs].unpack); } }
-        ++cfg.arcdefs;
-        continue; }
-
-	if(!strcmp(tmp,"REGNUM"))
-		continue;
-
-	if(!strcmp(tmp,"NOTIFY")) {
-		cfg.notify=atoi(cleanstr(p));
-		continue; }
-
-	if(!strcmp(tmp,"LOG")) {
-		cleanstr(p);
-		if(!stricmp(p,"ALL"))
-			cfg.log=0xffffffffUL;
-		else if(!stricmp(p,"DEFAULT"))
-			cfg.log=LOG_DEFAULTS;
-		else if(!stricmp(p,"NONE"))
-			cfg.log=0L;
-		else
-			cfg.log=strtol(cleanstr(p),0,16);
-		continue; }
-
-    if(!strcmp(tmp,"NOSWAP")) {
-        node_swap=0;
-        continue; }
-
-	if(!strcmp(tmp,"SECURE_ECHOMAIL")) {
-		misc|=SECURE;
-		continue; }
-
-    if(!strcmp(tmp,"CHECKMEM")) {
-        misc|=CHECKMEM;
-        continue; }
-
-    if(!strcmp(tmp,"STORE_SEENBY")) {
-        misc|=STORE_SEENBY;
-        continue; }
-
-    if(!strcmp(tmp,"STORE_PATH")) {
-        misc|=STORE_PATH;
-        continue; }
-
-    if(!strcmp(tmp,"STORE_KLUDGE")) {
-        misc|=STORE_KLUDGE;
-        continue; }
-
-    if(!strcmp(tmp,"FUZZY_ZONE")) {
-        misc|=FUZZY_ZONE;
-        continue; }
-
-	if(!strcmp(tmp,"FAST_OPEN")) {
-		continue; }
-
-    if(!strcmp(tmp,"FLO_MAILER")) {
-        misc|=FLO_MAILER;
-        continue; }
-
-	if(!strcmp(tmp,"ELIST_ONLY")) {
-		misc|=ELIST_ONLY;
-		continue; }
-
-	if(!strcmp(tmp,"KILL_EMPTY")) {
-		misc|=KILL_EMPTY_MAIL;
-		continue; }
-
-    if(!strcmp(tmp,"AREAFILE")) {
-        sprintf(cfg.areafile,"%-.80s",cleanstr(p));
-        continue; }
-
-    if(!strcmp(tmp,"LOGFILE")) {
-        sprintf(cfg.logfile,"%-.80s",cleanstr(p));
-        continue; }
-
-    if(!strcmp(tmp,"INBOUND")) {            /* Inbound directory */
-        sprintf(cfg.inbound,"%-.80s",cleanstr(p));
-        if(cfg.inbound[strlen(cfg.inbound)-1]!='\\')
-            strcat(cfg.inbound,"\\");
-        continue; }
-
-    if(!strcmp(tmp,"SECURE_INBOUND")) {     /* Secure Inbound directory */
-        sprintf(cfg.secure,"%-.80s",cleanstr(p));
-        if(cfg.secure[strlen(cfg.secure)-1]!='\\')
-            strcat(cfg.secure,"\\");
-        continue; }
-
-    if(!strcmp(tmp,"OUTBOUND")) {           /* Outbound directory */
-        sprintf(cfg.outbound,"%-.80s",cleanstr(p));
-        if(cfg.outbound[strlen(cfg.outbound)-1]!='\\')
-            strcat(cfg.outbound,"\\");
-        continue; }
-
-    if(!strcmp(tmp,"ARCSIZE")) {            /* Maximum bundle size */
-        cfg.maxbdlsize=atol(p);
-        continue; }
-
-    if(!strcmp(tmp,"PKTSIZE")) {            /* Maximum packet size */
-        cfg.maxpktsize=atol(p);
-        continue; }
-
-    if(!strcmp(tmp,"USEPACKER")) {          /* Which packer to use */
-		if(!*p)
-			continue;
-		strcpy(str,p);
-		p=str;
-		while(*p && *p>SP) p++;
-		if(!*p)
-			continue;
-		*p=0;
-		p++;
-		for(i=0;i<cfg.arcdefs;i++)
-			if(!strnicmp(cfg.arcdef[i].name,str
-				,strlen(cfg.arcdef[i].name)))
-				break;
-		if(i==cfg.arcdefs)				/* i = number of arcdef til done */
-			i=0xffff;					/* Uncompressed type if not found */
-		while(*p) {
-			while(*p && *p<=SP) p++;
-			if(!*p)
-				break;
-			addr=atofaddr(p);
-			while(*p && *p>SP) p++;
-			j=matchnode(addr,1);
-			if(j==cfg.nodecfgs) {
-				cfg.nodecfgs++;
-				if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-					,sizeof(nodecfg_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u.\n"
-						,j+1);
-					exit(1); }
-				memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-				cfg.nodecfg[j].faddr=addr; }
-			cfg.nodecfg[j].arctype=i; } }
-
-    if(!strcmp(tmp,"PKTPWD")) {         /* Packet Password */
-        if(!*p)
-            continue;
-        addr=atofaddr(p);
-        while(*p && *p>SP) p++;         /* Skip address */
-        while(*p && *p<=SP) p++;        /* Find beginning of password */
-		j=matchnode(addr,1);
-        if(j==cfg.nodecfgs) {
-            cfg.nodecfgs++;
-            if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-                ,sizeof(nodecfg_t)*(j+1)))==NULL) {
-				printf("\nError allocating memory for nodecfg #%u.\n"
-                    ,j+1);
-                exit(1); }
-            memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-            cfg.nodecfg[j].faddr=addr; }
-        sprintf(cfg.nodecfg[j].pktpwd,"%.8s",p); }
-
-	if(!strcmp(tmp,"PKTTYPE")) {            /* Packet Type to Use */
-		if(!*p)
-			continue;
-		strcpy(str,p);
-		p=str;
-		while(*p && *p>SP) p++;
-		*p=0;
-		p++;
-		while(*p) {
-			while(*p && *p<=SP) p++;
-			if(!*p)
-				break;
-			addr=atofaddr(p);
-			while(*p && *p>SP) p++;
-			j=matchnode(addr,1);
-			if(j==cfg.nodecfgs) {
-				cfg.nodecfgs++;
-				if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-					,sizeof(nodecfg_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u.\n"
-						,j+1);
-					exit(1); }
-				memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-				cfg.nodecfg[j].faddr=addr; }
-			if(!strcmp(str,"2+"))
-				cfg.nodecfg[j].pkt_type=PKT_TWO_PLUS;
-			else if(!strcmp(str,"2.2"))
-				cfg.nodecfg[j].pkt_type=PKT_TWO_TWO;
-			else if(!strcmp(str,"2"))
-				cfg.nodecfg[j].pkt_type=PKT_TWO; } }
-
-	if(!strcmp(tmp,"SEND_NOTIFY")) {    /* Nodes to send notify lists to */
-		while(*p) {
-            while(*p && *p<=SP) p++;
-            if(!*p)
-                break;
-            addr=atofaddr(p);
-            while(*p && *p>SP) p++;
-			j=matchnode(addr,1);
-            if(j==cfg.nodecfgs) {
-                cfg.nodecfgs++;
-                if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-                    ,sizeof(nodecfg_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u.\n"
-                        ,j+1);
-                    exit(1); }
-                memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-                cfg.nodecfg[j].faddr=addr; }
-			cfg.nodecfg[j].attr|=SEND_NOTIFY; } }
-
-    if(!strcmp(tmp,"PASSIVE")
-        || !strcmp(tmp,"HOLD")
-        || !strcmp(tmp,"CRASH")
-        || !strcmp(tmp,"DIRECT")) {         /* Set node attributes */
-        if(!strcmp(tmp,"PASSIVE"))
-            attr=ATTR_PASSIVE;
-        else if(!strcmp(tmp,"CRASH"))
-            attr=ATTR_CRASH;
-        else if(!strcmp(tmp,"HOLD"))
-            attr=ATTR_HOLD;
-        else if(!strcmp(tmp,"DIRECT"))
-            attr=ATTR_DIRECT;
-        while(*p) {
-            while(*p && *p<=SP) p++;
-            if(!*p)
-                break;
-            addr=atofaddr(p);
-            while(*p && *p>SP) p++;
-			j=matchnode(addr,1);
-            if(j==cfg.nodecfgs) {
-                cfg.nodecfgs++;
-                if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-                    ,sizeof(nodecfg_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u.\n"
-                        ,j+1);
-                    exit(1); }
-                memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-                cfg.nodecfg[j].faddr=addr; }
-            cfg.nodecfg[j].attr|=attr; } }
-
-	if(!strcmp(tmp,"ROUTE_TO")) {
-		while(*p && *p<=SP) p++;
-		if(*p) {
-			route_addr=atofaddr(p);
-			while(*p && *p>SP) p++; }
-        while(*p) {
-            while(*p && *p<=SP) p++;
-            if(!*p)
-                break;
-            addr=atofaddr(p);
-            while(*p && *p>SP) p++;
-			j=matchnode(addr,1);
-            if(j==cfg.nodecfgs) {
-                cfg.nodecfgs++;
-                if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-                    ,sizeof(nodecfg_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u.\n"
-                        ,j+1);
-                    exit(1); }
-                memset(&cfg.nodecfg[j],0,sizeof(nodecfg_t));
-                cfg.nodecfg[j].faddr=addr; }
-			cfg.nodecfg[j].route=route_addr; } }
-
-    if(!strcmp(tmp,"AREAFIX")) {            /* Areafix stuff here */
-		if(!*p)
-			continue;
-		addr=atofaddr(p);
-		i=matchnode(addr,1);
-		if(i==cfg.nodecfgs) {
-			cfg.nodecfgs++;
-			if((cfg.nodecfg=(nodecfg_t *)REALLOC(cfg.nodecfg
-				,sizeof(nodecfg_t)*(i+1)))==NULL) {
-				printf("\nError allocating memory for nodecfg #%u.\n"
-					,i+1);
-				exit(1); }
-			memset(&cfg.nodecfg[i],0,sizeof(nodecfg_t));
-			cfg.nodecfg[i].faddr=addr; }
-		cfg.nodecfg[i].flag=NULL;
-		while(*p && *p>SP) p++; 		/* Get to the end of the address */
-		while(*p && *p<=SP) p++;		/* Skip over whitespace chars */
-		tp=p;
-		while(*p && *p>SP) p++; 		/* Find end of password 	*/
-		*p=0;							/* and terminate the string */
-		++p;
-		sprintf(cfg.nodecfg[i].password,"%-.25s",tp);
-		while(*p && *p<=SP) p++;		/* Search for more chars */
-		if(!*p) 						/* Nothing else there */
-			continue;
-		while(*p) {
-			tp=p;
-			while(*p && *p>SP) p++; 	/* Find end of this flag */
-			*p=0;						/* and terminate it 	 */
-			++p;
-			for(j=0;j<cfg.nodecfg[i].numflags;j++)
-				if(!strnicmp(cfg.nodecfg[i].flag[j].flag,tp
-					,strlen(cfg.nodecfg[i].flag[j].flag)))
-					break;
-			if(j==cfg.nodecfg[i].numflags) {
-				if((cfg.nodecfg[i].flag=
-					(flag_t *)REALLOC(cfg.nodecfg[i].flag
-					,sizeof(flag_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for nodecfg #%u "
-						"flag #%u.\n",cfg.nodecfgs,j+1);
-					exit(1); }
-				cfg.nodecfg[i].numflags++;
-				sprintf(cfg.nodecfg[i].flag[j].flag,"%.4s",tp); }
-			while(*p && *p<=SP) p++; } }
-
-    if(!strcmp(tmp,"ECHOLIST")) {           /* Echolists go here */
-		if((cfg.listcfg=(echolist_t *)REALLOC(cfg.listcfg
-			,sizeof(echolist_t)*(cfg.listcfgs+1)))==NULL) {
-			printf("\nError allocating memory for echolist cfg #%u.\n"
-				,cfg.listcfgs+1);
-			exit(1); }
-		memset(&cfg.listcfg[cfg.listcfgs],0,sizeof(echolist_t));
-		++cfg.listcfgs;
-		/* Need to forward requests? */
-		if(!strnicmp(p,"FORWARD ",8) || !strnicmp(p,"HUB ",4)) {
-			if(!strnicmp(p,"HUB ",4))
-				cfg.listcfg[cfg.listcfgs-1].misc|=NOFWD;
-            while(*p && *p>SP) p++;
-            while(*p && *p<=SP) p++;
-            if(*p)
-				cfg.listcfg[cfg.listcfgs-1].forward=atofaddr(p);
-            while(*p && *p>SP) p++;
-			while(*p && *p<=SP) p++;
-			if(*p && !(cfg.listcfg[cfg.listcfgs-1].misc&NOFWD)) {
-				tp=p;
-				while(*p && *p>SP) p++;
-				*p=0;
-				++p;
-				while(*p && *p<=SP) p++;
-				sprintf(cfg.listcfg[cfg.listcfgs-1].password,"%.71s",tp); } }
-		else
-			cfg.listcfg[cfg.listcfgs-1].misc|=NOFWD;
-		if(!*p)
-			continue;
-		tp=p;
-		while(*p && *p>SP) p++;
-		*p=0;
-		p++;
-
-		sprintf(cfg.listcfg[cfg.listcfgs-1].listpath,"%-.128s",tp);
-		cfg.listcfg[cfg.listcfgs-1].numflags=0;
-		cfg.listcfg[cfg.listcfgs-1].flag=NULL;
-		while(*p && *p<=SP) p++;		/* Skip over whitespace chars */
-		while(*p) {
-			tp=p;
-			while(*p && *p>SP) p++; 	/* Find end of this flag */
-			*p=0;						/* and terminate it 	 */
-			++p;
-			for(j=0;j<cfg.listcfg[cfg.listcfgs-1].numflags;j++)
-				if(!strnicmp(cfg.listcfg[cfg.listcfgs-1].flag[j].flag,tp
-					,strlen(cfg.listcfg[cfg.listcfgs-1].flag[j].flag)))
-					break;
-			if(j==cfg.listcfg[cfg.listcfgs-1].numflags) {
-				if((cfg.listcfg[cfg.listcfgs-1].flag=
-					(flag_t *)REALLOC(cfg.listcfg[cfg.listcfgs-1].flag
-					,sizeof(flag_t)*(j+1)))==NULL) {
-					printf("\nError allocating memory for listcfg #%u "
-						"flag #%u.\n",cfg.listcfgs,j+1);
-					exit(1); }
-				cfg.listcfg[cfg.listcfgs-1].numflags++;
-				sprintf(cfg.listcfg[cfg.listcfgs-1].flag[j].flag,"%.4s",tp); }
-			while(*p && *p<=SP) p++; } }
-
-//    printf("Unrecognized line in SBBSECHO.CFG file.\n");
-}
-fclose(stream);
-printf("\n");
-}
-
diff --git a/src/sbbs2/echo/sbbsecho.c b/src/sbbs2/echo/sbbsecho.c
deleted file mode 100644
index dad5ece1105a258f3cec2d26fff35434e425026c..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/sbbsecho.c
+++ /dev/null
@@ -1,5060 +0,0 @@
-/* SBBSECHO.C */
-
-/* Developed 1990-2000 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885	*/
-
-/* Portions written by Allen Christiansen 1994-1996 						*/
-
-/* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
-
-#include <dos.h>
-#include <mem.h>
-#include <time.h>
-#include <errno.h>
-#include <stdio.h>
-#include <conio.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <share.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <process.h>
-#include <sys\stat.h>
-
-#include "sbbsdefs.h"
-#include "smblib.h"
-#include "scfglib.h"
-#define GLOBAL extern	/* turn vars.c and scfgvars.c files into headers */
-#include "scfgvars.c"
-#include "post.h"
-#include "lzh.h"
-#include "sbbsecho.h"
-
-extern long crc32tbl[];
-ulong crc32(char *str);
-
-#ifndef __FLAT__
-	#include "..\..\spawno\spawno.h"
-#endif
-
-#ifdef __TURBOC__
-    unsigned _stklen=20000;
-#endif
-
-#ifdef __WATCOMC__
-    #define O_DENYNONE SH_DENYNO
-#endif
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-
-smb_t *smb,*email;
-long misc=(IMPORT_PACKETS|IMPORT_NETMAIL|IMPORT_ECHOMAIL|EXPORT_ECHOMAIL
-			|DELETE_NETMAIL|DELETE_PACKETS);
-ulong netmail=0;
-char tmp[256],pkt_type=0;
-faddr_t sys_faddr;
-config_t cfg;
-int nodefile,secure,cur_smb=0;
-FILE *fidologfile=NULL;
-two_two_t two_two;
-two_plus_t two_plus;
-
-#ifdef __WATCOMC__
-/******************************************************************************
- A DOS to Unix function - because WATCOM doesn't have one
-******************************************************************************/
-time_t dostounix(struct date *d,struct time *t)
-{
-	struct tm tm;
-
-tm.tm_sec=t->ti_sec;
-tm.tm_min=t->ti_min;
-tm.tm_hour=t->ti_hour;
-tm.tm_mday=d->da_day;
-tm.tm_mon=(d->da_mon-1);
-tm.tm_year=d->da_year-1900;
-tm.tm_isdst=0;
-
-return(mktime(&tm));
-}
-#endif
-
-#ifndef __NT__
-#define delfile(x) remove(x)
-#else
-int delfile(char *filename)
-{
-	int i=0;
-
-while(remove(filename) && i++<120)	/* Wait up to 60 seconds to delete file */
-	delay(500); 					/* for Win95 bug fix */
-return(i);
-}
-#endif
-
-/******************************************************************************
- This turns the DOS file date garbage into a long
-******************************************************************************/
-long ddtol(ushort ftim, ushort fdat)
-{
-    struct date date;
-    struct time time;
-
-    date.da_year=((fdat&0xfe00)>>9)+1980;
-    date.da_mon=((fdat&0x01e0)>>5);
-    date.da_day=(fdat&0x001f);
-    time.ti_hour=((ftim&0xf800)>>11);
-    time.ti_min=((ftim&0x07e0)>>5);
-    time.ti_sec=((ftim&0x001f)<<1);
-    time.ti_hund=0;
-    return(dostounix(&date,&time));
-}
-void checkmem(void)
-{
-#ifdef __WATCOMC__
-	char *p=NULL;
-	long size=640L*1024L,over;
-
-	while(size>0) {
-		p=(char *)LMALLOC(size);
-		if(p)
-			break;
-		size-=1024L; }
-
-	printf("\nAvailable Memory = %ld bytes",size);
-	if(p)
-		LFREE(p);
-#elif !defined(__OS2__)
-	printf("\nAvailable Memory = %ld bytes",farcoreleft());
-#endif
-}
-
-/**********************/
-/* Log print function */
-/**********************/
-void logprintf(char *str, ...)
-{
-    va_list argptr;
-    char buf[256];
-    time_t now;
-    struct tm *gm;
-
-if(!(misc&LOGFILE) || fidologfile==NULL)
-    return;
-va_start(argptr,str);
-vsprintf(buf,str,argptr);
-va_end(argptr);
-now=time(NULL);
-gm=localtime(&now);
-fseek(fidologfile,0L,SEEK_END);
-fprintf(fidologfile,"%02u/%02u/%02u %02u:%02u:%02u %s\r\n"
-    ,gm->tm_mon+1,gm->tm_mday,TM_YEAR(gm->tm_year),gm->tm_hour,gm->tm_min,gm->tm_sec
-    ,buf);
-fflush(fidologfile);
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings                                         */
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/*****************************************************************************/
-/* Returns command line generated from instr with %c replacments             */
-/*****************************************************************************/
-char *cmdstr(char *instr, char *fpath, char *fspec)
-{
-    static char cmd[128];
-    char str[256],str2[128];
-    int i,j,len;
-
-len=strlen(instr);
-for(i=j=0;i<len && j<128;i++) {
-    if(instr[i]=='%') {
-        i++;
-        cmd[j]=0;
-        switch(toupper(instr[i])) {
-            case 'F':   /* File path */
-                strcat(cmd,fpath);
-                break;
-            case 'G':   /* Temp directory */
-                if(temp_dir[0]!='\\' && temp_dir[1]!=':') {
-                    strcpy(str,node_dir);
-                    strcat(str,temp_dir);
-                    if(_fullpath(str2,str,40))
-                        strcpy(str,str2);
-                    backslash(str);
-                    strcat(cmd,str);}
-                else
-                    strcat(cmd,temp_dir);
-                break;
-            case 'J':
-                if(data_dir[0]!='\\' && data_dir[1]!=':') {
-                    strcpy(str,node_dir);
-                    strcat(str,data_dir);
-                    if(_fullpath(str2,str,40))
-                        strcpy(str,str2);
-                    backslash(str);
-                    strcat(cmd,str); }
-                else
-                    strcat(cmd,data_dir);
-                break;
-            case 'K':
-                if(ctrl_dir[0]!='\\' && ctrl_dir[1]!=':') {
-                    strcpy(str,node_dir);
-                    strcat(str,ctrl_dir);
-                    if(_fullpath(str2,str,40))
-                        strcpy(str,str2);
-                    backslash(str);
-                    strcat(cmd,str); }
-                else
-                    strcat(cmd,ctrl_dir);
-                break;
-            case 'N':   /* Node Directory (same as SBBSNODE environment var) */
-                strcat(cmd,node_dir);
-                break;
-            case 'O':   /* SysOp */
-                strcat(cmd,sys_op);
-                break;
-            case 'Q':   /* QWK ID */
-                strcat(cmd,sys_id);
-                break;
-            case 'S':   /* File Spec */
-                strcat(cmd,fspec);
-                break;
-            case '!':   /* EXEC Directory */
-                if(exec_dir[0]!='\\' && exec_dir[1]!=':') {
-                    strcpy(str,node_dir);
-                    strcat(str,exec_dir);
-                    if(_fullpath(str2,str,40))
-                        strcpy(str,str2);
-                    backslash(str);
-                    strcat(cmd,str); }
-                else
-                    strcat(cmd,exec_dir);
-                break;
-            case '#':   /* Node number (same as SBBSNNUM environment var) */
-                sprintf(str,"%d",node_num);
-                strcat(cmd,str);
-                break;
-            case '*':
-                sprintf(str,"%03d",node_num);
-                strcat(cmd,str);
-                break;
-            case '%':   /* %% for percent sign */
-                strcat(cmd,"%");
-                break;
-            default:    /* unknown specification */
-				printf("ERROR Checking Command Line '%s'\n",instr);
-				logprintf("ERROR line %d Checking Command Line '%s'",__LINE__
-					,instr);
-				exit(1);
-                break; }
-        j=strlen(cmd); }
-    else
-        cmd[j++]=instr[i]; }
-cmd[j]=0;
-
-return(cmd);
-}
-
-/****************************************************************************/
-/* Runs an external program directly using spawnvp							*/
-/****************************************************************************/
-int execute(char *cmdline)
-{
-	char c,d,e,cmdlen,*arg[30],str[256];
-	int i;
-
-strcpy(str,cmdline);
-arg[0]=str;	/* point to the beginning of the string */
-cmdlen=strlen(str);
-for(c=0,d=1,e=0;c<cmdlen;c++,e++)	/* Break up command line */
-	if(str[c]==SP) {
-		str[c]=0;			/* insert nulls */
-		arg[d++]=str+c+1;	/* point to the beginning of the next arg */
-		e=0; }
-arg[d]=0;
-#ifndef __FLAT__
-if(node_swap) {
-	printf("Swapping...\n");
-	i=spawnvpo(".\\",(const char *)arg[0],(const char **)arg); }
-else
-#endif
-	i=spawnvp(P_WAIT,arg[0],arg);
-return(i);
-}
-/******************************************************************************
- Returns the system address with the same zone as the address passed
-******************************************************************************/
-faddr_t getsysfaddr(short zone)
-{
-	int i;
-	faddr_t sysfaddr;
-
-sysfaddr.zone=sysfaddr.net=sysfaddr.node=1;
-sysfaddr.point=0;
-if(!total_faddrs)
-	return(sys_faddr);
-sysfaddr=faddr[0];
-if(total_faddrs==1)
-	return(sysfaddr);
-for(i=0;i<total_faddrs;i++)
-	if(faddr[i].zone==zone)
-		return(faddr[i]);
-return(sysfaddr);
-}
-/******************************************************************************
- This function creates or appends on existing Binkley compatible .?LO file
- attach file.
- Returns 0 on success.
-******************************************************************************/
-int write_flofile(char *attachment, faddr_t dest)
-{
-	char fname[256],outbound[128],str[128],ch;
-	ushort attr=0;
-	int i,file;
-	FILE *stream;
-
-i=matchnode(dest,0);
-if(i<cfg.nodecfgs)
-    attr=cfg.nodecfg[i].attr;
-
-if(attr&ATTR_CRASH) ch='C';
-else if(attr&ATTR_HOLD) ch='H';
-else if(attr&ATTR_DIRECT) ch='D';
-else ch='F';
-if(dest.zone==faddr[0].zone)		/* Default zone, use default outbound */
-	strcpy(outbound,cfg.outbound);
-else								/* Inter-zone outbound is OUTBOUND.XXX */
-	sprintf(outbound,"%.*s.%03X\\"
-		,strlen(cfg.outbound)-1,cfg.outbound,dest.zone);
-if(dest.point) {					/* Point destination is OUTBOUND\*.PNT */
-	sprintf(str,"%04X%04X.PNT"
-		,dest.net,dest.node);
-	strcat(outbound,str); }
-if(outbound[strlen(outbound)-1]=='\\')
-	outbound[strlen(outbound)-1]=0;
-mkdir(outbound);
-strcat(outbound,"\\");
-if(dest.point)
-	sprintf(fname,"%s%08X.%cLO",outbound,dest.point,ch);
-else
-	sprintf(fname,"%s%04X%04X.%cLO",outbound,dest.net,dest.node,ch);
-if((stream=fnopen(&file,fname,O_WRONLY|O_CREAT))==NULL) {
-	printf("\7ERROR opening %s %s\n",fname,sys_errlist[errno]);
-	logprintf("ERROR line %d opening %s %s",__LINE__,fname,sys_errlist[errno]);
-	return(-1); }
-
-fseek(stream,0L,SEEK_END);
-fprintf(stream,"^%s\r\n",attachment);
-fclose(stream);
-return(0);
-}
-
-/******************************************************************************
- This function will create a netmail message (.MSG format).
- If file is non-zero, will set file attachment bit (for bundles).
- Returns 0 on success.
-******************************************************************************/
-int create_netmail(char *to,char *subject,char *body,faddr_t dest,int file)
-{
-	FILE *fstream;
-	char str[256],fname[256];
-	ushort attr=0;
-	int fmsg;
-	uint i;
-	static uint startmsg;
-	time_t t;
-	faddr_t	faddr;
-	fmsghdr_t hdr;
-	struct tm *tm;
-
-if(!startmsg) startmsg=1;
-i=matchnode(dest,0);
-if(i<cfg.nodecfgs) {
-	attr=cfg.nodecfg[i].attr;
-	if(!attr) {
-		i=matchnode(dest,2);
-		if(i<cfg.nodecfgs)
-			attr=cfg.nodecfg[i].attr; } }
-
-do {
-	for(i=startmsg;i;i++) {
-		sprintf(fname,"%s%u.MSG",netmail_dir,i);
-		if(!fexist(fname))
-			break; }
-	if(!i) {
-		printf("\7%s directory full!\n",netmail_dir);
-		logprintf("Directory full: %s",netmail_dir);
-		return(-1); }
-	startmsg=i+1;
-	strupr(fname);
-	if((fstream=fnopen(&fmsg,fname,O_RDWR|O_CREAT))==NULL) {
-		printf("\7ERROR opening %s %s\n",fname,sys_errlist[errno]);
-		logprintf("ERROR line %d opening %s %s",__LINE__,fname,sys_errlist[errno]);
-		return(-1); }
-
-	faddr=getsysfaddr(dest.zone);
-	memset(&hdr,0,sizeof(fmsghdr_t));
-	hdr.origzone=faddr.zone;
-	hdr.orignet=faddr.net;
-	hdr.orignode=faddr.node;
-	hdr.origpoint=faddr.point;
-	hdr.destzone=dest.zone;
-	hdr.destnet=dest.net;
-	hdr.destnode=dest.node;
-	hdr.destpoint=dest.point;
-
-	hdr.attr=(FIDO_PRIVATE|FIDO_KILLSENT|FIDO_LOCAL);
-	if(file)
-		hdr.attr|=FIDO_FILE;
-
-	if(attr&ATTR_HOLD)
-		hdr.attr|=FIDO_HOLD;
-	if(attr&ATTR_CRASH)
-		hdr.attr|=FIDO_CRASH;
-
-	sprintf(hdr.from,"SBBSecho");
-
-	t=time(NULL);
-	tm=gmtime(&t);
-	sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
-		,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
-		,tm->tm_hour,tm->tm_min,tm->tm_sec);
-
-	if(to)
-		sprintf(hdr.to,"%s",to);
-	else
-		sprintf(hdr.to,"SYSOP");
-
-	sprintf(hdr.subj,"%.71s",subject);
-
-	fwrite(&hdr,sizeof(fmsghdr_t),1,fstream);
-	sprintf(str,"\1INTL %u:%u/%u %u:%u/%u\r"
-		,hdr.destzone,hdr.destnet,hdr.destnode
-		,hdr.origzone,hdr.orignet,hdr.orignode);
-	fwrite(str,strlen(str),1,fstream);
-	if(attr&ATTR_DIRECT) {
-		fwrite("\1FLAGS DIR",10,1,fstream);
-		if(file)
-			fwrite(" KFS\r",5,1,fstream);
-		else
-			fwrite("\r",1,1,fstream); }
-	if(hdr.destpoint) {
-		sprintf(str,"\1TOPT %u\r",hdr.destpoint);
-		fwrite(str,strlen(str),1,fstream); }
-	if(hdr.origpoint) {
-		sprintf(str,"\1FMPT %u\r",hdr.origpoint);
-		fwrite(str,strlen(str),1,fstream); }
-	if(!file || (!(attr&ATTR_DIRECT) && file))
-		fwrite(body,strlen(body)+1,1,fstream);	/* Write additional NULL */
-	else
-		fwrite("\0",1,1,fstream);               /* Write NULL */
-	fclose(fstream);
-} while(!fexist(fname));
-return(0);
-}
-
-/******************************************************************************
- This function takes the contents of 'infile' and puts it into a netmail
- message bound for addr.
-******************************************************************************/
-void file_to_netmail(FILE *infile,char *title,faddr_t addr,char *to)
-{
-	char *buf,*p;
-	long l,m,len;
-
-l=len=ftell(infile);
-if(len>8192L)
-	len=8192L;
-rewind(infile);
-if((buf=(char *)MALLOC(len+1))==NULL) {
-	printf("ERROR allocating %lu bytes for file to netmail buffer.\n",len);
-	logprintf("ERROR line %d allocating %lu for file to netmail buf",__LINE__
-		,len);
-	return; }
-while((m=fread(buf,1,(len>8064L) ? 8064L:len,infile))>0) {
-	buf[m]=0;
-	if(l>8064L && (p=strrchr(buf,'\n'))!=NULL) {
-		p++;
-		if(*p) {
-			*p=0;
-			p++;
-			fseek(infile,-1L,SEEK_CUR);
-			while(*p) { 			/* Seek back to end of last line */
-				p++;
-				fseek(infile,-1L,SEEK_CUR); } } }
-	if(ftell(infile)<l)
-		strcat(buf,"\r\nContinued in next message...\r\n");
-	create_netmail(to,title,buf,addr,0); }
-FREE(buf);
-}
-/******************************************************************************
- This function sends a notify list to applicable nodes, this list includes the
- settings configured for the node, as well as a list of areas the node is
- connected to.
-******************************************************************************/
-void notify_list(void)
-{
-	FILE *tmpf;
-	char str[256];
-	int i,j,k;
-
-for(k=0;k<cfg.nodecfgs;k++) {
-
-	if(!(cfg.nodecfg[k].attr&SEND_NOTIFY))
-		continue;
-
-	if((tmpf=tmpfile())==NULL) {
-		printf("\7ERROR couldn't open tmpfile.\n");
-		logprintf("ERROR line %d couldn't open tmpfile",__LINE__);
-		return; }
-
-	fprintf(tmpf,"Following are the options set for your system and a list "
-		"of areas\r\nyou are connected to.  Please make sure everything "
-		"is correct.\r\n\r\n");
-	fprintf(tmpf,"Packet Type       %s\r\n"
-		,cfg.nodecfg[k].pkt_type==PKT_TWO ? "2"
-		:cfg.nodecfg[k].pkt_type==PKT_TWO_TWO ? "2.2":"2+");
-	fprintf(tmpf,"Archive Type      %s\r\n"
-		,(cfg.nodecfg[k].arctype>cfg.arcdefs) ?
-		 "None":cfg.arcdef[cfg.nodecfg[k].arctype].name);
-	fprintf(tmpf,"Mail Status       %s\r\n"
-		,cfg.nodecfg[k].attr&ATTR_CRASH ? "Crash"
-		:cfg.nodecfg[k].attr&ATTR_HOLD ? "Hold" : "None");
-	fprintf(tmpf,"Direct            %s\r\n"
-		,cfg.nodecfg[k].attr&ATTR_DIRECT ? "Yes":"No");
-	fprintf(tmpf,"Passive           %s\r\n"
-		,cfg.nodecfg[k].attr&ATTR_PASSIVE ? "Yes":"No");
-	fprintf(tmpf,"Remote AreaMgr    %s\r\n\r\n"
-		,cfg.nodecfg[k].password[0] ? "Yes" : "No");
-
-	fprintf(tmpf,"Connected Areas\r\n---------------\r\n");
-	for(i=0;i<cfg.areas;i++) {
-		sprintf(str,"%s\r\n",cfg.area[i].name);
-		if(str[0]=='*')
-			continue;
-		for(j=0;j<cfg.area[i].uplinks;j++)
-			if(!memcmp(&cfg.nodecfg[k].faddr,&cfg.area[i].uplink[j]
-				,sizeof(faddr_t)))
-				break;
-		if(j<cfg.area[i].uplinks)
-			fprintf(tmpf,"%s",str); }
-
-	if(ftell(tmpf))
-		file_to_netmail(tmpf,"SBBSecho Notify List",cfg.nodecfg[k].faddr,0);
-	fclose(tmpf); }
-}
-/******************************************************************************
- This function creates a netmail to addr showing a list of available areas (0),
- a list of connected areas (1), or a list of removed areas (2).
-******************************************************************************/
-void netmail_arealist(char type,faddr_t addr)
-{
-	FILE *stream,*tmpf;
-	char str[256],temp[256],title[81],match,*p;
-	int file,i,j,k,x,y;
-
-if(!type)
-	strcpy(title,"List of Available Areas");
-else if(type==1)
-	strcpy(title,"List of Connected Areas");
-else
-	strcpy(title,"List of Unlinked Areas");
-
-if((tmpf=tmpfile())==NULL) {
-	printf("\7ERROR couldn't open tmpfile.\n");
-	logprintf("ERROR line %d couldn't open tmpfile",__LINE__);
-	return; }
-
-if(type==1 || (type!=1 && !(misc&ELIST_ONLY))) {
-	for(i=0;i<cfg.areas;i++) {
-		sprintf(str,"%s\r\n",cfg.area[i].name);
-		if(type) {
-			for(j=0;j<cfg.area[i].uplinks;j++)
-				if(!memcmp(&addr,&cfg.area[i].uplink[j],sizeof(faddr_t)))
-					break;
-			if((type==1 && j<cfg.area[i].uplinks) ||
-				(type==2 && j==cfg.area[i].uplinks))
-					fprintf(tmpf,"%s",str); }
-		else
-			fprintf(tmpf,"%s",str); } }
-
-if(!type) {
-	i=matchnode(addr,0);
-	if(i<cfg.nodecfgs) {
-		for(j=0;j<cfg.listcfgs;j++) {
-			match=0;
-			for(k=0;k<cfg.listcfg[j].numflags;k++) {
-				if(match) break;
-				for(x=0;x<cfg.nodecfg[i].numflags;x++)
-					if(!stricmp(cfg.listcfg[j].flag[k].flag
-						,cfg.nodecfg[i].flag[x].flag)) {
-						if((stream=fnopen(&file
-							,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
-							printf("\7ERROR couldn't open %s.\n"
-								,cfg.listcfg[j].listpath);
-							logprintf("ERROR line %d couldn't open %s %s"
-								,__LINE__,cfg.listcfg[j].listpath
-								,sys_errlist[errno]);
-							match=1;
-							break; }
-						while(!feof(stream)) {
-							if(!fgets(str,255,stream))
-								break;
-							truncsp(str);
-							strcat(str,"\r\n");
-							p=str;
-							while(*p && *p<=SP) p++;
-							if(*p==';')     /* Ignore Comment Lines */
-								continue;
-							strcpy(temp,p);
-							p=temp;
-							while(*p && *p>SP) p++;
-							*p=0;
-							if(!(misc&ELIST_ONLY)) {
-								for(y=0;y<cfg.areas;y++)
-									if(!stricmp(cfg.area[y].name,temp))
-										break;
-								if(y==cfg.areas)
-									fprintf(tmpf,"%s",str); }
-							else
-								fprintf(tmpf,"%s",str); }
-						fclose(stream);
-						match=1;
-						break; } } } } }
-
-if(!ftell(tmpf))
-	create_netmail(0,title,"None.",addr,0);
-else
-	file_to_netmail(tmpf,title,addr,0);
-fclose(tmpf);
-}
-/******************************************************************************
- Imitation of Borland's tempnam function because Watcom doesn't have it
-******************************************************************************/
-//#ifdef __WATCOMC__
-char *tempname(char *dir, char *prefix)
-{
-	char str[256],*p;
-	int i;
-
-for(i=0;i<1000;i++) {
-	sprintf(str,"%s%s%03u.$$$",dir,prefix,i);
-	if(!fexist(str))
-		break; }
-if(i>=1000) {
-	logprintf("tempnam: too many files");
-	return(NULL); }
-p=malloc(strlen(str)+1);
-if(!p) {
-	logprintf("tempnam: couldn't malloc %u",strlen(str)+1);
-	return(NULL); }
-strcpy(p,str);
-return(p);
-}
-//#endif
-
-char check_elists(char *areatag,faddr_t addr)
-{
-	FILE *stream;
-	char str[1025],quit=0,match=0,*p;
-	int i,j,k,x,file;
-
-i=matchnode(addr,0);
-if(i<cfg.nodecfgs) {
-	for(j=0;j<cfg.listcfgs;j++) {
-		quit=0;
-		for(k=0;k<cfg.listcfg[j].numflags;k++) {
-			if(quit) break;
-			for(x=0;x<cfg.nodecfg[i].numflags;x++)
-				if(!stricmp(cfg.listcfg[j].flag[k].flag
-					,cfg.nodecfg[i].flag[x].flag)) {
-					if((stream=fnopen(&file
-						,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
-						printf("\7ERROR couldn't open %s.\n"
-							,cfg.listcfg[j].listpath);
-						logprintf("ERROR line %d opening %s"
-							,__LINE__,cfg.listcfg[j].listpath);
-						quit=1;
-						break; }
-					while(!feof(stream)) {
-						if(!fgets(str,255,stream))
-							break;
-						truncsp(str);
-						strcat(str,"\r\n");
-						p=str;
-						while(*p && *p<=SP) p++;
-						if(*p==';')     /* Ignore Comment Lines */
-							continue;
-						strcpy(str,p);
-						p=str;
-						while(*p && *p>SP) p++;
-						*p=0;
-						if(!stricmp(areatag,str)) {
-							match=1;
-							break; } }
-					fclose(stream);
-					quit=1;
-					if(match)
-						return(match);
-					break; } } } }
-return(match);
-}
-/******************************************************************************
- Used by AREAFIX to add/remove/change areas in the areas file
-******************************************************************************/
-void alter_areas(area_t add_area,area_t del_area,faddr_t addr)
-{
-	FILE *nmfile,*afilein,*afileout,*reqfile,*fwdfile;
-	char str[1025],fields[1025],field1[81],field2[81],field3[81]
-		,drive[3],dir[66],name[9],ext[5],outpath[128]
-		,*outname,*p,*tp,nomatch=0,match=0;
-	int i,j,k,x,y,file;
-	ulong tagcrc;
-
-_splitpath(cfg.areafile,drive,dir,name,ext);
-sprintf(outpath,"%s%s",drive,dir);
-if((outname=tempname(outpath,"AREAS"))==NULL) {
-	printf("\7ERROR creating temp file name for %s.\n",outpath);
-	logprintf("ERROR tempnam(%s,AREAS)",outpath);
-	return; }
-if((nmfile=tmpfile())==NULL) {
-	printf("\7ERROR couldn't open NetMail temp file.\n");
-	logprintf("ERROR in tmpfile()");
-	free(outname);
-	return; }
-if((afileout=fopen(outname,"w+b"))==NULL) {
-	printf("\7ERROR couldn't open %s.\n",outname);
-	logprintf("ERROR line %d opening %s %s",__LINE__,outname
-		,sys_errlist[errno]);
-	fclose(nmfile);
-	free(outname);
-    return; }
-if((afilein=fnopen(&file,cfg.areafile,O_RDONLY))==NULL) {
-	printf("\7ERROR couldn't open %s.\n",cfg.areafile);
-	logprintf("ERROR line %d opening %s %s",__LINE__,cfg.areafile
-		,sys_errlist[errno]);
-	fclose(afileout);
-	fclose(nmfile);
-	free(outname);
-	return; }
-while(!feof(afilein)) {
-	if(!fgets(fields,1024,afilein))
-		break;
-	truncsp(fields);
-	strcat(fields,"\r\n");
-	p=fields;
-	while(*p && *p<=SP) p++;
-	if(*p==';') {    /* Skip Comment Lines */
-		fprintf(afileout,"%s",fields);
-		continue; }
-	sprintf(field1,"%-.81s",p);         /* Internal Code Field */
-	tp=field1;
-	while(*tp && *tp>SP) tp++;
-	*tp=0;
-	while(*p && *p>SP) p++;
-	while(*p && *p<=SP) p++;
-	sprintf(field2,"%-.81s",p);         /* Areatag Field */
-	tp=field2;
-	while(*tp && *tp>SP) tp++;
-	*tp=0;
-	while(*p && *p>SP) p++;
-	while(*p && *p<=SP) p++;
-	if((tp=strchr(p,';'))!=NULL) {
-		sprintf(field3,"%-.81s",p);     /* Comment Field (if any) */
-		while(*tp && *tp>SP) tp++;
-		*tp=0; }
-	else
-		field3[0]=0;
-	if(del_area.tags) { 				/* Check for areas to remove */
-		for(i=0;i<del_area.tags;i++) {
-			if(!stricmp(del_area.tag[i],field2) ||
-				!stricmp(del_area.tag[0],"-ALL"))     /* Match Found */
-				break; }
-		if(i<del_area.tags) {
-			for(i=0;i<cfg.areas;i++) {
-				if(!stricmp(field2,cfg.area[i].name)) {
-					for(j=0;j<cfg.area[i].uplinks;j++)
-						if(!memcmp(&cfg.area[i].uplink[j],&addr
-							,sizeof(faddr_t)))
-							break;
-					if(j==cfg.area[i].uplinks &&
-						stricmp(del_area.tag[0],"-ALL")) {
-						fprintf(afileout,"%s",fields);
-						fprintf(nmfile,"%s not connected.\r\n",field2);
-						break; }
-
-					/* Added 12/4/95 to remove uplink from connected uplinks */
-
-					for(k=j;k<cfg.area[i].uplinks-1;k++)
-						memcpy(&cfg.area[i].uplink[k],&cfg.area[i].uplink[k+1]
-							,sizeof(faddr_t));
-					--cfg.area[i].uplinks;
-					if((cfg.area[i].uplink=(faddr_t *)
-						REALLOC(cfg.area[i].uplink,sizeof(faddr_t)
-						*(cfg.area[i].uplinks)))==NULL) {
-						printf("ERROR allocating memory for area #%u "
-							"uplinks.\n",i+1);
-						logprintf("ERROR line %d allocating memory for area "
-							"#%u uplinks.\n",__LINE__,i+1);
-						exit(1); }
-
-					fprintf(afileout,"%-16s%-23s ",field1,field2);
-					for(j=0;j<cfg.area[i].uplinks;j++) {
-						if(!memcmp(&cfg.area[i].uplink[j],&addr
-							,sizeof(faddr_t)))
-							continue;
-						fprintf(afileout,"%s "
-							,faddrtoa(cfg.area[i].uplink[j])); }
-					if(field3[0])
-						fprintf(afileout,"%s",field3);
-					fprintf(afileout,"\r\n");
-					fprintf(nmfile,"%s removed.\r\n",field2);
-					break; } }
-			if(i==cfg.areas)			/* Something screwy going on */
-				fprintf(afileout,"%s",fields);
-			continue; } }				/* Area match so continue on */
-	if(add_area.tags) { 				/* Check for areas to add */
-		for(i=0;i<add_area.tags;i++)
-			if(!stricmp(add_area.tag[i],field2) ||
-				!stricmp(add_area.tag[0],"+ALL"))      /* Match Found */
-				break;
-		if(i<add_area.tags) {
-			if(stricmp(add_area.tag[i],"+ALL"))
-				add_area.tag[i][0]=0;  /* So we can check other lists */
-			for(i=0;i<cfg.areas;i++) {
-				if(!stricmp(field2,cfg.area[i].name)) {
-					for(j=0;j<cfg.area[i].uplinks;j++)
-						if(!memcmp(&cfg.area[i].uplink[j],&addr
-							,sizeof(faddr_t)))
-							break;
-					if(j<cfg.area[i].uplinks) {
-						fprintf(afileout,"%s",fields);
-						fprintf(nmfile,"%s already connected.\r\n",field2);
-						break; }
-					if(misc&ELIST_ONLY && !check_elists(field2,addr)) {
-						fprintf(afileout,"%s",fields);
-						break; }
-
-					/* Added 12/4/95 to add uplink to connected uplinks */
-
-					++cfg.area[i].uplinks;
-					if((cfg.area[i].uplink=(faddr_t *)
-						REALLOC(cfg.area[i].uplink,sizeof(faddr_t)
-						*(cfg.area[i].uplinks)))==NULL) {
-						printf("ERROR allocating memory for area #%u "
-							"uplinks.\n",i+1);
-						logprintf("ERROR line %d allocating memory for area "
-							"#%u uplinks.\n",__LINE__,i+1);
-                        exit(1); }
-					memcpy(&cfg.area[i].uplink[j],&addr,sizeof(faddr_t));
-
-					fprintf(afileout,"%-16s%-23s ",field1,field2);
-					for(j=0;j<cfg.area[i].uplinks;j++)
-						fprintf(afileout,"%s "
-							,faddrtoa(cfg.area[i].uplink[j]));
-#if 0 // Removed (02/26/96) rrs
-					fprintf(afileout,"%s ",faddrtoa(addr));
-#endif
-					if(field3[0])
-						fprintf(afileout,"%s",field3);
-					fprintf(afileout,"\r\n");
-					fprintf(nmfile,"%s added.\r\n",field2);
-					break; } }
-			if(i==cfg.areas)			/* Something screwy going on */
-				fprintf(afileout,"%s",fields);
-			continue; } 				/* Area match so continue on */
-		nomatch=1; }					/* This area wasn't in there */
-	fprintf(afileout,"%s",fields); }    /* No match so write back line */
-fclose(afilein);
-if(nomatch || (add_area.tags && !stricmp(add_area.tag[0],"+ALL"))) {
-	i=matchnode(addr,0);
-	if(i<cfg.nodecfgs) {
-		for(j=0;j<cfg.listcfgs;j++) {
-			match=0;
-			for(k=0;k<cfg.listcfg[j].numflags;k++) {
-				if(match) break;
-				for(x=0;x<cfg.nodecfg[i].numflags;x++)
-					if(!stricmp(cfg.listcfg[j].flag[k].flag
-						,cfg.nodecfg[i].flag[x].flag)) {
-						if((fwdfile=tmpfile())==NULL) {
-							printf("\7ERROR couldn't open forwarding temp "
-								"file.\n");
-							logprintf("ERROR line %d opening forward temp "
-								"file",__LINE__);
-							match=1;
-							break; }
-						if((afilein=fnopen(&file
-							,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
-							printf("\7ERROR couldn't open %s.\n"
-								,cfg.listcfg[j].listpath);
-							logprintf("ERROR line %d opening %s"
-								,__LINE__,cfg.listcfg[j].listpath);
-							fclose(fwdfile);
-							match=1;
-							break; }
-						while(!feof(afilein)) {
-							if(!fgets(str,255,afilein))
-								break;
-							truncsp(str);
-							strcat(str,"\r\n");
-							p=str;
-							while(*p && *p<=SP) p++;
-							if(*p==';')     /* Ignore Comment Lines */
-								continue;
-							strcpy(str,p);
-							p=str;
-							while(*p && *p>SP) p++;
-							*p=0;
-							if(!stricmp(add_area.tag[0],"+ALL")) {
-								sprintf(fields,"%.1024s",str);
-								tagcrc=crc32(strupr(fields));
-								for(y=0;y<cfg.areas;y++)
-									if(tagcrc==cfg.area[y].tag)
-										break;
-								if(y<cfg.areas)
-									continue; }
-							for(y=0;y<add_area.tags;y++)
-								if((!stricmp(add_area.tag[y],str) &&
-									add_area.tag[y][0]) ||
-									!stricmp(add_area.tag[0],"+ALL"))
-									break;
-							if(y<add_area.tags) {
-								fprintf(afileout,"%-16s%-23s","P",str);
-								if(cfg.listcfg[j].forward.zone)
-									fprintf(afileout," %s"
-										,faddrtoa(cfg.listcfg[j].forward));
-								fprintf(afileout," %s\r\n",faddrtoa(addr));
-								fprintf(nmfile,"%s added.\r\n",str);
-								if(stricmp(add_area.tag[0],"+ALL"))
-									add_area.tag[y][0]=0;
-								if(!(cfg.listcfg[j].misc&NOFWD)
-									&& cfg.listcfg[j].forward.zone)
-									fprintf(fwdfile,"%s\r\n",str); } }
-						fclose(afilein);
-						if(!(cfg.listcfg[j].misc&NOFWD) && ftell(fwdfile)>0)
-							file_to_netmail(fwdfile,cfg.listcfg[j].password
-								,cfg.listcfg[j].forward,"Areafix");
-						fclose(fwdfile);
-						match=1;
-                        break; } } } } }
-if(add_area.tags && stricmp(add_area.tag[0],"+ALL")) {
-	for(i=0;i<add_area.tags;i++)
-		if(add_area.tag[i][0])
-			fprintf(nmfile,"%s not found.\r\n",add_area.tag[i]); }
-if(!ftell(nmfile))
-	create_netmail(0,"Area Change Request","No changes made.",addr,0);
-else
-	file_to_netmail(nmfile,"Area Change Request",addr,0);
-fclose(nmfile);
-fclose(afileout);
-if(delfile(cfg.areafile))					/* Delete AREAS.BBS */
-	logprintf("ERROR line %d removing %s %s",__LINE__,cfg.areafile
-		,sys_errlist[errno]);
-if(rename(outname,cfg.areafile))		   /* Rename new AREAS.BBS file */
-	logprintf("ERROR line %d renaming %s to %s",__LINE__,outname,cfg.areafile);
-free(outname);
-}
-/******************************************************************************
- Used by AREAFIX to add/remove/change uplink info in the configuration file
- old = the old setting for this option, new = what the setting is changing to
- option = 0 for compression type change
-		  1 for areafix password change
-		  2 to set this node to passive
-		  3 to set this node to active (remove passive)
-******************************************************************************/
-void alter_config(faddr_t addr,char *old,char *new,char option)
-{
-	FILE *outfile,*cfgfile;
-	char str[257],outpath[128],tmp[257],tmp2[257],*outname,*p,*tp
-		,drive[3],dir[66],name[9],ext[5],match=0;
-	int i,j,k,file;
-	faddr_t taddr;
-
-i=matchnode(addr,0);				  /* i = config number from here on */
-_splitpath(cfg.cfgfile,drive,dir,name,ext);
-sprintf(outpath,"%s%s",drive,dir);
-if((outname=tempname(outpath,"CFG"))==NULL) {
-	printf("\7ERROR creating temporary file name for %s.\n",outpath);
-	logprintf("ERROR tempnam(%s,CFG)",outpath);
-	return; }
-if((outfile=fopen(outname,"w+b"))==NULL) {
-	printf("\7ERROR couldn't open %s.\n",outname);
-	logprintf("ERROR line %d opening %s %s",__LINE__,outname
-		,sys_errlist[errno]);
-	free(outname);
-    return; }
-if((cfgfile=fnopen(&file,cfg.cfgfile,O_RDONLY))==NULL) {
-	printf("\7ERROR couldn't open %s.\n",cfg.cfgfile);
-	logprintf("ERROR line %d opening %s",__LINE__,cfg.cfgfile
-		,sys_errlist[errno]);
-	fclose(outfile);
-	free(outname);
-	return; }
-
-while(!feof(cfgfile)) {
-	if(!fgets(str,256,cfgfile))
-		break;
-	truncsp(str);
-	p=str;
-	while(*p && *p<=SP) p++;
-	if(*p==';') {
-		fprintf(outfile,"%s\r\n",str);
-        continue; }
-	sprintf(tmp,"%-.25s",p);
-	tp=strchr(tmp,SP);
-	if(tp)
-		*tp=0;								/* Chop off at space */
-	strupr(tmp);							/* Convert code to uppercase */
-	while(*p>SP) p++;						/* Skip code */
-    while(*p && *p<=SP) p++;                /* Skip white space */
-
-	if(option==0 && !strcmp(tmp,"USEPACKER")) {     /* Change Compression */
-		if(!*p)
-			continue;
-		strcpy(tmp2,p);
-		p=tmp2;
-		while(*p && *p>SP) p++;
-		*p=0;
-		p++;
-		if(!stricmp(new,tmp2)) {   /* Add to new definition */
-			fprintf(outfile,"%-10s %s %s %s\r\n",tmp,tmp2
-				,faddrtoa(cfg.nodecfg[i].faddr)
-				,(*p) ? p : "");
-			match=1;
-			continue; }
-		else if(!stricmp(old,tmp2)) {	/* Remove from old def */
-			for(j=k=0;j<cfg.nodecfgs;j++) {
-				if(j==i)
-					continue;
-				if(!stricmp(cfg.arcdef[cfg.nodecfg[j].arctype].name,tmp2)) {
-					if(!k) {
-						fprintf(outfile,"%-10s %s",tmp,tmp2);
-						k++; }
-					fprintf(outfile," %s"
-						,faddrtoa(cfg.nodecfg[j].faddr)); } }
-			fprintf(outfile,"\r\n");
-			continue; } }
-
-	if(option==1 && !strcmp(tmp,"AREAFIX")) {       /* Change Password */
-		if(!*p)
-			continue;
-		taddr=atofaddr(p);
-		if(!memcmp(&cfg.nodecfg[i].faddr,&taddr,sizeof(faddr_t))) {
-			while(*p && *p>SP) p++; 	/* Skip over address */
-			while(*p && *p<=SP) p++;	/* Skip over whitespace */
-			while(*p && *p>SP) p++; 	/* Skip over password */
-			while(*p && *p<=SP) p++;	/* Skip over whitespace */
-			fprintf(outfile,"%-10s %s %s %s\r\n",tmp
-				,faddrtoa(cfg.nodecfg[i].faddr),new,p);
-			continue; } }
-
-	if(option>1 && !strcmp(tmp,"PASSIVE")) {        /* Toggle Passive Areas */
-		match=1;
-		for(j=k=0;j<cfg.nodecfgs;j++) {
-			if(option==2 && j==i) {
-				if(!k) fprintf(outfile,"%-10s",tmp);
-				fprintf(outfile," %s",faddrtoa(cfg.nodecfg[j].faddr));
-				k++;
-				continue; }
-			if(option==3 && j==i)
-				continue;
-			if(cfg.nodecfg[j].attr&ATTR_PASSIVE) {
-				if(!k) fprintf(outfile,"%-10s",tmp);
-				fprintf(outfile," %s",faddrtoa(cfg.nodecfg[j].faddr));
-				k++; } }
-		if(k) fprintf(outfile,"\r\n");
-		continue; }
-	fprintf(outfile,"%s\r\n",str); }
-
-if(!match) {
-	if(option==0)
-		fprintf(outfile,"%-10s %s %s\r\n","USEPACKER",new
-			,faddrtoa(cfg.nodecfg[i].faddr));
-	if(option==2)
-		fprintf(outfile,"%-10s %s\r\n","PASSIVE"
-			,faddrtoa(cfg.nodecfg[i].faddr)); }
-
-fclose(cfgfile);
-fclose(outfile);
-if(delfile(cfg.cfgfile))
-	logprintf("ERROR line %d removing %s %s",__LINE__,cfg.cfgfile
-		,sys_errlist[errno]);
-if(rename(outname,cfg.cfgfile))
-	logprintf("ERROR line %d renaming %s to %s",__LINE__,outname,cfg.cfgfile);
-free(outname);
-}
-/******************************************************************************
- Used by AREAFIX to process any '%' commands that come in via netmail
-******************************************************************************/
-void command(char *instr,faddr_t addr)
-{
-	FILE *stream,*tmpf;
-	char str[256],temp[256],match,*buf,*p;
-	int  file,i,j,node;
-	long l;
-	area_t add_area,del_area;
-
-node=matchnode(addr,0);
-if(node>=cfg.nodecfgs)
-	return;
-memset(&add_area,0,sizeof(area_t));
-memset(&del_area,0,sizeof(area_t));
-strupr(instr);
-if((p=strstr(instr,"HELP"))!=NULL) {
-	sprintf(str,"%s%sAREAMGR.HLP",(exec_dir[0]=='.') ? node_dir:"",exec_dir);
-	if(!fexist(str))
-		return;
-	if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-		printf("\7ERROR couldn't open %s.\n",str);
-		logprintf("ERROR line %d opening %s %s",__LINE__,str
-			,sys_errlist[errno]);
-		return; }
-	l=filelength(file);
-	if((buf=(char *)LMALLOC(l+1L))==NULL) {
-		printf("ERROR line %d allocating %lu bytes for %s\n",__LINE__,l,str);
-		return; }
-	fread(buf,l,1,stream);
-	fclose(stream);
-	buf[l]=0;
-	create_netmail(0,"Area Manager Help",buf,addr,0);
-	LFREE(buf);
-	return; }
-
-if((p=strstr(instr,"LIST"))!=NULL) {
-	netmail_arealist(0,addr);
-	return; }
-
-if((p=strstr(instr,"QUERY"))!=NULL) {
-	netmail_arealist(1,addr);
-	return; }
-
-if((p=strstr(instr,"UNLINKED"))!=NULL) {
-	netmail_arealist(2,addr);
-	return; }
-
-if((p=strstr(instr,"COMPRESSION"))!=NULL) {
-	while(*p && *p>SP) p++;
-	while(*p && *p<=SP) p++;
-	for(i=0;i<cfg.arcdefs;i++)
-		if(!stricmp(p,cfg.arcdef[i].name))
-			break;
-	if(!stricmp(p,"NONE"))
-		i=0xffff;
-	if(i==cfg.arcdefs) {
-		if((tmpf=tmpfile())==NULL) {
-			printf("\7ERROR couldn't open tmpfile.\n");
-			logprintf("ERROR line %d opening tmpfile()",__LINE__);
-			return; }
-		fprintf(tmpf,"Compression type unavailable.\r\n\r\n"
-			"Available types are:\r\n");
-		for(i=0;i<cfg.arcdefs;i++)
-			fprintf(tmpf,"                     %s\r\n",cfg.arcdef[i].name);
-		file_to_netmail(tmpf,"Compression Type Change",addr,0);
-		fclose(tmpf);
-		LFREE(buf);
-		return; }
-	alter_config(addr,cfg.arcdef[cfg.nodecfg[node].arctype].name
-		,cfg.arcdef[i].name,0);
-	cfg.nodecfg[node].arctype=i;
-	sprintf(str,"Compression type changed to %s.",cfg.arcdef[i].name);
-	create_netmail(0,"Compression Type Change",str,addr,0);
-	return; }
-
-if((p=strstr(instr,"PASSWORD"))!=NULL) {
-	while(*p && *p>SP) p++;
-	while(*p && *p<=SP) p++;
-	sprintf(temp,"%-.25s",p);
-	p=temp;
-	while(*p && *p>SP) p++;
-	*p=0;
-	if(node==cfg.nodecfgs)		   /* Should never happen */
-		return;
-	if(!stricmp(temp,cfg.nodecfg[node].password)) {
-		sprintf(str,"Your password was already set to %s."
-			,cfg.nodecfg[node].password);
-		create_netmail(0,"Password Change Request",str,addr,0);
-		return; }
-	alter_config(addr,cfg.nodecfg[node].password,temp,1);
-	sprintf(str,"Your password has been changed from %s to %.25s."
-		,cfg.nodecfg[node].password,temp);
-	sprintf(cfg.nodecfg[node].password,"%.25s",temp);
-	create_netmail(0,"Password Change Request",str,addr,0);
-	return; }
-
-if((p=strstr(instr,"RESCAN"))!=NULL) {
-	export_echomail("",addr);
-	create_netmail(0,"Rescan Areas"
-		,"All connected areas carried by your hub have been rescanned."
-		,addr,0);
-	return; }
-
-if((p=strstr(instr,"ACTIVE"))!=NULL) {
-	if(!(cfg.nodecfg[node].attr&ATTR_PASSIVE)) {
-		create_netmail(0,"Reconnect Disconnected Areas"
-			,"Your areas are already connected.",addr,0);
-		return; }
-	alter_config(addr,0,0,3);
-	create_netmail(0,"Reconnect Disconnected Areas"
-		,"Temporarily disconnected areas have been reconnected.",addr,0);
-	return; }
-
-if((p=strstr(instr,"PASSIVE"))!=NULL) {
-	if(cfg.nodecfg[node].attr&ATTR_PASSIVE) {
-		create_netmail(0,"Temporarily Disconnect Areas"
-			,"Your areas are already temporarily disconnected.",addr,0);
-		return; }
-	alter_config(addr,0,0,2);
-	create_netmail(0,"Temporarily Disconnect Areas"
-		,"Your areas have been temporarily disconnected.",addr,0);
-	return; }
-
-if((p=strstr(instr,"FROM"))!=NULL);
-
-if((p=strstr(instr,"+ALL"))!=NULL) {
-	if((add_area.tag=(char **)REALLOC(add_area.tag
-		,sizeof(char *)*add_area.tags+1))==NULL) {
-		printf("ERROR allocating memory for add area tag #%u.\n"
-			,add_area.tags+1);
-		logprintf("ERROR line %d allocating memory for add area tag #%u"
-			,__LINE__,add_area.tags+1);
-		exit(1); }
-	if((add_area.tag[add_area.tags]=(char *)LMALLOC(strlen(instr)+1))==NULL) {
-		printf("ERROR allocating memory for add area tag #%u.\n"
-			,add_area.tags+1);
-		logprintf("ERROR line %d allocating memory for add area tag #%u"
-			,__LINE__,add_area.tags+1);
-        exit(1); }
-	strcpy(add_area.tag[add_area.tags],instr);
-	add_area.tags++;
-	alter_areas(add_area,del_area,addr);
-	for(i=0;i<add_area.tags;i++)
-		LFREE(add_area.tag[i]);
-	FREE(add_area.tag);
-	return; }
-
-if((p=strstr(instr,"-ALL"))!=NULL) {
-	if((del_area.tag=(char **)REALLOC(del_area.tag
-		,sizeof(char *)*del_area.tags+1))==NULL) {
-		printf("ERROR allocating memory for del area tag #%u.\n"
-			,del_area.tags+1);
-		logprintf("ERROR line %d allocating memory for del area tag #%u"
-			,__LINE__,del_area.tags+1);
-		exit(1); }
-	if((del_area.tag[del_area.tags]=(char *)LMALLOC(strlen(instr)+1))==NULL) {
-		printf("ERROR allocating memory for del area tag #%u.\n"
-			,del_area.tags+1);
-		logprintf("ERROR line %d allocating memory for del area tag #%u"
-			,__LINE__,del_area.tags+1);
-        exit(1); }
-	strcpy(del_area.tag[del_area.tags],instr);
-	del_area.tags++;
-	alter_areas(add_area,del_area,addr);
-	for(i=0;i<del_area.tags;i++)
-		LFREE(del_area.tag[i]);
-	FREE(del_area.tag);
-	return; }
-}
-/******************************************************************************
- This is where we're gonna process any netmail that comes in for areafix.
- Returns text for message body for the local sysop if necessary.
-******************************************************************************/
-char *process_areafix(faddr_t addr,char HUGE16 *inbuf,char *password)
-{
-	static char body[512],str[81];
-	char *p,*tp,action,percent=0;
-	int i;
-	ulong l,m;
-	area_t add_area,del_area;
-
-p=(char *)inbuf;
-
-while(*p==1) {				/* Skip kludge lines 11/05/95 */
-	while(*p && *p!=CR)
-		p++;				/* Skip meat */
-	if(*p)
-		p++; }				/* Skip CR */
-
-#if 0 // Removed 11/05/95
-while(*p && (tp=strchr(p,'\1'))!=NULL) {    /* Remove ^A kludge lines */
-	p=tp;
-	while(*p && *p!=CR) p++; }
-if(*p==CR)
-	p++;
-#endif
-
-if(((tp=strstr(p,"---\r"))!=NULL || (tp=strstr(p,"--- "))!=NULL) &&
-	(*(tp-1)==10 || *(tp-1)==13))
-	*tp=0;
-
-if(!strnicmp(p,"%FROM",5)) {    /* Remote Remote Maintenance (must be first) */
-	sprintf(str,"%.80s",p+6);
-	if((tp=strchr(str,CR))!=NULL)
-		*tp=0;
-	logprintf("Remote maintenance for %s requested via %s",str,faddrtoa(addr));
-	addr=atofaddr(str); }
-
-i=matchnode(addr,0);
-if(i==cfg.nodecfgs) {
-	sprintf(body,"Your node is not configured for Areafix, please "
-		"contact your hub.\r\n");
-	create_netmail(0,"Areafix Request",body,addr,0);
-	sprintf(body,"An areafix request was made by node %s.\r\nThis node "
-		"is not currently configured for areafix.\r\n",faddrtoa(addr));
-	return(body); }
-
-if(stricmp(cfg.nodecfg[i].password,password)) {
-    create_netmail(0,"Areafix Request","Invalid Password.",addr,0);
-    sprintf(body,"Node %s attempted an areafix request using an invalid "
-        "password.\r\nThe password attempted was %s.\r\nThe correct password "
-        "for this node is %s.\r\n",faddrtoa(addr),password
-		,(cfg.nodecfg[i].password[0]) ? cfg.nodecfg[i].password
-		 : "[None Defined]");
-    return(body); }
-
-m=strlen(p);
-add_area.tags=0;
-add_area.tag=NULL;
-del_area.tags=0;
-del_area.tag=NULL;
-for(l=0;l<m;l++) {
-	while(*(p+l) && *(p+l)<=SP) l++;
-	if(!(*(p+l))) break;
-	if(*(p+l)=='+' || *(p+l)=='-' || *(p+l)=='%') {
-		action=*(p+l);
-		l++; }
-	else
-		action='+';
-	sprintf(str,"%.80s",p+l);
-	if((tp=strchr(str,CR))!=NULL)
-		*tp=0;
-	switch(action) {
-		case '+':                       /* Add Area */
-			if((add_area.tag=(char **)REALLOC(add_area.tag
-				,sizeof(char *)*add_area.tags+1))==NULL) {
-				printf("ERROR allocating memory for add area tag #%u.\n"
-					,add_area.tags+1);
-				logprintf("ERROR line %d allocating memory for add area "
-					"tag #%u",__LINE__,add_area.tags+1);
-				exit(1); }
-			if((add_area.tag[add_area.tags]=(char *)LMALLOC(strlen(str)+1))
-				==NULL) {
-				printf("ERROR allocating memory for add area tag #%u.\n"
-					,add_area.tags+1);
-				logprintf("ERROR line %d allocating memory for add area "
-					"tag #%u",__LINE__,add_area.tags+1);
-                exit(1); }
-			strcpy(add_area.tag[add_area.tags],str);
-			add_area.tags++;
-			break;
-		case '-':                       /* Remove Area */
-			if((del_area.tag=(char **)REALLOC(del_area.tag
-				,sizeof(char *)*del_area.tags+1))==NULL) {
-				printf("ERROR allocating memory for del area tag #%u.\n"
-					,del_area.tags+1);
-				logprintf("ERROR line %d allocating memory for del area "
-					"tag #%u",__LINE__,del_area.tags+1);
-				exit(1); }
-			if((del_area.tag[del_area.tags]=(char *)LMALLOC(strlen(str)+1))
-				==NULL) {
-				printf("ERROR allocating memory for del area tag #%u.\n"
-					,del_area.tags+1);
-				logprintf("ERROR line %d allocating memory for del area "
-					"tag #%u",__LINE__,del_area.tags+1);
-				exit(1); }
-			strcpy(del_area.tag[del_area.tags],str);
-			del_area.tags++;
-			break;
-		case '%':                       /* Process Command */
-			command(str,addr);
-			percent++;
-			break; }
-
-	while(*(p+l) && *(p+l)!=CR) l++; }
-
-if(!percent && !add_area.tags && !del_area.tags) {
-	create_netmail(0,"Areafix Request","No commands to process.",addr,0);
-	sprintf(body,"Node %s attempted an areafix request with an empty message "
-		"body or with no valid commands.\r\n",faddrtoa(addr));
-    return(body); }
-if(add_area.tags || del_area.tags)
-	alter_areas(add_area,del_area,addr);
-if(add_area.tags) {
-	for(i=0;i<add_area.tags;i++)
-		LFREE(add_area.tag[i]);
-	FREE(add_area.tag); }
-if(del_area.tags) {
-	for(i=0;i<del_area.tags;i++)
-		LFREE(del_area.tag[i]);
-	FREE(del_area.tag); }
-return(0);
-}
-/******************************************************************************
- This function will compare the archive signatures defined in the CFG file and
- extract 'infile' using the appropriate de-archiver.
-******************************************************************************/
-int unpack(char *infile)
-{
-	FILE *stream;
-	char str[256],tmp[3];
-	int i,j,k,ch,file;
-
-if((stream=fnopen(&file,infile,O_RDONLY))==NULL) {
-	printf("\7ERROR couldn't open %s.\n",infile);
-	logprintf("ERROR line %d opening %s %s",__LINE__,infile
-		,sys_errlist[errno]);
-	exit(1); }
-for(i=0;i<cfg.arcdefs;i++) {
-	str[0]=0;
-	fseek(stream,cfg.arcdef[i].byteloc,SEEK_SET);
-	for(j=0;j<strlen(cfg.arcdef[i].hexid)/2;j++) {
-		ch=fgetc(stream);
-		if(ch==EOF) {
-			i=cfg.arcdefs;
-			break; }
-		sprintf(tmp,"%02X",ch);
-		strcat(str,tmp); }
-	if(!stricmp(str,cfg.arcdef[i].hexid))
-		break; }
-fclose(stream);
-
-if(i==cfg.arcdefs) {
-	printf("\7ERROR couldn't determine filetype of %s.\n",infile);
-	logprintf("ERROR line %d determining filetype of %s",__LINE__,infile);
-	return(1); }
-
-j=execute(cmdstr(cfg.arcdef[i].unpack,infile
-	,secure ? cfg.secure : cfg.inbound));
-if(j) {
-	printf("\7ERROR %d (%d) executing %s\n"
-		,j,errno,cmdstr(cfg.arcdef[i].unpack,infile
-			,secure ? cfg.secure : cfg.inbound));
-	logprintf("ERROR %d (%d) line %d executing %s"
-		,j,errno,__LINE__,cmdstr(cfg.arcdef[i].unpack,infile
-            ,secure ? cfg.secure : cfg.inbound));
-	return(j); }
-return(0);
-}
-/******************************************************************************
- This function will check the 'dest' for the type of archiver to use (as
- defined in the CFG file) and compress 'srcfile' into 'destfile' using the
- appropriate archive program.
-******************************************************************************/
-void pack(char *srcfile,char *destfile,faddr_t dest)
-{
-	int i,j;
-	uint use=0;
-
-i=matchnode(dest,0);
-if(i<cfg.nodecfgs)
-	use=cfg.nodecfg[i].arctype;
-
-j=execute(cmdstr(cfg.arcdef[use].pack,destfile,srcfile));
-if(j) {
-	printf("\7ERROR %d (%d) executing %s\n"
-		,j,errno,cmdstr(cfg.arcdef[use].pack,destfile,srcfile));
-	logprintf("ERROR %d (%d) line %d executing %s"
-		,j,errno,__LINE__,cmdstr(cfg.arcdef[use].pack,destfile,srcfile)); }
-}
-
-char attachment(char *bundlename,faddr_t dest,char cleanup)
-{
-	FILE *fidomsg,*stream;
-	char str[1025],path[512],fname[129],*p;
-	int last,fmsg,file,error=0L;
-	long fncrc,*mfncrc=0L,num_mfncrc=0L;
-	struct find_t ff;
-    attach_t attach;
-	fmsghdr_t hdr;
-
-sprintf(fname,"%sBUNDLES.SBE",cfg.outbound);
-if((stream=fnopen(&file,fname,O_RDWR|O_CREAT))==NULL) {
-    printf("\7ERROR opening %s %s\n",fname,sys_errlist[errno]);
-    logprintf("ERROR line %d opening %s %s",__LINE__,fname,sys_errlist[errno]);
-	return(1); }
-
-if(cleanup==2) {				/* Check for existance in BUNDLES.SBE */
-	while(!feof(stream)) {
-		if(!fread(&attach,1,sizeof(attach_t),stream))
-			break;
-		if(!stricmp(attach.fname,bundlename)) {
-			fclose(stream);
-			return(1); } }
-	fclose(stream);
-	return(0); }
-
-if(cleanup==1) {				/* Create netmail attaches */
-
-if(!filelength(file)) {
-	fclose(stream);
-	return(0); }
-								/* Get attach names from existing MSGs */
-sprintf(str,"%s*.MSG",netmail_dir);
-for(last=_dos_findfirst(str,0,&ff);!last;last=_dos_findnext(&ff)) {
-	sprintf(path,"%s%s",netmail_dir,ff.name);
-	strupr(path);
-	if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
-		printf("\7ERROR opening %s\n",path);
-		logprintf("ERROR line %d opening %s %s",__LINE__,path
-			,sys_errlist[errno]);
-		continue; }
-	if(filelength(fmsg)<sizeof(fmsghdr_t)) {
-		printf("\7ERROR %s has invalid length of %u bytes\n",path
-			,filelength(fmsg));
-		logprintf("ERROR line %d %s has invalid length of %u bytes"
-			,__LINE__,path,filelength(fmsg));
-		fclose(fidomsg);
-		continue; }
-	if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
-		fclose(fidomsg);
-		printf("\7ERROR reading %u bytes from %s"
-			,sizeof(fmsghdr_t),path);
-		logprintf("ERROR line %d reading %u bytes from %s"
-			,__LINE__,sizeof(fmsghdr_t),path);
-		continue; }
-	fclose(fidomsg);
-	if(!(hdr.attr&FIDO_FILE))		/* Not a file attach */
-		continue;
-	num_mfncrc++;
-	if((p=strrchr(hdr.subj,'\\'))!=NULL)
-		p++;
-	else
-		p=hdr.subj;
-	if((mfncrc=(long *)REALLOC(mfncrc,num_mfncrc*sizeof(long)))==NULL) {
-		printf("ERROR allocating %lu bytes for bundle name crc.\n"
-			,num_mfncrc*sizeof(long));
-		logprintf("ERROR line %d allocating %lu for bundle name crc"
-			,__LINE__,num_mfncrc*sizeof(long));
-		continue; }
-	mfncrc[num_mfncrc-1]=crc32(strupr(p)); }
-
-    while(!feof(stream)) {
-		if(!fread(&attach,1,sizeof(attach_t),stream))
-            break;
-        sprintf(str,"%s%s",cfg.outbound,attach.fname);
-		if(!fexist(str))
-			continue;
-		fncrc=crc32(strupr(attach.fname));
-		for(last=0;last<num_mfncrc;last++)
-			if(mfncrc[last]==fncrc)
-				break;
-		if(last==num_mfncrc)
-			if(create_netmail(0,str,"\1FLAGS KFS\r",attach.dest,1))
-				error=1; }
-	if(!error)				/* don't truncate if an error occured */
-		chsize(file,0L);
-    fclose(stream);
-	if(num_mfncrc)
-		FREE(mfncrc);
-#ifdef __WATCOMC__
-   _dos_findclose(&ff);
-#endif
-	return(0); }
-
-while(!feof(stream)) {
-	if(!fread(&attach,1,sizeof(attach_t),stream))
-        break;
-    if(!stricmp(attach.fname,bundlename)) {
-        fclose(stream);
-		return(0); } }
-
-memcpy(&attach.dest,&dest,sizeof(faddr_t));
-strcpy(attach.fname,bundlename);
-fwrite(&attach,sizeof(attach_t),1,stream);
-fclose(stream);
-return(0);
-}
-
-/******************************************************************************
- This function is called when a message packet has reached it's maximum size.
- It places packets into a bundle until that bundle is full, at which time the
- last character of the extension increments (1 thru 0 and then A thru Z).  If
- all bundles have reached their maximum size remaining packets are placed into
- the Z bundle.
-******************************************************************************/
-void pack_bundle(char *infile,faddr_t dest)
-{
-	char str[256],fname[256],outbound[128],day[3],ch,*p;
-	int i,j,file,node;
-	time_t now;
-
-node=matchnode(dest,0);
-strcpy(str,infile);
-str[strlen(str)-1]='T';
-if(rename(infile,str))				   /* Change .PK_ file to .PKT file */
-	logprintf("ERROR line %d renaming %s to %s",__LINE__,infile,str);
-infile[strlen(infile)-1]='T';
-time(&now);
-sprintf(day,"%-.2s",ctime(&now));
-strupr(day);
-if(misc&FLO_MAILER) {
-	if(node<cfg.nodecfgs && cfg.nodecfg[node].route.zone)
-		dest=cfg.nodecfg[node].route;
-	if(dest.zone==faddr[0].zone)	/* Default zone, use default outbound */
-		strcpy(outbound,cfg.outbound);
-	else							/* Inter-zone outbound is OUTBOUND.XXX */
-		sprintf(outbound,"%.*s.%03X\\"
-			,strlen(cfg.outbound)-1,cfg.outbound,dest.zone);
-	if(dest.point) {				/* Point destination is OUTBOUND\*.PNT */
-		sprintf(str,"%04X%04X.PNT"
-			,dest.net,dest.node);
-		strcat(outbound,str); }
-	}
-else
-	strcpy(outbound,cfg.outbound);
-if(outbound[strlen(outbound)-1]=='\\')
-    outbound[strlen(outbound)-1]=0;
-mkdir(outbound);
-strcat(outbound,"\\");
-
-if(node<cfg.nodecfgs)
-	if(cfg.nodecfg[node].arctype==0xffff) {    /* Uncompressed! */
-		if(misc&FLO_MAILER)
-			i=write_flofile(infile,dest);
-		else
-			i=create_netmail(0,infile,"\1FLAGS KFS\r",dest,1);
-		if(i) exit(1);
-		return; }
-
-sprintf(fname,"%s%04hX%04hX.%s",outbound,(short)(faddr[0].net-dest.net)
-	,(short)(faddr[0].node-dest.node),day);
-if(dest.point && !(misc&FLO_MAILER))
-	sprintf(fname,"%s%04hXP%03hX.%s",outbound,0,(short)dest.point,day);
-for(i='0';i<='Z';i++) {
-	if(i==':')
-		i='A';
-	sprintf(str,"%s%c",fname,i);
-	if(flength(str)==0)
-		if(delfile(str))
-			logprintf("ERROR line %d removing %s %s",__LINE__,str
-				,sys_errlist[errno]);
-	if(fexist(str)) {
-		if((p=strrchr(str,'\\'))!=NULL)
-			p++;
-		else
-			p=str;
-		if(flength(str)>=cfg.maxbdlsize)
-			continue;
-		file=sopen(str,O_WRONLY,SH_DENYRW);
-		if(file==-1)		/* Can't open?!? Probably being sent */
-			continue;
-		close(file);
-		if(!attachment(p,dest,2))
-			attachment(p,dest,0);
-		pack(infile,str,dest);
-		if(delfile(infile))
-			logprintf("ERROR line %d removing %s %s",__LINE__,infile
-				,sys_errlist[errno]);
-		return; }
-	else {
-		if(misc&FLO_MAILER)
-			j=write_flofile(str,dest);
-		else {
-			if((p=strrchr(str,'\\'))!=NULL)
-				p++;
-			else
-				p=str;
-			j=attachment(p,dest,0); }
-        if(j)
-            exit(1);
-		pack(infile,str,dest);
-		if(delfile(infile))
-			logprintf("ERROR line %d removing %s %s",__LINE__,infile
-				,sys_errlist[errno]);
-		return; } }
-
-pack(infile,str,dest);	/* Won't get here unless all bundles are full */
-}
-
-/******************************************************************************
- This function checks the inbound directory for the first bundle it finds, it
- will then unpack and delete the bundle.  If no bundles exist this function
- returns a 0, otherwise a 1 is returned.
-******************************************************************************/
-int unpack_bundle(void)
-{
-	char str[256];
-	static char fname[256];
-	int i,j;
-	static struct find_t ff;
-
-for(i=0;i<7;i++) {
-	sprintf(str,"%s*.%s?",secure ? cfg.secure : cfg.inbound
-		,(i==0) ? "SU" : (i==1) ? "MO" : (i==2) ? "TU" : (i==3) ? "WE" : (i==4)
-		? "TH" : (i==5) ? "FR" : "SA");
-	if(!ff.name[0])
-		j=_dos_findfirst(str,0,&ff);
-	else {
-		j=_dos_findnext(&ff);
-		if(j) {
-#ifdef __WATCOMC__
-			_dos_findclose(&ff);
-#endif
-			j=_dos_findfirst(str,0,&ff); } }
-	if(!j) {
-		sprintf(fname,"%s%s",secure ? cfg.secure : cfg.inbound,ff.name);
-		if(unpack(fname)) {
-			if((ddtol(ff.wr_time,ff.wr_date)+(48L*60L*60L))>time(NULL)) {
-				strcpy(str,fname);
-				str[strlen(str)-2]='_';
-				if(fexist(str))
-					str[strlen(str)-2]='-';
-				if(fexist(str))
-					delfile(str);
-				if(rename(fname,str))
-					logprintf("ERROR line %d renaming %s to %s"
-						,__LINE__,fname,str); } }
-		else if(delfile(fname))
-			logprintf("ERROR line %d removing %s %s",__LINE__,fname
-				,sys_errlist[errno]);
-		return(1); } }
-
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-return(0);
-}
-
-
-/******************************************************************************
- Displays characters locally
-******************************************************************************/
-long lputs(char *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-/******************************************/
-/* CRC-16 routines required for SMB index */
-/******************************************/
-
-/***********************************************)**********************)*****/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(uint number, node_t *node, char lockit)
-{
-	char str[256];
-	int count=0;
-
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count==LOOP_NODEDAB) {
-	printf("\7ERROR unlocking and reading NODE.DAB\n");
-	logprintf("ERROR line %d unlocking and reading NODE.DAB",__LINE__); }
-}
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(uint number, node_t node)
-{
-	char str[256];
-	int count;
-
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	printf("\7ERROR writing NODE.DAB for node %u\n",number+1);
-	logprintf("ERROR line %d writing NODE.DAB for node %u",__LINE__,number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-
-/****************************************************************************/
-/* Creates a short message for 'usernumber' than contains 'strin'			*/
-/****************************************************************************/
-void putsmsg(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-    node_t node;
-
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("\7ERROR opening/creating %s for create/append access\n",str);
-	logprintf("ERROR line %d opening/creating %s",__LINE__,str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-	close(file);
-	printf("\7ERROR writing %u bytes to %s\n",i,str);
-	logprintf("ERROR line %d writing to %s",__LINE__,str);
-	return; }
-close(file);
-for(i=1;i<=sys_nodes;i++) {		/* flag node if user on that msg waiting */
-	getnodedat(i,&node,0);
-	if(node.useron==usernumber
-		&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
-		&& !(node.misc&NODE_MSGW)) {
-		getnodedat(i,&node,1);
-		node.misc|=NODE_MSGW;
-        putnodedat(i,node); } }
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Moves or copies a file from one dir to another                           */
-/* both 'src' and 'dest' must contain full path and filename                */
-/* returns 0 if successful, -1 if error                                     */
-/****************************************************************************/
-int mv(char *src, char *dest, char copy)
-{
-	char buf[4096],str[256];
-	int  ind,outd;
-	long length,chunk=4096,l;
-#ifdef __WATCOMC__
-	unsigned short ftime,fdate;
-#else
-	unsigned ftime,fdate;
-#endif
-    FILE *inp,*outp;
-
-if(!strcmp(src,dest))	/* source and destination are the same! */
-	return(0);
-if(!fexist(src)) {
-	logprintf("MV ERROR: Source doesn't exist '%s",src);
-	return(-1); }
-if(!copy && fexist(dest)) {
-	logprintf("MV ERROR: Destination already exists '%s'",dest);
-	return(-1); }
-if(!copy && ((src[1]!=':' && dest[1]!=':')
-	|| (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
-	if(rename(src,dest)) {						/* same drive, so move */
-		logprintf("MV ERROR: Error renaming %s to %s",src,dest);
-		return(-1); }
-	return(0); }
-if((ind=nopen(src,O_RDONLY))==-1) {
-	logprintf("MV ERROR: ERR_OPEN %s",src);
-	return(-1); }
-if((inp=fdopen(ind,"rb"))==NULL) {
-	close(ind);
-	logprintf("MV ERROR: ERR_FDOPEN %s",str);
-	return(-1); }
-setvbuf(inp,NULL,_IOFBF,8*1024);
-if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-	fclose(inp);
-	logprintf("MV ERROR: ERR_OPEN %s",dest);
-	return(-1); }
-if((outp=fdopen(outd,"wb"))==NULL) {
-	close(outd);
-	fclose(inp);
-	logprintf("MV ERROR: ERR_FDOPEN %s",str);
-	return(-1); }
-setvbuf(outp,NULL,_IOFBF,8*1024);
-length=filelength(ind);
-l=0L;
-while(l<length) {
-	if(l+chunk>length)
-		chunk=length-l;
-	fread(buf,chunk,1,inp);
-	fwrite(buf,chunk,1,outp);
-	l+=chunk; }
-_dos_getftime(ind,&fdate,&ftime);
-_dos_setftime(outd,fdate,ftime);
-fclose(inp);
-fclose(outp);
-if(!copy && delfile(src)) {
-	logprintf("ERROR line %d removing %s %s",__LINE__,src,sys_errlist[errno]);
-	return(-1); }
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the total number of msgs in the sub-board and sets 'ptr' to the  */
-/* date of the last message in the sub (0) if no messages.					*/
-/****************************************************************************/
-ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
-{
-	char str[256];
-	int i;
-	smb_t smbfile;
-
-if(subnum>=total_subs) {
-	printf("\nERROR getlastmsg, subnum=%d\n",subnum);
-	logprintf("ERROR line %d getlastmsg %d",__LINE__,subnum);
-	exit(1); }
-sprintf(smbfile.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smbfile.retry_time=smb_retry_time;
-if((i=smb_open(&smbfile))!=0) {
-	printf("ERROR %d opening %s\n",i,smbfile.file);
-	logprintf("ERROR %d line %d opening %s",i,__LINE__,smbfile.file);
-	return(0); }
-
-if(!filelength(fileno(smbfile.shd_fp))) {			/* Empty base */
-	if(ptr) (*ptr)=0;
-	smb_close(&smbfile);
-	return(0); }
-#if 0	// Not necessary with SMBLIB v2.0
-if((i=smb_locksmbhdr(&smbfile))!=0) {
-	smb_close(&smbfile);
-	printf("ERROR %d locking %s\n",i,smbfile.file);
-	logprintf("ERROR %d line %d locking %s smbhdr",i,__LINE__
-		,smbfile.file);
-	return(0); }
-if((i=smb_getstatus(&smbfile))!=0) {
-	smb_unlocksmbhdr(&smbfile);
-	smb_close(&smbfile);
-	printf("ERROR %d reading %s\n",i,smbfile.file);
-	logprintf("ERROR %d line %d reading %s",i,__LINE__,smbfile.file);
-	return(0); }
-smb_unlocksmbhdr(&smbfile);
-#endif
-smb_close(&smbfile);
-if(ptr) (*ptr)=smbfile.status.last_msg;
-return(smbfile.status.total_msgs);
-}
-
-
-ulong loadmsgs(post_t HUGE16 **post, ulong ptr)
-{
-	int i;
-	long l=0,total;
-	idxrec_t idx;
-
-
-if((i=smb_locksmbhdr(&smb[cur_smb]))!=0) {
-	printf("ERROR %d locking %s\n",i,smb[cur_smb].file);
-	logprintf("ERROR %d line %d locking %s",i,__LINE__,smb[cur_smb].file);
-	return(0L); }
-
-/* total msgs in sub */
-total=filelength(fileno(smb[cur_smb].sid_fp))/sizeof(idxrec_t);
-
-if(!total) {			/* empty */
-	smb_unlocksmbhdr(&smb[cur_smb]);
-    return(0); }
-
-if(((*post)=(post_t HUGE16 *)LMALLOC(sizeof(post_t)*total))    /* alloc for max */
-	==NULL) {
-	smb_unlocksmbhdr(&smb[cur_smb]);
-	printf("ERROR allocating %lu bytes for %s\n",sizeof(post_t *)*total
-		,smb[cur_smb].file);
-	logprintf("ERROR line %d allocating %lu bytes for %s",__LINE__
-		,sizeof(post_t *)*total,smb[cur_smb].file);
-    return(0); }
-
-fseek(smb[cur_smb].sid_fp,0L,SEEK_SET);
-while(!feof(smb[cur_smb].sid_fp)) {
-	if(!fread(&idx,sizeof(idxrec_t),1,smb[cur_smb].sid_fp))
-        break;
-
-	if(idx.number<=ptr || idx.attr&MSG_DELETE)
-		continue;
-
-	if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED))
-		break;
-
-	(*post)[l].offset=idx.offset;
-	(*post)[l].number=idx.number;
-	(*post)[l].to=idx.to;
-	(*post)[l].from=idx.from;
-    (*post)[l].subj=idx.subj;
-	l++; }
-smb_unlocksmbhdr(&smb[cur_smb]);
-if(!l)
-	LFREE(*post);
-return(l);
-}
-
-void allocfail(uint size)
-{
-printf("\7ERROR allocating %u bytes of memory.\n",size);
-bail(1);
-}
-
-void bail(int code)
-{
-exit(code);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,0,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-	return(f.size);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,0,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-    return(1);
-return(0);
-}
-
-typedef struct {
-	ulong	alias,
-			real;
-			} username_t;
-
-/****************************************************************************/
-/* Note: Wrote another version of this function that read all userdata into */
-/****************************************************************************/
-/* Looks for a perfect match amoung all usernames (not deleted users)		*/
-/* Returns the number of the perfect matched username or 0 if no match		*/
-/* Called from functions waitforcall and newuser							*/
-/* memory then scanned it from memory... took longer - always.              */
-/****************************************************************************/
-ulong matchname(char *inname)
-{
-	static ulong total_users;
-	static username_t *username;
-	ulong last_user;
-	int userdat,i;
-	char str[256],name[LEN_NAME+1],alias[LEN_ALIAS+1],c;
-	ulong l,crc;
-
-if(!total_users) {		/* Load CRCs */
-	fprintf(stderr,"\n%-25s","Loading user names...");
-	sprintf(str,"%sUSER\\USER.DAT",data_dir);
-	if((userdat=nopen(str,O_RDONLY|O_DENYNONE))==-1)
-		return(0);
-	last_user=filelength(userdat)/U_LEN;
-	for(total_users=0;total_users<last_user;total_users++) {
-		printf("%5ld\b\b\b\b\b",total_users);
-		if((username=(username_t *)REALLOC(username
-			,(total_users+1L)*sizeof(username_t)))==NULL)
-            break;
-		username[total_users].alias=0;
-		username[total_users].real=0;
-		i=0;
-		while(i<LOOP_NODEDAB
-			&& lock(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS
-				,LEN_ALIAS+LEN_NAME)==-1)
-			i++;
-		if(i>=LOOP_NODEDAB) {	   /* Couldn't lock USER.DAT record */
-			logprintf("ERROR locking USER.DAT record #%ld",total_users);
-            continue; }
-		lseek(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS,SEEK_SET);
-		read(userdat,alias,LEN_ALIAS);
-		read(userdat,name,LEN_NAME);
-		lseek(userdat,(long)(((long)total_users)*U_LEN)+U_MISC,SEEK_SET);
-		read(userdat,tmp,8);
-		for(c=0;c<8;c++)
-			if(tmp[c]==ETX || tmp[c]==CR) break;
-		tmp[c]=0;
-		unlock(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS
-			,LEN_ALIAS+LEN_NAME);
-		if(ahtoul(tmp)&DELETED)
-			continue;
-		for(c=0;c<LEN_ALIAS;c++)
-			if(alias[c]==ETX || alias[c]==CR) break;
-		alias[c]=0;
-		strupr(alias);
-		for(c=0;c<LEN_NAME;c++)
-            if(name[c]==ETX || name[c]==CR) break;
-        name[c]=0;
-        strupr(name);
-		username[total_users].alias=crc32(alias);
-		username[total_users].real=crc32(name); }
-	close(userdat);
-	fprintf(stderr,"     \b\b\b\b\b");  // Clear counter
-	fprintf(stderr,
-		"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
-		"%25s"
-		"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
-		,""); }
-
-strcpy(str,inname);
-strupr(str);
-crc=crc32(str);
-for(l=0;l<total_users;l++)
-	if((crc==username[l].alias || crc==username[l].real))
-		return(l+1);
-return(0);
-}
-
-/****************************************************************************/
-/* Converts goofy FidoNet time format into Unix format						*/
-/****************************************************************************/
-time_t fmsgtime(char *str)
-{
-	char month[4];
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-if(isdigit(str[1])) {	/* Regular format: "01 Jan 86  02:34:56" */
-	tm.tm_mday=atoi(str);
-	sprintf(month,"%3.3s",str+3);
-	if(!stricmp(month,"jan"))
-		tm.tm_mon=0;
-	else if(!stricmp(month,"feb"))
-		tm.tm_mon=1;
-	else if(!stricmp(month,"mar"))
-		tm.tm_mon=2;
-	else if(!stricmp(month,"apr"))
-		tm.tm_mon=3;
-	else if(!stricmp(month,"may"))
-		tm.tm_mon=4;
-	else if(!stricmp(month,"jun"))
-		tm.tm_mon=5;
-	else if(!stricmp(month,"jul"))
-		tm.tm_mon=6;
-	else if(!stricmp(month,"aug"))
-		tm.tm_mon=7;
-	else if(!stricmp(month,"sep"))
-		tm.tm_mon=8;
-	else if(!stricmp(month,"oct"))
-		tm.tm_mon=9;
-	else if(!stricmp(month,"nov"))
-		tm.tm_mon=10;
-	else
-		tm.tm_mon=11;
-	tm.tm_year=atoi(str+7);
-	if(tm.tm_year<Y2K_2DIGIT_WINDOW)
-		tm.tm_year+=100;
-	tm.tm_hour=atoi(str+11);
-	tm.tm_min=atoi(str+14);
-	tm.tm_sec=atoi(str+17); }
-
-else {					/* SEAdog  format: "Mon  1 Jan 86 02:34" */
-	tm.tm_mday=atoi(str+4);
-	sprintf(month,"%3.3s",str+7);
-	if(!stricmp(month,"jan"))
-		tm.tm_mon=0;
-	else if(!stricmp(month,"feb"))
-		tm.tm_mon=1;
-	else if(!stricmp(month,"mar"))
-		tm.tm_mon=2;
-	else if(!stricmp(month,"apr"))
-		tm.tm_mon=3;
-	else if(!stricmp(month,"may"))
-		tm.tm_mon=4;
-	else if(!stricmp(month,"jun"))
-		tm.tm_mon=5;
-	else if(!stricmp(month,"jul"))
-		tm.tm_mon=6;
-	else if(!stricmp(month,"aug"))
-		tm.tm_mon=7;
-	else if(!stricmp(month,"sep"))
-		tm.tm_mon=8;
-	else if(!stricmp(month,"oct"))
-		tm.tm_mon=9;
-	else if(!stricmp(month,"nov"))
-		tm.tm_mon=10;
-	else
-		tm.tm_mon=11;
-	tm.tm_year=atoi(str+11);
-	if(tm.tm_year<Y2K_2DIGIT_WINDOW)
-		tm.tm_year+=100;
-	tm.tm_hour=atoi(str+14);
-	tm.tm_min=atoi(str+17);
-	tm.tm_sec=0; }
-return(mktime(&tm));
-}
-
-#if 1		/* Old way */
-
-char HUGE16 *getfmsg(FILE *stream, ulong *outlen)
-{
-	uchar HUGE16 *fbuf;
-	int ch;
-	ulong l,length,start;
-
-length=0L;
-start=ftell(stream);						/* Beginning of Message */
-while(1) {
-	ch=fgetc(stream);						/* Look for Terminating NULL */
-	if(!ch || ch==EOF)						/* Found end of message */
-		break;
-	length++; } 							/* Increment the Length */
-
-if((fbuf=(char *)LMALLOC(length+1))==NULL) {
-	printf("Unable to allocate %lu bytes for message.\n",length+1);
-	logprintf("ERROR line %d allocating %lu bytes of memory",__LINE__,length+1);
-	exit(0); }
-
-fseek(stream,start,SEEK_SET);
-for(l=0;l<length;l++)
-	fbuf[l]=fgetc(stream);
-fbuf[length]=0;
-if(!ch)
-	fgetc(stream);		/* Read NULL */
-if(outlen)
-	*outlen=length;
-return(fbuf);
-}
-
-#else
-
-#define FBUF_BLOCK 4096
-
-char *getfmsg(FILE *stream)
-{
-	uchar *fbuf,*p;
-	ulong l,n,length,start;
-
-length=0L;
-start=ftell(stream);						/* Beginning of Message */
-if((fbuf=LMALLOC(FBUF_BLOCK))==NULL)
-	return(fbuf);
-while(!feof(stream)) {
-	l=fread(fbuf+length,1,FBUF_BLOCK,stream);
-	if(l<1)
-		break;
-	*(fbuf+length+l)=0;
-	n=strlen(fbuf+length);
-	if(n<l) {
-		length+=(n+1);
-		break; }
-	printf(",");
-	length+=l;
-	if(l<FBUF_BLOCK)
-		break;
-	printf("<");
-	if((p=REALLOC(fbuf,length+FBUF_BLOCK+1))==NULL) {
-		LFREE(fbuf);
-		printf("!");
-		fseek(stream,-l,SEEK_CUR);
-		return(NULL); }
-	fbuf=p;
-	printf(">");
-	}
-printf(".");
-
-fseek(stream,start+length,SEEK_SET);
-return(fbuf);
-}
-
-#endif
-
-#define MAX_TAILLEN 1024
-
-/****************************************************************************/
-/* Coverts a FidoNet message into a Synchronet message						*/
-/* Returns 1 on success, 0 on failure, -1 on dupe.							*/
-/****************************************************************************/
-int fmsgtosmsg(uchar HUGE16 *fbuf, fmsghdr_t fmsghdr, uint user, uint subnum)
-{
-	uchar	ch,HUGE16 *sbody,HUGE16 *stail,HUGE16 *outbuf
-			,done,col,esc,cr,*p,str[128];
-	int 	i,chunk,lzh=0,storage;
-	ushort	xlat,net;
-	ulong	l,m,length,lzhlen,bodylen,taillen,crc;
-	faddr_t faddr,origaddr,destaddr;
-	smbmsg_t	msg;
-	smb_t	*smbfile;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-if(fmsghdr.attr&FIDO_PRIVATE)
-	msg.idx.attr|=MSG_PRIVATE;
-msg.hdr.attr=msg.idx.attr;
-
-if(fmsghdr.attr&FIDO_FILE)
-	msg.hdr.auxattr|=MSG_FILEATTACH;
-
-msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_imported.zone=sys_timezone;
-msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
-
-origaddr.zone=fmsghdr.origzone; 	/* only valid if NetMail */
-origaddr.net=fmsghdr.orignet;
-origaddr.node=fmsghdr.orignode;
-origaddr.point=fmsghdr.origpoint;
-
-destaddr.zone=fmsghdr.destzone; 	/* only valid if NetMail */
-destaddr.net=fmsghdr.destnet;
-destaddr.node=fmsghdr.destnode;
-destaddr.point=fmsghdr.destpoint;
-
-smb_hfield(&msg,SENDER,strlen(fmsghdr.from),fmsghdr.from);
-strlwr(fmsghdr.from);
-if(subnum==INVALID_SUB)
-	msg.idx.from=0;
-else
-	msg.idx.from=crc16(fmsghdr.from);
-
-smb_hfield(&msg,RECIPIENT,strlen(fmsghdr.to),fmsghdr.to);
-strlwr(fmsghdr.to);
-msg.idx.to=crc16(fmsghdr.to);
-
-if(user) {
-	sprintf(str,"%u",user);
-	smb_hfield(&msg,RECIPIENTEXT,strlen(str),str);
-	msg.idx.to=user; }
-
-smb_hfield(&msg,SUBJECT,strlen(fmsghdr.subj),fmsghdr.subj);
-remove_re(fmsghdr.subj);
-strlwr(fmsghdr.subj);
-msg.idx.subj=crc16(fmsghdr.subj);
-if(fbuf==NULL) {
-	printf("ERROR allocating fbuf\n");
-	logprintf("ERROR line %d allocating fbuf",__LINE__);
-	smb_freemsgmem(&msg);
-	return(0); }
-length=strlen((char *)fbuf);
-if((sbody=(char HUGE16 *)LMALLOC((length+1)*2))==NULL) {
-	printf("ERROR allocating %lu bytes for body",(length+1)*2L);
-	logprintf("ERROR line %d allocating %lu bytes for body",__LINE__
-		,(length+1)*2L);
-	smb_freemsgmem(&msg);
-	return(0); }
-if((stail=(char HUGE16 *)LMALLOC(MAX_TAILLEN))==NULL) {
-	printf("ERROR allocating %lu bytes\n",MAX_TAILLEN);
-	logprintf("ERROR line %d allocating %lu bytes for tail",__LINE__
-		,MAX_TAILLEN);
-	LFREE(sbody);
-	smb_freemsgmem(&msg);
-	return(0); }
-
-for(col=l=esc=done=bodylen=taillen=0,cr=1;l<length;l++) {
-
-	if(!l && !strncmp((char *)fbuf,"AREA:",5)) {
-        l+=5;
-        while(l<length && fbuf[l]<=SP) l++;
-        m=l;
-        while(m<length && fbuf[m]!=CR) m++;
-        while(m && fbuf[m-1]<=SP) m--;
-        if(m>l)
-            smb_hfield(&msg,FIDOAREA,m-l,fbuf+l);
-        while(l<length && fbuf[l]!=CR) l++;
-        continue; }
-
-	ch=fbuf[l];
-	if(ch==1 && cr) {	/* kludge line */
-
-		if(!strncmp((char *)fbuf+l+1,"TOPT ",5))
-			destaddr.point=atoi((char *)fbuf+l+6);
-
-		else if(!strncmp((char *)fbuf+l+1,"FMPT ",5))
-			origaddr.point=atoi((char *)fbuf+l+6);
-
-		else if(!strncmp((char *)fbuf+l+1,"INTL ",5)) {
-			faddr=atofaddr((char *)fbuf+l+6);
-			destaddr.zone=faddr.zone;
-			destaddr.net=faddr.net;
-			destaddr.node=faddr.node;
-			l+=6;
-			while(l<length && fbuf[l]!=SP) l++;
-			faddr=atofaddr((char *)fbuf+l+1);
-			origaddr.zone=faddr.zone;
-			origaddr.net=faddr.net;
-			origaddr.node=faddr.node; }
-
-		else if(!strncmp((char *)fbuf+l+1,"MSGID:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOMSGID,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"REPLY:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOREPLYID,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"FLAGS:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOFLAGS,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"PATH:",5)) {
-			l+=6;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l && misc&STORE_PATH)
-				smb_hfield(&msg,FIDOPATH,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"PID:",4)) {
-			l+=5;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOPID,m-l,fbuf+l); }
-
-		else {		/* Unknown kludge line */
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l && misc&STORE_KLUDGE)
-				smb_hfield(&msg,FIDOCTRL,m-l,fbuf+l); }
-
-		while(l<length && fbuf[l]!=CR) l++;
-		continue; }
-
-	if(ch!=LF && ch!=0x8d) {	/* ignore LF and soft CRs */
-		if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
-			|| !strncmp((char *)fbuf+l,"---\r",4)))
-			done=1; 			/* tear line and down go into tail */
-		if(done && cr && !strncmp((char *)fbuf+l,"SEEN-BY:",8)) {
-			l+=8;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l && misc&STORE_SEENBY)
-				smb_hfield(&msg,FIDOSEENBY,m-l,fbuf+l);
-			while(l<length && fbuf[l]!=CR) l++;
-			continue; }
-		if(done) {
-			if(taillen<MAX_TAILLEN)
-				stail[taillen++]=ch; }
-		else
-			sbody[bodylen++]=ch;
-		col++;
-		if(ch==CR) {
-			cr=1;
-			col=0;
-			if(done) {
-				if(taillen<MAX_TAILLEN)
-					stail[taillen++]=LF; }
-			else
-				sbody[bodylen++]=LF; }
-		else {
-			cr=0;
-			if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
-				p=(char *)fbuf+l+11;
-				while(*p && *p!=CR) p++;	 /* Find CR */
-				while(p && *p!='(') p--;     /* rewind to '(' */
-				if(p)
-					origaddr=atofaddr(p+1); 	/* get orig address */
-				done=1; }
-			if(done)
-				continue;
-
-			if(ch==ESC) esc=1;		/* ANSI codes */
-			if(ch==SP && col>40 && !esc) {	/* word wrap */
-				for(m=l+1;m<length;m++) 	/* find next space */
-					if(fbuf[m]<=SP)
-						break;
-				if(m<length && m-l>80-col) {  /* if it's beyond the eol */
-					sbody[bodylen++]=CR;
-					sbody[bodylen++]=LF;
-					col=0; } }
-			} } }
-
-if(bodylen>=2 && sbody[bodylen-2]==CR && sbody[bodylen-1]==LF)
-	bodylen-=2; 						/* remove last CRLF if present */
-
-if(smb[cur_smb].status.max_crcs) {
-	for(l=0,crc=0xffffffff;l<bodylen;l++)
-		crc=ucrc32(sbody[l],crc);
-	crc=~crc;
-	i=smb_addcrc(&smb[cur_smb],crc);
-	if(i) {
-		if(i==1)
-			printf("Duplicate ");
-		else
-			printf("smb_addcrc returned %d ",i);
-		smb_freemsgmem(&msg);
-		LFREE(sbody);
-		LFREE(stail);
-		if(i==1)
-			return(-1);
-		return(0); } }
-
-while(taillen && stail[taillen-1]<=SP)	/* trim all garbage off the tail */
-	taillen--;
-
-if(!origaddr.zone && subnum==INVALID_SUB)
-	net=NET_NONE;						/* Message from SBBSecho */
-else
-	net=NET_FIDO;						/* Record origin address */
-
-if(net) {
-	smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
-	smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr); }
-
-if(subnum==INVALID_SUB) {
-	smbfile=email;
-	if(net) {
-		smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
-		smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr); } }
-else
-	smbfile=&smb[cur_smb];
-
-if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_LZH
-	&& bodylen+2L+taillen+2L>=SDT_BLOCK_LEN && bodylen) {
-	if((outbuf=(char *)LMALLOC(bodylen*2L))==NULL) {
-		printf("ERROR allocating %lu bytes for lzh\n",bodylen*2);
-		logprintf("ERROR line %d allocating %lu bytes for lzh",__LINE__
-			,bodylen*2);
-		smb_freemsgmem(&msg);
-		LFREE(sbody);
-		LFREE(stail);
-		return(0); }
-	lzhlen=lzh_encode((uchar *)sbody,bodylen,(uchar *)outbuf);
-	if(lzhlen>1 &&
-		smb_datblocks(lzhlen+4L+taillen+2L)<
-		smb_datblocks(bodylen+2L+taillen+2L)) {
-		bodylen=lzhlen; 	/* Compressable */
-		l=bodylen+4;
-		LFREE(sbody);
-		lzh=1;
-		sbody=outbuf; }
-	else {					/* Uncompressable */
-		l=bodylen+2;
-		LFREE(outbuf); } }
-else
-    l=bodylen+2;
-
-if(taillen)
-	l+=(taillen+2);
-
-if(l&0xfff00000) {
-	printf("ERROR checking msg len %lu\n",l);
-	logprintf("ERROR line %d checking msg len %lu",__LINE__,l);
-	smb_freemsgmem(&msg);
-	LFREE(sbody);
-	LFREE(stail);
-	return(0); }
-
-if(smbfile->status.attr&SMB_HYPERALLOC) {
-	if((i=smb_locksmbhdr(smbfile))!=0) {
-		printf("ERROR %d locking %s\n",i,smbfile->file);
-		logprintf("ERROR %d line %d locking %s",i,__LINE__,smbfile->file);
-		smb_freemsgmem(&msg);
-		LFREE(sbody);
-		LFREE(stail);
-		return(0); }
-	msg.hdr.offset=smb_hallocdat(smbfile);
-	storage=SMB_HYPERALLOC; }
-else {
-	if((i=smb_open_da(smbfile))!=0) {
-		smb_freemsgmem(&msg);
-		printf("ERROR %d opening %s.SDA\n",i,smbfile->file);
-		logprintf("ERROR %d line %d opening %s.SDA",i,__LINE__
-			,smbfile->file);
-		LFREE(sbody);
-		LFREE(stail);
-		return(0); }
-	if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_FAST) {
-		msg.hdr.offset=smb_fallocdat(smbfile,l,1);
-		storage=SMB_FASTALLOC; }
-	else {
-		msg.hdr.offset=smb_allocdat(smbfile,l,1);
-		storage=SMB_SELFPACK; }
-	smb_close_da(smbfile); }
-
-if(msg.hdr.offset && msg.hdr.offset<1L) {
-	if(smbfile->status.attr&SMB_HYPERALLOC)
-		smb_unlocksmbhdr(smbfile);
-	smb_freemsgmem(&msg);
-	LFREE(sbody);
-	LFREE(stail);
-	printf("ERROR %ld allocating records\n",msg.hdr.offset);
-	logprintf("ERROR line %d %ld allocating records",__LINE__,msg.hdr.offset);
-	return(0); }
-fseek(smbfile->sdt_fp,msg.hdr.offset,SEEK_SET);
-if(lzh) {
-	xlat=XLAT_LZH;
-	fwrite(&xlat,2,1,smbfile->sdt_fp); }
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smbfile->sdt_fp);
-chunk=30000;
-for(l=0;l<bodylen;l+=chunk) {
-	if(l+chunk>bodylen)
-		chunk=bodylen-l;
-	fwrite(sbody+l,1,chunk,smbfile->sdt_fp); }
-if(taillen) {
-	fwrite(&xlat,2,1,smbfile->sdt_fp);
-	fwrite(stail,1,taillen,smbfile->sdt_fp); }
-LFREE(sbody);
-LFREE(stail);
-fflush(smbfile->sdt_fp);
-if(smbfile->status.attr&SMB_HYPERALLOC)
-	smb_unlocksmbhdr(smbfile);
-
-if(lzh)
-	bodylen+=2;
-bodylen+=2;
-smb_dfield(&msg,TEXT_BODY,bodylen);
-if(taillen)
-	smb_dfield(&msg,TEXT_TAIL,taillen+2);
-
-i=smb_addmsghdr(smbfile,&msg,storage);
-smb_freemsgmem(&msg);
-if(i) {
-	printf("ERROR smb_addmsghdr returned %d\n",i);
-	logprintf("ERROR line %d smb_addmsghdr returned %d"
-		,__LINE__,i);
-	return(0); }
-return(1);
-}
-
-/***********************************************************************/
-/* Get zone and point from kludge lines from the stream  if they exist */
-/***********************************************************************/
-void getzpt(FILE *stream, fmsghdr_t *hdr)
-{
-	char buf[0x1000];
-	int i,len,cr=0;
-	long pos;
-	faddr_t faddr;
-
-pos=ftell(stream);
-len=fread(buf,1,0x1000,stream);
-for(i=0;i<len;i++) {
-	if((!i || cr) && buf[i]==1) {	/* kludge */
-		if(!strncmp(buf+i+1,"TOPT ",5))
-			hdr->destpoint=atoi(buf+i+6);
-		else if(!strncmp(buf+i+1,"FMPT ",5))
-			hdr->origpoint=atoi(buf+i+6);
-		else if(!strncmp(buf+i+1,"INTL ",5)) {
-			faddr=atofaddr(buf+i+6);
-			hdr->destzone=faddr.zone;
-			hdr->destnet=faddr.net;
-			hdr->destnode=faddr.node;
-			i+=6;
-			while(buf[i] && buf[i]!=SP) i++;
-			faddr=atofaddr(buf+i+1);
-			hdr->origzone=faddr.zone;
-			hdr->orignet=faddr.net;
-			hdr->orignode=faddr.node; }
-		while(i<len && buf[i]!=CR) i++;
-		cr=1;
-		continue; }
-	if(buf[i]==CR)
-		cr=1;
-	else
-		cr=0; }
-fseek(stream,pos,SEEK_SET);
-}
-/******************************************************************************
- This function will seek to the next NULL found in stream
-******************************************************************************/
-void seektonull(FILE *stream)
-{
-	char ch;
-
-while(!feof(stream)) {
-	if(!fread(&ch,1,1,stream))
-		break;
-	if(!ch)
-		break; }
-
-}
-
-/******************************************************************************
- This function returns a packet name - used for outgoing packets
-******************************************************************************/
-char *pktname(void)
-{
-	static char str[128];
-	int i;
-    time_t now;
-    struct tm *tm;
-
-now=time(NULL);
-for(i=0;i<MAX_TOTAL_PKTS*2;i++) {
-	now+=i;
-	tm=gmtime(&now);
-	sprintf(str,"%s%02u%02u%02u%02u.PK_",cfg.outbound,tm->tm_mday,tm->tm_hour
-		,tm->tm_min,tm->tm_sec);
-	if(!fexist(str))				/* Add 1 second if name exists */
-		break; }
-return(str);
-}
-/******************************************************************************
- This function puts a message into a Fido packet, writing both the header
- information and the message body
-******************************************************************************/
-void putfmsg(FILE *stream,uchar HUGE16 *fbuf,fmsghdr_t fmsghdr,areasbbs_t area
-	,addrlist_t seenbys,addrlist_t paths)
-{
-	char str[256],seenby[256],*p;
-	short i,j,lastlen=0,net_exists=0;
-	faddr_t addr,sysaddr;
-
-addr=getsysfaddr(fmsghdr.destzone);
-
-i=0x0002;
-fwrite(&i,2,1,stream);
-fwrite(&addr.node,2,1,stream);
-fwrite(&fmsghdr.destnode,2,1,stream);
-fwrite(&addr.net,2,1,stream);
-fwrite(&fmsghdr.destnet,2,1,stream);
-fwrite(&fmsghdr.attr,2,1,stream);
-fwrite(&fmsghdr.cost,2,1,stream);
-fwrite(fmsghdr.time,strlen(fmsghdr.time)+1,1,stream);
-fwrite(fmsghdr.to,strlen(fmsghdr.to)+1,1,stream);
-fwrite(fmsghdr.from,strlen(fmsghdr.from)+1,1,stream);
-fwrite(fmsghdr.subj,strlen(fmsghdr.subj)+1,1,stream);
-if(area.name)
-	if(strncmp((char *)fbuf,"AREA:",5))                     /* No AREA: Line */
-		fprintf(stream,"AREA:%s\r",area.name);              /* So add one */
-fwrite(fbuf,strlen((char *)fbuf),1,stream);
-lastlen=9;
-if(fbuf[strlen((char *)fbuf)-1]!=CR)
-	fputc(CR,stream);
-
-if(area.name && addr.zone!=fmsghdr.destzone)	/* Zone Gate */
-	fprintf(stream,"SEEN-BY: %d/%d\r",fmsghdr.destnet,fmsghdr.destnode);
-
-if(area.name && addr.zone==fmsghdr.destzone) {	/* Not NetMail */
-	fprintf(stream,"SEEN-BY:");
-	for(i=0;i<seenbys.addrs;i++) {			  /* Put back original SEEN-BYs */
-		strcpy(seenby," ");
-		if(seenbys.addr[i].zone!=addr.zone)
-			continue;
-		if(seenbys.addr[i].net!=addr.net || !net_exists) {
-			net_exists=1;
-			addr.net=seenbys.addr[i].net;
-			sprintf(str,"%d/",addr.net);
-			strcat(seenby,str); }
-		sprintf(str,"%d",seenbys.addr[i].node);
-		strcat(seenby,str);
-		if(lastlen+strlen(seenby)<80) {
-			fwrite(seenby,strlen(seenby),1,stream);
-			lastlen+=strlen(seenby); }
-		else {
-			--i;
-			lastlen=9; /* +strlen(seenby); */
-			net_exists=0;
-			fprintf(stream,"\rSEEN-BY:"); } }
-
-	for(i=0;i<area.uplinks;i++) {			/* Add all uplinks to SEEN-BYs */
-		strcpy(seenby," ");
-		if(area.uplink[i].zone!=addr.zone || area.uplink[i].point)
-			continue;
-		for(j=0;j<seenbys.addrs;j++)
-			if(!memcmp(&area.uplink[i],&seenbys.addr[j],sizeof(faddr_t)))
-				break;
-		if(j==seenbys.addrs) {
-			if(area.uplink[i].net!=addr.net || !net_exists) {
-				net_exists=1;
-				addr.net=area.uplink[i].net;
-				sprintf(str,"%d/",addr.net);
-				strcat(seenby,str); }
-			sprintf(str,"%d",area.uplink[i].node);
-			strcat(seenby,str);
-			if(lastlen+strlen(seenby)<80) {
-				fwrite(seenby,strlen(seenby),1,stream);
-				lastlen+=strlen(seenby); }
-			else {
-				--i;
-				lastlen=9; /* +strlen(seenby); */
-				net_exists=0;
-				fprintf(stream,"\rSEEN-BY:"); } } }
-
-	for(i=0;i<total_faddrs;i++) {				/* Add AKAs to SEEN-BYs */
-		strcpy(seenby," ");
-		if(faddr[i].zone!=addr.zone || faddr[i].point)
-			continue;
-		for(j=0;j<seenbys.addrs;j++)
-			if(!memcmp(&faddr[i],&seenbys.addr[j],sizeof(faddr_t)))
-				break;
-		if(j==seenbys.addrs) {
-			if(faddr[i].net!=addr.net || !net_exists) {
-				net_exists=1;
-				addr.net=faddr[i].net;
-				sprintf(str,"%d/",addr.net);
-				strcat(seenby,str); }
-			sprintf(str,"%d",faddr[i].node);
-			strcat(seenby,str);
-			if(lastlen+strlen(seenby)<80) {
-				fwrite(seenby,strlen(seenby),1,stream);
-				lastlen+=strlen(seenby); }
-			else {
-				--i;
-				lastlen=9; /* +strlen(seenby); */
-				net_exists=0;
-				fprintf(stream,"\rSEEN-BY:"); } } }
-
-	lastlen=7;
-	net_exists=0;
-	fprintf(stream,"\r\1PATH:");
-	addr=getsysfaddr(fmsghdr.destzone);
-	for(i=0;i<paths.addrs;i++) {			  /* Put back the original PATH */
-		strcpy(seenby," ");
-		if(paths.addr[i].zone!=addr.zone || paths.addr[i].point)
-			continue;
-		if(paths.addr[i].net!=addr.net || !net_exists) {
-			net_exists=1;
-			addr.net=paths.addr[i].net;
-			sprintf(str,"%d/",addr.net);
-			strcat(seenby,str); }
-		sprintf(str,"%d",paths.addr[i].node);
-		strcat(seenby,str);
-		if(lastlen+strlen(seenby)<80) {
-			fwrite(seenby,strlen(seenby),1,stream);
-			lastlen+=strlen(seenby); }
-		else {
-			--i;
-			lastlen=7; /* +strlen(seenby); */
-			net_exists=0;
-			fprintf(stream,"\r\1PATH:"); } }
-
-	strcpy(seenby," ");         /* Add first address with same zone to PATH */
-	sysaddr=getsysfaddr(fmsghdr.destzone);
-	if(!sysaddr.point) {
-		if(sysaddr.net!=addr.net || !net_exists) {
-			net_exists=1;
-			addr.net=sysaddr.net;
-			sprintf(str,"%d/",addr.net);
-			strcat(seenby,str); }
-		sprintf(str,"%d",sysaddr.node);
-		strcat(seenby,str);
-		if(lastlen+strlen(seenby)<80)
-			fwrite(seenby,strlen(seenby),1,stream);
-		else {
-			fprintf(stream,"\r\1PATH:");
-			fwrite(seenby,strlen(seenby),1,stream); } }
-
-	fputc(CR,stream); }
-
-fputc(0,stream);
-}
-
-/******************************************************************************
- This function creates a binary list of the message seen-bys and path from
- inbuf.
-******************************************************************************/
-void gen_psb(addrlist_t *seenbys,addrlist_t *paths,char HUGE16 *inbuf
-	,ushort zone)
-{
-	char str[128],seenby[256],*p,*p1,*p2,HUGE16 *fbuf;
-	int i,j,len;
-	faddr_t addr;
-
-if(!inbuf)
-	return;
-fbuf=strstr((char *)inbuf,"\r * Origin: ");
-if(!fbuf)
-fbuf=strstr((char *)inbuf,"\n * Origin: ");
-if(!fbuf)
-	fbuf=inbuf;
-if(seenbys->addr) {
-	FREE(seenbys->addr);
-	seenbys->addr=0;
-	seenbys->addrs=0; }
-addr.zone=addr.net=addr.node=addr.point=seenbys->addrs=0;
-p=strstr((char *)fbuf,"\rSEEN-BY:");
-if(!p) p=strstr((char *)fbuf,"\nSEEN-BY:");
-if(p) {
-	while(1) {
-		sprintf(str,"%-.100s",p+10);
-		if((p1=strchr(str,CR))!=NULL)
-			*p1=0;
-		p1=str;
-		i=j=0;
-		len=strlen(str);
-		while(i<len) {
-			j=i;
-			while(i<len && *(p1+i)!=SP)
-				++i;
-			if(j>len)
-				break;
-			sprintf(seenby,"%-.*s",(i-j),p1+j);
-			if((p2=strchr(seenby,':'))!=NULL) {
-				addr.zone=atoi(seenby);
-				addr.net=atoi(p2+1); }
-			else if((p2=strchr(seenby,'/'))!=NULL)
-				addr.net=atoi(seenby);
-			if((p2=strchr(seenby,'/'))!=NULL)
-				addr.node=atoi(p2+1);
-			else
-				addr.node=atoi(seenby);
-			if((p2=strchr(seenby,'.'))!=NULL)
-				addr.point=atoi(p2+1);
-			if(!addr.zone)
-				addr.zone=zone; 		/* Was 1 */
-			if((seenbys->addr=(faddr_t *)REALLOC(seenbys->addr
-				,sizeof(faddr_t)*(seenbys->addrs+1)))==NULL) {
-				printf("ERROR allocating memory for seenbys\n");
-				logprintf("ERROR line %d allocating memory for message "
-					"seenbys.",__LINE__);
-				exit(1); }
-			memcpy(&seenbys->addr[seenbys->addrs],&addr,sizeof(faddr_t));
-			seenbys->addrs++;
-			++i; }
-		p1=strstr(p+10,"\rSEEN-BY:");
-		if(!p1)
-			p1=strstr(p+10,"\nSEEN-BY:");
-		if(!p1)
-			break;
-		p=p1; } }
-else {
-	if((seenbys->addr=(faddr_t *)REALLOC(seenbys->addr
-		,sizeof(faddr_t)))==NULL) {
-		printf("ERROR allocating memory for seenbys\n");
-		logprintf("ERROR line %d allocating memory for message seenbys."
-			,__LINE__);
-		exit(1); }
-	memset(&seenbys->addr[0],0,sizeof(faddr_t)); }
-
-if(paths->addr) {
-	FREE(paths->addr);
-	paths->addr=0;
-	paths->addrs=0; }
-addr.zone=addr.net=addr.node=addr.point=paths->addrs=0;
-if((p=strstr((char *)fbuf,"\1PATH:"))!=NULL) {
-	while(1) {
-		sprintf(str,"%-.100s",p+7);
-		if((p1=strchr(str,CR))!=NULL)
-			*p1=0;
-		p1=str;
-		i=j=0;
-		len=strlen(str);
-		while(i<len) {
-			j=i;
-			while(i<len && *(p1+i)!=SP)
-				++i;
-			if(j>len)
-				break;
-			sprintf(seenby,"%-.*s",(i-j),p1+j);
-			if((p2=strchr(seenby,':'))!=NULL) {
-				addr.zone=atoi(seenby);
-				addr.net=atoi(p2+1); }
-			else if((p2=strchr(seenby,'/'))!=NULL)
-				addr.net=atoi(seenby);
-			if((p2=strchr(seenby,'/'))!=NULL)
-				addr.node=atoi(p2+1);
-			else
-                addr.node=atoi(seenby);
-			if((p2=strchr(seenby,'.'))!=NULL)
-				addr.point=atoi(p2+1);
-			if(!addr.zone)
-				addr.zone=zone; 		/* Was 1 */
-			if((paths->addr=(faddr_t *)REALLOC(paths->addr
-				,sizeof(faddr_t)*(paths->addrs+1)))==NULL) {
-				printf("ERROR allocating memory for paths\n");
-				logprintf("ERROR line %d allocating memory for message "
-					"paths.",__LINE__);
-				exit(1); }
-			memcpy(&paths->addr[paths->addrs],&addr,sizeof(faddr_t));
-			paths->addrs++;
-			++i; }
-		if((p1=strstr(p+7,"\1PATH:"))==NULL)
-			break;
-		p=p1; } }
-else {
-	if((paths->addr=(faddr_t *)REALLOC(paths->addr
-		,sizeof(faddr_t)))==NULL) {
-		printf("ERROR allocating memory for paths\n");
-		logprintf("ERROR line %d allocating memory for message paths."
-			,__LINE__);
-		exit(1); }
-	memset(&paths->addr[0],0,sizeof(faddr_t)); }
-}
-
-/******************************************************************************
- This function takes the addrs passed to it and compares them to the address
- passed in inaddr.	1 is returned if inaddr matches any of the addrs
- otherwise a 0 is returned.
-******************************************************************************/
-char check_psb(addrlist_t addrlist,faddr_t inaddr)
-{
-	int i;
-
-for(i=0;i<addrlist.addrs;i++) {
-	if(!memcmp(&addrlist.addr[i],&inaddr,sizeof(faddr_t)))
-		return(1); }
-return(0);
-}
-/******************************************************************************
- This function strips the message seen-bys and path from inbuf.
-******************************************************************************/
-void strip_psb(char HUGE16 *inbuf)
-{
-	char *p,HUGE16 *fbuf;
-
-if(!inbuf)
-	return;
-fbuf=strstr((char *)inbuf,"\r * Origin: ");
-if(!fbuf)
-	fbuf=inbuf;
-if((p=strstr((char *)fbuf,"\rSEEN-BY:"))!=NULL)
-	*(p)=0;
-if((p=strstr((char *)fbuf,"\r\1PATH:"))!=NULL)
-	*(p)=0;
-}
-void attach_bundles()
-{
-	FILE *fidomsg;
-	char str[1025],path[512],packet[128];
-	int fmsg;
-	ulong l;
-	faddr_t pkt_faddr;
-	pkthdr_t pkthdr;
-	struct find_t ff;
-
-sprintf(path,"%s*.PK_",cfg.outbound);
-for(l=_dos_findfirst(path,0,&ff);!l && !kbhit();l=_dos_findnext(&ff)) {
-	sprintf(packet,"%s%s",cfg.outbound,ff.name);
-	printf("%21s: %s ","Outbound Packet",packet);
-	if((fmsg=sopen(packet,O_RDWR,SH_DENYRW))==-1) {
-		printf("ERROR opening.\n");
-		logprintf("ERROR line %d opening %s",__LINE__,packet);
-		continue; }
-	if((fidomsg=fdopen(fmsg,"r+b"))==NULL) {
-		close(fmsg);
-		printf("\7ERROR fdopening.\n");
-		logprintf("ERROR line %d fdopening %s",__LINE__,packet);
-		continue; }
-	if(filelength(fmsg)<sizeof(pkthdr_t)) {
-		printf("ERROR invalid length of %u bytes for %s\n",filelength(fmsg)
-			,packet);
-		logprintf("ERROR line %d invalid length of %u bytes for %s"
-			,__LINE__,filelength(fmsg),packet);
-		fclose(fidomsg);
-		if(delfile(packet))
-			logprintf("ERROR line %d removing %s %s",__LINE__,packet
-				,sys_errlist[errno]);
-		continue; }
-	if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
-		fclose(fidomsg);
-		printf("\7ERROR reading %u bytes from %s\n",sizeof(pkthdr_t),packet);
-		logprintf("ERROR line %d reading %u bytes from %s",__LINE__
-			,sizeof(pkthdr_t),packet);
-		continue; }
-	fseek(fidomsg,-2L,SEEK_END);
-	fread(str,2,1,fidomsg);
-	fclose(fidomsg);
-	if(!str[0] && !str[1]) {	/* Check for two nulls at end of packet */
-		pkt_faddr.zone=pkthdr.destzone;
-		pkt_faddr.net=pkthdr.destnet;
-		pkt_faddr.node=pkthdr.destnode;
-		pkt_faddr.point=0;				/* No point info in the 2.0 hdr! */
-		memcpy(&two_plus,&pkthdr.empty,20);
-		if(two_plus.cword==_rotr(two_plus.cwcopy,8)  /* 2+ Packet Header */
-			&& two_plus.cword && two_plus.cword&1)
-			pkt_faddr.point=two_plus.destpoint;
-		else if(pkthdr.baud==2) {				/* Type 2.2 Packet Header */
-			memcpy(&two_two,&pkthdr.empty,20);
-			pkt_faddr.point=pkthdr.month; }
-		printf("Sending to %s\n",faddrtoa(pkt_faddr));
-		pack_bundle(packet,pkt_faddr); }
-	else {
-		fclose(fidomsg);
-        printf("Possibly still in use\n"); } }
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-}
-/******************************************************************************
- This is where we put outgoing messages into packets.  Set the 'cleanup'
- parameter to 1 to force all the remaining packets closed and stuff them into
- a bundle.
-******************************************************************************/
-void pkt_to_pkt(uchar HUGE16 *fbuf,areasbbs_t area,faddr_t faddr
-	,fmsghdr_t fmsghdr,addrlist_t seenbys,addrlist_t paths,char cleanup)
-{
-	int i,j,k,file;
-	short node;
-	time_t now;
-	struct tm *tm;
-	pkthdr_t pkthdr;
-	static ushort openpkts,totalpkts;
-	static outpkt_t outpkt[MAX_TOTAL_PKTS];
-	faddr_t sysaddr;
-	two_two_t two;
-	two_plus_t two_p;
-
-
-if(cleanup==1) {
-	for(i=0;i<totalpkts;i++) {
-		if(i>=MAX_TOTAL_PKTS) {
-			printf("MAX_TOTAL_PKTS (%d) REACHED!\n",MAX_TOTAL_PKTS);
-			logprintf("MAX_TOTAL_PKTS (%d) REACHED!\n",MAX_TOTAL_PKTS);
-			break;
-		}
-		if(outpkt[i].curopen) {
-			fputc(0,outpkt[i].stream);
-			fputc(0,outpkt[i].stream);
-			fclose(outpkt[i].stream); }
-		else {
-			if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
-				,O_WRONLY|O_APPEND))==NULL) {
-				printf("ERROR opening %s for write.\n",outpkt[i].filename);
-				logprintf("ERROR line %d opening %s %s",__LINE__
-					,outpkt[i].filename,sys_errlist[errno]);
-				continue; }
-			fputc(0,outpkt[i].stream);
-			fputc(0,outpkt[i].stream);
-			fclose(outpkt[i].stream); }
-//		  pack_bundle(outpkt[i].filename,outpkt[i].uplink);
-		memset(&outpkt[i],0,sizeof(outpkt_t)); }
-	totalpkts=openpkts=0;
-	attach_bundles();
-	attachment(0,faddr,1);
-	return; }
-
-if(fbuf==NULL) {
-	printf("ERROR allocating fbuf\n");
-	logprintf("ERROR line %d allocating fbuf",__LINE__);
-    return; }
-/* We want to see if there's already a packet open for this area.   */
-/* If not, we'll open a new one.  Once we have a packet, we'll add  */
-/* messages to it as they come in.	If necessary, we'll close an    */
-/* open packet to open a new one.									*/
-
-for(j=0;j<area.uplinks;j++) {
-	if((cleanup==2 && memcmp(&faddr,&area.uplink[j],sizeof(faddr_t))) ||
-		(!cleanup && (!memcmp(&faddr,&area.uplink[j],sizeof(faddr_t)) ||
-		check_psb(seenbys,area.uplink[j]))))
-		continue;
-	node=matchnode(area.uplink[j],0);
-	if(node<cfg.nodecfgs && cfg.nodecfg[node].attr&ATTR_PASSIVE)
-		continue;
-	sysaddr=getsysfaddr(area.uplink[j].zone);
-	printf("%s ",faddrtoa(area.uplink[j]));
-	for(i=0;i<totalpkts;i++) {
-		if(i>=MAX_TOTAL_PKTS) {
-			printf("MAX_TOTAL_PKTS (%d) REACHED!\n",MAX_TOTAL_PKTS);
-			logprintf("MAX_TOTAL_PKTS (%d) REACHED!\n",MAX_TOTAL_PKTS);
-			break;
-        }
-		if(!memcmp(&area.uplink[j],&outpkt[i].uplink,sizeof(faddr_t))) {
-			if(!outpkt[i].curopen) {
-				if(openpkts==DFLT_OPEN_PKTS)
-					for(k=0;k<totalpkts;k++) {
-						if(outpkt[k].curopen) {
-							fclose(outpkt[k].stream);
-							outpkt[k].curopen=0;
-							break; } }
-				if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
-					,O_WRONLY|O_APPEND))==NULL) {
-					printf("Unable to open %s for write.\n"
-						,outpkt[i].filename);
-					logprintf("ERROR line %d opening %s %s",__LINE__
-						,outpkt[i].filename,sys_errlist[errno]);
-					exit(1); }
-				outpkt[i].curopen=1; }
-			if((strlen((char *)fbuf)+1+ftell(outpkt[i].stream))
-				<=cfg.maxpktsize) {
-				fmsghdr.destnode=area.uplink[j].node;
-				fmsghdr.destnet=area.uplink[j].net;
-				fmsghdr.destzone=area.uplink[j].zone;
-				putfmsg(outpkt[i].stream,fbuf,fmsghdr,area,seenbys,paths); }
-			else {
-				fputc(0,outpkt[i].stream);
-				fputc(0,outpkt[i].stream);
-				fclose(outpkt[i].stream);
-//				  pack_bundle(outpkt[i].filename,outpkt[i].uplink);
-				outpkt[i].stream=outpkt[totalpkts-1].stream;
-				memcpy(&outpkt[i],&outpkt[totalpkts-1],sizeof(outpkt_t));
-				memset(&outpkt[totalpkts-1],0,sizeof(outpkt_t));
-				--totalpkts;
-				--openpkts;
-				i=totalpkts; }
-			break; } }
-		if(i==totalpkts) {
-			if(openpkts==DFLT_OPEN_PKTS)
-				for(k=0;k<totalpkts;k++) {
-					if(outpkt[k].curopen) {
-						fclose(outpkt[k].stream);
-						outpkt[k].curopen=0;
-						--openpkts;
-						break; } }
-			strcpy(outpkt[i].filename,pktname());
-			now=time(NULL);
-			tm=gmtime(&now);
-			if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
-				,O_WRONLY|O_CREAT))==NULL) {
-				printf("Unable to open %s for write.\n"
-					,outpkt[i].filename);
-				logprintf("ERROR line %d opening %s %s"
-					,__LINE__,outpkt[i].filename,sys_errlist[errno]);
-				exit(1); }
-			pkthdr.orignode=sysaddr.node;
-			fmsghdr.destnode=pkthdr.destnode=area.uplink[j].node;
-			if(node<cfg.nodecfgs && cfg.nodecfg[node].pkt_type==PKT_TWO_TWO) {
-				pkthdr.year=sysaddr.point;
-				pkthdr.month=area.uplink[j].point;
-				pkthdr.day=0;
-				pkthdr.hour=0;
-				pkthdr.min=0;
-				pkthdr.sec=0;
-				pkthdr.baud=0x0002; }
-			else {
-				pkthdr.year=tm->tm_year+1900;
-				pkthdr.month=tm->tm_mon;
-				pkthdr.day=tm->tm_mday;
-				pkthdr.hour=tm->tm_hour;
-				pkthdr.min=tm->tm_min;
-				pkthdr.sec=tm->tm_sec;
-				pkthdr.baud=0; 
-			}
-			pkthdr.pkttype=0x0002;
-			pkthdr.orignet=sysaddr.net;
-			fmsghdr.destnet=pkthdr.destnet=area.uplink[j].net;
-			pkthdr.prodcode=0;
-			pkthdr.sernum=0;
-			if(node<cfg.nodecfgs)
-				memcpy(pkthdr.password,cfg.nodecfg[node].pktpwd,8);
-			else
-				memset(pkthdr.password,0,8);
-			pkthdr.origzone=sysaddr.zone;
-			fmsghdr.destzone=pkthdr.destzone=area.uplink[j].zone;
-			memset(pkthdr.empty,0,sizeof(two_two_t));
-
-			if(node<cfg.nodecfgs) {
-				if(cfg.nodecfg[node].pkt_type==PKT_TWO_TWO) {
-					memset(&two,0,20);
-					strcpy(two.origdomn,"fidonet");
-					strcpy(two.destdomn,"fidonet");
-					memcpy(&pkthdr.empty,&two,20); }
-				else if(cfg.nodecfg[node].pkt_type==PKT_TWO_PLUS) {
-					memset(&two_p,0,20);
-					if(sysaddr.point) {
-						pkthdr.orignet=-1;
-						two_p.auxnet=sysaddr.net; }
-					two_p.cwcopy=0x0100;
-					two_p.prodcode=pkthdr.prodcode;
-					two_p.revision=pkthdr.sernum;
-					two_p.cword=0x0001;
-					two_p.origzone=pkthdr.origzone;
-					two_p.destzone=pkthdr.destzone;
-					two_p.origpoint=sysaddr.point;
-					two_p.destpoint=area.uplink[j].point;
-					memcpy(&pkthdr.empty,&two_p,sizeof(two_plus_t)); 
-				}
-			}
-
-			fwrite(&pkthdr,sizeof(pkthdr_t),1,outpkt[totalpkts].stream);
-			putfmsg(outpkt[totalpkts].stream,fbuf,fmsghdr,area,seenbys,paths);
-			outpkt[totalpkts].curopen=1;
-			memcpy(&outpkt[totalpkts].uplink,&area.uplink[j]
-				,sizeof(faddr_t));
-			++openpkts;
-			++totalpkts;
-			if(totalpkts>=MAX_TOTAL_PKTS) {
-				fclose(outpkt[totalpkts-1].stream);
-//				  pack_bundle(outpkt[totalpkts-1].filename
-//					  ,outpkt[totalpkts-1].uplink);
-				--totalpkts;
-				--openpkts; }
-			} }
-}
-
-/**************************************/
-/* Send netmail, returns 0 on success */
-/**************************************/
-int import_netmail(char *path,fmsghdr_t hdr, FILE *fidomsg)
-{
-	uchar info[512],str[256],tmp[256],subj[256]
-		,HUGE16 *fmsgbuf=NULL,*p,*tp,*sp;
-	int i,match,usernumber;
-	ulong l;
-	faddr_t addr;
-
-hdr.destzone=hdr.origzone=sys_faddr.zone;
-hdr.destpoint=hdr.origpoint=0;
-getzpt(fidomsg,&hdr);				/* use kludge if found */
-for(match=0;match<total_faddrs;match++)
-	if((hdr.destzone==faddr[match].zone || misc&FUZZY_ZONE)
-		&& hdr.destnet==faddr[match].net
-		&& hdr.destnode==faddr[match].node
-		&& hdr.destpoint==faddr[match].point)
-		break;
-if(match<total_faddrs && misc&FUZZY_ZONE)
-	hdr.origzone=hdr.destzone=faddr[match].zone;
-if(hdr.origpoint)
-	sprintf(tmp,".%u",hdr.origpoint);
-else
-	tmp[0]=0;
-if(hdr.destpoint)
-	sprintf(str,".%u",hdr.destpoint);
-else
-	str[0]=0;
-sprintf(info,"%s%s%s (%u:%u/%u%s) To: %s (%u:%u/%u%s)"
-	,path,path[0] ? " ":""
-	,hdr.from,hdr.origzone,hdr.orignet,hdr.orignode,tmp
-	,hdr.to,hdr.destzone,hdr.destnet,hdr.destnode,str);
-printf("%s ",info);
-
-if(!(misc&IMPORT_NETMAIL)) {
-	if(!path[0]) {
-		fmsgbuf=getfmsg(fidomsg,&l);
-		if(!fmsgbuf) {
-			printf("ERROR Netmail allocation");
-			logprintf("ERROR line %d netmail allocation",__LINE__);
-			return(2); }
-
-		if(!l && misc&KILL_EMPTY_MAIL)
-			printf("Empty NetMail - ");
-		else {
-			for(i=1;i;i++) {
-				sprintf(str,"%s%u.MSG",netmail_dir,i);
-				if(!fexist(str))
-					break; }
-			if(!i) {
-				printf("Too many netmail messages");
-				logprintf("Too many netmail messages");
-				return(2); }
-			if((i=nopen(str,O_WRONLY|O_CREAT))==-1) {
-				printf("ERROR opening %s",str);
-				logprintf("ERROR opening %s",str);
-				return(2); }
-			write(i,&hdr,sizeof(hdr));
-			write(i,fmsgbuf,strlen((char *)fmsgbuf)+1); /* Write the NULL too */
-			close(i); }
-		FREE(fmsgbuf); }
-	printf("Ignored");
-	if(cfg.log&LOG_IGNORED)
-		logprintf("%s Ignored",info);
-	return(-1); }
-
-if(hdr.attr&FIDO_ORPHAN) {
-	printf("Orphaned");
-    return(1); }
-if(!(misc&IGNORE_ADDRESS) && match==total_faddrs && path[0]) {
-	printf("Skipped");
-	return(2); }
-if(!(misc&IGNORE_RECV) && hdr.attr&FIDO_RECV) {
-	printf("Already received");
-	return(3); }
-if(hdr.attr&FIDO_LOCAL && !(misc&LOCAL_NETMAIL)) {
-	printf("Created locally");
-	return(4); }
-
-if(email->shd_fp==NULL) {
-	sprintf(email->file,"%sMAIL",data_dir);
-	email->retry_time=smb_retry_time;
-	if((i=smb_open(email))!=0) {
-		printf("ERROR %d opening %s\n",i,email->file);
-		logprintf("ERROR %d line %d opening %s",i,__LINE__,email->file);
-		exit(1); } }
-
-if(!filelength(fileno(email->shd_fp))) {
-	email->status.max_crcs=mail_maxcrcs;
-	email->status.max_msgs=MAX_SYSMAIL;
-	email->status.max_age=mail_maxage;
-	email->status.attr=SMB_EMAIL;
-	if((i=smb_create(email))!=0) {
-		sprintf(str,"ERROR %d creating %s",i,email->file);
-        printf("%s\n",str);
-        logprintf(str);
-		exit(1); } }
-
-if(!stricmp(hdr.to,"AREAFIX") || !stricmp(hdr.to,"SBBSECHO")) {
-	fmsgbuf=getfmsg(fidomsg,NULL);
-	if(path[0]) {
-		if(misc&DELETE_NETMAIL) {
-			fclose(fidomsg);
-			if(delfile(path))
-				logprintf("ERROR line %d removing %s %s",__LINE__,path
-					,sys_errlist[errno]); }
-		else {
-			hdr.attr|=FIDO_RECV;
-			fseek(fidomsg,0L,SEEK_SET);
-			fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg);
-			fclose(fidomsg); } }	/* Gotta close it here for areafix stuff */
-	addr.zone=hdr.origzone;
-	addr.net=hdr.orignet;
-	addr.node=hdr.orignode;
-	addr.point=hdr.origpoint;
-	strcpy(hdr.to,sys_op);
-	strcpy(hdr.from,"SBBSecho");
-	strcpy(str,hdr.subj);
-	strcpy(hdr.subj,"Areafix Request");
-	hdr.origzone=hdr.orignet=hdr.orignode=hdr.origpoint=0;
-	p=process_areafix(addr,fmsgbuf,str);
-#if 0 // Not necessary with SMBLIB v2.0
-	if((i=smb_locksmbhdr(email))!=0) {
-		printf("ERROR %d locking %s smbhdr",i,email->file);
-		logprintf("ERROR %d line %d locking %s smbhdr",i,__LINE__,email->file);
-		exit(1); }
-	if((i=smb_getstatus(email))!=0) {
-		printf("ERROR %d reading %s status header",i,email->file);
-		logprintf("ERROR %d line %d reading %s status header",i,__LINE__
-			,email->file);
-		exit(1); }
-#endif
-	if(p && cfg.notify)
-		if(fmsgtosmsg(p,hdr,cfg.notify,INVALID_SUB)==1) {
-			sprintf(str,"\7\1n\1hSBBSecho \1n\1msent you mail\r\n");
-			putsmsg(cfg.notify,str); }
-//	  smb_unlocksmbhdr(email);
-	if(fmsgbuf)
-		FREE(fmsgbuf);
-	if(cfg.log&LOG_AREAFIX)
-		logprintf(info);
-	return(-2); }
-
-usernumber=atoi(hdr.to);
-if(!stricmp(hdr.to,"SYSOP"))  /* NetMail to "sysop" goes to #1 */
-	usernumber=1;
-if(!usernumber && match<total_faddrs)
-	usernumber=matchname(hdr.to);
-if(!usernumber) {
-	if(misc&UNKNOWN_NETMAIL && match<total_faddrs)	/* receive unknown user */
-		usernumber=1;								/* mail to 1 */
-	else {
-		if(match<total_faddrs) {
-			printf("Unknown user ");
-			if(cfg.log&LOG_UNKNOWN)
-				logprintf("%s Unknown user",info); }
-/***
-		hdr.attr|=FIDO_ORPHAN;
-		fseek(fidomsg,0L,SEEK_SET);
-		fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg);
-***/
-		if(!path[0]) {
-			fmsgbuf=getfmsg(fidomsg,&l);
-			if(!fmsgbuf) {
-				printf("ERROR Netmail allocation");
-				logprintf("ERROR line %d netmail allocation",__LINE__);
-				return(2); }
-			if(!l && misc&KILL_EMPTY_MAIL) {
-				printf("Empty NetMail - Ignored");
-				if(cfg.log&LOG_IGNORED)
-					logprintf("%s Empty - Ignored",info); }
-			else {
-				for(i=1;i;i++) {
-					sprintf(str,"%s%u.MSG",netmail_dir,i);
-					if(!fexist(str))
-						break; }
-				if(!i) {
-					printf("Too many netmail messages");
-					logprintf("Too many netmail messages");
-					return(2); }
-				if((i=nopen(str,O_WRONLY|O_CREAT))==-1) {
-					printf("ERROR opening %s",str);
-					logprintf("ERROR opening %s",str);
-					return(2); }
-				write(i,&hdr,sizeof(hdr));
-				write(i,fmsgbuf,strlen((char *)fmsgbuf)+1); /* Write the NULL too */
-				close(i); }
-			FREE(fmsgbuf); }
-		return(2); } }
-
-/*********************/
-/* Importing NetMail */
-/*********************/
-
-fmsgbuf=getfmsg(fidomsg,&l);
-
-#if 0 // Unnecessary with SMBLIB v2.0
-if((i=smb_locksmbhdr(email))!=0) {
-	printf("ERROR %d locking %s smbhdr",i,email->file);
-	logprintf("ERROR %d line %d locking %s smbhdr",i,__LINE__,email->file);
-    exit(1); }
-if((i=smb_getstatus(email))!=0) {
-	printf("ERROR %d reading %s status header",i,email->file);
-	logprintf("ERROR %d line %d reading %s status header"
-		,i,__LINE__,email->file);
-    exit(1); }
-#endif
-
-if(!l && misc&KILL_EMPTY_MAIL) {
-	printf("Empty NetMail - Ignored");
-	if(cfg.log&LOG_IGNORED)
-		logprintf("%s Empty - Ignored",info);
-	if(fmsgbuf)
-		FREE(fmsgbuf);
-	return(0); }
-
-i=fmsgtosmsg(fmsgbuf,hdr,usernumber,INVALID_SUB);
-if(i!=1) {
-	printf("ERROR (%d) Importing",i);
-	logprintf("ERROR (%d) Importing %s",i,info);
-	if(fmsgbuf)
-		FREE(fmsgbuf);
-	return(10); }
-
-addr.zone=hdr.origzone;
-addr.net=hdr.orignet;
-addr.node=hdr.orignode;
-addr.point=hdr.origpoint;
-sprintf(str,"\7\1n\1hSBBSecho: \1m%.36s \1n\1msent you NetMail from "
-	"\1h%s\1n\r\n",hdr.from,faddrtoa(addr));
-putsmsg(usernumber,str);
-
-if(hdr.attr&FIDO_FILE) {	/* File attachment */
-	strcpy(subj,hdr.subj);
-	tp=subj;
-	while(1) {
-		p=strchr(tp,SP);
-		if(p) *p=0;
-		sp=strrchr(tp,'/');              /* sp is slash pointer */
-		if(!sp) sp=strrchr(tp,'\\');
-		if(sp) tp=sp+1;
-		sprintf(str,"%s%s",fidofile_dir,tp);
-		sprintf(tmp,"%sFILE\\%04u.IN",data_dir,usernumber);
-		mkdir(tmp);
-		strcat(tmp,"\\");
-		strcat(tmp,tp);
-		mv(str,tmp,0);
-		if(!p)
-			break;
-		tp=p+1; } }
-netmail++;
-
-if(fmsgbuf)
-	FREE(fmsgbuf);
-
-/***************************/
-/* Updating message header */
-/***************************/
-/***	NOT packet compatible
-if(!(misc&DONT_SET_RECV)) {
-	hdr.attr|=FIDO_RECV;
-	fseek(fidomsg,0L,SEEK_SET);
-	fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg); }
-***/
-if(cfg.log&LOG_IMPORTED)
-	logprintf("%s Imported",info);
-return(0);
-}
-
-/******************************************************************************
- This is where we export echomail.	This was separated from function main so
- it could be used for the remote rescan function.  Passing anything but an
- empty address as 'addr' designates that a rescan should be done for that
- address.
-******************************************************************************/
-void export_echomail(char *sub_code,faddr_t addr)
-{
-	char str[1025],tear,cr,HUGE16 *buf;
-	uchar HUGE16 *fmsgbuf=NULL;
-	int g,i,j,k,file;
-	ulong f,l,m,exp,ptr,msgs,lastmsg,posts,exported=0;
-	float export_time;
-	smbmsg_t msg;
-	fmsghdr_t hdr;
-	struct	tm *tm;
-	faddr_t pkt_faddr;
-	post_t HUGE16 *post;
-	areasbbs_t fakearea,curarea;
-	addrlist_t msg_seen,msg_path;
-    clock_t start_tick=0,export_ticks=0;
-
-memset(&msg_seen,0,sizeof(addrlist_t));
-memset(&msg_path,0,sizeof(addrlist_t));
-memset(&pkt_faddr,0,sizeof(faddr_t));
-start_tick=0;
-
-printf("\nScanning for Outbound EchoMail...\n");
-
-for(g=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		for(j=0;j<cfg.areas;j++)	/* Skip areas with no uplinks */
-			if(cfg.area[j].sub==i)
-				break;
-		if(j==cfg.areas || (j<cfg.areas && !cfg.area[j].uplinks))
-			continue;
-		if(addr.zone) { 		/* Skip areas not meant for this address */
-			if(j<cfg.areas)
-				for(k=0;k<cfg.area[j].uplinks;k++)
-					if(!memcmp(&cfg.area[j].uplink[k],&addr,sizeof(faddr_t)))
-						break;
-			if(k==cfg.area[j].uplinks)
-				continue; }
-		if(sub_code[0] && stricmp(sub_code,sub[i]->code))
-            continue;
-		printf("\nScanning %-15.15s %s\n"
-			,grp[sub[i]->grp]->sname,sub[i]->lname);
-		ptr=0;
-		if(!addr.zone && !(misc&IGNORE_MSGPTRS)) {
-			sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-			if((file=nopen(str,O_RDONLY))!=-1) {
-				read(file,&ptr,sizeof(time_t));
-				close(file); } }
-
-		msgs=getlastmsg(i,&lastmsg,0);
-		if(!msgs || (!addr.zone && !(misc&IGNORE_MSGPTRS) && ptr>=lastmsg)) {
-			printf("No new messages.");
-			if(ptr>lastmsg && !addr.zone && !(misc&LEAVE_MSGPTRS)) {
-				printf("Fixing new-scan pointer.");
-                sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-				if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
-					printf("\7ERROR opening/creating %s",str);
-					logprintf("ERROR line %d opening/creating %s"
-						,__LINE__,str); }
-				else {
-					write(file,&lastmsg,4);
-					close(file); } }
-			continue; }
-
-		sprintf(smb[cur_smb].file,"%s%s"
-			,sub[i]->data_dir,sub[i]->code);
-		smb[cur_smb].retry_time=smb_retry_time;
-		if((j=smb_open(&smb[cur_smb]))!=0) {
-			printf("ERROR %d opening %s\n",j,smb[cur_smb].file);
-			logprintf("ERROR %d line %d opening %s",j,__LINE__
-				,smb[cur_smb].file);
-			continue; }
-
-		post=NULL;
-		posts=loadmsgs(&post,ptr);
-
-		if(!posts)	{ /* no new messages */
-			smb_close(&smb[cur_smb]);
-			if(post)
-				LFREE(post);
-			continue; }
-
-		if(start_tick)
-			export_ticks+=clock()-start_tick;
-        start_tick=clock();
-
-		for(m=exp=0;m<posts;m++) {
-			printf("\r%8s %5lu of %-5lu  "
-				,sub[i]->code,m+1,posts);
-			msg.idx.offset=post[m].offset;
-			if((k=smb_lockmsghdr(&smb[cur_smb],&msg))!=0) {
-				printf("ERROR %d locking %s msghdr\n",k,smb[cur_smb].file);
-				logprintf("ERROR %d line %d locking %s msghdr\n"
-					,k,__LINE__,smb[cur_smb].file);
-				continue; }
-			k=smb_getmsghdr(&smb[cur_smb],&msg);
-			if(k || msg.hdr.number!=post[m].number) {
-				smb_unlockmsghdr(&smb[cur_smb],&msg);
-				smb_freemsgmem(&msg);
-
-				msg.hdr.number=post[m].number;
-				if((k=smb_getmsgidx(&smb[cur_smb],&msg))!=0) {
-					printf("ERROR %d reading %s index\n",k,smb[cur_smb].file);
-					logprintf("ERROR %d line %d reading %s index",k,__LINE__
-						,smb[cur_smb].file);
-					continue; }
-				if((k=smb_lockmsghdr(&smb[cur_smb],&msg))!=0) {
-					printf("ERROR %d locking %s msghdr\n",k,smb[cur_smb].file);
-					logprintf("ERROR %d line %d locking %s msghdr",k,__LINE__
-						,smb[cur_smb].file);
-					continue; }
-				if((k=smb_getmsghdr(&smb[cur_smb],&msg))!=0) {
-					smb_unlockmsghdr(&smb[cur_smb],&msg);
-					printf("ERROR %d reading %s msghdr\n",k,smb[cur_smb].file);
-					logprintf("ERROR %d line %d reading %s msghdr",k,__LINE__
-						,smb[cur_smb].file);
-					continue; } }
-
-			if((!addr.zone && !(misc&EXPORT_ALL)
-				&& msg.from_net.type==NET_FIDO)
-				|| !strnicmp(msg.subj,"NE:",3)) {   /* no echo */
-				smb_unlockmsghdr(&smb[cur_smb],&msg);
-				smb_freemsgmem(&msg);
-				continue; }  /* From a Fido node, ignore it */
-
-			if(msg.from_net.type && msg.from_net.type!=NET_FIDO
-				&& !(sub[i]->misc&SUB_GATE)) {
-				smb_unlockmsghdr(&smb[cur_smb],&msg);
-				smb_freemsgmem(&msg);
-				continue; }
-
-			memset(&hdr,0,sizeof(fmsghdr_t));	 /* Zero the header */
-			hdr.origzone=sub[i]->faddr.zone;
-			hdr.orignet=sub[i]->faddr.net;
-			hdr.orignode=sub[i]->faddr.node;
-			hdr.origpoint=sub[i]->faddr.point;
-
-			hdr.attr=FIDO_LOCAL;
-			if(msg.hdr.attr&MSG_PRIVATE)
-				hdr.attr|=FIDO_PRIVATE;
-
-			sprintf(hdr.from,"%.35s",msg.from);
-
-			tm=gmtime((time_t *)&msg.hdr.when_written.time);
-			sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
-				,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
-				,tm->tm_hour,tm->tm_min,tm->tm_sec);
-
-			sprintf(hdr.to,"%.35s",msg.to);
-
-			sprintf(hdr.subj,"%.71s",msg.subj);
-
-			buf=smb_getmsgtxt(&smb[cur_smb],&msg,GETMSGTXT_TAILS);
-			if(!buf) {
-				smb_unlockmsghdr(&smb[cur_smb],&msg);
-				smb_freemsgmem(&msg);
-				continue; }
-			fmsgbuf=MALLOC(strlen((char *)buf)+512);
-			if(!fmsgbuf) {
-				printf("ERROR allocating %lu bytes for fmsgbuf\n");
-				logprintf("ERROR line %d allocating %lu bytes for fmsgbuf"
-					,__LINE__,strlen((char *)buf)+512);
-				smb_unlockmsghdr(&smb[cur_smb],&msg);
-				smb_freemsgmem(&msg);
-				continue; }
-
-			tear=0;
-			for(l=f=0,cr=1;buf[l];l++) {
-				if(buf[l]==1) { /* Ctrl-A, so skip it and the next char */
-					l++;
-					if(!buf[l])
-						break;
-					continue; }
-				if(buf[l]==LF)	/* Ignore line feeds */
-					continue;
-				if(cr) {
-					if(buf[l]=='-' && buf[l+1]=='-'
-						&& buf[l+2]=='-'
-						&& (buf[l+3]==SP || buf[l+3]==CR)) {
-						if(misc&CONVERT_TEAR)	/* Convert to === */
-							buf[l]=buf[l+1]=buf[l+2]='=';
-						else
-							tear=1; }
-					else if(!strncmp((char *)buf+l," * Origin: ",11))
-						buf[l+1]='#'; } /* Convert * Origin into # Origin */
-
-				if(buf[l]==CR)
-					cr=1;
-				else
-					cr=0;
-				if(sub[i]->misc&SUB_ASCII || misc&ASCII_ONLY) {
-					if(buf[l]<SP && buf[l]!=CR) /* Ctrl ascii */
-						buf[l]='.';             /* converted to '.' */
-					if((uchar)buf[l]>0x7f)		/* extended ASCII */
-						buf[l]='*'; }           /* converted to '*' */
-
-				fmsgbuf[f++]=buf[l]; }
-
-			FREE(buf);
-			fmsgbuf[f]=0;
-
-			if(!(sub[i]->misc&SUB_NOTAG)) {
-				if(!tear) {  /* No previous tear line */
-					sprintf(str,"--- Synchronet+SBBSecho v%s\r",SBBSECHO_VER);
-					strcat((char *)fmsgbuf,str); }
-
-				sprintf(str," * Origin: %s (%s)\r"
-					,sub[i]->origline[0] ? sub[i]->origline : origline
-					,faddrtoa(sub[i]->faddr));
-				strcat((char *)fmsgbuf,str); }
-
-			for(k=0;k<cfg.areas;k++)
-				if(cfg.area[k].sub==i) {
-					cfg.area[k].exported++;
-					pkt_to_pkt(fmsgbuf,cfg.area[k]
-						,(addr.zone) ? addr:pkt_faddr,hdr,msg_seen
-						,msg_path,(addr.zone) ? 2:0);
-					break; }
-			FREE(fmsgbuf);
-			exported++;
-			exp++;
-			printf("Exp: %lu ",exp);
-			smb_unlockmsghdr(&smb[cur_smb],&msg);
-			smb_freemsgmem(&msg); }
-
-		smb_close(&smb[cur_smb]);
-		LFREE(post);
-
-		/***********************/
-		/* Update FIDO_PTR.DAB */
-		/***********************/
-		if(!addr.zone && !(misc&LEAVE_MSGPTRS) && lastmsg>ptr) {
-			sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-			if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
-				printf("\7ERROR opening/creating %s",str);
-				logprintf("ERROR line %d opening/creating %s",__LINE__,str); }
-			else {
-				write(file,&lastmsg,4);
-				close(file); } } }
-
-printf("\n");
-if(start_tick)	/* Last possible increment of export_ticks */
-	export_ticks+=clock()-start_tick;
-
-pkt_to_pkt(buf,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
-
-if(!addr.zone && cfg.log&LOG_AREA_TOTALS && exported)
-    for(i=0;i<cfg.areas;i++)
-        if(cfg.area[i].exported)
-			logprintf("Exported: %5u msgs %8s -> %s"
-				,cfg.area[i].exported,sub[cfg.area[i].sub]->code
-				,cfg.area[i].name);
-
-export_time=((float)export_ticks)/(float)CLK_TCK;
-if(cfg.log&LOG_TOTALS && exported && export_time) {
-	printf("\nExported %lu EchoMail messages in %.1f seconds "
-		,exported,export_time);
-	logprintf("Exported: %5lu msgs in %.1f sec (%.1f/min %.1f/sec)"
-		,exported,export_time
-		,export_time/60.0 ? (float)exported/(export_time/60.0) :(float)exported
-		,(float)exported/export_time);
-	if(export_time/60.0)
-		printf("(%.1f/min) ",(float)exported/(export_time/60.0));
-	printf("(%.1f/sec)\n",(float)exported/export_time); }
-
-}
-/***********************************/
-/* Synchronet/FidoNet Message util */
-/***********************************/
-int main(int argc, char **argv)
-{
-	FILE	*fidomsg;
-	char	ch,str[1025],fname[256],path[512],sub_code[9]
-			,*p,*tp,*sp,*buf,cr,tear,lzh
-			,areatagstr[129],packet[128],outbound[128]
-			,password[16];
-	uchar	HUGE16 *fmsgbuf=NULL;
-	ushort	xlat,attr;
-	int 	i,j,k,n,x,y,z,last,file,fmsg,g,grunged;
-	uint	subnum[MAX_OPEN_SMBS]={INVALID_SUB};
-	ulong	files,msgfiles,echomail=0,crc,ptr,
-			l,m,f,length,lastmsg,posts,msgs,exp,areatag;
-	time_t	now;
-	float	import_time;
-	clock_t start_tick=0,import_ticks=0;
-	read_cfg_text_t txt;
-	struct	find_t ff;
-	struct	tm *tm;
-	fmsghdr_t hdr;
-	faddr_t addr,pkt_faddr;
-	post_t	HUGE16 *post;
-	FILE	*stream,*fstream;
-	smbmsg_t msg;
-	pkthdr_t pkthdr;
-	addrlist_t msg_seen,msg_path;
-	areasbbs_t fakearea,curarea;
-	char *usage="\n"
-"usage: sbbsecho [cfg_file] [/switches] [sub_code]\n"
-"\n"
-"where: cfg_file is the filename of config file (default is ctrl\\sbbsecho.cfg)\n"
-"       sub_code is the internal code for a sub-board (default is ALL subs)\n"
-"\n"
-"valid switches:\n"
-"\n"
-"p: do not import packets                 x: do not delete packets after import\n"
-"n: do not import netmail                 d: do not delete netmail after import\n"
-"i: do not import echomail                e: do not export echomail\n"
-"m: ignore echomail ptrs (export all)     u: update echomail ptrs (export none)\n"
-"j: ignore recieved bit on netmail        t: do not update echomail ptrs\n"
-"l: create log file (data\\sbbsecho.log)   r: create report of import totals\n"
-"h: export all echomail (hub rescan)      b: import locally created netmail too\n"
-"a: export ASCII characters only          f: create packets for outbound netmail\n"
-"g: generate notify lists                 =: change existing tear lines to ===\n"
-"y: import netmail for unknown users to sysop\n"
-"o: import all netmail regardless of destination address\n"
-"s: import private echomail override (strip private status)\n"
-"!: notify users of received echomail\n";
-
-if((email=(smb_t *)MALLOC(sizeof(smb_t)))==NULL) {
-	printf("ERROR allocating memory for email.\n");
-	exit(1); }
-memset(email,0,sizeof(smb_t));
-if((smb=(smb_t *)MALLOC(MAX_OPEN_SMBS*sizeof(smb_t)))==NULL) {
-	printf("ERROR allocating memory for smbs.\n");
-	exit(1); }
-for(i=0;i<MAX_OPEN_SMBS;i++)
-	memset(&smb[i],0,sizeof(smb_t));
-memset(&cfg,0,sizeof(config_t));
-memset(&msg_seen,0,sizeof(addrlist_t));
-memset(&msg_path,0,sizeof(addrlist_t));
-printf("\nSBBSecho Version %s (%s) SMBLIB %s � Synchronet FidoNet Packet "
-	"Tosser\n"
-	,SBBSECHO_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-	,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	,smb_lib_ver()
-	);
-
-putenv("TZ=UCT0");
-putenv("TMP=");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-txt.openerr="\7\nError opening %s for read.\n";
-txt.reading="\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\nError allocating %u bytes of memory\n";
-txt.error="\7\nERROR: Offset %lu in %s\n\n";
-
-node_dir[0]=sub_code[0]=0;
-for(i=1;i<argc;i++) {
-	if(argv[i][0]=='/') {
-		j=1;
-		while(argv[i][j]) {
-			switch(toupper(argv[i][j])) {
-				case 'A':
-                    misc|=ASCII_ONLY;
-                    break;
-				case 'B':
-					misc|=LOCAL_NETMAIL;
-					break;
-				case 'D':
-                    misc&=~DELETE_NETMAIL;
-                    break;
-				case 'E':
-                    misc&=~EXPORT_ECHOMAIL;
-                    break;
-				case 'F':
-					misc|=PACK_NETMAIL;
-					break;
-				case 'G':
-					misc|=GEN_NOTIFY_LIST;
-					break;
-				case 'H':
-                    misc|=EXPORT_ALL;
-                    break;
-				case 'I':
-                    misc&=~IMPORT_ECHOMAIL;
-                    break;
-                case 'J':
-					misc|=IGNORE_RECV;
-                    break;
-                case 'L':
-                    misc|=LOGFILE;
-                    break;
-				case 'M':
-                    misc|=IGNORE_MSGPTRS;
-                    break;
-				case 'N':
-					misc&=~IMPORT_NETMAIL;
-					break;
-				case 'O':
-                    misc|=IGNORE_ADDRESS;
-                    break;
-				case 'P':
-					misc&=~IMPORT_PACKETS;
-					break;
-				case 'R':
-                    misc|=REPORT;
-                    break;
-				case 'S':
-                    misc|=IMPORT_PRIVATE;
-                    break;
-				case 'T':
-                    misc|=LEAVE_MSGPTRS;
-                    break;
-                case 'U':
-                    misc|=UPDATE_MSGPTRS;
-                    misc&=~EXPORT_ECHOMAIL;
-                    break;
-				case 'X':
-					misc&=~DELETE_PACKETS;
-					break;
-                case 'Y':
-                    misc|=UNKNOWN_NETMAIL;
-                    break;
-				case '=':
-					misc|=CONVERT_TEAR;
-					break;
-				case '!':
-					misc|=NOTIFY_RECEIPT;
-					break;
-				case 'Q':
-					exit(0);
-				default:
-					printf(usage);
-					exit(0); }
-			j++; } }
-	else {
-		if(strchr(argv[i],'\\') || argv[i][1]==':' || strchr(argv[i],'.'))
-			sprintf(cfg.cfgfile,"%.100s",argv[i]);
-		else
-			sprintf(sub_code,"%.8s",argv[i]); }  }
-
-if(!(misc&(IMPORT_NETMAIL|IMPORT_ECHOMAIL)))
-	misc&=~IMPORT_PACKETS;
-if(!node_dir[0]) {
-	p=getenv("SBBSNODE");
-	if(p==NULL) {
-		printf("\7\nSBBSNODE environment variable not set.\n");
-		exit(1); }
-	strcpy(node_dir,p); }
-
-strupr(node_dir);
-
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,ctrl_dir,40))
-		strcpy(ctrl_dir,str); }
-backslash(ctrl_dir);
-
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,data_dir,40))
-		strcpy(data_dir,str); }
-backslash(data_dir);
-if(text_dir[0]=='.') {   /* Relative path */
-	strcpy(str,text_dir);
-	sprintf(text_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,text_dir,40))
-		strcpy(text_dir,str); }
-backslash(text_dir);
-read_msgs_cfg(txt);
-
-#ifndef __FLAT__
-
-__spawn_ext = (node_swap & SWAP_EXT) != 0 ;
-__spawn_ems = (node_swap & SWAP_EMS) != 0 ;
-__spawn_xms = (node_swap & SWAP_XMS) != 0 ;
-
-#endif
-
-if(total_faddrs<1) {
-	sys_faddr.zone=sys_faddr.net=sys_faddr.node=1;
-	sys_faddr.point=0; }
-else
-	sys_faddr=faddr[0];
-
-sprintf(str,"%s%s",ctrl_dir,"NODE.DAB");
-if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO))==-1) {
-	printf("\n\7ERROR opening %s\n",str);
-    exit(1); }
-
-if(!cfg.cfgfile[0])
-    sprintf(cfg.cfgfile,"%sSBBSECHO.CFG",ctrl_dir);
-strcpy(cfg.inbound,fidofile_dir);
-sprintf(cfg.areafile,"%sAREAS.BBS",data_dir);
-sprintf(cfg.logfile,"%sSBBSECHO.LOG",data_dir);
-
-read_cfg();
-
-if(misc&LOGFILE)
-	if((fidologfile=_fsopen(cfg.logfile,"ab",SH_DENYNO))==NULL) {
-		printf("\7ERROR opening %s\n",cfg.logfile);
-        exit(1); }
-
-if(exec_dir[0]!='\\' && exec_dir[1]!=':') {
-	strcpy(path,node_dir);
-	strcat(path,exec_dir);
-	if(_fullpath(str,path,40))
-		strcpy(path,str);
-	backslash(path); }
-else
-	strcpy(path,exec_dir);
-
-/******* READ IN AREAS.BBS FILE *********/
-
-printf("Reading %s",cfg.areafile);
-if((stream=fnopen(&file,cfg.areafile,O_RDONLY))==NULL) {
-	printf("Unable to open %s for read.\n",cfg.areafile);
-    exit(1); }
-cfg.areas=0;		/* Total number of areas in AREAS.BBS */
-cfg.area=NULL;
-while(1) {
-	if(!fgets(str,1024,stream))
-        break;
-	truncsp(str);
-	p=str;
-	while(*p && *p<=SP) p++;	/* Find first printable char */
-	if(*p==';' || !*p)          /* Ignore blank lines or start with ; */
-		continue;
-	if((cfg.area=(areasbbs_t *)REALLOC(cfg.area,sizeof(areasbbs_t)*
-		(cfg.areas+1)))==NULL) {
-		printf("ERROR allocating memory for area #%u.\n",cfg.areas+1);
-		exit(1); }
-	memset(&cfg.area[cfg.areas],0,sizeof(areasbbs_t));
-
-	cfg.area[cfg.areas].sub=INVALID_SUB;	/* Default to passthru */
-
-	sprintf(tmp,"%-.8s",p);
-	tp=tmp;
-	while(*tp>SP) tp++;
-	*tp=0;
-	for(i=0;i<total_subs;i++)
-		if(!stricmp(tmp,sub[i]->code))
-			break;
-	if(i<total_subs)
-		cfg.area[cfg.areas].sub=i;
-	else if(stricmp(tmp,"P")) {
-		printf("\n%s: Unrecongized internal code, assumed passthru",tmp);
-		logprintf("%s: Unrecognized internal code, assumed passthru",tmp); }
-
-	while(*p>SP) p++;				/* Skip code */
-	while(*p && *p<=SP) p++;		/* Skip white space */
-	sprintf(tmp,"%-.50s",p);        /* Area tag */
-	if((tp=strchr(tmp,TAB))!=NULL)	/* Chop off any TABs */
-		*tp=0;
-	if((tp=strchr(tmp,SP))!=NULL)	/* Chop off any spaces */
-		*tp=0;
-	strupr(tmp);
-	if(tmp[0]=='*')         /* UNKNOWN-ECHO area */
-		cfg.badecho=cfg.areas;
-	if((cfg.area[cfg.areas].name=(char *)MALLOC(strlen(tmp)+1))==NULL) {
-		printf("ERROR allocating memory for area #%u tag name.\n"
-			,cfg.areas+1);
-        exit(1); }
-	strcpy(cfg.area[cfg.areas].name,tmp);
-	strupr(tmp);
-	cfg.area[cfg.areas].tag=crc32(tmp);
-
-	while(*p>SP) p++;				/* Skip tag */
-	while(*p && *p<=SP) p++;		/* Skip white space */
-
-	while(*p && *p!=';') {
-		if((cfg.area[cfg.areas].uplink=(faddr_t *)
-			REALLOC(cfg.area[cfg.areas].uplink
-			,sizeof(faddr_t)*(cfg.area[cfg.areas].uplinks+1)))==NULL) {
-			printf("ERROR allocating memory for area #%u uplinks.\n"
-				,cfg.areas+1);
-			exit(1); }
-		cfg.area[cfg.areas].uplink[cfg.area[cfg.areas].uplinks]=atofaddr(p);
-		while(*p>SP) p++;			/* Skip address */
-		while(*p && *p<=SP) p++;	/* Skip white space */
-		cfg.area[cfg.areas].uplinks++; }
-
-	if(cfg.area[cfg.areas].sub!=INVALID_SUB || cfg.area[cfg.areas].uplinks)
-		cfg.areas++;		/* Don't allocate if no tossing */
-	}
-fclose(stream);
-
-printf("\n");
-
-if(!cfg.areas) {
-	printf("No areas defined!\n");
-	exit(1); }
-
-#if 0
-	/* AREAS.BBS DEBUG */
-	for(i=0;i<cfg.areas;i++) {
-		printf("%4u: %-8s"
-			,i+1
-			,cfg.area[i].sub==INVALID_SUB ? "Passthru" :
-			sub[cfg.area[i].sub]->code);
-		for(j=0;j<cfg.area[i].uplinks;j++)
-			printf(" %s",faddrtoa(cfg.area[i].uplink[j]));
-		printf("\n"); }
-#endif
-
-if(misc&GEN_NOTIFY_LIST) {
-printf("\nGenerating Notify Lists...\n");
-notify_list(); }
-
-/* Find any packets that have been left behind in the OUTBOUND directory */
-printf("\nScanning for Stray Outbound Packets...\n");
-sprintf(path,"%s*.PK_",cfg.outbound);
-for(l=_dos_findfirst(path,0,&ff);!l && !kbhit();l=_dos_findnext(&ff)) {
-	sprintf(packet,"%s%s",cfg.outbound,ff.name);
-	printf("%21s: %s ","Outbound Packet",packet);
-	if((fmsg=sopen(packet,O_RDWR,SH_DENYRW))==-1) {
-		printf("ERROR opening.\n");
-		logprintf("ERROR line %d opening %s",__LINE__,packet);
-		continue; }
-	if((fidomsg=fdopen(fmsg,"r+b"))==NULL) {
-		close(fmsg);
-		printf("\7ERROR fdopening.\n");
-		logprintf("ERROR line %d fdopening %s",__LINE__,packet);
-		continue; }
-	if(filelength(fmsg)<sizeof(pkthdr_t)) {
-		printf("ERROR invalid length of %u bytes for %s\n",filelength(fmsg)
-			,packet);
-		logprintf("ERROR line %d invalid length of %u bytes for %s"
-			,__LINE__,filelength(fmsg),packet);
-		fclose(fidomsg);
-		if(delfile(packet))
-			logprintf("ERROR line %d removing %s %s",__LINE__,packet
-				,sys_errlist[errno]);
-		continue; }
-	if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
-		fclose(fidomsg);
-		printf("\7ERROR reading %u bytes from %s\n",sizeof(pkthdr_t),packet);
-		logprintf("ERROR line %d reading %u bytes from %s",__LINE__
-			,sizeof(pkthdr_t),packet);
-		continue; }
-	if((ddtol(ff.wr_time,ff.wr_date)+(60L*60L))<=time(NULL)) {
-		fseek(fidomsg,-3L,SEEK_END);
-		fread(str,3,1,fidomsg);
-		if(str[2])						/* No ending NULL, probably junk */
-			fputc(0,fidomsg);
-		if(str[1])
-			fputc(0,fidomsg);
-		if(str[0])
-			fputc(0,fidomsg);
-		fclose(fidomsg);
-		pkt_faddr.zone=pkthdr.destzone;
-		pkt_faddr.net=pkthdr.destnet;
-		pkt_faddr.node=pkthdr.destnode;
-		pkt_faddr.point=0;				/* No point info in the 2.0 hdr! */
-		memcpy(&two_plus,&pkthdr.empty,20);
-		if(two_plus.cword==_rotr(two_plus.cwcopy,8)  /* 2+ Packet Header */
-			&& two_plus.cword && two_plus.cword&1)
-			pkt_faddr.point=two_plus.destpoint;
-		else if(pkthdr.baud==2) {				/* Type 2.2 Packet Header */
-			memcpy(&two_two,&pkthdr.empty,20);
-			pkt_faddr.point=pkthdr.month; }
-		printf("Sending to %s\n",faddrtoa(pkt_faddr));
-		pack_bundle(packet,pkt_faddr); }
-	else {
-		fclose(fidomsg);
-		printf("Possibly still in use (%u minutes old)\n"
-			,(time(NULL)-ddtol(ff.wr_time,ff.wr_date))/60); } }
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-
-if(misc&IMPORT_PACKETS) {
-
-printf("\nScanning for Inbound Packets...\n");
-
-/* We want to loop while there are bundles waiting for us, but first we want */
-/* to take care of any packets that may already be hanging around for some	 */
-/* reason or another (thus the do/while loop) */
-
-echomail=0;
-for(secure=0;secure<2;secure++) {
-	if(secure && !cfg.secure[0])
-		break;
-do {
-/****** START OF IMPORT PKT ROUTINE ******/
-
-sprintf(path,"%s*.PKT",secure ? cfg.secure : cfg.inbound);
-for(l=_dos_findfirst(path,0,&ff);!l && !kbhit();l=_dos_findnext(&ff)) {
-
-	sprintf(packet,"%s%s",secure ? cfg.secure : cfg.inbound,ff.name);
-
-	if((fidomsg=fnopen(&fmsg,packet,O_RDWR))==NULL) {
-		printf("\7ERROR opening %s\n",packet);
-		logprintf("ERROR line %d opening %s %s",__LINE__,packet
-			,sys_errlist[errno]);
-		continue; }
-	if(filelength(fmsg)<sizeof(pkthdr_t)) {
-		printf("\7Invalid length of %u bytes\n",filelength(fmsg));
-		fclose(fidomsg);
-		continue; }
-
-	fseek(fidomsg,-2L,SEEK_END);
-	fread(str,2,1,fidomsg);
-	if((str[0] || str[1]) &&
-		(ddtol(ff.wr_time,ff.wr_date)+(48L*60L*60L))<=time(NULL)) {
-		fclose(fidomsg);
-		printf("\7ERROR packet %s not terminated correctly\n",packet);
-		logprintf("ERROR line %d packet %s not terminated correctly",__LINE__
-			,packet);
-		continue; }
-	fseek(fidomsg,0L,SEEK_SET);
-	if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
-		fclose(fidomsg);
-		printf("\7ERROR reading %u bytes\n",sizeof(pkthdr_t));
-		logprintf("ERROR line %d reading %u bytes from %s",__LINE__
-			,sizeof(pkthdr_t),packet);
-		continue; }
-
-	pkt_faddr.zone=pkthdr.origzone ? pkthdr.origzone:sys_faddr.zone;
-    pkt_faddr.net=pkthdr.orignet;
-    pkt_faddr.node=pkthdr.orignode;
-    pkt_faddr.point=0;
-
-	printf("%21s: %s "
-		,secure ? "Importing Secure Pkt" : "Importing Packet",ff.name);
-	memcpy(&two_plus,&pkthdr.empty,20);
-	if(two_plus.cword==_rotr(two_plus.cwcopy,8)  /* 2+ Packet Header */
-		&& two_plus.cword && two_plus.cword&1) {
-		pkt_type=PKT_TWO_PLUS;
-		pkt_faddr.point=two_plus.origpoint ? two_plus.origpoint:0;
-		if(pkt_faddr.point && pkthdr.orignet==-1)
-			pkt_faddr.net=two_plus.auxnet ? two_plus.auxnet:sys_faddr.zone;
-		printf("(Type 2+)");
-		if(cfg.log&LOG_PACKETS)
-			logprintf("Importing %s%s (Type 2+) from %s"
-				,secure ? "(secure) ":"",ff.name,faddrtoa(pkt_faddr)); }
-	else if(pkthdr.baud==2) {				/* Type 2.2 Packet Header */
-		pkt_type=PKT_TWO_TWO;
-		memcpy(&two_two,&pkthdr.empty,20);
-		pkt_faddr.point=pkthdr.year ? pkthdr.year:0;
-		printf("(Type 2.2)");
-		if(cfg.log&LOG_PACKETS)
-			logprintf("Importing %s%s (Type 2.2) from %s"
-				,secure ? "(secure) ":"",ff.name,faddrtoa(pkt_faddr)); }
-	else {
-		pkt_type=PKT_TWO;
-		printf("(Type 2)");
-		if(cfg.log&LOG_PACKETS)
-			logprintf("Importing %s%s (Type 2) from %s"
-				,secure ? "(secure) ":"",ff.name,faddrtoa(pkt_faddr)); }
-
-	printf(" from %s\n",faddrtoa(pkt_faddr));
-
-	if(misc&SECURE) {
-		k=matchnode(pkt_faddr,1);
-		sprintf(password,"%.8s",pkthdr.password);
-		if(k<cfg.nodecfgs && cfg.nodecfg[k].pktpwd[0] &&
-			stricmp(password,cfg.nodecfg[k].pktpwd)) {
-			sprintf(str,"Packet %s from %s - "
-				"Incorrect password ('%s' instead of '%s')"
-				,ff.name,faddrtoa(pkt_faddr)
-				,password,cfg.nodecfg[k].pktpwd);
-			printf("Security Violation (Incorrect Password)\n");
-			if(cfg.log&LOG_SECURITY)
-				logprintf(str);
-			fclose(fidomsg);
-			continue; } }
-
-	while(!feof(fidomsg)) {
-
-		memset(&hdr,0,sizeof(fmsghdr_t));
-
-		if(start_tick)
-			import_ticks+=clock()-start_tick;
-		start_tick=clock();
-
-		if(fmsgbuf) {
-			FREE(fmsgbuf);
-			fmsgbuf=0; }
-		if(misc&CHECKMEM)
-			checkmem();
-		if(!fread(&ch,1,1,fidomsg)) 		 /* Message type (0200h) */
-			break;
-		if(ch!=02)
-			continue;
-		if(!fread(&ch,1,1,fidomsg))
-			break;
-		if(ch!=00)
-			continue;
-		fread(&hdr.orignode,2,1,fidomsg);
-		fread(&hdr.destnode,2,1,fidomsg);
-		fread(&hdr.orignet,2,1,fidomsg);
-		fread(&hdr.destnet,2,1,fidomsg);
-		fread(&hdr.attr,2,1,fidomsg);
-		fread(&hdr.cost,2,1,fidomsg);
-
-		grunged=0;
-
-		for(i=0;i<sizeof(hdr.time);i++) 		/* Read in the Date/Time */
-			if(!fread(hdr.time+i,1,1,fidomsg) || !hdr.time[i])
-				break;
-		if(i==sizeof(hdr.time)) grunged=1;
-
-		for(i=0;!grunged && i<sizeof(hdr.to);i++) /* Read in the 'To' Field */
-			if(!fread(hdr.to+i,1,1,fidomsg) || !hdr.to[i])
-				break;
-		if(i==sizeof(hdr.to)) grunged=1;
-
-		for(i=0;!grunged && i<sizeof(hdr.from);i++) /* Read in 'From' Field */
-			if(!fread(hdr.from+i,1,1,fidomsg) || !hdr.from[i])
-				break;
-		if(i==sizeof(hdr.from)) grunged=1;
-
-		for(i=0;!grunged && i<sizeof(hdr.subj);i++) /* Read in 'Subj' Field */
-			if(!fread(hdr.subj+i,1,1,fidomsg) || !hdr.subj[i])
-				break;
-		if(i==sizeof(hdr.subj)) grunged=1;
-
-		str[0]=0;
-		for(i=0;!grunged && i<sizeof(str);i++)	/* Read in the 'AREA' Field */
-			if(!fread(str+i,1,1,fidomsg) || str[i]==CR)
-				break;
-		if(i<sizeof(str))
-			str[i]=0;
-		else
-			grunged=1;
-
-		if(!str[0] || grunged) {
-			start_tick=0;
-			if(cfg.log&LOG_GRUNGED)
-				logprintf("Grunged message");
-            seektonull(fidomsg);
-            printf("Grunged message!\n");
-            continue; }
-
-		if(i)
-			fseek(fidomsg,(long)-(i+1),SEEK_CUR);
-
-		truncsp(str);
-		strupr(str);
-		p=strstr(str,"AREA:");
-		if(!p) {					/* Netmail */
-			start_tick=0;
-			if(import_netmail("",hdr,fidomsg))
-				seektonull(fidomsg);
-			printf("\n");
-			continue; }
-
-		if(!(misc&IMPORT_ECHOMAIL)) {
-			start_tick=0;
-			printf("EchoMail Ignored");
-			seektonull(fidomsg);
-			printf("\n");
-			continue; }
-
-		p+=5;								/* Skip "AREA:" */
-		while(*p && *p<=SP) p++;			/* Skip any white space */
-		printf("%21s: ",p);                 /* Show areaname: */
-		sprintf(areatagstr,"%.128s",p);
-		strupr(p);
-		areatag=crc32(p);
-
-		for(i=0;i<cfg.areas;i++)				/* Do we carry this area? */
-			if(cfg.area[i].tag==areatag) {
-				if(cfg.area[i].sub!=INVALID_SUB)
-					printf("%s ",sub[cfg.area[i].sub]->code);
-				else
-					printf("(Passthru) ");
-				fmsgbuf=getfmsg(fidomsg,NULL);
-				gen_psb(&msg_seen,&msg_path,fmsgbuf,pkthdr.destzone);
-				break; }
-
-		if(i==cfg.areas) {
-			printf("(Unknown) ");
-			if(cfg.badecho>=0) {
-				i=cfg.badecho;
-				if(cfg.area[i].sub!=INVALID_SUB)
-					printf("%s ",sub[cfg.area[i].sub]->code);
-				else
-                    printf("(Passthru) ");
-				fmsgbuf=getfmsg(fidomsg,NULL);
-				gen_psb(&msg_seen,&msg_path,fmsgbuf,pkthdr.destzone); }
-			else {
-				start_tick=0;
-				printf("Skipped\n");
-				seektonull(fidomsg);
-				continue; } }
-
-		if(misc&SECURE && cfg.area[i].sub!=INVALID_SUB) {
-			for(j=0;j<cfg.area[i].uplinks;j++)
-				if(!memcmp(&cfg.area[i].uplink[j],&pkt_faddr,sizeof(faddr_t)))
-					break;
-			if(j==cfg.area[i].uplinks) {
-				if(cfg.log&LOG_SECURITY)
-					logprintf("%s: Security violation - %s not in AREAS.BBS"
-						,areatagstr,faddrtoa(pkt_faddr));
-				printf("Security Violation (Not in AREAS.BBS)\n");
-				seektonull(fidomsg);
-				continue; } }
-
-		/* From here on out, i = area number and area[i].sub = sub number */
-
-		memcpy(&curarea,&cfg.area[i],sizeof(areasbbs_t));
-		curarea.name=areatagstr;
-
-		if(cfg.area[i].sub==INVALID_SUB) {			/* Passthru */
-			start_tick=0;
-			strip_psb(fmsgbuf);
-			pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen,msg_path,0);
-			printf("\n");
-			continue; } 						/* On to the next message */
-
-
-		for(j=0;j<total_faddrs;j++)
-			if(check_psb(msg_path,faddr[j]))
-				break;
-		if(j<total_faddrs) {
-			start_tick=0;
-			printf("Circular path (%s) ",faddrtoa(faddr[j]));
-			cfg.area[i].circular++;
-			if(cfg.log&LOG_CIRCULAR)
-				logprintf("%s: Circular path detected for %s"
-					,areatagstr,faddrtoa(faddr[j]));
-			strip_psb(fmsgbuf);
-			pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen,msg_path,0);
-			printf("\n");
-			continue; }
-
-#if 0 // Allen's way (broken?)
-		for(j=0;j<num_open;j++)
-			if(openbase[j]==cfg.area[i].sub)
-                break;
-		if(j && j<num_open) {
-			cur_smb=j;
-			k=openbase[0];
-			openbase[0]=openbase[j];
-			openbase[j]=k; }
-		else if(j && j==num_open && j<MAX_OPEN_SMBS) {
-			cur_smb=j;
-			openbase[j]=openbase[0];
-			openbase[0]=INVALID_SUB; }
-		else if(j==num_open && j>=MAX_OPEN_SMBS) {
-			cur_smb=j-1;
-			k=openbase[0];
-			openbase[0]=openbase[j-1];
-			openbase[j-1]=k; }
-
-		if(openbase[0]!=cfg.area[i].sub) {
-			if(openbase[0]!=INVALID_SUB) {
-				smb_close(&smb[cur_smb]);
-				--num_open; }
-#endif
-
-		// Rob's way
-		for(j=0;j<MAX_OPEN_SMBS;j++)
-			if(subnum[j]==cfg.area[i].sub)
-				break;
-		if(j<MAX_OPEN_SMBS) 				/* already open */
-            cur_smb=j;
-		else {
-			if(smb[cur_smb].shd_fp) 		/* If open */
-				cur_smb=!cur_smb;			/* toggle between 0 and 1 */
-			smb_close(&smb[cur_smb]);		/* close, if open */
-			subnum[cur_smb]=INVALID_SUB; }	/* reset subnum (just incase) */
-
-		if(smb[cur_smb].shd_fp==NULL) { 	/* Currently closed */
-			sprintf(smb[cur_smb].file,"%s%s",sub[cfg.area[i].sub]->data_dir
-				,sub[cfg.area[i].sub]->code);
-			smb[cur_smb].retry_time=smb_retry_time;
-			if((j=smb_open(&smb[cur_smb]))!=0) {
-				sprintf(str,"ERROR %d opening %s area #%d, sub #%d)"
-					,j,smb[cur_smb].file,i+1,cfg.area[i].sub+1);
-				printf(str);
-				logprintf(str);
-				strip_psb(fmsgbuf);
-				pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
-					,msg_path,0);
-				printf("\n");
-				continue; }
-			if(!filelength(fileno(smb[cur_smb].shd_fp))) {
-				smb[cur_smb].status.max_crcs=sub[cfg.area[i].sub]->maxcrcs;
-				smb[cur_smb].status.max_msgs=sub[cfg.area[i].sub]->maxmsgs;
-				smb[cur_smb].status.max_age=sub[cfg.area[i].sub]->maxage;
-				smb[cur_smb].status.attr=sub[cfg.area[i].sub]->misc&SUB_HYPER
-						? SMB_HYPERALLOC:0;
-				if((j=smb_create(&smb[cur_smb]))!=0) {
-					sprintf(str,"ERROR %d creating %s",j,smb[cur_smb].file);
-					printf(str);
-					logprintf(str);
-					smb_close(&smb[cur_smb]);
-					strip_psb(fmsgbuf);
-					pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
-						,msg_path,0);
-					printf("\n");
-					continue; } }
-
-#if 0	// Unnecessary with SMBLIB v2.0
-
-			if((j=smb_locksmbhdr(&smb[cur_smb]))!=0) {
-				printf("ERROR %d locking %s smbhdr\n",j,smb[cur_smb].file);
-				logprintf("ERROR %d line %d locking %s smbhdr",j,__LINE__
-					,smb[cur_smb].file);
-				smb_close(&smb[cur_smb]);
-				strip_psb(fmsgbuf);
-				pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
-					,msg_path,0);
-				printf("\n");
-				continue; }
-
-			if((j=smb_getstatus(&smb[cur_smb]))!=0) {
-				sprintf(str,"ERROR %d reading %s SMB header",j
-					,smb[cur_smb].file);
-				printf(str);
-				logprintf(str);
-				smb_unlocksmbhdr(&smb[cur_smb]);
-				smb_close(&smb[cur_smb]);
-				strip_psb(fmsgbuf);
-				pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
-					,msg_path,0);
-				printf("\n");
-				continue; }
-
-			smb_unlocksmbhdr(&smb[cur_smb]);
-#endif
-			//openbase[0]=cfg.area[i].sub;
-			//++num_open;
-			subnum[cur_smb]=cfg.area[i].sub;
-			}
-
-		if(hdr.attr&FIDO_PRIVATE && !(sub[cfg.area[i].sub]->misc&SUB_PRIV)) {
-			if(misc&IMPORT_PRIVATE)
-				hdr.attr&=~FIDO_PRIVATE;
-            else {
-				start_tick=0;
-				printf("Private posts disallowed.");
-				if(cfg.log&LOG_PRIVATE)
-					logprintf("%s: Private posts disallowed"
-						,areatagstr);
-				strip_psb(fmsgbuf);
-				pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
-					,msg_path,0);
-				printf("\n");
-				continue; } }
-
-		if(!(hdr.attr&FIDO_PRIVATE) && sub[cfg.area[i].sub]->misc&SUB_PONLY)
-			hdr.attr|=MSG_PRIVATE;
-
-		/**********************/
-		/* Importing EchoMail */
-		/**********************/
-		j=fmsgtosmsg(fmsgbuf,hdr,0,cfg.area[i].sub);
-
-		if(start_tick) {
-			import_ticks+=clock()-start_tick;
-			start_tick=0; }
-
-		if(j==-1) {
-			if(cfg.log&LOG_DUPES)
-				logprintf("%s Duplicate message",areatagstr);
-			cfg.area[i].dupes++; }
-		else {	   /* Not a dupe */
-			strip_psb(fmsgbuf);
-			pkt_to_pkt(fmsgbuf,curarea,pkt_faddr
-				,hdr,msg_seen,msg_path,0); }
-
-		if(j==1) {		/* Successful import */
-			echomail++;
-			cfg.area[i].imported++;
-			if(misc&NOTIFY_RECEIPT && (m=matchname(hdr.to))!=0) {
-				sprintf(str
-				,"\7\1n\1hSBBSecho: \1m%.36s \1n\1msent you EchoMail on "
-					"\1h%s \1n\1m%s\1n\r\n"
-					,hdr.from
-					,grp[sub[cfg.area[i].sub]->grp]->sname
-					,sub[cfg.area[i].sub]->sname);
-				putsmsg(m,str); } }
-		printf("\n");
-		}
-	fclose(fidomsg);
-
-	if(misc&DELETE_PACKETS)
-		if(delfile(packet))
-			logprintf("ERROR line %d removing %s %s",__LINE__,packet
-				,sys_errlist[errno]); }
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-
-if(start_tick) {
-	import_ticks+=clock()-start_tick;
-	start_tick=0; }
-
-} while(!kbhit() && unpack_bundle());
-
-if(kbhit()) printf("\nKey pressed - premature termination\n");
-while(kbhit()) getch();
-
-}	/* End of Secure : Inbound loop */
-
-if(start_tick)	/* Last possible increment of import_ticks */
-	import_ticks+=clock()-start_tick;
-
-for(j=MAX_OPEN_SMBS-1;(int)j>=0;j--)		/* Close open bases */
-	if(smb[j].shd_fp)
-		smb_close(&smb[j]);
-
-pkt_to_pkt(fmsgbuf,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
-
-/******* END OF IMPORT PKT ROUTINE *******/
-
-if(cfg.log&LOG_AREA_TOTALS) {
-	for(i=0;i<cfg.areas;i++) {
-		if(cfg.area[i].imported)
-			logprintf("Imported: %5u msgs %8s <- %s"
-				,cfg.area[i].imported,sub[cfg.area[i].sub]->code
-				,cfg.area[i].name); }
-	for(i=0;i<cfg.areas;i++) {
-		if(cfg.area[i].circular)
-			logprintf("Circular: %5u detected in %s"
-				,cfg.area[i].circular,cfg.area[i].name); }
-	for(i=0;i<cfg.areas;i++) {
-		if(cfg.area[i].dupes)
-			logprintf("Duplicate: %5u detected in %s"
-				,cfg.area[i].dupes,cfg.area[i].name); } }
-
-import_time=((float)import_ticks)/(float)CLK_TCK;
-if(cfg.log&LOG_TOTALS && import_time && echomail) {
-	printf("\nImported %lu EchoMail messages in %.1f seconds "
-		,echomail,import_time);
-	logprintf("Imported: %5lu msgs in %.1f sec (%.1f/min %.1f/sec)"
-		,echomail,import_time
-		,import_time/60.0 ? (float)echomail/(import_time/60.0) :(float)echomail
-		,(float)echomail/import_time);
-	if(import_time/60.0)
-		printf("(%.1f/min) ",(float)echomail/(import_time/60.0));
-	printf("(%.1f/sec)\n",(float)echomail/import_time); }
-if(fmsgbuf) {
-	FREE(fmsgbuf);
-	fmsgbuf=0; }
-
-}
-
-if(misc&IMPORT_NETMAIL) {
-
-printf("\nScanning for Inbound NetMail Messages...\n");
-
-sprintf(str,"%s*.MSG",netmail_dir);
-
-for(last=_dos_findfirst(str,0,&ff);!last;last=_dos_findnext(&ff)) {
-    sprintf(path,"%s%s",netmail_dir,ff.name);
-    strupr(path);
-    if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
-		printf("\7ERROR opening %s\n",path);
-		logprintf("ERROR line %d opening %s %s",__LINE__,path
-			,sys_errlist[errno]);
-        continue; }
-    if(filelength(fmsg)<sizeof(fmsghdr_t)) {
-		printf("\7ERROR invalid length of %u bytes for %s\n",filelength(fmsg)
-			,path);
-		logprintf("ERROR line %d invalid length of %u bytes for %s",__LINE__
-			,filelength(fmsg),path);
-        fclose(fidomsg);
-        continue; }
-    if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
-        fclose(fidomsg);
-        printf("\7ERROR reading %u bytes from %s"
-            ,sizeof(fmsghdr_t),path);
-		logprintf("ERROR line %d reading %u bytes from %s",__LINE__
-			,sizeof(fmsghdr_t),path);
-        continue; }
-    i=import_netmail(path,hdr,fidomsg);
-    /**************************************/
-    /* Delete source netmail if specified */
-    /**************************************/
-	if(i==0) {
-		if(misc&DELETE_NETMAIL) {
-			fclose(fidomsg);
-			if(delfile(path))
-				logprintf("ERROR line %d removing %s %s",__LINE__,path
-					,sys_errlist[errno]); }
-		else {
-			hdr.attr|=FIDO_RECV;
-			fseek(fidomsg,0L,SEEK_SET);
-			fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg);
-			fclose(fidomsg); } }
-	else if(i!=-2)
-		fclose(fidomsg);
-    printf("\n"); 
-	}
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-}
-
-
-if(misc&EXPORT_ECHOMAIL) {
-	memset(&addr,0,sizeof(faddr_t));
-	export_echomail(sub_code,addr);
-}
-
-
-if(misc&PACK_NETMAIL) {
-
-memset(&msg_seen,0,sizeof(addrlist_t));
-memset(&msg_path,0,sizeof(addrlist_t));
-memset(&fakearea,0,sizeof(areasbbs_t));
-
-printf("\nPacking Outbound NetMail...\n");
-
-sprintf(str,"%s*.MSG",netmail_dir);
-
-for(last=_dos_findfirst(str,0,&ff);!last;last=_dos_findnext(&ff)) {
-    sprintf(path,"%s%s",netmail_dir,ff.name);
-	strupr(path);
-    if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
-		printf("\7ERROR opening %s\n",path);
-		logprintf("ERROR line %d opening %s %s",__LINE__,path
-			,sys_errlist[errno]);
-        continue; }
-    if(filelength(fmsg)<sizeof(fmsghdr_t)) {
-        printf("\7%s Invalid length of %u bytes\n",path,filelength(fmsg));
-        fclose(fidomsg);
-        continue; }
-    if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
-        fclose(fidomsg);
-        printf("\7ERROR reading %u bytes from %s"
-            ,sizeof(fmsghdr_t),path);
-		logprintf("ERROR line %d reading %u bytes from %s",__LINE__
-			,sizeof(fmsghdr_t),path);
-        continue; }
-	hdr.destzone=hdr.origzone=sys_faddr.zone;
-	hdr.destpoint=hdr.origpoint=0;
-	getzpt(fidomsg,&hdr);				/* use kludge if found */
-	addr.zone=hdr.destzone;
-	addr.net=hdr.destnet;
-	addr.node=hdr.destnode;
-	addr.point=hdr.destpoint;
-	for(i=0;i<total_faddrs;i++)
-		if(!memcmp(&addr,&faddr[i],sizeof(faddr_t)))
-			break;
-	if(i<total_faddrs)	{				  /* In-bound, so ignore */
-		fclose(fidomsg);
-		continue;
-	}
-	printf("\n%s to %s ",path,faddrtoa(addr));
-	if(cfg.log&LOG_PACKING)
-		logprintf("Packing %s (%s)",path,faddrtoa(addr));
-	fmsgbuf=getfmsg(fidomsg,NULL);
-	if(!fmsgbuf) {
-		printf("ERROR allocating memory for NetMail fmsgbuf\n");
-		logprintf("ERROR line %d allocating memory for NetMail fmsgbuf"
-			,__LINE__);
-		exit(1); }
-	fclose(fidomsg);
-
-	if(misc&FLO_MAILER) {
-		attr=0;
-		i=matchnode(addr,0);
-		if(i<cfg.nodecfgs)
-			if(cfg.nodecfg[i].route.zone
-				&& !(hdr.attr&(FIDO_CRASH|FIDO_HOLD))) {
-				addr=cfg.nodecfg[i].route;		/* Routed */
-				if(cfg.log&LOG_ROUTING)
-					logprintf("Routing %s to %s",path,faddrtoa(addr));
-				i=matchnode(addr,0); }
-		if(i<cfg.nodecfgs)
-			attr=cfg.nodecfg[i].attr;
-		if(hdr.attr&FIDO_CRASH)
-			attr|=ATTR_CRASH;
-		else if(hdr.attr&FIDO_HOLD)
-			attr|=ATTR_HOLD;
-		if(attr&ATTR_CRASH) ch='C';
-		else if(attr&ATTR_HOLD) ch='H';
-		else if(attr&ATTR_DIRECT) ch='D';
-		else ch='O';
-		if(addr.zone==faddr[0].zone) /* Default zone, use default outbound */
-			strcpy(outbound,cfg.outbound);
-		else						 /* Inter-zone outbound is OUTBOUND.XXX */
-			sprintf(outbound,"%.*s.%03X\\"
-				,strlen(cfg.outbound)-1,cfg.outbound,addr.zone);
-		if(addr.point) {			/* Point destination is OUTBOUND.PNT */
-			sprintf(str,"%04X%04X.PNT"
-				,addr.net,addr.node);
-			strcat(outbound,str); }
-		if(outbound[strlen(outbound)-1]=='\\')
-			outbound[strlen(outbound)-1]=0;
-		mkdir(outbound);
-		strcat(outbound,"\\");
-		if(addr.point)
-			sprintf(packet,"%s%08X.%cUT",outbound,addr.point,ch);
-		else
-			sprintf(packet,"%s%04X%04X.%cUT",outbound,addr.net,addr.node,ch);
-		if(hdr.attr&FIDO_FILE)
-			if(write_flofile(hdr.subj,addr))
-				exit(1); }
-	else
-		strcpy(packet,pktname());
-
-	now=time(NULL);
-	tm=gmtime(&now);
-	if((stream=fnopen(&file,packet,O_WRONLY|O_APPEND|O_CREAT))==NULL) {
-		printf("Unable to open %s for write.\n"
-			,packet);
-		logprintf("ERROR line %d opening %s %s",__LINE__,packet
-			,sys_errlist[errno]);
-		exit(1); }
-
-	if(!filelength(file)) {
-		pkthdr.orignode=hdr.orignode;
-		pkthdr.destnode=hdr.destnode;
-		pkthdr.year=tm->tm_year+1900;
-		pkthdr.month=tm->tm_mon;
-		pkthdr.day=tm->tm_mday;
-		pkthdr.hour=tm->tm_hour;
-		pkthdr.min=tm->tm_min;
-		pkthdr.sec=tm->tm_sec;
-		pkthdr.baud=0x00;
-		pkthdr.pkttype=0x0002;
-		pkthdr.orignet=hdr.orignet;
-		pkthdr.destnet=hdr.destnet;
-		pkthdr.prodcode=0x00;
-		pkthdr.sernum=0;
-		i=matchnode(addr,0);
-		if(i<cfg.nodecfgs)
-			memcpy(pkthdr.password,cfg.nodecfg[i].pktpwd,8);
-		else
-			memset(pkthdr.password,0,8);
-		pkthdr.origzone=hdr.origzone;
-		pkthdr.destzone=hdr.destzone;
-		memset(pkthdr.empty,0,20);
-		fwrite(&pkthdr,sizeof(pkthdr_t),1,stream); }
-
-	putfmsg(stream,fmsgbuf,hdr,fakearea,msg_seen,msg_path);
-
-	FREE(fmsgbuf);
-	fclose(stream);
-    /**************************************/
-    /* Delete source netmail if specified */
-    /**************************************/
-	if(misc&DELETE_NETMAIL)
-		if(delfile(path))
-			logprintf("ERROR line %d removing %s %s",__LINE__,path
-				,sys_errlist[errno]);
-    printf("\n"); }
-#ifdef __WATCOMC__
-_dos_findclose(&ff);
-#endif
-}
-
-
-if(misc&UPDATE_MSGPTRS) {
-
-printf("\nUpdating Message Pointers to Last Posted Message...\n");
-
-for(g=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		printf("\n%-15.15s %s\n"
-			,grp[sub[i]->grp]->sname,sub[i]->lname);
-		getlastmsg(i,&l,0);
-		sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-		if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
-			printf("\7ERROR opening/creating %s",str);
-			logprintf("ERROR line %d opening/creating %s",__LINE__,str); }
-		else {
-			write(file,&l,sizeof(time_t));
-			close(file); } } 
-}
-
-if(misc&(IMPORT_NETMAIL|IMPORT_ECHOMAIL) && misc&REPORT) {
-	now=time(NULL);
-	sprintf(str,"%sSBBSECHO.MSG",text_dir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		printf("ERROR opening %s\n",str);
-		logprintf("ERROR line %d opening %s",__LINE__,str);
-		exit(1); }
-	sprintf(fname,"\1c\1h               "
-		"���������������������������������������������������\r\n");
-	sprintf(path,"\1c\1h               "
-		"���������������������������������������������������\r\n");
-	write(file,fname,strlen(fname));
-	sprintf(str,"               \1n\1k\0016"
-		" Last FidoNet Transfer on %.24s \1n\r\n",ctime(&now));
-	write(file,str,strlen(str));
-	write(file,path,strlen(path));
-	write(file,fname,strlen(fname));
-	sprintf(tmp,"Imported %lu EchoMail and %lu NetMail Messages"
-		,echomail,netmail);
-	sprintf(str,"               \1n\1k\0016 %-50.50s\1n\r\n",tmp);
-	write(file,str,strlen(str));
-	write(file,path,strlen(path));
-	close(file); }
-
-pkt_to_pkt(buf,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
-if(email->shd_fp)
-	smb_close(email);
-
-FREE(smb);
-FREE(email);
-return(0);
-}
diff --git a/src/sbbs2/echo/sbbsecho.h b/src/sbbs2/echo/sbbsecho.h
deleted file mode 100644
index e01a0ca34ccdabd813476b62ca74b8b08dd13dd1..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/sbbsecho.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* SBBSECHO.H */
-
-/* Developed 1990-2000 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Portions written by Allen Christiansen 1994-1996 						*/
-
-#define SBBSECHO_VER "1.32"
-
-#define IMPORT_NETMAIL  (1L<<0)
-#define IMPORT_PACKETS	(1L<<1)
-#define IMPORT_ECHOMAIL (1L<<2)
-#define EXPORT_ECHOMAIL (1L<<3)
-#define DELETE_NETMAIL	(1L<<4)
-#define DELETE_PACKETS	(1L<<5)
-#define STORE_SEENBY	(1L<<6) 		/* Store SEEN-BYs in SMB */
-#define STORE_PATH		(1L<<7) 		/* Store PATHs in SMB */
-#define STORE_KLUDGE	(1L<<8) 		/* Store unknown kludges in SMB */
-#define IGNORE_MSGPTRS	(1L<<9)
-#define UPDATE_MSGPTRS	(1L<<10)
-#define LEAVE_MSGPTRS	(1L<<11)
-#define CHECKMEM		(1L<<12)		/* Display available memory */
-#define ASCII_ONLY		(1L<<13)
-#define LOGFILE 		(1L<<14)
-#define REPORT			(1L<<15)
-#define EXPORT_ALL		(1L<<16)
-#define UNKNOWN_NETMAIL (1L<<17)
-#define IGNORE_ADDRESS	(1L<<18)
-#define IGNORE_RECV 	(1L<<19)
-#define CONVERT_TEAR	(1L<<20)
-#define IMPORT_PRIVATE	(1L<<21)
-#define LOCAL_NETMAIL	(1L<<22)
-#define NOTIFY_RECEIPT	(1L<<23)
-#define FLO_MAILER		(1L<<24)		/* Binkley .FLO style mailer */
-#define PACK_NETMAIL	(1L<<25)		/* Pack *.MSG NetMail into packets */
-#define FUZZY_ZONE		(1L<<26)
-#define FAST_OPEN		(1L<<27)
-#define SECURE			(1L<<28)		/* Secure operation */
-#define ELIST_ONLY		(1L<<29)		/* Allow adding from AREAS.BBS */
-#define GEN_NOTIFY_LIST (1L<<30)		/* Generate Notify Lists */
-#define KILL_EMPTY_MAIL (1L<<31)		/* Kill empty netmail messages */
-
-#define ATTR_HOLD		(1<<0)			/* Hold */
-#define ATTR_CRASH		(1<<1)			/* Crash */
-#define ATTR_DIRECT 	(1<<2)			/* Direct */
-#define ATTR_PASSIVE	(1<<3)			/* Used to temp disconnect */
-#define SEND_NOTIFY 	(1<<4)			/* Send Notify Lists */
-
-
-#define LOG_AREAFIX 	(1L<<0) 		/* Log areafix messages */
-#define LOG_IMPORTED	(1L<<1) 		/* Log imported netmail messages */
-#define LOG_PACKETS 	(1L<<2) 		/* Log imported packet names/types */
-#define LOG_SECURITY	(1L<<3) 		/* Log security violations */
-#define LOG_GRUNGED 	(1L<<4) 		/* Log grunged messages */
-#define LOG_PRIVATE 	(1L<<5) 		/* Log disallowed private msgs */
-#define LOG_AREA_TOTALS (1L<<6) 		/* Log totals for each area */
-#define LOG_TOTALS		(1L<<7) 		/* Log over-all totals */
-#define LOG_PACKING 	(1L<<8) 		/* Log packing of out-bound netmail */
-#define LOG_ROUTING 	(1L<<9) 		/* Log routing of out-bound netmail */
-
-#define LOG_DUPES		(1L<<24)		 /* Log individual dupe messages */
-#define LOG_CIRCULAR	(1L<<25)		 /* Log individual circ paths */
-#define LOG_IGNORED 	(1L<<26)		 /* Log ignored netmail */
-#define LOG_UNKNOWN 	(1L<<27)		 /* Log netmail for unknown users */
-
-#define LOG_DEFAULTS	0xffffffL		/* Low 24 bits default to ON */
-
-#define PKT_TWO_PLUS	0				/* Type 2+ Packet Header  */
-#define PKT_TWO_TWO 	1				/* Type 2.2 Packet Header */
-#define PKT_TWO 		2				/* Old Type Packet Header */
-
-#define MAX_OPEN_SMBS	2
-#define DFLT_OPEN_PKTS  4
-#define MAX_TOTAL_PKTS  100
-#define DFLT_PKT_SIZE   250*1024L
-#define DFLT_BDL_SIZE   250*1024L
-
-#define NOFWD			(1<<0)			/* Do not forward requests */
-
-typedef struct {                        /* Fidonet Packet Header */
-    short orignode,                     /* Origination Node of Packet */
-          destnode,                     /* Destination Node of Packet */
-          year,                         /* Year of Packet Creation e.g. 1995 */
-          month,                        /* Month of Packet Creation 0-11 */
-          day,                          /* Day of Packet Creation 1-31 */
-          hour,                         /* Hour of Packet Creation 0-23 */
-          min,                          /* Minute of Packet Creation 0-59 */
-          sec,                          /* Second of Packet Creation 0-59 */
-          baud,                         /* Max Baud Rate of Orig & Dest */
-          pkttype,                      /* Packet Type (-1 is obsolete) */
-          orignet,                      /* Origination Net of Packet */
-          destnet;                      /* Destination Net of Packet */
-    uchar prodcode,                     /* Product Code (00h is Fido) */
-          sernum,                       /* Binary Serial Number or NULL */
-          password[8];                  /* Session Password or NULL */
-    short origzone,                     /* Origination Zone of Packet or NULL */
-          destzone;                     /* Destination Zone of Packet or NULL */
-    uchar empty[20];                    /* Fill Characters */
-	} pkthdr_t;
-
-typedef struct {						/* Type 2+ Packet Header Info */
-	short auxnet,						/* Orig Net if Origin is a Point */
-		  cwcopy;						/* Must be Equal to cword */
-	uchar prodcode, 					/* Product Code */
-		  revision; 					/* Revision */
-	short cword,						/* Compatibility Word */
-		  origzone, 					/* Zone of Packet Sender or NULL */
-		  destzone, 					/* Zone of Packet Receiver or NULL */
-		  origpoint,					/* Origination Point of Packet */
-		  destpoint;					/* Destination Point of Packet */
-	uchar empty[4];
-	} two_plus_t;
-
-typedef struct {						/* Type 2.2 Packet Header Info */
-	uchar origdomn[8],					/* Origination Domain */
-		  destdomn[8],					/* Destination Domain */
-		  empty[4]; 					/* Product Specific Data */
-	} two_two_t;
-
-typedef struct {
-    uint  sub;                  /* Set to INVALID_SUB if pass-thru */
-	ulong tag;					/* CRC-32 of tag name */
-    char *name;                 /* Area tag name */
-    uint  uplinks;              /* Total number of uplinks for this echo */
-	uint  imported; 			/* Total messages imported this run */
-	uint  exported; 			/* Total messages exported this run */
-	uint  circular; 			/* Total circular paths detected */
-	uint  dupes;				/* Total duplicate messages detected */
-    faddr_t *uplink;            /* Each uplink */
-    } areasbbs_t;
-
-typedef struct {
-	char flag[5];
-	} flag_t;
-
-typedef struct {
-	uint tags;					/* Number of area tags */
-	char **tag; 				/* Name of each area tag */
-	} area_t;
-
-typedef struct {
-	FILE *stream;				/* The stream associated with this packet */
-	faddr_t uplink; 			/* The current uplink for this packet */
-	uchar filename[128],curopen;/* Name of the file and if it's open or not */
-    } outpkt_t;
-
-typedef struct {
-	uint addrs; 				/* Total number of uplinks */
-	faddr_t *addr;				/* Each uplink */
-	} addrlist_t;
-
-typedef struct {
-	char name[26]				/* Short name of archive type */
-		,hexid[26]				/* Hexadecimal ID to search for */
-		,pack[81]				/* Pack command line */
-		,unpack[81];			/* Unpack command line */
-	uint byteloc;				/* Offset to Hex ID */
-	} arcdef_t;
-
-typedef struct {
-	faddr_t 	faddr				/* Fido address of this node */
-			   ,route;				/* Address to route FLO stuff through */
-	ushort		arctype 			/* De/archiver to use for this node */
-			   ,numflags			/* Number of flags defined for this node */
-			   ,pkt_type;			/* Packet type to use for outgoing PKTs */
-	ushort		attr;				/* Message bits to set for this node */
-	char		password[26];		/* Areafix password for this node */
-	char		pktpwd[9];			/* Packet password for this node */
-	flag_t		*flag;				/* Areafix flags for this node */
-	} nodecfg_t;
-
-typedef struct {
-	char		listpath[129];		/* Path to this echolist */
-	uint		numflags,misc;		/* Number of flags for this echolist */
-	flag_t		*flag;				/* Flags to access this echolist */
-	faddr_t 	forward;			/* Where to forward requests */
-	char		password[72];		/* Password to use for forwarding req's */
-	} echolist_t;
-
-typedef struct {
-	faddr_t 	dest;
-	char		fname[13];
-	} attach_t;
-
-typedef struct {
-	char		inbound[82] 		/* Inbound directory */
-			   ,secure[82]			/* Secure Inbound directory */
-			   ,outbound[82]		/* Outbound directory */
-			   ,areafile[128]		/* AREAS.BBS path/filename */
-			   ,logfile[128]		/* LOG path/filename */
-			   ,cfgfile[128];		/* Configuration path/filename */
-	ulong		maxpktsize			/* Maximum size for packets */
-			   ,maxbdlsize			/* Maximum size for bundles */
-			   ,log;				/* What do we log? */
-	int 		badecho;			/* Area to store bad echomail msgs */
-	uint		arcdefs 			/* Number of archive definitions */
-			   ,nodecfgs			/* Number of nodes with configs */
-			   ,listcfgs			/* Number of echolists defined */
-			   ,areas				/* Number of areas defined */
-			   ,notify; 			/* User number (sysop) to notify */
-	arcdef_t   *arcdef; 			/* Each archive definition */
-	nodecfg_t  *nodecfg;			/* Each node configuration */
-	echolist_t *listcfg;			/* Each echolist configuration */
-	areasbbs_t *area;				/* Each area configuration */
-	} config_t;
-
-#ifdef __WATCOMC__
-struct	time	{
-    unsigned char   ti_min;     /* Minutes */
-    unsigned char   ti_hour;    /* Hours */
-    unsigned char   ti_hund;    /* Hundredths of seconds */
-    unsigned char   ti_sec;     /* Seconds */
-};
-
-struct  date    {
-	int 		da_year;	/* Year - 1980 */
-    char        da_day;     /* Day of the month */
-    char        da_mon;     /* Month (1 = Jan) */
-};
-#endif
-
-/***********************/
-/* Function prototypes */
-/***********************/
-void bail(int code);
-char *ultoac(ulong l,char *str);
-int  bstrlen(char *str);
-int  nopen(char *str, int access);
-FILE *fnopen(int *file, char *str,int access);
-char *sectostr(uint sec, char *str);
-void truncsp(char *str);
-ulong ahtoul(char *str);
-int  mv(char *src, char *dest, char copy); /* fast file move/copy function */
-char *timestr(time_t *intime);  /* ASCII representation of time_t */
-time_t dstrtounix(char *str);	/* ASCII date (MM/DD/YY) to unix conversion */
-char *unixtodstr(time_t unix, char *str); /* Unix time to ASCII date */
-int chk_ar(char *str, user_t user); /* checks access requirements */
-ushort crc16(char *str);
-void ucrc16(uchar ch, ushort *rcrc);
-char fexist(char *filespec);
-long flength(char *filespec);
-long fdate(char *filespec);
-faddr_t atofaddr(char *str);
-int  matchnode(faddr_t addr, int exact);
-void export_echomail(char *sub_code,faddr_t addr);
diff --git a/src/sbbs2/echo/sbbsecho.wat b/src/sbbs2/echo/sbbsecho.wat
deleted file mode 100644
index e155042c5812142bd03b52f94efb72e59feb4cee..0000000000000000000000000000000000000000
--- a/src/sbbs2/echo/sbbsecho.wat
+++ /dev/null
@@ -1,81 +0,0 @@
-############################################
-# Makefile for Synchronet SBBSECHO Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..\smb;..\rio;..
-!ifeq OS DOS
-CFLAGS	= -s -I$(INCLUDE) -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml -DLZH_DYNAMIC_BUF
-!else
-CFLAGS	= -s -I$(INCLUDE) -fh=$*.pch -bt=$(OS) -fo=$(OS)\ 
-!endif
-
-!ifeq OS NT
-SYSTEM  = NT
-!endif
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOS4G
-SYSTEM  = DOS4G
-!endif
-
-LFLAGS  = option stack=20k system $(SYSTEM)
-
-MAIN	= $(OS)\sbbsecho.exe
-OBJS	= $(OS)\sbbsecho.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\smblib.obj $(OS)\ars.obj $(OS)\lzh.obj &
-	  $(OS)\read_cfg.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	  ..\smb\smbdefs.h ..\smb\smblib.h
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-	@echo Linking $[@ ...
-        $(LD) $(LFLAGS) file { $(OBJS) } option map
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-		    ..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) -DSMB_GETMSGTXT $(CFLAGS) $[@
-
-$(OS)\lzh.obj: ..\smb\lzh.c ..\smb\lzh.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h 
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\sbbsecho.obj: sbbsecho.c sbbsecho.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
diff --git a/src/sbbs2/email.c b/src/sbbs2/email.c
deleted file mode 100644
index 236bd0d8af4f4da10c5e40f389f4aa5ba804cd56..0000000000000000000000000000000000000000
--- a/src/sbbs2/email.c
+++ /dev/null
@@ -1,276 +0,0 @@
-#line 1 "EMAIL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-/****************************************************************************/
-/* Mails a message to usernumber. 'top' is a buffer to place at beginning   */
-/* of message.                                                              */
-/* Called from functions main_sec, newuser, readmail and scanposts			*/
-/****************************************************************************/
-void email(int usernumber, char *top, char *subj, char mode)
-{
-	char	str[256],str2[256],msgpath[256],title[LEN_TITLE+1],ch
-			,buf[SDT_BLOCK_LEN];
-	ushort	xlat=XLAT_NONE,msgattr=0;
-	int 	i,j,x,file;
-	long	l;
-	ulong	length,offset,crc=0xffffffffUL;
-	FILE	*instream;
-	node_t	node;
-	smbmsg_t msg;
-
-sprintf(title,"%.*s",LEN_TITLE,subj);
-
-if(useron.etoday>=level_emailperday[useron.level] && !SYSOP) {
-	bputs(text[TooManyEmailsToday]);
-	return; }
-
-if(usernumber==1 && useron.rest&FLAG('S')
-	&& (node_valuser!=1 || useron.fbacks || useron.emails)) { /* ! val fback */
-    bprintf(text[R_Feedback],sys_op);
-    return; }
-if(usernumber!=1 && useron.rest&FLAG('E')
-	&& (node_valuser!=usernumber || useron.fbacks || useron.emails)) {
-    bputs(text[R_Email]);
-    return; }
-if(!usernumber) {
-    bputs(text[UnknownUser]);
-    return; }
-getuserrec(usernumber,U_MISC,8,str);
-l=ahtoul(str);
-if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
-    bputs(text[UnknownUser]);
-    return; }
-if(l&NETMAIL && sys_misc&SM_FWDTONET
-	&& yesno(text[ForwardMailQ])) { /* Forward to netmail address */
-    getuserrec(usernumber,U_NETMAIL,LEN_NETMAIL,str);
-	netmail(str,subj,mode);
-    return; }
-bprintf(text[Emailing],username(usernumber,tmp),usernumber);
-action=NODE_SMAL;
-nodesync();
-
-sprintf(str,"%sFEEDBACK.BIN",exec_dir);
-if(usernumber==1 && useron.fbacks && fexist(str)) {
-	exec_bin("FEEDBACK",&main_csi);
-	if(main_csi.logic!=LOGIC_TRUE)
-		return; }
-
-if(sys_misc&SM_ANON_EM && (SYSOP || useron.exempt&FLAG('A'))
-    && !noyes(text[AnonymousQ]))
-	msgattr|=MSG_ANONYMOUS;
-
-if(sys_misc&SM_DELREADM)
-	msgattr|=MSG_KILLREAD;
-
-sprintf(msgpath,"%sINPUT.MSG",node_dir);
-sprintf(str2,"%s #%u",username(usernumber,tmp),usernumber);
-if(!writemsg(msgpath,top,title,mode,0,str2)) {
-    bputs(text[Aborted]);
-    return; }
-
-if(mode&WM_FILE) {
-	sprintf(str2,"%sFILE\\%04u.IN",data_dir,usernumber);
-	mkdir(str2);
-	sprintf(str2,"%sFILE\\%04u.IN\\%s",data_dir,usernumber,title);
-	if(fexist(str2)) {
-		bputs(text[FileAlreadyThere]);
-		remove(msgpath);
-		return; }
-	if(online==ON_LOCAL) {		/* Local upload */
-		bputs(text[EnterPath]);
-		if(!getstr(str,60,K_LINE|K_UPPER)) {
-			bputs(text[Aborted]);
-			remove(msgpath);
-			return; }
-		backslash(str);
-		strcat(str,title);
-		mv(str,str2,1); }
-	else { /* Remote */
-		menu("ULPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(str,"Q");
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && chk_ar(prot[x]->ar,useron)) {
-				sprintf(tmp,"%c",prot[x]->mnemonic);
-				strcat(str,tmp); }
-		ch=getkeys(str,0);
-		if(ch=='Q' || sys_status&SS_ABORT) {
-			bputs(text[Aborted]);
-			remove(msgpath);
-			return; }
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && prot[x]->mnemonic==ch
-				&& chk_ar(prot[x]->ar,useron))
-				break;
-		if(x<total_prots)	/* This should be always */
-			protocol(cmdstr(prot[x]->ulcmd,str2,nulstr,NULL),0); }
-	l=flength(str2);
-	if(l>0)
-		bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
-	else {
-		bprintf(text[FileNotReceived],title);
-		remove(msgpath);
-		return; } }
-
-bputs(text[WritingIndx]);
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=mail_maxcrcs;
-	smb.status.max_age=mail_maxage;
-	smb.status.max_msgs=MAX_SYSMAIL;
-	smb.status.attr=SMB_EMAIL;
-	if((i=smb_create(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return; } }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return; }
-
-length=flength(msgpath)+2;	 /* +2 for translation string */
-
-if(length&0xfff00000UL) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LEN,msgpath,length);
-    return; }
-
-if((i=smb_open_da(&smb))!=0) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if(sys_misc&SM_FASTMAIL)
-	offset=smb_fallocdat(&smb,length,1);
-else
-	offset=smb_allocdat(&smb,length,1);
-smb_close_da(&smb);
-
-if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_freemsgdat(&smb,offset,length,1);
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
-	return; }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;
-	if(mail_maxcrcs) {
-		for(i=0;i<j;i++)
-			crc=ucrc32(buf[i],crc); }
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-crc=~crc;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-msg.hdr.attr=msg.idx.attr=msgattr;
-if(mode&WM_FILE)
-	msg.hdr.auxattr|=MSG_FILEATTACH;
-msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone;
-
-if(mail_maxcrcs) {
-	i=smb_addcrc(&smb,crc);
-	if(i) {
-		smb_freemsgdat(&smb,offset,length,1);
-		smb_unlocksmbhdr(&smb);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		bputs("\1r\1h\1iDuplicate message!\r\n");
-		return; } }
-
-msg.hdr.offset=offset;
-
-username(usernumber,str);
-smb_hfield(&msg,RECIPIENT,strlen(str),str);
-
-sprintf(str,"%u",usernumber);
-smb_hfield(&msg,RECIPIENTEXT,strlen(str),str);
-msg.idx.to=usernumber;
-
-strcpy(str,useron.alias);
-smb_hfield(&msg,SENDER,strlen(str),str);
-
-sprintf(str,"%u",useron.number);
-smb_hfield(&msg,SENDEREXT,strlen(str),str);
-msg.idx.from=useron.number;
-
-smb_hfield(&msg,SUBJECT,strlen(title),title);
-strlwr(title);
-msg.idx.subj=crc16(title);
-
-smb_dfield(&msg,TEXT_BODY,length);
-
-smb_unlocksmbhdr(&smb);
-i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-smb_freemsgmem(&msg);
-if(i) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return; }
-
-if(usernumber==1) {
-    useron.fbacks++;
-    logon_fbacks++;
-    putuserrec(useron.number,U_FBACKS,5,itoa(useron.fbacks,tmp,10)); }
-else {
-    useron.emails++;
-    logon_emails++;
-    putuserrec(useron.number,U_EMAILS,5,itoa(useron.emails,tmp,10)); }
-useron.etoday++;
-putuserrec(useron.number,U_ETODAY,5,itoa(useron.etoday,tmp,10));
-bprintf(text[Emailed],username(usernumber,tmp),usernumber);
-sprintf(str,"E-mailed %s #%d",username(usernumber,tmp),usernumber);
-logline("E+",str);
-if(mode&WM_FILE && online==ON_REMOTE)
-	autohangup();
-if(msgattr&MSG_ANONYMOUS)				/* Don't tell user if anonymous */
-    return;
-for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
-    getnodedat(i,&node,0);
-    if(node.useron==usernumber && !(node.misc&NODE_POFF)
-        && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
-        sprintf(str,text[EmailNodeMsg],node_num,useron.alias);
-		putnmsg(i,str);
-        break; } }
-if(i>sys_nodes) {	/* User wasn't online, so leave short msg */
-	sprintf(str,text[UserSentYouMail],useron.alias);
-	putsmsg(usernumber,str); }
-}
diff --git a/src/sbbs2/etext.c b/src/sbbs2/etext.c
deleted file mode 100644
index 3a25776c2cdadc10f145fdb20aaea3c4eb369980..0000000000000000000000000000000000000000
--- a/src/sbbs2/etext.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* ETEXT.C */
-
-#include "etext.h"
-
-unsigned long VersionNoticeDOS[]={ 3356835823UL,3314249220UL,374396000UL,3922003403UL,2881467347UL,2486246197UL,3111832648UL,4155039507UL,42307UL };
-unsigned long VersionNoticeOS2[]={ 3356835822UL,3314249220UL,374396000UL,3922003403UL,1532953555UL,2026511120UL,3143769178UL,3289372253UL,5547459UL };
-unsigned long VersionNoticeW32[]={ 3356835809UL,3314249220UL,374396000UL,3922003403UL,1586398163UL,88738067UL,3070891308UL,395014492UL,726984154UL };
-unsigned long CopyrightNotice[]={ 2870097002UL,1320491556UL,3387089248UL,1175526980UL,47313347UL,3589138741UL,3110223426UL,207123671UL };
-unsigned long CopyrightAddress[]={ 2870096911UL,1320491556UL,3387089248UL,1175526980UL,47313347UL,3589138741UL,3110223426UL,1280865495UL,730555715UL,2860505763UL,506422981UL,3822509617UL,1593759605UL,2730878830UL,2073372242UL,94853UL };
-unsigned long Unregistered[]={ 4089925185UL,456418497UL };
-unsigned long Synchronet[]={ 3356835779UL,3314249220UL,5216UL };
-unsigned long QWKheader[]={ 3090677251UL,1335831276UL,2558259650UL,3930102115UL,921508403UL,3652942133UL,2169713010UL,4229477056UL,3478431186UL,2126281968UL,510119879UL,3510789355UL,3377605456UL,2160545622UL,2276673404UL,236723209UL,580UL };
diff --git a/src/sbbs2/etext.dat b/src/sbbs2/etext.dat
deleted file mode 100644
index 60a479552e30f841e1f0464235e5633e2bd990c1..0000000000000000000000000000000000000000
--- a/src/sbbs2/etext.dat
+++ /dev/null
@@ -1,16 +0,0 @@
-VersionNoticeDOS:
-Synchronet_BBS_for_DOS__Version_2.30__
-VersionNoticeOS2:
-Synchronet_BBS_for_OS/2__Version_2.30__
-VersionNoticeW32:
-Synchronet_BBS_for_Win32__Version_2.30__
-CopyrightNotice:
-Developed 1990-2000 by Rob Swindell
-CopyrightAddress:
-Developed 1990-2000 by Rob Swindell;_PO_Box_501,_Yorba_Linda,_CA_92885
-Unregistered:
-00000000
-Synchronet:
-Synchronet
-QWKheader:
-Produced_by_Synchronet_BBS__Version_2__Developed 1990-2000 by Rob Swindell
diff --git a/src/sbbs2/etext.h b/src/sbbs2/etext.h
deleted file mode 100644
index f08e15773dd8e59b5d328fa6bcea00c703a27506..0000000000000000000000000000000000000000
--- a/src/sbbs2/etext.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* ETEXT.H */
-
-extern unsigned long VersionNoticeDOS[];
-extern unsigned long VersionNoticeOS2[];
-extern unsigned long VersionNoticeW32[];
-extern unsigned long CopyrightNotice[];
-extern unsigned long CopyrightAddress[];
-extern unsigned long Unregistered[];
-extern unsigned long Synchronet[];
-extern unsigned long QWKheader[];
diff --git a/src/sbbs2/exec.c b/src/sbbs2/exec.c
deleted file mode 100644
index e62230eb3e147314f6192290dc71ef9889acbc99..0000000000000000000000000000000000000000
--- a/src/sbbs2/exec.c
+++ /dev/null
@@ -1,1557 +0,0 @@
-#line 1 "EXEC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-char *readtext(long *line, FILE *stream);
-
-extern csi_t main_csi;
-extern FILE *nodefile_fp,*node_ext_fp,*logfile_fp;
-
-uint global_str_vars=0;
-char **global_str_var=0;
-long *global_str_var_name=0;
-uint global_int_vars=0;
-long *global_int_var=0;
-long *global_int_var_name=0;
-
-char *sysvar_p[MAX_SYSVARS]={NULL};
-int sysvar_pi=0;
-long sysvar_l[MAX_SYSVARS]={0L};
-int sysvar_li=0;
-
-char **getstrvar(csi_t *bin, long name)
-{
-	int i;
-
-if(sysvar_pi>=MAX_SYSVARS) sysvar_pi=0;
-switch(name) {
-	case 0:
-		return((char **)&(bin->str));
-	case 0x490873f1:
-		sysvar_p[sysvar_pi]=useron.alias;
-		break;
-	case 0x5de44e8b:
-		sysvar_p[sysvar_pi]=useron.name;
-		break;
-	case 0x979ef1de:
-		sysvar_p[sysvar_pi]=useron.handle;
-		break;
-	case 0xc8cd5fb7:
-		sysvar_p[sysvar_pi]=useron.comp;
-		break;
-	case 0xcc7aca99:
-		sysvar_p[sysvar_pi]=useron.note;
-		break;
-	case 0xa842c43b:
-		sysvar_p[sysvar_pi]=useron.address;
-		break;
-	case 0x4ee1ff3a:
-		sysvar_p[sysvar_pi]=useron.location;
-		break;
-	case 0xf000aa78:
-		sysvar_p[sysvar_pi]=useron.zipcode;
-		break;
-	case 0xcdb7e4a9:
-		sysvar_p[sysvar_pi]=useron.pass;
-		break;
-	case 0x94d59a7a:
-		sysvar_p[sysvar_pi]=useron.birth;
-		break;
-	case 0xec2b8fb8:
-		sysvar_p[sysvar_pi]=useron.phone;
-		break;
-	case 0x08f65a2a:
-		sysvar_p[sysvar_pi]=useron.modem;
-		break;
-	case 0xc7e0e8ce:
-		sysvar_p[sysvar_pi]=useron.netmail;
-		break;
-	case 0xd3606303:
-		sysvar_p[sysvar_pi]=useron.tmpext;
-		break;
-	case 0x3178f9d6:
-		sysvar_p[sysvar_pi]=useron.comment;
-		break;
-
-    case 0x41239e21:
-		sysvar_p[sysvar_pi]=connection;
-		break;
-	case 0xe9f1fad0:
-		sysvar_p[sysvar_pi]=cap_fname;
-		break;
-	case 0x90fc82b4:
-		sysvar_p[sysvar_pi]=cid;
-		break;
-	case 0x15755030:
-		return((char **)&comspec);
-
-	case 0xf19cd046:
-		sysvar_p[sysvar_pi]=wordwrap;
-		break;
-
-	default:
-		if(bin->str_var && bin->str_var_name)
-			for(i=0;i<bin->str_vars;i++)
-				if(bin->str_var_name[i]==name)
-					return((char **)&(bin->str_var[i]));
-		if(global_str_var && global_str_var_name)
-			for(i=0;i<global_str_vars;i++)
-				if(global_str_var_name[i]==name)
-					return(&(global_str_var[i]));
-		return(NULL); }
-
-return((char **)&sysvar_p[sysvar_pi++]);
-}
-
-long *getintvar(csi_t *bin, long name)
-{
-	int i;
-
-if(sysvar_li==MAX_SYSVARS) sysvar_li=0;
-switch(name) {
-	case 0:
-		sysvar_l[sysvar_li]=strtol(bin->str,0,0);
-		break;
-	case 0x908ece53:
-		sysvar_l[sysvar_li]=useron.number;
-		break;
-	case 0xdcedf626:
-		sysvar_l[sysvar_li]=useron.uls;
-		break;
-	case 0xc1093f61:
-		sysvar_l[sysvar_li]=useron.dls;
-		break;
-	case 0x2039a29f:
-		sysvar_l[sysvar_li]=useron.posts;
-		break;
-	case 0x4a9f3955:
-		sysvar_l[sysvar_li]=useron.emails;
-		break;
-	case 0x0c8dcf3b:
-		sysvar_l[sysvar_li]=useron.fbacks;
-		break;
-	case 0x9a13bf95:
-		sysvar_l[sysvar_li]=useron.etoday;
-		break;
-	case 0xc9082cbd:
-		sysvar_l[sysvar_li]=useron.ptoday;
-		break;
-	case 0x7c72376d:
-		sysvar_l[sysvar_li]=useron.timeon;
-		break;
-	case 0xac72c50b:
-		sysvar_l[sysvar_li]=useron.textra;
-		break;
-	case 0x04807a11:
-		sysvar_l[sysvar_li]=useron.logons;
-		break;
-	case 0x52996eab:
-		sysvar_l[sysvar_li]=useron.ttoday;
-		break;
-	case 0x098bdfcb:
-		sysvar_l[sysvar_li]=useron.tlast;
-		break;
-	case 0xbd1cee5d:
-		sysvar_l[sysvar_li]=useron.ltoday;
-		break;
-	case 0x07954570:
-		sysvar_l[sysvar_li]=useron.xedit;
-		break;
-	case 0xedf6aa98:
-		sysvar_l[sysvar_li]=useron.shell;
-		break;
-	case 0x328ed476:
-		sysvar_l[sysvar_li]=useron.level;
-		break;
-	case 0x9e70e855:
-		sysvar_l[sysvar_li]=useron.sex;
-		break;
-	case 0x094cc42c:
-		sysvar_l[sysvar_li]=useron.rows;
-		break;
-	case 0xabc4317e:
-		sysvar_l[sysvar_li]=useron.prot;
-		break;
-	case 0x7dd9aac0:
-		sysvar_l[sysvar_li]=useron.leech;
-		break;
-	case 0x7c602a37:
-		return((long *)&useron.misc);
-	case 0x61be0d36:
-		return((long *)&useron.qwk);
-	case 0x665ac227:
-		return((long *)&useron.chat);
-	case 0x951341ab:
-		return((long *)&useron.flags1);
-	case 0x0c1a1011:
-		return((long *)&useron.flags2);
-	case 0x7b1d2087:
-		return((long *)&useron.flags3);
-	case 0xe579b524:
-		return((long *)&useron.flags4);
-	case 0x12e7d6d2:
-		return((long *)&useron.exempt);
-	case 0xfed3115d:
-		return((long *)&useron.rest);
-	case 0xb65dd6d4:
-		return((long *)&useron.ulb);
-	case 0xabb91f93:
-		return((long *)&useron.dlb);
-	case 0x92fb364f:
-		return((long *)&useron.cdt);
-	case 0xd0a99c72:
-		return((long *)&useron.min);
-	case 0xd7ae3022:
-		return((long *)&useron.freecdt);
-	case 0x1ef214ef:
-		return((long *)&useron.firston);
-	case 0x0ea515b1:
-		return((long *)&useron.laston);
-	case 0x2aaf9bd3:
-		return((long *)&useron.expire);
-	case 0x89c91dc8:
-		return((long *)&useron.pwmod);
-	case 0x5b0d0c54:
-		return((long *)&useron.ns_time);
-
-	case 0xae256560:
-		return((long *)&cur_rate);
-	case 0x2b3c257f:
-		return((long *)&cur_cps);
-	case 0x1c4455ee:
-		return((long *)&dte_rate);
-	case 0x7fbf958e:
-		return((long *)&lncntr);
-	case 0x5c1c1500:
-		return((long *)&tos);
-	case 0x613b690e:
-		return((long *)&rows);
-	case 0x205ace36:
-		return((long *)&autoterm);
-	case 0x7d0ed0d1:
-		return((long *)&console);
-	case 0xbf31a280:
-		return((long *)&answertime);
-	case 0x83aa2a6a:
-		return((long *)&logontime);
-	case 0xb50cb889:
-		return((long *)&ns_time);
-	case 0xae92d249:
-		return((long *)&last_ns_time);
-	case 0x97f99eef:
-		return((long *)&online);
-	case 0x381d3c2a:
-		return((long *)&sys_status);
-	case 0x7e29c819:
-		return((long *)&sys_misc);
-	case 0x11c83294:
-		return((long *)&sys_psnum);
-	case 0x02408dc5:
-		sysvar_l[sysvar_li]=sys_timezone;
-		break;
-	case 0x78afeaf1:
-		sysvar_l[sysvar_li]=sys_pwdays;
-		break;
-	case 0xd859385f:
-		sysvar_l[sysvar_li]=sys_deldays;
-		break;
-	case 0x6392dc62:
-		sysvar_l[sysvar_li]=sys_autodel;
-		break;
-	case 0x698d59b4:
-		sysvar_l[sysvar_li]=sys_nodes;
-		break;
-	case 0x6fb1c46e:
-		sysvar_l[sysvar_li]=sys_exp_warn;
-		break;
-	case 0xdf391ca7:
-		sysvar_l[sysvar_li]=sys_lastnode;
-		break;
-	case 0xdd982780:
-		sysvar_l[sysvar_li]=sys_autonode;
-		break;
-	case 0xf53db6c7:
-		sysvar_l[sysvar_li]=node_scrnlen;
-		break;
-	case 0xa1f0fcb7:
-		sysvar_l[sysvar_li]=node_scrnblank;
-		break;
-	case 0x709c07da:
-		return((long *)&node_misc);
-	case 0xb17e7914:
-		sysvar_l[sysvar_li]=node_valuser;
-		break;
-	case 0xadae168a:
-		sysvar_l[sysvar_li]=node_ivt;
-		break;
-	case 0x2aa89801:
-		sysvar_l[sysvar_li]=node_swap;
-		break;
-	case 0x4f02623a:
-		sysvar_l[sysvar_li]=node_minbps;
-		break;
-	case 0xe7a7fb07:
-		sysvar_l[sysvar_li]=node_num;
-		break;
-	case 0x6c8e350a:
-		sysvar_l[sysvar_li]=new_level;
-		break;
-	case 0xccfe7c5d:
-		return((long *)&new_flags1);
-	case 0x55f72de7:
-		return((long *)&new_flags2);
-	case 0x22f01d71:
-		return((long *)&new_flags3);
-	case 0xbc9488d2:
-		return((long *)&new_flags4);
-	case 0x4b0aeb24:
-		return((long *)&new_exempt);
-	case 0x20cb6325:
-		return((long *)&new_rest);
-	case 0x31178ba2:
-		return((long *)&new_cdt);
-	case 0x7345219f:
-		return((long *)&new_min);
-	case 0xb3f64be4:
-		sysvar_l[sysvar_li]=new_shell;
-		break;
-	case 0xa278584f:
-		return((long *)&new_misc);
-	case 0x7342a625:
-		sysvar_l[sysvar_li]=new_expire;
-		break;
-	case 0x75dc4306:
-		sysvar_l[sysvar_li]=new_prot;
-		break;
-	case 0xfb394e27:
-		sysvar_l[sysvar_li]=expired_level;
-		break;
-	case 0x89b69753:
-		return((long *)&expired_flags1);
-	case 0x10bfc6e9:
-		return((long *)&expired_flags2);
-	case 0x67b8f67f:
-		return((long *)&expired_flags3);
-	case 0xf9dc63dc:
-		return((long *)&expired_flags4);
-	case 0x0e42002a:
-		return((long *)&expired_exempt);
-	case 0x4569c62e:
-		return((long *)&expired_rest);
-	case 0xfcf3542e:
-		sysvar_l[sysvar_li]=min_dspace;
-		break;
-	case 0xcf9ce02c:
-		sysvar_l[sysvar_li]=cdt_min_value;
-		break;
-	case 0xfcb5b274:
-		return((long *)&cdt_per_dollar);
-	case 0x4db200d2:
-		sysvar_l[sysvar_li]=leech_pct;
-		break;
-	case 0x9a7d9cca:
-		sysvar_l[sysvar_li]=leech_sec;
-		break;
-	case 0x396b7167:
-		return((long *)&netmail_cost);
-	case 0x5eeaff21:
-		sysvar_l[sysvar_li]=netmail_misc;
-		break;
-	case 0x82d9484e:
-		return((long *)&inetmail_cost);
-	case 0xe558c608:
-		return((long *)&inetmail_misc);
-
-	case 0xc6e8539d:
-		return((long *)&logon_ulb);
-	case 0xdb0c9ada:
-		return((long *)&logon_dlb);
-	case 0xac58736f:
-		return((long *)&logon_uls);
-	case 0xb1bcba28:
-		return((long *)&logon_dls);
-	case 0x9c5051c9:
-		return((long *)&logon_posts);
-	case 0xc82ba467:
-		return((long *)&logon_emails);
-	case 0x8e395209:
-		return((long *)&logon_fbacks);
-	case 0x8b12ba9d:
-		return((long *)&posts_read);
-	case 0xe51c1956:
-		sysvar_l[sysvar_li]=(ulong)logfile_fp;
-		break;
-	case 0x5a22d4bd:
-		sysvar_l[sysvar_li]=(ulong)nodefile_fp;
-		break;
-	case 0x3a37c26b:
-		sysvar_l[sysvar_li]=(ulong)node_ext_fp;
-		break;
-
-	case 0xeb6c9c73:
-		sysvar_l[sysvar_li]=errorlevel;
-		break;
-
-	case 0x5aaccfc5:
-		sysvar_l[sysvar_li]=errno;
-		break;
-
-	case 0x057e4cd4:
-		sysvar_l[sysvar_li]=timeleft;
-		break;
-
-	case 0x1e5052a7:
-		return((long *)&max_minutes);
-	case 0xedc643f1:
-		return((long *)&max_qwkmsgs);
-
-	case 0x430178ec:
-		return((long *)&uq);
-
-	default:
-		if(bin->int_var && bin->int_var_name)
-			for(i=0;i<bin->int_vars;i++)
-				if(bin->int_var_name[i]==name)
-					return(&bin->int_var[i]);
-		if(global_int_var && global_int_var_name)
-			for(i=0;i<global_int_vars;i++)
-				if(global_int_var_name[i]==name)
-					return(&global_int_var[i]);
-		return(NULL); }
-
-return(&sysvar_l[sysvar_li++]);
-}
-
-void clearvars(csi_t *bin)
-{
-bin->str_vars=0;
-bin->str_var=NULL;
-bin->str_var_name=NULL;
-bin->int_vars=0;
-bin->int_var=NULL;
-bin->int_var_name=NULL;
-bin->files=0;
-bin->retval=0;
-}
-
-void freevars(csi_t *bin)
-{
-	int i;
-
-if(bin->str_var) {
-	for(i=0;i<bin->str_vars;i++)
-		if(bin->str_var[i])
-			FREE(bin->str_var[i]);
-	FREE(bin->str_var); }
-if(bin->int_var)
-	FREE(bin->int_var);
-if(bin->str_var_name)
-	FREE(bin->str_var_name);
-if(bin->int_var_name)
-	FREE(bin->int_var_name);
-for(i=0;i<bin->files;i++)
-	if(bin->file[i]) {
-		fclose((FILE *)bin->file[i]);
-		bin->file[i]=0; }
-}
-
-/****************************************************************************/
-/* Copies a new value (str) into the string variable pointed to by p		*/
-/* re-allocating if necessary												*/
-/****************************************************************************/
-char *copystrvar(csi_t *csi, char *p, char *str)
-{
-	char *np;	/* New pointer after realloc */
-	int i;
-
-if(p!=csi->str) {
-	if(p)
-		for(i=0;i<MAX_SYSVARS;i++)
-			if(p==sysvar_p[i])
-				break;
-	if(!p || i==MAX_SYSVARS) {		/* Not system variable */
-		if((np=REALLOC(p,strlen(str)+1))==NULL)
-			errormsg(WHERE,ERR_ALLOC,"variable",strlen(str)+1);
-		else
-			p=np; } }
-if(p)
-	strcpy(p,str);
-return(p);
-}
-
-
-long exec_bin(uchar *mod, csi_t *csi)
-{
-    char    str[128];
-	int 	i,file;
-    csi_t   bin;
-
-//lprintf("%s %d\r\n",__FILE__,__LINE__);
-memcpy(&bin,csi,sizeof(csi_t));
-clearvars(&bin);
-
-sprintf(str,"%s%s.BIN",exec_dir,mod);
-if((file=nopen(str,O_RDONLY|O_BINARY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
-	return(-1); }
-
-//lprintf("%s %d\r\n",__FILE__,__LINE__);
-bin.length=filelength(file);
-if((bin.cs=(uchar *)MALLOC(bin.length))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,bin.length);
-	return(-1); }
-if(lread(file,bin.cs,bin.length)!=bin.length) {
-    close(file);
-    errormsg(WHERE,ERR_READ,str,bin.length);
-    FREE(bin.cs);
-	return(-1); }
-close(file);
-
-bin.ip=bin.cs;
-bin.rets=bin.cmdrets=bin.misc=0;
-//lprintf("%s %d\r\n",__FILE__,__LINE__);
-while(exec(&bin)==0)
-	if(!(bin.misc&CS_OFFLINE_EXEC)) {
-		checkline();
-		if(!online)
-			break; }
-//lprintf("%s %d logic=%d\r\n",__FILE__,__LINE__,bin.logic);
-freevars(&bin);
-FREE(bin.cs);
-csi->logic=bin.logic;
-return(bin.retval);
-}
-
-/****************************************************************************/
-/* Skcsi->ip to a specific instruction                                           */
-/****************************************************************************/
-void skipto(csi_t *csi, uchar inst)
-{
-	int i,j;
-
-while(csi->ip<csi->cs+csi->length && ((inst&0x80) || *csi->ip!=inst)) {
-
-	if(*csi->ip==CS_IF_TRUE || *csi->ip==CS_IF_FALSE
-		|| (*csi->ip>=CS_IF_GREATER && *csi->ip<=CS_IF_LESS_OR_EQUAL)) {
-        csi->ip++;
-        skipto(csi,CS_ENDIF);
-        csi->ip++;
-        continue; }
-
-    if(inst==CS_ELSEORENDIF
-        && (*csi->ip==CS_ELSE || *csi->ip==CS_ENDIF))
-        break;
-
-	if(inst==CS_NEXTCASE
-		&& (*csi->ip==CS_CASE || *csi->ip==CS_DEFAULT
-			|| *csi->ip==CS_END_SWITCH))
-		break;
-
-	if(*csi->ip==CS_SWITCH) {
-		csi->ip++;
-		csi->ip+=4; /* Skip variable name */
-		skipto(csi,CS_END_SWITCH);
-		csi->ip++;
-		continue; }
-
-    if(*csi->ip==CS_CASE) {
-        csi->ip++;
-        csi->ip+=4; /* Skip value */
-        skipto(csi,CS_NEXTCASE);
-        continue; }
-
-    if(*csi->ip==CS_CMDKEY) {
-        csi->ip+=2;
-        skipto(csi,CS_END_CMD);
-        csi->ip++;
-        continue; }
-	if(*csi->ip==CS_CMDSTR || *csi->ip==CS_CMDKEYS) {
-        csi->ip++;              /* skip inst */
-        while(*(csi->ip++));    /* skip string */
-        skipto(csi,CS_END_CMD);
-        csi->ip++;
-        continue; }
-
-    if(*csi->ip>=CS_FUNCTIONS) {
-        csi->ip++;
-        continue; }
-
-    if(*csi->ip>=CS_MISC) {
-        switch(*csi->ip) {
-			case CS_VAR_INSTRUCTION:
-				csi->ip++;
-				switch(*(csi->ip++)) {
-					case SHOW_VARS:
-						continue;
-					case PRINT_VAR:
-					case DEFINE_STR_VAR:
-					case DEFINE_INT_VAR:
-					case DEFINE_GLOBAL_STR_VAR:
-					case DEFINE_GLOBAL_INT_VAR:
-					case TIME_INT_VAR:
-					case STRUPR_VAR:
-					case STRLWR_VAR:
-					case TRUNCSP_STR_VAR:
-					case CHKFILE_VAR:
-					case STRIP_CTRL_STR_VAR:
-						csi->ip+=4; /* Skip variable name */
-						continue;
-					case GETSTR_VAR:
-					case GETNAME_VAR:
-					case GETLINE_VAR:
-					case GETSTRUPR_VAR:
-					case SHIFT_STR_VAR:
-					case SEND_FILE_VIA_VAR:
-					case RECEIVE_FILE_VIA_VAR:
-						csi->ip+=4; /* Skip variable name */
-						csi->ip++;	/* Skip char */
-						continue;
-					case PRINTTAIL_VAR_MODE:
-						csi->ip++;	/* Skip length */
-					case PRINTFILE_VAR_MODE:
-					case GETNUM_VAR:
-						csi->ip+=4; /* Skip variable name */
-						csi->ip+=2;  /* Skip max num */
-                        continue;
-					case STRNCMP_VAR:
-						csi->ip++;	/* Skip length */
-					case SET_STR_VAR:
-					case COMPARE_STR_VAR:
-					case CAT_STR_VAR:
-					case STRSTR_VAR:
-						csi->ip+=4; /* Skip variable name */
-						while(*(csi->ip++));	/* skip string */
-						continue;
-					case FORMAT_TIME_STR:
-						csi->ip+=4; /* Skip destination variable */
-						while(*(csi->ip++));	/* Skip string */
-						csi->ip+=4; /* Skip int variable */
-						continue;
-					case FORMAT_STR_VAR:	/* SPRINTF */
-						csi->ip+=4; /* Skip destination variable */
-					case VAR_PRINTF:
-						while(*(csi->ip++));	/* Skip string */
-						j=*(csi->ip++); /* Skip number of arguments */
-						for(i=0;i<j;i++)
-							csi->ip+=4; /* Skip arguments */
-						continue;
-					case SEND_FILE_VIA:
-					case RECEIVE_FILE_VIA:
-						csi->ip++;				/* Skip prot */
-						while(*(csi->ip++));	/* Skip filepath */
-						continue;
-					case GETSTR_MODE:
-					case STRNCMP_VARS:
-						csi->ip++;	/* Skip length */
-					default:
-						csi->ip+=8; /* Skip two variable names or var & val */
-						continue; }
-
-			case CS_FIO_FUNCTION:
-				csi->ip++;
-				switch(*(csi->ip++)) {
-					case FIO_OPEN:
-						csi->ip+=4; 			/* File handle */
-						csi->ip+=2; 			/* Access */
-						while(*(csi->ip++));	/* path/filename */
-						continue;
-					case FIO_CLOSE:
-					case FIO_FLUSH:
-					case FIO_EOF:
-					case REMOVE_FILE:
-					case REMOVE_DIR:
-					case CHANGE_DIR:
-					case MAKE_DIR:
-					case REWIND_DIR:
-					case CLOSE_DIR:
-						csi->ip+=4; 			/* File handle */
-						continue;
-					case FIO_SET_ETX:
-						csi->ip++;
-						continue;
-					case FIO_PRINTF:
-						csi->ip+=4; 			/* File handle */
-						while(*(csi->ip++));	/* String */
-						j=*(csi->ip++); 		/* Number of arguments */
-						for(i=0;i<j;i++)
-							csi->ip+=4; 		/* Arguments */
-                        continue;
-					case FIO_READ:
-					case FIO_WRITE:
-					case FIO_SEEK:
-					case FIO_SEEK_VAR:
-					case FIO_OPEN_VAR:
-						csi->ip+=4; 			/* File handle */
-						csi->ip+=4; 			/* Variable */
-						csi->ip+=2; 			/* Length/access */
-						continue;
-					case FIO_READ_VAR:
-					case FIO_WRITE_VAR:
-						csi->ip+=4; 			/* File handle */
-						csi->ip+=4; 			/* Buf Variable */
-						csi->ip+=4; 			/* Length Variable */
-                        continue;
-					default:
-                        csi->ip+=4;             /* File handle */
-                        csi->ip+=4;             /* Variable */
-						continue; }
-
-			case CS_COMPARE_ARS:
-                csi->ip++;
-                csi->ip+=(*csi->ip);
-                csi->ip++;
-                break;
-            case CS_TOGGLE_USER_MISC:
-            case CS_COMPARE_USER_MISC:
-			case CS_TOGGLE_USER_CHAT:
-			case CS_COMPARE_USER_CHAT:
-			case CS_TOGGLE_USER_QWK:
-			case CS_COMPARE_USER_QWK:
-                csi->ip+=5;
-                break;
-            case CS_REPLACE_TEXT:
-                csi->ip+=3;     /* skip inst and text # */
-                while(*(csi->ip++));    /* skip string */
-                break;
-			case CS_USE_INT_VAR:
-				csi->ip+=7; // inst, var, offset, len
-				break;
-            default:
-                csi->ip++; }
-        continue; }
-
-	if(*csi->ip==CS_ONE_MORE_BYTE) {
-		csi->ip++;				/* skip extension */
-		csi->ip++;				/* skip instruction */
-		continue; }
-
-	if(*csi->ip==CS_TWO_MORE_BYTES) {
-		csi->ip++;				/* skip extension */
-		csi->ip++;				/* skip instruction */
-		csi->ip++;				/* skip argument */
-        continue; }
-
-	if(*csi->ip==CS_THREE_MORE_BYTES) {
-		csi->ip++;				/* skip extension */
-		csi->ip++;				/* skip instruction */
-		csi->ip+=2; 			/* skip argument */
-        continue; }
-
-	if(*csi->ip==CS_STR_FUNCTION) {
-		csi->ip++;				/* skip extension */
-		csi->ip++;				/* skip instruction */
-        while(*(csi->ip++));    /* skip string */
-        continue; }
-
-    if(*csi->ip>=CS_ASCIIZ) {
-        csi->ip++;              /* skip inst */
-        while(*(csi->ip++));    /* skip string */
-        continue; }
-
-    if(*csi->ip>=CS_THREE_BYTE) {
-        csi->ip+=3;
-        continue; }
-
-    if(*csi->ip>=CS_TWO_BYTE) {
-        csi->ip+=2;
-        continue; }
-
-    csi->ip++; }
-}
-
-
-int exec(csi_t *csi)
-{
-	uchar	str[256],tmp2[128],buf[1025],*path,ch,*p,**pp,**pp1,**pp2;
-	int 	i,j,k,s,file,x,y;
-	long	l,*lp,*lp1,*lp2;
-	stats_t stats;
-	time_t	t;
-	FILE	*stream;
-
-//lprintf("line %d (%d %d %d)\r\n",__LINE__,curgrp,cursub[curgrp],usrsub[curgrp]);
-#if 0
-if(curgrp>=total_grps)
-	curgrp=0;
-if(cursub[curgrp]>=total_subs)
-	cursub[curgrp]=0;
-if(curlib>=total_libs)
-	curlib=0;
-if(curdir[curlib]>=total_dirs)
-	curdir[curlib]=0;
-#endif
-
-if(usrgrps)
-	cursubnum=usrsub[curgrp][cursub[curgrp]];		/* Used for ARS */
-else
-	cursubnum=INVALID_SUB;
-if(usrlibs) {
-	curdirnum=usrdir[curlib][curdir[curlib]];		/* Used for ARS */
-	path=dir[usrdir[curlib][curdir[curlib]]]->path; }
-else {
-	curdirnum=INVALID_DIR;
-	path=nulstr; }
-now=time(NULL);
-
-if(csi->ip>=csi->cs+csi->length)
-	return(1);
-
-//lprintf("%04X: %02X ",(uint)(csi->ip-csi->cs),*csi->ip);
-
-if(*csi->ip>=CS_FUNCTIONS)
-	return(exec_function(csi));
-
-/**********************************************/
-/* Miscellaneous variable length instructions */
-/**********************************************/
-
-if(*csi->ip>=CS_MISC)
-	return(exec_misc(csi,path));
-
-/********************************/
-/* ASCIIZ argument instructions */
-/********************************/
-
-if(*csi->ip>=CS_ASCIIZ) {
-	switch(*(csi->ip++)) {
-		case CS_STR_FUNCTION:
-			switch(*(csi->ip++)) {
-				case CS_LOGIN:
-					csi->logic=login(csi->str,csi->ip);
-					break;
-				case CS_LOAD_TEXT:
-					csi->logic=LOGIC_FALSE;
-					for(i=0;i<TOTAL_TEXT;i++)
-						if(text[i]!=text_sav[i]) {
-							if(text[i]!=nulstr)
-								FREE(text[i]);
-							text[i]=text_sav[i]; }
-					sprintf(str,"%s%s.DAT"
-						,ctrl_dir,cmdstr(csi->ip,path,csi->str,buf));
-					if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-						errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-						break; }
-					for(i=0;i<TOTAL_TEXT && !feof(stream);i++) {
-						if((text[i]=readtext((long *)NULL,stream))==NULL) {
-							i--;
-							continue; }
-						if(!strcmp(text[i],text_sav[i])) {	/* If identical */
-							FREE(text[i]);					/* Don't alloc */
-							text[i]=text_sav[i]; }
-						else if(text[i][0]==0) {
-							FREE(text[i]);
-							text[i]=nulstr; } }
-					if(i<TOTAL_TEXT) {
-						fclose(stream);
-						errormsg(WHERE,ERR_READ,str,TOTAL_TEXT);
-						break; }
-					fclose(stream);
-					csi->logic=LOGIC_TRUE;
-					break;
-				default:
-					errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-					break; }
-			while(*(csi->ip++));	 /* Find NULL */
-			return(0);
-		case CS_LOG:
-			log(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_GETCMD:
-			csi->cmd=getkeys(csi->ip,0);
-			if((char)csi->cmd==-1)
-				csi->cmd=3;
-			break;
-		case CS_CMDSTR:
-			if(stricmp(csi->str,csi->ip)) {
-				while(*(csi->ip++));		/* Find NULL */
-				skipto(csi,CS_END_CMD);
-				csi->ip++;
-				return(0); }
-			break;
-		case CS_CMDKEYS:
-			for(i=0;csi->ip[i];i++)
-				if(csi->cmd==csi->ip[i])
-					break;
-			if(!csi->ip[i]) {
-				while(*(csi->ip++));		/* Find NULL */
-				skipto(csi,CS_END_CMD);
-				csi->ip++;
-				return(0); }
-			break;
-		case CS_GET_TEMPLATE:
-			gettmplt(csi->str,csi->ip,K_LINE);
-			if(sys_status&SS_ABORT)
-				csi->str[0]=0;
-			csi->cmd=csi->str[0];
-			break;
-		case CS_TRASHCAN:
-			csi->logic=!trashcan(csi->str,csi->ip);
-			break;
-		case CS_CREATE_SIF:
-			create_sif_dat(csi->ip,csi->str);
-			break;
-		case CS_READ_SIF:
-			read_sif_dat(csi->ip,csi->str);
-			break;
-		case CS_MNEMONICS:
-			mnemonics(csi->ip);
-			break;
-		case CS_PRINT:
-			putmsg(cmdstr(csi->ip,path,csi->str,buf),P_SAVEATR|P_NOABORT);
-			break;
-		case CS_PRINT_LOCAL:
-			lputs(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_PRINT_REMOTE:
-			putcom(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_PRINTFILE:
-			printfile(cmdstr(csi->ip,path,csi->str,buf),P_SAVEATR);
-			break;
-		case CS_PRINTFILE_REMOTE:
-			if(online!=ON_REMOTE || !(console&CON_R_ECHO))
-				break;
-			console&=~CON_L_ECHO;
-			printfile(cmdstr(csi->ip,path,csi->str,buf),P_SAVEATR);
-			console|=CON_L_ECHO;
-			break;
-		case CS_PRINTFILE_LOCAL:
-			if(!(console&CON_L_ECHO))
-				break;
-			console&=~CON_R_ECHO;
-			printfile(cmdstr(csi->ip,path,csi->str,buf),P_SAVEATR);
-			console|=CON_R_ECHO;
-			break;
-		case CS_CHKFILE:
-			csi->logic=!fexist(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_EXEC:
-			external(cmdstr(csi->ip,path,csi->str,buf),0);
-			break;
-		case CS_EXEC_INT:
-			external(cmdstr(csi->ip,path,csi->str,buf),EX_OUTR|EX_INR|EX_OUTL);
-			break;
-		case CS_EXEC_XTRN:
-			for(i=0;i<total_xtrns;i++)
-				if(!stricmp(xtrn[i]->code,csi->ip))
-					break;
-			if(i<total_xtrns)
-				exec_xtrn(i);
-			break;
-		case CS_EXEC_BIN:
-			exec_bin(cmdstr(csi->ip,path,csi->str,buf),csi);
-			break;
-		case CS_YES_NO:
-			csi->logic=!yesno(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_NO_YES:
-			csi->logic=!noyes(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_MENU:
-			menu(cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_SETSTR:
-			strcpy(csi->str,cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_SET_MENU_DIR:
-			cmdstr(csi->ip,path,csi->str,menu_dir);
-			break;
-		case CS_SET_MENU_FILE:
-			cmdstr(csi->ip,path,csi->str,menu_file);
-			break;
-		case CS_COMPARE_STR:
-			csi->logic=stricmp(csi->str,cmdstr(csi->ip,path,csi->str,buf));
-			break;
-		case CS_COMPARE_KEYS:
-			for(i=0;csi->ip[i];i++)
-				if(csi->cmd==csi->ip[i])
-					break;
-			if(csi->ip[i])
-				csi->logic=LOGIC_TRUE;
-			else
-				csi->logic=LOGIC_FALSE;
-			break;
-		case CS_COMPARE_WORD:
-			csi->logic=strnicmp(csi->str,csi->ip,strlen(csi->ip));
-			break;
-		default:
-			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-			break; }
-	while(*(csi->ip++));	 /* Find NULL */
-	return(0); }
-
-if(*csi->ip>=CS_THREE_BYTE) {
-	switch(*(csi->ip++)) {
-		case CS_THREE_MORE_BYTES:
-			switch(*(csi->ip++)) {
-				}
-			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-			return(0);
-		case CS_GOTO:
-			csi->ip=csi->cs+*((ushort *)(csi->ip));
-			return(0);
-		case CS_CALL:
-			csi->ret[csi->rets++]=csi->ip+2;
-			csi->ip=csi->cs+*((ushort *)(csi->ip));
-			return(0);
-		case CS_MSWAIT:
-			mswait(*(ushort *)csi->ip);
-			csi->ip+=2;
-			return(0);
-		case CS_TOGGLE_NODE_MISC:
-			getnodedat(node_num,&thisnode,1);
-			thisnode.misc^=*(ushort *)csi->ip;
-			csi->ip+=2;
-			putnodedat(node_num,thisnode);
-            return(0);
-		case CS_COMPARE_NODE_MISC:
-			getnodedat(node_num,&thisnode,0);
-			if((thisnode.misc&*(ushort *)csi->ip)==*(ushort *)csi->ip)
-				csi->logic=LOGIC_TRUE;
-			else
-				csi->logic=LOGIC_FALSE;
-			csi->ip+=2;
-            return(0);
-		case CS_ADJUST_USER_CREDITS:
-			i=*(short *)csi->ip;
-			l=i*1024L;
-			if(l<0)
-				subtract_cdt(-l);
-			else
-				useron.cdt=adjustuserrec(useron.number,U_CDT,10,l);
-			csi->ip+=2;
-			return(0);
-		case CS_ADJUST_USER_MINUTES:
-			i=*(short *)csi->ip;
-			useron.min=adjustuserrec(useron.number,U_MIN,10,i);
-			csi->ip+=2;
-            return(0);
-		case CS_GETNUM:
-			i=*(short *)csi->ip;
-			csi->ip+=2;
-			l=getnum(i);
-			if(l<=0) {
-				csi->str[0]=0;
-				csi->logic=LOGIC_FALSE; }
-			else {
-				sprintf(csi->str,"%lu",l);
-				csi->logic=LOGIC_TRUE; }
-			return(0);
-
-		case CS_TOGGLE_USER_FLAG:
-			i=*(csi->ip++);
-			ch=*(csi->ip++);
-			switch(i) {
-				case '1':
-					useron.flags1^=FLAG(ch);
-					putuserrec(useron.number,U_FLAGS1,8
-						,ultoa(useron.flags1,tmp,16));
-					break;
-				case '2':
-					useron.flags2^=FLAG(ch);
-					putuserrec(useron.number,U_FLAGS2,8
-						,ultoa(useron.flags2,tmp,16));
-					break;
-				case '3':
-					useron.flags3^=FLAG(ch);
-					putuserrec(useron.number,U_FLAGS3,8
-						,ultoa(useron.flags3,tmp,16));
-					break;
-				case '4':
-					useron.flags4^=FLAG(ch);
-					putuserrec(useron.number,U_FLAGS4,8
-						,ultoa(useron.flags4,tmp,16));
-					break;
-				case 'R':
-					useron.rest^=FLAG(ch);
-					putuserrec(useron.number,U_REST,8
-						,ultoa(useron.rest,tmp,16));
-					break;
-				case 'E':
-					useron.exempt^=FLAG(ch);
-					putuserrec(useron.number,U_EXEMPT,8
-						,ultoa(useron.exempt,tmp,16));
-					break;
-				default:
-					errormsg(WHERE,ERR_CHK,"user flag type",*(csi->ip-2));
-					return(0); }
-			statusline();
-			return(0);
-		case CS_REVERT_TEXT:
-            i=*(ushort *)csi->ip;
-            csi->ip+=2;
-			if((ushort)i==0xffff) {
-				for(i=0;i<TOTAL_TEXT;i++) {
-					if(text[i]!=text_sav[i] && text[i]!=nulstr)
-						FREE(text[i]);
-					text[i]=text_sav[i]; }
-				return(0); }
-            i--;
-            if(i>=TOTAL_TEXT) {
-				errormsg(WHERE,ERR_CHK,"revert text #",i);
-                return(0); }
-			if(text[i]!=text_sav[i] && text[i]!=nulstr)
-                FREE(text[i]);
-            text[i]=text_sav[i];
-			return(0);
-		default:
-			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-			return(0); } }
-
-if(*csi->ip>=CS_TWO_BYTE) {
-	switch(*(csi->ip++)) {
-		case CS_TWO_MORE_BYTES:
-			switch(*(csi->ip++)) {
-				case CS_USER_EVENT:
-					user_event(*(csi->ip++));
-					return(0);
-				}
-			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-			return(0);
-		case CS_SETLOGIC:
-			csi->logic=*csi->ip++;
-			return(0);
-		case CS_CMDKEY:
-			if( ((*csi->ip)==CS_DIGIT && isdigit(csi->cmd))
-				|| ((*csi->ip)==CS_EDIGIT && csi->cmd&0x80
-				&& isdigit(csi->cmd&0x7f))) {
-				csi->ip++;
-				return(0); }
-			if(csi->cmd!=*csi->ip) {
-				csi->ip++;
-				skipto(csi,CS_END_CMD); }	 /* skip code */
-			csi->ip++;						/* skip key */
-			return(0);
-		case CS_NODE_ACTION:
-			action=*csi->ip++;
-			return(0);
-		case CS_NODE_STATUS:
-			getnodedat(node_num,&thisnode,1);
-			thisnode.status=*csi->ip++;
-            putnodedat(node_num,thisnode);
-			return(0);
-		case CS_GETSTR:
-			csi->logic=LOGIC_TRUE;
-			getstr(csi->str,*csi->ip++,0);
-			if(sys_status&SS_ABORT) {
-				csi->str[0]=0;
-				csi->logic=LOGIC_FALSE; }
-			if(csi->str[0]=='/' && csi->str[1])
-				csi->cmd=csi->str[1]|0x80;
-			else
-				csi->cmd=csi->str[0];
-            return(0);
-		case CS_GETLINE:
-			getstr(csi->str,*csi->ip++,K_LINE);
-			if(sys_status&SS_ABORT)
-				csi->str[0]=0;
-			if(csi->str[0]=='/' && csi->str[1])
-				csi->cmd=csi->str[1]|0x80;
-			else
-				csi->cmd=csi->str[0];
-            return(0);
-		case CS_GETSTRUPR:
-			getstr(csi->str,*csi->ip++,K_UPPER);
-			if(sys_status&SS_ABORT)
-                csi->str[0]=0;
-			if(csi->str[0]=='/' && csi->str[1])
-				csi->cmd=csi->str[1]|0x80;
-			else
-                csi->cmd=csi->str[0];
-			return(0);
-		case CS_GETNAME:
-			getstr(csi->str,*csi->ip++,K_UPRLWR);
-			if(sys_status&SS_ABORT)
-                csi->str[0]=0;
-			return(0);
-		case CS_SHIFT_STR:
-			if(strlen(csi->str)>=*csi->ip)
-				memmove(csi->str,csi->str+(*csi->ip)
-					,strlen(csi->str)+1);
-			csi->ip++;
-			return(0);
-		case CS_COMPARE_KEY:
-			if( ((*csi->ip)==CS_DIGIT && isdigit(csi->cmd))
-				|| ((*csi->ip)==CS_EDIGIT && csi->cmd&0x80
-				&& isdigit(csi->cmd&0x7f))) {
-				csi->ip++;
-				csi->logic=LOGIC_TRUE; }
-			else {
-				if(csi->cmd==*(csi->ip++))
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE; }
-			return(0);
-		case CS_SET_USER_LEVEL:
-			useron.level=*(csi->ip++);
-            putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10));
-			statusline();
-			return(0);
-		case CS_SET_USER_STRING:
-			csi->logic=LOGIC_FALSE;
-			if(!csi->str[0]) {
-				csi->ip++;
-				return(0); }
-			switch(*(csi->ip++)) {
-				case USER_STRING_ALIAS:
-					if(!isalpha(csi->str[0]) || trashcan(csi->str,"NAME"))
-						break;
-					i=matchuser(csi->str);
-					if(i && i!=useron.number)
-						break;
-					sprintf(useron.alias,"%.*s",LEN_ALIAS,csi->str);
-					putuserrec(useron.number,U_ALIAS,LEN_ALIAS,useron.alias);
-					putusername(useron.number,useron.alias);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_REALNAME:
-					if(trashcan(csi->str,"NAME"))
-						break;
-					if(uq&UQ_DUPREAL
-						&& userdatdupe(useron.number,U_NAME,LEN_NAME
-						,csi->str,0))
-						break;
-					sprintf(useron.name,"%.*s",LEN_NAME,csi->str);
-					putuserrec(useron.number,U_NAME,LEN_NAME
-						,useron.name);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_HANDLE:
-					if(trashcan(csi->str,"NAME"))
-						break;
-					if(uq&UQ_DUPHAND
-						&& userdatdupe(useron.number,U_HANDLE,LEN_HANDLE
-						,csi->str,0))
-						break;
-					sprintf(useron.handle,"%.*s",LEN_HANDLE,csi->str);
-					putuserrec(useron.number,U_HANDLE,LEN_HANDLE
-						,useron.handle);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_COMPUTER:
-					sprintf(useron.comp,"%.*s",LEN_COMP,csi->str);
-					putuserrec(useron.number,U_COMP,LEN_COMP
-						,useron.comp);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_NOTE:
-					sprintf(useron.note,"%.*s",LEN_NOTE,csi->str);
-					putuserrec(useron.number,U_NOTE,LEN_NOTE
-						,useron.note);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_ADDRESS:
-					sprintf(useron.address,"%.*s",LEN_ADDRESS,csi->str);
-					putuserrec(useron.number,U_ADDRESS,LEN_ADDRESS
-						,useron.address);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_LOCATION:
-					sprintf(useron.location,"%.*s",LEN_LOCATION,csi->str);
-					putuserrec(useron.number,U_LOCATION,LEN_LOCATION
-						,useron.location);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_ZIPCODE:
-					sprintf(useron.zipcode,"%.*s",LEN_ZIPCODE,csi->str);
-					putuserrec(useron.number,U_ZIPCODE,LEN_ZIPCODE
-						,useron.zipcode);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_PASSWORD:
-					sprintf(useron.pass,"%.*s",LEN_PASS,csi->str);
-					putuserrec(useron.number,U_PASS,LEN_PASS
-						,useron.pass);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_BIRTHDAY:
-					if(!getage(csi->str))
-						break;
-					sprintf(useron.birth,"%.*s",LEN_BIRTH,csi->str);
-					putuserrec(useron.number,U_BIRTH,LEN_BIRTH
-						,useron.birth);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_PHONE:
-					if(trashcan(csi->str,"PHONE"))
-						break;
-					sprintf(useron.phone,"%.*s",LEN_PHONE,csi->str);
-					putuserrec(useron.number,U_PHONE,LEN_PHONE
-						,useron.phone);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_MODEM:
-					sprintf(useron.modem,"%.*s",LEN_MODEM,csi->str);
-					putuserrec(useron.number,U_MODEM,LEN_MODEM
-						,useron.phone);
-					csi->logic=LOGIC_TRUE;
-					break;
-				case USER_STRING_COMMENT:
-					sprintf(useron.comment,"%.*s",LEN_COMMENT,csi->str);
-					putuserrec(useron.number,U_COMMENT,LEN_COMMENT
-						,useron.comment);
-					csi->logic=LOGIC_TRUE;
-					break;
-				default:
-					errormsg(WHERE,ERR_CHK,"user string type",*(csi->ip-1));
-					return(0); }
-			statusline();
-			return(0);
-		default:
-			errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-			return(0); } }
-
-
-/*********************************/
-/* Single Byte Instrcutions ONLY */
-/*********************************/
-
-switch(*(csi->ip++)) {
-	case CS_ONE_MORE_BYTE:				 /* Just one MORE byte */
-		switch(*(csi->ip++)) {
-			case CS_OFFLINE:
-				csi->misc|=CS_OFFLINE_EXEC;
-				return(0);
-			case CS_ONLINE:
-				csi->misc&=~CS_OFFLINE_EXEC;
-				return(0);
-			case CS_NEWUSER:
-				newuser();
-				return(0);
-			case CS_LOGON:
-				if(logon())
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case CS_LOGOUT:
-				logout();
-				return(0);
-			case CS_EXIT:
-				return(1);
-			default:
-				errormsg(WHERE,ERR_CHK,"one byte extended function"
-					,*(csi->ip-1));
-				return(0); }
-	case CS_CRLF:
-		CRLF;
-		return(0);
-	case CS_CLS:
-		CLS;
-		return(0);
-	case CS_PAUSE:
-		pause();
-		return(0);
-	case CS_PAUSE_RESET:
-		lncntr=0;
-		return(0);
-	case CS_GETLINES:
-		getlines();
-		return(0);
-	case CS_HANGUP:
-		hangup();
-		return(0);
-	case CS_LOGKEY:
-		logch(csi->cmd,0);
-		return(0);
-	case CS_LOGKEY_COMMA:
-		logch(csi->cmd,1);
-		return(0);
-	case CS_LOGSTR:
-		log(csi->str);
-		return(0);
-	case CS_CHKSYSPASS:
-		csi->logic=!chksyspass(0);
-		return(0);
-	case CS_PUT_NODE:
-		getnodedat(node_num,&thisnode,1);
-		putnodedat(node_num,thisnode);
-		return(0);
-	case CS_SYNC:
-		SYNC;
-		return(0);
-	case CS_ASYNC:
-		ASYNC;
-		return(0);
-	case CS_RIOSYNC:
-		RIOSYNC(0);
-		return(0);
-	case CS_GETTIMELEFT:
-		gettimeleft();
-		return(0);
-	case CS_RETURN:
-		if(!csi->rets)
-			return(1);
-		csi->ip=csi->ret[--csi->rets];
-		return(0);
-	case CS_GETKEY:
-		csi->cmd=getkey(K_UPPER);
-		return(0);
-	case CS_INKEY:
-		csi->cmd=toupper(inkey(K_GETSTR));
-		if(csi->cmd)
-			csi->logic=LOGIC_TRUE;
-		else
-			csi->logic=LOGIC_FALSE;
-        return(0);
-	case CS_GETKEYE:
-		csi->cmd=getkey(K_UPPER);
-		if(csi->cmd=='/') {
-			outchar('/');
-			csi->cmd=getkey(K_UPPER);
-			csi->cmd|=0x80; }
-		return(0);
-	case CS_GETFILESPEC:
-		if(getfilespec(csi->str))
-			csi->logic=LOGIC_TRUE;
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_SAVELINE:
-		SAVELINE;
-		return(0);
-	case CS_RESTORELINE:
-		RESTORELINE;
-		return(0);
-	case CS_SELECT_SHELL:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<total_shells;i++)
-			uselect(1,i,"Command Shell",shell[i]->name,shell[i]->ar);
-		if((i=uselect(0,useron.shell,0,0,0))>=0) {
-			useron.shell=i;
-			putuserrec(useron.number,U_SHELL,8,shell[i]->code); }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_SET_SHELL:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<total_shells;i++)
-			if(!stricmp(csi->str,shell[i]->code)
-				&& chk_ar(shell[i]->ar,useron))
-				break;
-		if(i<total_shells) {
-			useron.shell=i;
-			putuserrec(useron.number,U_SHELL,8,shell[i]->code); }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-
-	case CS_SELECT_EDITOR:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<total_xedits;i++)
-			uselect(1,i,"External Editor",xedit[i]->name,xedit[i]->ar);
-		if(useron.xedit) useron.xedit--;
-		if((i=uselect(0,useron.xedit,0,0,0))>=0) {
-			useron.xedit=i+1;
-			putuserrec(useron.number,U_XEDIT,8,xedit[i]->code); }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_SET_EDITOR:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<total_xedits;i++)
-			if(!stricmp(csi->str,xedit[i]->code)
-				&& chk_ar(xedit[i]->ar,useron))
-				break;
-		if(i<total_xedits) {
-			useron.xedit=i+1;
-			putuserrec(useron.number,U_XEDIT,8,xedit[i]->code); }
-		else
-			csi->logic=LOGIC_FALSE;
-        return(0);
-
-	case CS_CLEAR_ABORT:
-		sys_status&=~SS_ABORT;
-		return(0);
-	case CS_FINDUSER:
-		i=finduser(csi->str);
-		if(i) {
-			csi->logic=LOGIC_TRUE;
-			username(i,csi->str); }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_UNGETKEY:
-		ungetkey(csi->cmd&0x7f);
-		return(0);
-	case CS_UNGETSTR:
-		j=strlen(csi->str);
-		for(i=0;i<j;i++)
-			ungetkey(csi->str[i]);
-		return(0);
-	case CS_PRINTKEY:
-		if((csi->cmd&0x7f)>=SP)
-			outchar(csi->cmd&0x7f);
-		return(0);
-	case CS_PRINTSTR:
-		putmsg(csi->str,P_SAVEATR|P_NOABORT);
-		return(0);
-	case CS_CMD_HOME:
-		csi->cmdret[csi->cmdrets++]=(csi->ip-1);
-		return(0);
-	case CS_END_CMD:
-		if(csi->cmdrets)
-			csi->ip=csi->cmdret[--csi->cmdrets];
-/*													Removed 06/07/95
-		else
-			errormsg(WHERE,ERR_CHK,"misplaced end_cmd",(csi->ip-csi->cs)-1);
-*/
-		return(0);
-	case CS_CMD_POP:
-		if(csi->cmdrets)
-			csi->cmdrets--;
-		return(0);
-	case CS_IF_TRUE:
-		if(csi->logic!=LOGIC_TRUE) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-		return(0);
-	case CS_IF_GREATER:
-		if(csi->logic!=LOGIC_GREATER) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-		return(0);
-	case CS_IF_GREATER_OR_EQUAL:
-		if(csi->logic!=LOGIC_GREATER && csi->logic!=LOGIC_EQUAL) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-		return(0);
-	case CS_IF_LESS:
-		if(csi->logic!=LOGIC_LESS) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-		return(0);
-	case CS_IF_LESS_OR_EQUAL:
-		if(csi->logic!=LOGIC_LESS && csi->logic!=LOGIC_EQUAL) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-        return(0);
-	case CS_IF_FALSE:
-		if(csi->logic==LOGIC_TRUE) {
-			skipto(csi,CS_ELSEORENDIF);
-			csi->ip++; }
-		return(0);
-	case CS_ELSE:
-		skipto(csi,CS_ENDIF);
-		csi->ip++;
-		return(0);
-	case CS_END_CASE:
-		skipto(csi,CS_END_SWITCH);
-		csi->misc&=~CS_IN_SWITCH;
-		csi->ip++;
-		return(0);
-	case CS_DEFAULT:
-	case CS_END_SWITCH:
-		csi->misc&=~CS_IN_SWITCH;
-		return(0);
-	case CS_ENDIF:
-		return(0);
-	default:
-		errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-		return(0); }
-}
-
diff --git a/src/sbbs2/execdos/execdos.c b/src/sbbs2/execdos/execdos.c
deleted file mode 100644
index 30091ddcecd67da303d9ec65c375eaa3e33892e2..0000000000000000000000000000000000000000
--- a/src/sbbs2/execdos/execdos.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* EXECDOS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Execute DOS external BBS programs from OS/2 BBS */
-
-#include "sbbs.h"
-
-extern unsigned _heaplen=2048;
-
-extern uint riobp;
-
-ulong user_misc;
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	uint c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-void interrupt (*oldfunc)(void);
-
-/*****************************************************************************/
-/* Interrupt routine to expand WWIV Ctrl-C# codes into ANSI escape sequences */
-/*****************************************************************************/
-void interrupt wwiv_expand()
-{
-	char str[256],al;
-	static int ctrl_c;
-	int i,j;
-
-al=_AL;
-if(al!=3 && !ctrl_c)
-	oldfunc();
-else if(al!=3 && ctrl_c) {
-	ctrl_c=0;
-	if(user_misc&ANSI) {
-		switch(al) {
-			default:
-				strcpy(str,"\x1b[0m");          /* low grey */
-				break;
-			case '1':
-				strcpy(str,"\x1b[0;1;36m");     /* high cyan */
-				break;
-			case '2':
-				strcpy(str,"\x1b[0;1;33m");     /* high yellow */
-				break;
-			case '3':
-				strcpy(str,"\x1b[0;35m");       /* low magenta */
-				break;
-			case '4':
-				strcpy(str,"\x1b[0;1;44m");     /* white on blue */
-				break;
-			case '5':
-				strcpy(str,"\x1b[0;32m");       /* low green */
-				break;
-			case '6':
-				strcpy(str,"\x1b[0;1;5;31m");   /* high blinking red */
-				break;
-			case '7':
-				strcpy(str,"\x1b[0;1;34m");     /* high blue */
-				break;
-			case '8':
-				strcpy(str,"\x1b[0;34m");       /* low blue */
-				break;
-			case '9':
-				strcpy(str,"\x1b[0;36m");       /* low cyan */
-				break; }
-		j=strlen(str);
-		for(i=0;i<j;i++) {
-			_AL=str[i];
-			oldfunc(); } } }
-else
-	ctrl_c=1;
-}
-
-int main(int argc, char **argv)
-{
-	char str[256],commandline[128],sbbsnode[81],sbbsnnum[81],msr[31]="0"
-		,user_name[LEN_NAME+1]
-		,user_alias[LEN_ALIAS+1]
-		,user_phone[LEN_PHONE+1]
-		,user_location[LEN_LOCATION+1]
-		,user_age
-		,user_sex
-		,user_level
-		,node_scrnlen
-		,*envvar[30],*arg[30],c,d;
-	int i,file,base,com_base=0,com_irq,dte_rate,rmode,mode,node_num,col,row;
-	FILE *stream;
-
-if(argc<2) {
-	printf("This program is for the internal use of Synchronet.\r\n");
-	return(-1); }
-
-sprintf(sbbsnode,"SBBSNODE=%s",argv[1]);
-putenv(sbbsnode);
-sprintf(str,"%sEXECDOS.DAT",argv[1]);
-if((file=open(str,O_RDONLY|O_BINARY))!=-1) {
-	stream=fdopen(file,"rb");
-	str[0]=0;
-	fgets(str,128,stream);
-	truncsp(str);
-	if(strcmp(str,"V1.00")) {
-		printf("\7EXECDOS: SBBS VERSION MISMATCH!\7\r\n");
-		delay(5000);
-		return(-1); }
-	str[0]=0;
-	fgets(str,128,stream);
-	com_base=strtoul(str,0,16);
-	str[0]=0;
-	fgets(str,128,stream);
-	com_irq=atoi(str);
-	str[0]=0;
-	fgets(str,128,stream);
-	dte_rate=atoi(str);
-	str[0]=0;
-    fgets(str,128,stream);
-	rmode=strtoul(str,0,16);
-	str[0]=0;
-    fgets(str,128,stream);
-	mode=strtoul(str,0,16);
-	str[0]=0;
-    fgets(str,128,stream);
-	user_misc=strtoul(str,0,16);
-	str[0]=0;
-    fgets(str,128,stream);
-	node_num=atoi(str);
-	if(node_num) {
-		sprintf(sbbsnnum,"SBBSNNUM=%u",node_num);
-		putenv(sbbsnnum); }
-	fgets(commandline,128,stream);
-	truncsp(commandline);
-	str[0]=0;
-    fgets(str,128,stream);
-	i=atoi(str);	/* total env vars */
-	while(i--) {
-		str[0]=0;
-		fgets(str,128,stream);
-		truncsp(str);
-		if((envvar[i]=MALLOC(strlen(str)+1))!=NULL) {
-			strcpy(envvar[i],str);
-			putenv(envvar[i]); } }
-	str[0]=0;
-	fgets(str,128,stream);
-	truncsp(str);
-	sprintf(user_alias,"%.*s",LEN_ALIAS,str);
-	str[0]=0;
-	fgets(str,128,stream);
-	truncsp(str);
-	sprintf(user_name,"%.*s",LEN_NAME,str);
-	str[0]=0;
-	fgets(str,128,stream);
-	user_level=atoi(str);
-	str[0]=0;
-	fgets(str,128,stream);
-	user_age=atoi(str);
-	str[0]=0;
-	fgets(str,128,stream);
-	user_sex=str[0];
-	str[0]=0;
-	fgets(str,128,stream);
-	truncsp(str);
-	sprintf(user_phone,"%.*s",LEN_PHONE,str);
-	str[0]=0;
-	fgets(str,128,stream);
-	truncsp(str);
-	sprintf(user_location,"%.*s",LEN_LOCATION,str);
-	fclose(stream); }
-
-printf("\nEXECDOS: %s\n",commandline);
-
-if(rmode && com_base) { 	/* Capture the port and intercept I/O */
-	base=0xffff;
-	switch(com_base) {
-		case 0xb:
-			rioctl(I14PC);
-			break;
-		case 0xffff:
-		case 0xd:
-			rioctl(I14DB);
-			break;
-		case 0xe:
-			rioctl(I14PS);
-			break;
-		case 0xf:
-			rioctl(I14FO);
-			break;
-		default:
-			base=com_base;
-			break; }
-
-	if(rioini(base,com_irq)) {
-		printf("\7EXECDOS: Error initializing COM port (%x,%d)\7\r\n"
-			,base,com_irq);
-		return(-1); }
-	rioctl(IOSM|CTSCK|RTSCK|PAUSE|ABORT);
-	rioctl(CPTON);	/* Cvt ^p to ^^ */
-
-	sprintf(msr,"%lu",&riobp-1);
-
-	sprintf(str,"%sINTRSBBS.DAT",argv[1]);
-	if((stream=fopen(str,"wb"))!=NULL) {
-		fprintf(stream,"%lu\r\n",&riobp-1);
-		fclose(stream); } }
-
-setbaud(dte_rate);
-
-if(rmode) {
-	ivhctl(rmode);
-
-	if(mode&EX_WWIV) {	/* WWIV code expansion */
-		rioctl(CPTOFF); /* turn off ctrl-p translation */
-		oldfunc=getvect(0x29);
-		setvect(0x29,wwiv_expand); } }
-
-
-if(rmode&INT29L && user_alias[0]) {
-	node_scrnlen=lclini(0xd<<8);	  /* Tab expansion, no CRLF expansion */
-	lclini(node_scrnlen-1);
-	col=lclwx();
-	row=lclwy();
-	lclxy(1,node_scrnlen);
-	lclatr(CYAN|HIGH|(BLUE<<4));
-	lputs("  ");
-	sprintf(str,"%-25.25s %02d %-25.25s  %02d %c %s"
-		,user_alias,user_level,user_name[0] ? user_name : user_location
-		,user_age
-		,user_sex ? user_sex : SP
-		,user_phone);
-	lputs(str);
-	lputc(CLREOL);
-	lclatr(LIGHTGRAY);
-	lclxy(col,row); }
-
-/* separate args */
-
-arg[0]=commandline; /* point to the beginning of the string */
-for(c=0,d=1;commandline[c];c++)   /* Break up command line */
-	if(commandline[c]==SP) {
-		commandline[c]=0;		/* insert nulls */
-		if(!strncmp(commandline+c+1,"%& ",3))
-			arg[d++]=msr;
-		else					/* point to the beginning of the next arg */
-			arg[d++]=commandline+c+1; } 
-arg[d]=0;
-
-/* spawn it */
-
-i=spawnvp(P_WAIT,arg[0],arg);
-
-if(rmode) {
-	rioctl(TXSYNC|(3<<8));
-	rioctl(IOFB);
-	if(mode&EX_WWIV)
-		setvect(0x29,oldfunc);
-	ivhctl(0);			/* replace DOS output interrupt vectors */
-	if(com_base)
-		rioini(0,0); }	/* replace com port */
-
-//if(i) 			// debug
-//	  getch();
-return(i);
-}
diff --git a/src/sbbs2/execdos/make.bat b/src/sbbs2/execdos/make.bat
deleted file mode 100755
index fcacf7981669af69e33e6b7c639ee8aa5c72fa9b..0000000000000000000000000000000000000000
--- a/src/sbbs2/execdos/make.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-bcc -w-pro -I..;..\rio;..\smb -ml execdos.c ..\dos\rciol.obj
-if errorlevel 1 goto end
-rem exe2bin execdos.exe execdos.com
-:end
diff --git a/src/sbbs2/execfile.c b/src/sbbs2/execfile.c
deleted file mode 100644
index 966b7279a956cf5a0142446e9a48eb4b5a9a7e5e..0000000000000000000000000000000000000000
--- a/src/sbbs2/execfile.c
+++ /dev/null
@@ -1,481 +0,0 @@
-#line 1 "EXECFILE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-int execfile(csi_t *csi)
-{
-	uchar	str[256],tmp2[128],*path,ch,*p;
-	int 	i,j,k,s,file,x,y;
-	long	l;
-	stats_t stats;
-	node_t	node;
-	file_t	f;
-	time_t	t;
-    csi_t   bin;
-
-switch(*(csi->ip++)) {
-
-	case CS_FILE_SELECT_AREA:
-		csi->logic=LOGIC_FALSE;
-		if(!usrlibs) return(0);
-		while(online) {
-			j=0;
-			if(usrlibs>1) {
-				sprintf(str,"%sMENU\\LIBS.*",text_dir);
-				if(fexist(str))
-					menu("LIBS");
-				else {
-					bputs(text[CfgLibLstHdr]);
-					for(i=0;i<usrlibs && !msgabort();i++) {
-						if(i==curlib)
-							outchar('*');
-						else outchar(SP);
-						if(i<9) outchar(SP);
-						if(i<99) outchar(SP);
-						bprintf(text[CfgLibLstFmt]
-							,i+1,lib[usrlib[i]]->lname); } }
-				sprintf(str,text[JoinWhichLib],curlib+1);
-				mnemonics(str);
-				j=getnum(usrlibs);
-				if((int)j==-1)
-					return(0);
-				if(!j)
-					j=curlib;
-				else
-					j--; }
-			sprintf(str,"%sMENU\\DIRS%u.*",text_dir,usrlib[j]+1);
-			if(fexist(str)) {
-				sprintf(str,"DIRS%u",usrlib[j]+1);
-				menu(str); }
-			else {
-				CLS;
-				bprintf(text[DirLstHdr],lib[usrlib[j]]->lname);
-				for(i=0;i<usrdirs[j] && !msgabort();i++) {
-					if(i==curdir[j]) outchar('*');
-					else outchar(SP);
-					sprintf(str,text[DirLstFmt],i+1
-						,dir[usrdir[j][i]]->lname,nulstr
-						,getfiles(usrdir[j][i]));
-					if(i<9) outchar(SP);
-					if(i<99) outchar(SP);
-					bputs(str); } }
-			sprintf(str,text[JoinWhichDir],curdir[j]+1);
-			mnemonics(str);
-			i=getnum(usrdirs[j]);
-			if((int)i==-1) {
-				if(usrlibs==1)
-					return(0);
-				continue; }
-			if(!i)
-				i=curdir[j];
-			else
-				i--;
-			curlib=j;
-			curdir[curlib]=i;
-			csi->logic=LOGIC_TRUE;
-			return(0); }
-		return(0);
-
-	case CS_FILE_GET_DIR_NUM:
-
-		if(useron.misc&COLDKEYS) {
-			i=atoi(csi->str);
-			if(i && i<=usrdirs[curlib] && usrlibs)
-				curdir[curlib]=i-1;
-			return(0); }
-
-		ch=getkey(K_UPPER);
-		outchar(ch);
-		if((ch&0xf)*10<=usrdirs[curlib] && (ch&0xf) && usrlibs) {
-			i=(ch&0xf)*10;
-			ch=getkey(K_UPPER);
-			if(!isdigit(ch) && ch!=CR) {
-				ungetkey(ch);
-				curdir[curlib]=(i/10)-1;
-				return(0); }
-			outchar(ch);
-			if(ch==CR) {
-				curdir[curlib]=(i/10)-1;
-				return(0); }
-			logch(ch,0);
-			i+=ch&0xf;
-			if(i*10<=usrdirs[curlib]) { 	/* 100+ dirs */
-				i*=10;
-				ch=getkey(K_UPPER);
-				if(!isdigit(ch) && ch!=CR) {
-					ungetkey(ch);
-					curdir[curlib]=(i/10)-1;
-					return(0); }
-				outchar(ch);
-				if(ch==CR) {
-					curdir[curlib]=(i/10)-1;
-					return(0); }
-				logch(ch,0);
-				i+=ch&0xf; }
-			if(i<=usrdirs[curlib])
-				curdir[curlib]=i-1;
-			return(0); }
-		if((ch&0xf)<=usrdirs[curlib] && (ch&0xf) && usrlibs)
-			curdir[curlib]=(ch&0xf)-1;
-		return(0);
-
-	case CS_FILE_GET_LIB_NUM:
-
-		if(useron.misc&COLDKEYS) {
-			i=atoi(csi->str);
-			if(i && i<=usrlibs)
-				curlib=i-1;
-			return(0); }
-
-		ch=getkey(K_UPPER);
-		outchar(ch);
-		if((ch&0xf)*10<=usrlibs && (ch&0xf)) {
-			i=(ch&0xf)*10;
-			ch=getkey(K_UPPER);
-			if(!isdigit(ch) && ch!=CR) {
-				ungetkey(ch);
-				curlib=(i/10)-1;
-				return(0); }
-			outchar(ch);
-			if(ch==CR) {
-				curlib=(i/10)-1;
-				return(0); }
-			logch(ch,0);
-			i+=ch&0xf;
-			if(i<=usrlibs)
-				curlib=i-1;
-			return(0); }
-		if((ch&0xf)<=usrlibs && (ch&0xf))
-			curlib=(ch&0xf)-1;
-		return(0);
-
-	case CS_FILE_SHOW_LIBRARIES:
-		if(!usrlibs) return(0);
-		sprintf(str,"%sMENU\\LIBS.*",text_dir);
-		if(fexist(str)) {
-			menu("LIBS");
-			return(0); }
-		bputs(text[LibLstHdr]);
-		for(i=0;i<usrlibs && !msgabort();i++) {
-			if(i==curlib)
-				outchar('*');
-			else outchar(SP);
-			if(i<9) outchar(SP);
-			bprintf(text[LibLstFmt],i+1
-				,lib[usrlib[i]]->lname,nulstr,usrdirs[i]); }
-		return(0);
-
-	case CS_FILE_SHOW_DIRECTORIES:
-		if(!usrlibs) return(0);
-		sprintf(str,"%sMENU\\DIRS%u.*",text_dir,usrlib[curlib]+1);
-		if(fexist(str)) {
-			sprintf(str,"DIRS%u",usrlib[curlib]+1);
-			menu(str);
-			return(0); }
-		CRLF;
-		bprintf(text[DirLstHdr],lib[usrlib[curlib]]->lname);
-		for(i=0;i<usrdirs[curlib] && !msgabort();i++) {
-			if(i==curdir[curlib]) outchar('*');
-			else outchar(SP);
-			sprintf(str,text[DirLstFmt],i+1
-				,dir[usrdir[curlib][i]]->lname,nulstr
-				,getfiles(usrdir[curlib][i]));
-			if(i<9) outchar(SP);
-			if(i<99) outchar(SP);
-			bputs(str); }
-		return(0);
-
-	case CS_FILE_LIBRARY_UP:
-		curlib++;
-		if(curlib>=usrlibs)
-			curlib=0;
-		return(0);
-	case CS_FILE_LIBRARY_DOWN:
-		if(!curlib)
-			curlib=usrlibs-1;
-		else curlib--;
-		return(0);
-	case CS_FILE_DIRECTORY_UP:
-		if(!usrlibs) return(0);
-		curdir[curlib]++;
-		if(curdir[curlib]>=usrdirs[curlib])
-			curdir[curlib]=0;
-		return(0);
-	case CS_FILE_DIRECTORY_DOWN:
-		if(!usrlibs) return(0);
-		if(!curdir[curlib])
-			curdir[curlib]=usrdirs[curlib]-1;
-		else curdir[curlib]--;
-		return(0);
-	case CS_FILE_SET_AREA:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<usrlibs;i++)
-			for(j=0;j<usrdirs[i];j++)
-				if(!stricmp(csi->str,dir[usrdir[i][j]]->code)) {
-					curlib=i;
-					curdir[i]=j;
-					return(0); }
-		csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_FILE_SET_LIBRARY:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<usrlibs;i++)
-			if(!stricmp(lib[usrlib[i]]->sname,csi->str))
-				break;
-		if(i<usrlibs)
-			curlib=i;
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-
-	case CS_FILE_UPLOAD:
-		csi->logic=LOGIC_FALSE;
-		if(useron.rest&FLAG('U')) {
-			bputs(text[R_Upload]);
-			return(0); }
-		if(usrlibs) {
-			i=usrdir[curlib][curdir[curlib]];
-			if(upload_dir!=INVALID_DIR
-				&& !chk_ar(dir[i]->ul_ar,useron))
-				i=upload_dir; }
-		else
-			i=upload_dir;
-
-		if((uint)i==INVALID_DIR || !chk_ar(dir[i]->ul_ar,useron)) {
-			bputs(text[CantUploadHere]);
-			return(0); }
-
-		if(gettotalfiles(i)>=dir[i]->maxfiles)
-			bputs(text[DirFull]);
-		else {
-			upload(i);
-			csi->logic=LOGIC_TRUE; }
-		return(0);
-	case CS_FILE_UPLOAD_USER:
-		csi->logic=LOGIC_FALSE;
-		if(user_dir==INVALID_DIR) {
-			bputs(text[NoUserDir]);
-			return(0); }
-		if(gettotalfiles(user_dir)>=dir[user_dir]->maxfiles)
-			bputs(text[UserDirFull]);
-		else if(useron.rest&FLAG('U'))
-			bputs(text[R_Upload]);
-		else if(!chk_ar(dir[user_dir]->ul_ar,useron))
-			bputs(text[CantUploadToUser]);
-		else {
-			upload(user_dir);
-			csi->logic=LOGIC_TRUE; }
-		return(0);
-	case CS_FILE_UPLOAD_SYSOP:
-		csi->logic=LOGIC_FALSE;
-		if(sysop_dir==INVALID_DIR) {
-			bputs(text[NoSysopDir]);
-			return(0); }
-		if(gettotalfiles(sysop_dir)>=dir[sysop_dir]->maxfiles)
-			bputs(text[DirFull]);
-		else if(useron.rest&FLAG('U'))
-			bputs(text[R_Upload]);
-		else if(!chk_ar(dir[sysop_dir]->ul_ar,useron))
-			bputs(text[CantUploadToSysop]);
-		else {
-			upload(sysop_dir);
-			csi->logic=LOGIC_TRUE; }
-		return(0);
-	case CS_FILE_DOWNLOAD:
-		if(!usrlibs) return(0);
-		if(useron.rest&FLAG('D')) {
-			bputs(text[R_Download]);
-			return(0); }
-		padfname(csi->str,str);
-		strupr(str);
-		if(!listfileinfo(usrdir[curlib][curdir[curlib]],str,FI_DOWNLOAD)) {
-			bputs(text[SearchingAllDirs]);
-			for(i=0;i<usrdirs[curlib];i++)
-				if(i!=curdir[curlib] &&
-					(s=listfileinfo(usrdir[curlib][i],str,FI_DOWNLOAD))!=0)
-					if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-						return(0);
-			bputs(text[SearchingAllLibs]);
-			for(i=0;i<usrlibs;i++) {
-				if(i==curlib) continue;
-				for(j=0;j<usrdirs[i];j++)
-					if((s=listfileinfo(usrdir[i][j],str,FI_DOWNLOAD))!=0)
-						if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-							return(0); } }
-		return(0);
-	case CS_FILE_DOWNLOAD_USER: /* Download from user dir */
-		csi->logic=LOGIC_FALSE;
-		if(user_dir==INVALID_DIR) {
-			bputs(text[NoUserDir]);
-			return(0); }
-		if(useron.rest&FLAG('D')) {
-			bputs(text[R_Download]);
-			return(0); }
-		CRLF;
-		if(!listfileinfo(user_dir,nulstr,FI_USERXFER))
-			bputs(text[NoFilesForYou]);
-		else
-			csi->logic=LOGIC_TRUE;
-		return(0);
-	case CS_FILE_DOWNLOAD_BATCH:
-		if(batdn_total && yesno(text[DownloadBatchQ])) {
-			start_batch_download();
-			csi->logic=LOGIC_TRUE; }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_FILE_BATCH_ADD_LIST:
-		batch_add_list(csi->str);
-		return(0);
-	case CS_FILE_BATCH_ADD:
-		csi->logic=LOGIC_FALSE;
-		if(!csi->str[0])
-			return(0);
-		padfname(csi->str,f.name);
-		strupr(f.name);
-		for(x=0;x<usrlibs;x++) {
-			for(y=0;y<usrdirs[x];y++)
-				if(findfile(usrdir[x][y],f.name))
-					break;
-			if(y<usrdirs[x])
-				break; }
-		if(x>=usrlibs)
-			return(0);
-		f.dir=usrdir[x][y];
-		getfileixb(&f);
-		f.size=0;
-		getfiledat(&f);
-		addtobatdl(f);
-		csi->logic=LOGIC_TRUE;
-		return(0);
-	case CS_FILE_BATCH_CLEAR:
-		if(!batdn_total) {
-			csi->logic=LOGIC_FALSE;
-			return(0); }
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<batdn_total;i++) {
-			f.dir=batdn_dir[i];
-			f.datoffset=batdn_offset[i];
-			f.size=batdn_size[i];
-			strcpy(f.name,batdn_name[i]);
-			closefile(f); }
-		batdn_total=0;
-		return(0);
-
-	case CS_FILE_VIEW:
-		if(!usrlibs) return(0);
-		padfname(csi->str,str);
-		strupr(str);
-		csi->logic=LOGIC_TRUE;
-		if(listfiles(usrdir[curlib][curdir[curlib]],str,0,FL_VIEW))
-			return(0);
-		bputs(text[SearchingAllDirs]);
-		for(i=0;i<usrdirs[curlib];i++) {
-			if(i==curdir[curlib]) continue;
-			if(listfiles(usrdir[curlib][i],str,0,FL_VIEW))
-				break; }
-		if(i<usrdirs[curlib])
-			return(0);
-		bputs(text[SearchingAllLibs]);
-		for(i=0;i<usrlibs;i++) {
-			if(i==curlib) continue;
-			for(j=0;j<usrdirs[i];j++)
-				if(listfiles(usrdir[i][j],str,0,FL_VIEW))
-					return(0); }
-		csi->logic=LOGIC_FALSE;
-		bputs(text[FileNotFound]);
-		return(0);
-	case CS_FILE_LIST:	  /* List files in current dir */
-		if(!usrlibs) return(0);
-		csi->logic=LOGIC_FALSE;
-		if(!getfiles(usrdir[curlib][curdir[curlib]])) {
-			bputs(text[EmptyDir]);
-			return(0); }
-		padfname(csi->str,str);
-		strupr(str);
-		s=listfiles(usrdir[curlib][curdir[curlib]],str,0,0);
-		if(s>1) {
-			bprintf(text[NFilesListed],s); }
-		csi->logic=!s;
-		return(0);
-	case CS_FILE_LIST_EXTENDED: /* Extended Information on files */
-		if(!usrlibs) return(0);
-		padfname(csi->str,str);
-		strupr(str);
-		if(!listfileinfo(usrdir[curlib][curdir[curlib]],str,FI_INFO)) {
-			bputs(text[SearchingAllDirs]);
-			for(i=0;i<usrdirs[curlib];i++)
-				if(i!=curdir[curlib] && (s=listfileinfo(usrdir[curlib][i]
-					,str,FI_INFO))!=0)
-					if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-						return(0);
-			bputs(text[SearchingAllLibs]);
-			for(i=0;i<usrlibs;i++) {
-				if(i==curlib) continue;
-				for(j=0;j<usrdirs[i];j++)
-					if((s=listfileinfo(usrdir[i][j],str,FI_INFO))!=0)
-						if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-							return(0); } }
-		return(0);
-	case CS_FILE_FIND_TEXT: 	/* Find text in descriptions */
-		scandirs(FL_FINDDESC);
-		return(0);
-	case CS_FILE_FIND_TEXT_ALL: 	/* Find text in descriptions */
-		scanalldirs(FL_FINDDESC);
-		return(0);
-	case CS_FILE_FIND_NAME: 	/* Find text in descriptions */
-		scandirs(FL_NO_HDR);
-		return(0);
-	case CS_FILE_FIND_NAME_ALL: 	/* Find text in descriptions */
-		scanalldirs(FL_NO_HDR);
-		return(0);
-	case CS_FILE_BATCH_SECTION:
-		batchmenu();
-		return(0);
-	case CS_FILE_TEMP_SECTION:
-		temp_xfer();
-		return(0);
-	case CS_FILE_PTRS_CFG:
-		csi->logic=!inputnstime(&ns_time);
-		return(0);
-	case CS_FILE_NEW_SCAN:
-		scandirs(FL_ULTIME);
-		return(0);
-	case CS_FILE_NEW_SCAN_ALL:
-		scanalldirs(FL_ULTIME);
-		return(0);
-	case CS_FILE_REMOVE:
-		if(!usrlibs) return(0);
-		if(useron.rest&FLAG('R')) {
-			bputs(text[R_RemoveFiles]);
-			return(0); }
-		padfname(csi->str,str);
-		strupr(str);
-		if(!listfileinfo(usrdir[curlib][curdir[curlib]],str,FI_REMOVE)) {
-			if(user_dir!=INVALID_DIR
-				&& user_dir!=usrdir[curlib][curdir[curlib]])
-				if((s=listfileinfo(user_dir,str,FI_REMOVE))!=0)
-					if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-						return(0);
-			bputs(text[SearchingAllDirs]);
-			for(i=0;i<usrdirs[curlib];i++)
-				if(i!=curdir[curlib] && i!=user_dir
-					&& (s=listfileinfo(usrdir[curlib][i],str,FI_REMOVE))!=0)
-					if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-						return(0);
-			bputs(text[SearchingAllLibs]);
-			for(i=0;i<usrlibs;i++) {
-				if(i==curlib || i==user_dir) continue;
-				for(j=0;j<usrdirs[i]; j++)
-					if((s=listfileinfo(usrdir[i][j],str,FI_REMOVE))!=0)
-						if(s==-1 || (!strchr(str,'?') && !strchr(str,'*')))
-							return(0); } }
-		return(0);
- }
-
-errormsg(WHERE,ERR_CHK,"shell function",*(csi->ip-1));
-return(0);
-}
diff --git a/src/sbbs2/execfunc.c b/src/sbbs2/execfunc.c
deleted file mode 100644
index e84805da10305acbea7b915c9c24e236f9a6984e..0000000000000000000000000000000000000000
--- a/src/sbbs2/execfunc.c
+++ /dev/null
@@ -1,665 +0,0 @@
-#line 1 "EXECFUNC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-int exec_function(csi_t *csi)
-{
-	uchar	str[256],tmp2[128],ch,*p;
-	int 	i,j,k,s,file;
-	long	l;
-	stats_t stats;
-	node_t	node;
-	file_t	f;
-	time_t	t;
-
-switch(*(csi->ip++)) {
-
-
-	case CS_PRINTFILE_STR:
-		printfile(csi->str,P_NOATCODES);
-		return(0);
-
-/********************************/
-/* General Main Menu Type Stuff */
-/********************************/
-	case CS_AUTO_MESSAGE:
-		automsg();
-		return(0);
-	case CS_MINUTE_BANK:
-		if(sys_misc&SM_TIMEBANK) {	/* Allow users to deposit free time */
-			s=(level_timeperday[useron.level]-useron.ttoday)+useron.textra;
-			if(s<0) s=0;
-			if(s>level_timepercall[useron.level])
-				s=level_timepercall[useron.level];
-			s-=(now-starttime)/60;
-			if(s<0) s=0;
-			bprintf(text[FreeMinLeft],s);
-			bprintf(text[UserMinutes],ultoac(useron.min,tmp));
-			if(max_minutes && useron.min>=max_minutes) {
-				bputs(text[YouHaveTooManyMinutes]);
-				return(0); }
-			if(max_minutes)
-				while(s>0 && s+useron.min>max_minutes) s--;
-			bprintf(text[FreeMinToDeposit],s);
-			s=getnum(s);
-			if(s>0) {
-				logline("  ","Minute Bank Deposit");
-				useron.min=adjustuserrec(useron.number,U_MIN,10,s);
-				useron.ttoday=adjustuserrec(useron.number,U_TTODAY,10,s);
-				sprintf(str,"Minute Adjustment: %u",s*cdt_min_value);
-				logline("*+",str); } }
-
-		if(!(sys_misc&SM_NOCDTCVT)) {
-			bprintf(text[ConversionRate],cdt_min_value);
-			bprintf(text[UserCredits]
-				,ultoac(useron.cdt,tmp)
-				,ultoac(useron.freecdt,tmp2)
-				,ultoac(level_freecdtperday[useron.level],str));
-			bprintf(text[UserMinutes],ultoac(useron.min,tmp));
-			if(useron.cdt/102400L<1L) {
-				bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt,tmp));
-				return(0); }
-			if(max_minutes && useron.min>=max_minutes) {
-				bputs(text[YouHaveTooManyMinutes]);
-				return(0); }
-			s=useron.cdt/102400L;
-			if(max_minutes)
-				while(s>0 && (s*cdt_min_value)+useron.min>max_minutes) s--;
-			bprintf(text[CreditsToMin],s);
-			s=getnum(s);
-			if(s>0) {
-				logline("  ","Credit to Minute Conversion");
-				useron.cdt=adjustuserrec(useron.number,U_CDT,10,-(s*102400L));
-				useron.min=adjustuserrec(useron.number,U_MIN,10,s*cdt_min_value);
-				sprintf(str,"Credit Adjustment: %ld",-(s*102400L));
-				logline("$-",str);
-				sprintf(str,"Minute Adjustment: %u",s*cdt_min_value);
-				logline("*+",str); } }
-		return(0);
-	case CS_CHAT_SECTION:
-		if(useron.rest&FLAG('C'))
-			bputs(text[R_Chat]);
-		else
-			chatsection();
-		return(0);
-	case CS_USER_DEFAULTS:
-		maindflts(useron);
-		if(!(useron.rest&FLAG('G')))    /* not guest */
-			getuserdat(&useron);
-		return(0);
-	case CS_TEXT_FILE_SECTION:
-		text_sec();
-		return(0);
-	case CS_INFO_SYSTEM:   /* System information */
-		bputs(text[SiHdr]);
-		getstats(0,&stats);
-		bprintf(text[SiSysName],sys_name);
-		bprintf(text[SiSysID],sys_id);	/* QWK ID */
-		for(i=0;i<total_faddrs;i++)
-			bprintf(text[SiSysFaddr],faddrtoa(faddr[i]));
-		if(sys_psname[0])				/* PostLink/PCRelay */
-			bprintf(text[SiSysPsite],sys_psname,sys_psnum);
-		bprintf(text[SiSysLocation],sys_location);
-		bprintf(text[SiSysop],sys_op);
-		bprintf(text[SiSysNodes],sys_nodes);
-		bprintf(text[SiNodeNumberName],node_num,node_name);
-		bprintf(text[SiNodePhone],node_phone);
-		bprintf(text[SiTotalLogons],ultoac(stats.logons,tmp));
-		bprintf(text[SiLogonsToday],ultoac(stats.ltoday,tmp));
-		bprintf(text[SiTotalTime],ultoac(stats.timeon,tmp));
-		bprintf(text[SiTimeToday],ultoac(stats.ttoday,tmp));
-		ver();
-		if(yesno(text[ViewSysInfoFileQ])) {
-			CLS;
-			sprintf(str,"%sSYSTEM.MSG",text_dir);
-			printfile(str,0); }
-		if(yesno(text[ViewLogonMsgQ])) {
-			CLS;
-			menu("LOGON"); }
-		return(0);
-	case CS_INFO_SUBBOARD:	 /* Sub-board information */
-		if(!usrgrps) return(0);
-		subinfo(usrsub[curgrp][cursub[curgrp]]);
-		return(0);
-	case CS_INFO_DIRECTORY:   /* Sub-board information */
-		if(!usrlibs) return(0);
-		dirinfo(usrdir[curlib][curdir[curlib]]);
-		return(0);
-	case CS_INFO_VERSION:	/* Version */
-		ver();
-		return(0);
-	case CS_INFO_USER:	 /* User's statistics */
-		bprintf(text[UserStats],useron.alias,useron.number);
-		unixtodos(useron.laston,&date,&curtime);
-		bprintf(text[UserDates]
-			,unixtodstr(useron.firston,str)
-			,unixtodstr(useron.expire,tmp)
-			,unixtodstr(useron.laston,tmp2)
-			,curtime.ti_hour,curtime.ti_min);
-		bprintf(text[UserTimes]
-			,useron.timeon,useron.ttoday
-			,level_timeperday[useron.level]
-			,useron.tlast
-			,level_timepercall[useron.level]
-			,useron.textra);
-		bprintf(text[UserLogons]
-			,useron.logons,useron.ltoday
-			,level_callsperday[useron.level],useron.posts
-			,i ? 100/i : useron.posts>useron.logons ? 100 : 0
-			,useron.ptoday);
-		bprintf(text[UserEmails]
-			,useron.emails,useron.fbacks
-			,getmail(useron.number,0),useron.etoday);
-		CRLF;
-		bprintf(text[UserUploads]
-			,ultoac(useron.ulb,tmp),useron.uls);
-		bprintf(text[UserDownloads]
-			,ultoac(useron.dlb,tmp),useron.dls,nulstr);
-		bprintf(text[UserCredits],ultoac(useron.cdt,tmp)
-			,ultoac(useron.freecdt,tmp2)
-			,ultoac(level_freecdtperday[useron.level],str));
-		bprintf(text[UserMinutes],ultoac(useron.min,tmp));
-		return(0);
-	case CS_INFO_XFER_POLICY:
-		if(!usrlibs) return(0);
-		sprintf(str,"%sMENU\\TPOLICY.*",text_dir);
-		if(fexist(str))
-			menu("TPOLICY");
-		else {
-			bprintf(text[TransferPolicyHdr],sys_name);
-			bprintf(text[TpUpload]
-				,dir[usrdir[curlib][curdir[curlib]]]->up_pct);
-			bprintf(text[TpDownload]
-				,dir[usrdir[curlib][curdir[curlib]]]->dn_pct);
-			}
-		return(0);
-	case CS_XTRN_EXEC:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<total_xtrns;i++)
-			if(!stricmp(xtrn[i]->code,csi->str))
-				break;
-		if(i<total_xtrns)
-			exec_xtrn(i);
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_XTRN_SECTION:
-		if(useron.rest&FLAG('X'))
-			bputs(text[R_ExternalPrograms]);
-		else
-			xtrn_sec(); 	/* If external available, don't pause */
-		return(0);
-	case CS_LOGOFF:
-		if(!noyes(text[LogOffQ])) {
-			if(logoff_mod[0])
-				exec_bin(logoff_mod,csi);
-			user_event(EVENT_LOGOFF);
-			menu("LOGOFF");
-			SYNC;
-			hangup(); }
-		return(0);
-	case CS_LOGOFF_FAST:
-		SYNC;
-		if(online==ON_REMOTE && !(mdm_misc&MDM_NODTR))
-			dtr(0);
-		hangup();
-		return(0);
-	case CS_NODELIST_ALL:
-		CRLF;
-		bputs(text[NodeLstHdr]);
-		for(i=1;i<=sys_nodes && i<=sys_lastnode;i++) {
-			getnodedat(i,&node,0);
-			printnodedat(i,node); }
-		return(0);
-	case CS_NODELIST_USERS:
-		whos_online(1);
-		return(0);
-	case CS_USERLIST_SUB:
-		userlist(UL_SUB);
-		return(0);
-	case CS_USERLIST_DIR:
-		userlist(UL_DIR);
-		return(0);
-	case CS_USERLIST_ALL:
-		userlist(UL_ALL);
-		return(0);
-	case CS_USERLIST_LOGONS:
-		sprintf(str,"%sLOGON.LST",data_dir);
-		if(flength(str)<1) {
-			bputs("\r\n\r\n");
-			bputs(text[NoOneHasLoggedOnToday]); }
-		else {
-			bputs(text[CallersToday]);
-			printfile(str,P_NOATCODES|P_OPENCLOSE);
-			CRLF; }
-		return(0);
-	case CS_PAGE_SYSOP:
-		ch=kbd_state(); 	 /* Check scroll lock */
-		if(ch&16 || (sys_chat_ar[0] && chk_ar(sys_chat_ar,useron))
-			|| useron.exempt&FLAG('C')) {
-			sysop_page();
-			return(0); }
-		bprintf(text[SysopIsNotAvailable],sys_op);
-		return(0);
-	case CS_PAGE_GURU:
-		csi->logic=LOGIC_FALSE;
-		for(i=0;i<total_gurus;i++)
-			if(!stricmp(csi->str,guru[i]->code)
-				&& chk_ar(guru[i]->ar,useron))
-				break;
-		if(i>=total_gurus)
-			return(0);
-        sprintf(str,"%s%s.DAT",ctrl_dir,guru[i]->code);
-		if((file=nopen(str,O_RDONLY))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-			return(0); }
-		if((p=MALLOC(filelength(file)+1))==NULL) {
-			close(file);
-			errormsg(WHERE,ERR_ALLOC,str,filelength(file)+1);
-			return(0); }
-		read(file,p,filelength(file));
-		p[filelength(file)]=0;
-		close(file);
-		localguru(p,i);
-		FREE(p);
-		csi->logic=LOGIC_TRUE;
-		return(0);
-	case CS_PRIVATE_CHAT:
-		privchat();
-		return(0);
-	case CS_PRIVATE_MESSAGE:
-		nodemsg();
-		return(0);
-
-/*******************/
-/* Sysop Functions */
-/*******************/
-	case CS_USER_EDIT:
-		useredit(csi->str[0] ? finduser(csi->str) : 0,0);
-		return(0);
-
-
-/******************/
-/* Mail Functions */
-/******************/
-
-	case CS_MAIL_READ:	 /* Read E-mail */
-		readmail(useron.number,MAIL_YOUR);
-		return(0);
-	case CS_MAIL_READ_SENT: 	  /* Kill/read sent mail */
-		if(useron.rest&FLAG('K'))
-			bputs(text[R_ReadSentMail]);
-		else
-			readmail(useron.number,MAIL_SENT);
-		return(0);
-	case CS_MAIL_READ_ALL:
-		readmail(useron.number,MAIL_ALL);
-		return(0);
-	case CS_MAIL_SEND:		 /* Send E-mail */
-		if(strchr(csi->str,'@')) {
-			i=1;
-			netmail(csi->str,nulstr,0); }
-		else if((i=finduser(csi->str))!=0)
-			email(i,nulstr,nulstr,WM_EMAIL);
-		csi->logic=!i;
-		return(0);
-	case CS_MAIL_SEND_FEEDBACK: 	  /* Feedback */
-		if((i=finduser(csi->str))!=0)
-			email(i,text[ReFeedback],nulstr,WM_EMAIL);
-		csi->logic=!i;
-		return(0);
-	case CS_MAIL_SEND_NETMAIL:
-		bputs(text[EnterNetMailAddress]);
-		if(getstr(str,60,K_LINE)) {
-			netmail(str,nulstr,0);
-			csi->logic=LOGIC_TRUE; }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-
-	case CS_MAIL_SEND_NETFILE:
-		bputs(text[EnterNetMailAddress]);
-		if(getstr(str,60,K_LINE)) {
-			netmail(str,nulstr,WM_FILE);
-			csi->logic=LOGIC_TRUE; }
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-
-	case CS_MAIL_SEND_FILE:   /* Upload Attached File to E-mail */
-		if(strchr(csi->str,'@')) {
-			i=1;
-			netmail(csi->str,nulstr,WM_FILE); }
-		else if((i=finduser(csi->str))!=0)
-			email(i,nulstr,nulstr,WM_EMAIL|WM_FILE);
-		csi->logic=!i;
-		return(0);
-	case CS_MAIL_SEND_BULK:
-		if(csi->str[0])
-			p=arstr(0,csi->str);
-		else
-			p=nulstr;
-		bulkmail(p);
-		if(p && p[0])
-			FREE(p);
-		return(0);
-
-    case CS_INC_MAIN_CMDS:
-        main_cmds++;
-        return(0);
-
-    case CS_INC_FILE_CMDS:
-        xfer_cmds++;
-        return(0);
-
-    case CS_SYSTEM_LOG:                 /* System log */
-		if(!chksyspass(0))
-            return(0);
-        unixtodos(now,&date,&curtime);
-        sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG",data_dir
-            ,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900));
-        printfile(str,0);
-        return(0);
-    case CS_SYSTEM_YLOG:                /* Yesterday's log */
-		if(!chksyspass(0))
-            return(0);
-        now-=(ulong)60L*24L*60L;
-        unixtodos(now,&date,&curtime);
-        sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG",data_dir
-            ,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900));
-        printfile(str,0);
-        return(0);
-    case CS_SYSTEM_STATS:               /* System Statistics */
-        bputs(text[SystemStatsHdr]);
-        getstats(0,&stats);
-        bprintf(text[StatsTotalLogons],ultoac(stats.logons,tmp));
-        bprintf(text[StatsLogonsToday],ultoac(stats.ltoday,tmp));
-        bprintf(text[StatsTotalTime],ultoac(stats.timeon,tmp));
-        bprintf(text[StatsTimeToday],ultoac(stats.ttoday,tmp));
-        bprintf(text[StatsUploadsToday],ultoac(stats.ulb,tmp)
-            ,stats.uls);
-        bprintf(text[StatsDownloadsToday],ultoac(stats.dlb,tmp)
-            ,stats.dls);
-        bprintf(text[StatsPostsToday],ultoac(stats.ptoday,tmp));
-        bprintf(text[StatsEmailsToday],ultoac(stats.etoday,tmp));
-        bprintf(text[StatsFeedbacksToday],ultoac(stats.ftoday,tmp));
-        return(0);
-    case CS_NODE_STATS:              /* Node Statistics */
-        i=atoi(csi->str);
-        if(i>sys_nodes) {
-            bputs(text[InvalidNode]);
-            return(0); }
-        if(!i) i=node_num;
-        bprintf(text[NodeStatsHdr],i);
-        getstats(i,&stats);
-        bprintf(text[StatsTotalLogons],ultoac(stats.logons,tmp));
-        bprintf(text[StatsLogonsToday],ultoac(stats.ltoday,tmp));
-        bprintf(text[StatsTotalTime],ultoac(stats.timeon,tmp));
-        bprintf(text[StatsTimeToday],ultoac(stats.ttoday,tmp));
-        bprintf(text[StatsUploadsToday],ultoac(stats.ulb,tmp)
-            ,stats.uls);
-        bprintf(text[StatsDownloadsToday],ultoac(stats.dlb,tmp)
-            ,stats.dls);
-        bprintf(text[StatsPostsToday],ultoac(stats.ptoday,tmp));
-        bprintf(text[StatsEmailsToday],ultoac(stats.etoday,tmp));
-        bprintf(text[StatsFeedbacksToday],ultoac(stats.ftoday,tmp));
-        return(0);
-    case CS_CHANGE_USER:                 /* Change to another user */
-		if(!chksyspass(0))
-            return(0);
-        bputs(text[ChUserPrompt]);
-        if(!getstr(str,LEN_ALIAS,K_UPPER))
-            return(0);
-        if((i=finduser(str))==0)
-            return(0);
-        if(online==ON_REMOTE) {
-            getuserrec(i,U_LEVEL,2,str);
-            if(atoi(str)>logon_ml) {
-                getuserrec(i,U_PASS,8,tmp);
-                bputs(text[ChUserPwPrompt]);
-                console|=CON_R_ECHOX;
-                if(!(sys_misc&SM_ECHO_PW))
-                    console|=CON_L_ECHOX;
-                getstr(str,8,K_UPPER);
-                console&=~(CON_R_ECHOX|CON_L_ECHOX);
-                if(strcmp(str,tmp))
-                    return(0); } }
-        putmsgptrs();
-		putuserrec(useron.number,U_CURSUB,8
-			,sub[usrsub[curgrp][cursub[curgrp]]]->code);
-		putuserrec(useron.number,U_CURDIR,8
-			,dir[usrdir[curlib][curdir[curlib]]]->code);
-        useron.number=i;
-        getuserdat(&useron);
-		getnodedat(node_num,&thisnode,1);
-		thisnode.useron=useron.number;
-		putnodedat(node_num,thisnode);
-        getmsgptrs();
-        if(REALSYSOP) sys_status&=~SS_TMPSYSOP;
-        else sys_status|=SS_TMPSYSOP;
-        statline=sys_def_stat;
-        statusline();
-        sprintf(str,"Changed into %s #%u",useron.alias,useron.number);
-        logline("S+",str);
-        return(0);
-    case CS_SHOW_MEM:
-#ifdef __MSDOS__
-         bprintf(text[NBytesFreeMemory],farcoreleft());
-#endif
-        return(0);
-    case CS_ERROR_LOG:
-        sprintf(str,"%sERROR.LOG",data_dir);
-        if(fexist(str)) {
-            bputs(text[ErrorLogHdr]);
-            printfile(str,0);
-            if(!noyes(text[DeleteErrorLogQ]))
-                remove(str); }
-        else
-            bputs(text[NoErrorLogExists]);
-        for(i=1;i<=sys_nodes;i++) {
-            getnodedat(i,&node,0);
-            if(node.errors)
-                break; }
-        if(i<=sys_nodes || criterrs) {
-            if(!noyes(text[ClearErrCounter])) {
-                for(i=1;i<=sys_nodes;i++) {
-                    getnodedat(i,&node,1);
-                    node.errors=0;
-                    putnodedat(i,node); }
-                criterrs=0; } }
-        return(0);
-    case CS_ANSI_CAPTURE:           /* Capture ANSI codes */
-        sys_status^=SS_ANSCAP;
-        bprintf(text[ANSICaptureIsNow]
-            ,sys_status&SS_ANSCAP ? text[ON] : text[OFF]);
-        return(0);
-    case CS_LIST_TEXT_FILE:              /* View ASCII/ANSI/Ctrl-A file */
-		if(!chksyspass(0))
-            return(0);
-        bputs(text[Filename]);
-        if(getstr(str,60,K_UPPER))
-            printfile(str,0);
-        return(0);
-    case CS_EDIT_TEXT_FILE:              /* Edit ASCII/Ctrl-A file */
-		if(!chksyspass(0))
-            return(0);
-        bputs(text[Filename]);
-        if(getstr(str,60,K_UPPER))
-            editfile(str);
-        return(0);
-    case CS_GURU_LOG:
-        sprintf(str,"%sGURU.LOG",data_dir);
-        if(fexist(str)) {
-            printfile(str,0);
-            CRLF;
-            if(!noyes(text[DeleteGuruLogQ]))
-                remove(str); }
-        return(0);
-    case CS_FILE_SET_ALT_PATH:
-        altul=atoi(csi->str);
-        if(altul>altpaths)
-            altul=0;
-        bprintf(text[AltULPathIsNow],altul ? altpath[altul-1] : text[OFF]);
-        return(0);
-    case CS_FILE_RESORT_DIRECTORY:
-        for(i=1;i<=sys_nodes;i++)
-            if(i!=node_num) {
-                getnodedat(i,&node,0);
-                if(node.status==NODE_INUSE
-                    || node.status==NODE_QUIET)
-                    break; }
-
-        if(i<=sys_nodes) {
-            bputs(text[ResortWarning]);
-            return(0); }
-
-        if(!stricmp(csi->str,"ALL")) {     /* all libraries */
-            for(i=0;i<usrlibs;i++)
-                for(j=0;j<usrdirs[i];j++)
-                    resort(usrdir[i][j]);
-            return(0); }
-        if(!stricmp(csi->str,"LIB")) {     /* current library */
-            for(i=0;i<usrdirs[curlib];i++)
-                resort(usrdir[curlib][i]);
-            return(0); }
-        resort(usrdir[curlib][curdir[curlib]]);
-        return(0);
-
-    case CS_FILE_GET:
-
-        if(!fexist(csi->str)) {
-            bputs(text[FileNotFound]);
-            return(0); }
-		if(!chksyspass(0))
-            return(0);
-
-	case CS_FILE_SEND:
-
-        menu("DLPROT");
-        mnemonics(text[ProtocolOrQuit]);
-        strcpy(str,"Q");
-        for(i=0;i<total_prots;i++)
-            if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
-                sprintf(tmp,"%c",prot[i]->mnemonic);
-                strcat(str,tmp); }
-        ch=getkeys(str,0);
-        if(ch=='Q' || sys_status&SS_ABORT) {
-            return(0); }
-        for(i=0;i<total_prots;i++)
-            if(prot[i]->mnemonic==ch && chk_ar(prot[i]->ar,useron))
-                break;
-        if(i<total_prots) {
-			protocol(cmdstr(prot[i]->dlcmd,csi->str,csi->str,str),0);
-            autohangup(); }
-        return(0);
-
-    case CS_FILE_PUT:
-		if(!chksyspass(0))
-            return(0);
-        menu("ULPROT");
-        mnemonics(text[ProtocolOrQuit]);
-        strcpy(str,"Q");
-        for(i=0;i<total_prots;i++)
-            if(prot[i]->ulcmd[0] && chk_ar(prot[i]->ar,useron)) {
-                sprintf(tmp,"%c",prot[i]->mnemonic);
-                strcat(str,tmp); }
-        ch=getkeys(str,0);
-        if(ch=='Q' || sys_status&SS_ABORT) {
-            lncntr=0;
-            return(0); }
-        for(i=0;i<total_prots;i++)
-            if(prot[i]->mnemonic==ch && chk_ar(prot[i]->ar,useron))
-                break;
-        if(i<total_prots) {
-			protocol(cmdstr(prot[i]->ulcmd,csi->str,csi->str,str),0);
-            autohangup(); }
-        return(0);
-
-    case CS_FILE_UPLOAD_BULK:
-
-        if(!usrlibs) return(0);
-
-        if(!stricmp(csi->str,"ALL")) {     /* all libraries */
-            for(i=0;i<usrlibs;i++)
-                for(j=0;j<usrdirs[i];j++) {
-                    if(lib[i]->offline_dir==usrdir[i][j])
-                        continue;
-                    if(bulkupload(usrdir[i][j])) return(0); }
-            return(0); }
-        if(!stricmp(csi->str,"LIB")) {     /* current library */
-            for(i=0;i<usrdirs[curlib];i++) {
-                if(lib[usrlib[curlib]]->offline_dir
-                    ==usrdir[curlib][i])
-                    continue;
-                if(bulkupload(usrdir[curlib][i])) return(0); }
-            return(0); }
-        bulkupload(usrdir[curlib][curdir[curlib]]); /* current dir */
-        return(0);
-
-    case CS_FILE_FIND_OLD:
-    case CS_FILE_FIND_OPEN:
-    case CS_FILE_FIND_OFFLINE:
-    case CS_FILE_FIND_OLD_UPLOADS:
-        if(!usrlibs) return(0);
-        if(!getfilespec(tmp))
-            return(0);
-        padfname(tmp,str);
-        k=0;
-        bputs("\r\nSearching ");
-        if(!stricmp(csi->str,"ALL"))
-            bputs("all libraries");
-        else if(!stricmp(csi->str,"LIB"))
-            bputs("library");
-        else
-            bputs("directory");
-        bputs(" for files ");
-        if(*(csi->ip-1)==CS_FILE_FIND_OLD_UPLOADS) {
-            l=FI_OLDUL;
-            bprintf("uploaded before %s\r\n",timestr(&ns_time)); }
-        else if(*(csi->ip-1)==CS_FILE_FIND_OLD) { /* go by download date */
-            l=FI_OLD;
-            bprintf("not downloaded since %s\r\n",timestr(&ns_time)); }
-        else if(*(csi->ip-1)==CS_FILE_FIND_OFFLINE) {
-            l=FI_OFFLINE;
-            bputs("not online...\r\n"); }
-        else {
-            l=FI_CLOSE;
-            bputs("currently open...\r\n"); }
-        if(!stricmp(csi->str,"ALL")) {
-            for(i=0;i<usrlibs;i++)
-                for(j=0;j<usrdirs[i];j++) {
-                    if(lib[i]->offline_dir==usrdir[i][j])
-                        continue;
-                    if((s=listfileinfo(usrdir[i][j],str,l))==-1)
-                        return(0);
-                    else k+=s; } }
-        else if(!stricmp(csi->str,"LIB")) {
-            for(i=0;i<usrdirs[curlib];i++) {
-                if(lib[usrlib[curlib]]->offline_dir==usrdir[curlib][i])
-                        continue;
-                if((s=listfileinfo(usrdir[curlib][i],str,l))==-1)
-                    return(0);
-                else k+=s; } }
-        else {
-            s=listfileinfo(usrdir[curlib][curdir[curlib]],str,l);
-            if(s==-1)
-                return(0);
-            k=s; }
-        if(k>1) {
-            bprintf(text[NFilesListed],k); }
-		return(0); }
-
-if(*(csi->ip-1)>=CS_MSG_SET_AREA && *(csi->ip-1)<=CS_MSG_UNUSED1) {
-	csi->ip--;
-	return(execmsg(csi)); }
-
-if(*(csi->ip-1)>=CS_FILE_SET_AREA && *(csi->ip-1)<=CS_FILE_UNUSED1) {
-	csi->ip--;
-	return(execfile(csi)); }
-
-errormsg(WHERE,ERR_CHK,"shell function",*(csi->ip-1));
-return(0);
-}
diff --git a/src/sbbs2/execmisc.c b/src/sbbs2/execmisc.c
deleted file mode 100644
index 9b0f98bf4300903ba6d0304021d91ae5dce5ee16..0000000000000000000000000000000000000000
--- a/src/sbbs2/execmisc.c
+++ /dev/null
@@ -1,1373 +0,0 @@
-#line 1 "EXECMISC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-#include <sys/locking.h>
-#include <dirent.h>
-
-
-int exec_misc(csi_t *csi, uchar *path)
-{
-	uchar	str[256],tmp2[128],buf[1025],ch,*p,**pp,**pp1,**pp2;
-	ushort	w;
-	int 	i,j,k,s,file;
-	long	l,*lp,*lp1,*lp2;
-	void	*vp;
-	va_list arglist[64];
-	struct	dirent *de;
-    struct  tm *tm_p;
-	struct	ftime ft;
-	FILE	*fp;
-
-switch(*(csi->ip++)) {
-	case CS_VAR_INSTRUCTION:
-		switch(*(csi->ip++)) {	/* sub-op-code stored as next byte */
-			case PRINT_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				if(!pp || !*pp) {
-					lp=getintvar(csi,*(long *)csi->ip);
-					if(lp)
-						bprintf("%ld",*lp); }
-				else
-					putmsg(cmdstr(*pp,path,csi->str,buf)
-						,P_SAVEATR|P_NOABORT);
-				csi->ip+=4;
-				return(0);
-			case VAR_PRINTF:
-				strcpy(str,csi->ip);
-				while(*(csi->ip++));	/* Find NULL */
-				j=*(csi->ip++); 		/* total args */
-				for(i=0;i<j;i++) {
-					vp=getstrvar(csi,*(long *)csi->ip);
-					if(!vp) {
-						lp=getintvar(csi,*(long *)csi->ip);
-						if(!lp)
-							arglist[i]=0;
-						else
-							arglist[i]=(void *)*lp; }
-					else
-						arglist[i]=*(char **)vp;
-					csi->ip+=4; }
-				vsprintf(tmp,str,arglist);
-				putmsg(cmdstr(tmp,path,csi->str,buf),P_SAVEATR|P_NOABORT);
-				return(0);
-			case SHOW_VARS:
-				bprintf("shell     str=(%08lX) %s\r\n"
-					,csi->str,csi->str);
-				for(i=0;i<csi->str_vars;i++)
-					bprintf("local  str[%d]=(%08lX) (%08lX) %s\r\n"
-						,i,csi->str_var_name[i]
-						,csi->str_var[i]
-						,csi->str_var[i]);
-				for(i=0;i<csi->int_vars;i++)
-					bprintf("local  int[%d]=(%08lX) (%08lX) %ld\r\n"
-						,i,csi->int_var_name[i]
-						,csi->int_var[i]
-						,csi->int_var[i]);
-				for(i=0;i<global_str_vars;i++)
-					bprintf("global str[%d]=(%08lX) (%08lX) %s\r\n"
-						,i,global_str_var_name[i]
-						,global_str_var[i]
-						,global_str_var[i]);
-				for(i=0;i<global_int_vars;i++)
-					bprintf("global int[%d]=(%08lX) (%08lX) %ld\r\n"
-						,i,global_int_var_name[i]
-						,global_int_var[i]
-						,global_int_var[i]);
-				return(0);
-			case DEFINE_STR_VAR:
-				if(getstrvar(csi,*(long *)csi->ip)) {
-					csi->ip+=4;
-					return(0); }
-				csi->str_vars++;
-				csi->str_var=REALLOC(csi->str_var
-					,sizeof(char *)*csi->str_vars);
-				csi->str_var_name=REALLOC(csi->str_var_name
-					,sizeof(long)*csi->str_vars);
-				if(csi->str_var==NULL
-					|| csi->str_var_name==NULL) { /* REALLOC failed */
-					errormsg(WHERE,ERR_ALLOC,"local str var"
-						,sizeof(char *)*csi->str_vars);
-					if(csi->str_var_name) {
-						FREE(csi->str_var_name);
-						csi->str_var_name=0; }
-					if(csi->str_var) {
-						FREE(csi->str_var);
-						csi->str_var=0; }
-					csi->str_vars=0; }
-				else {
-					csi->str_var_name[csi->str_vars-1]=*(long *)csi->ip;
-					csi->str_var[csi->str_vars-1]=0; }
-				csi->ip+=4; /* Skip variable name */
-				return(0);
-			case DEFINE_INT_VAR:
-				if(getintvar(csi,*(long *)csi->ip)) {
-					csi->ip+=4;
-					return(0); }
-				csi->int_vars++;
-				csi->int_var=REALLOC(csi->int_var
-					,sizeof(char *)*csi->int_vars);
-				csi->int_var_name=REALLOC(csi->int_var_name
-					,sizeof(long)*csi->int_vars);
-				if(csi->int_var==NULL
-					|| csi->int_var_name==NULL) { /* REALLOC failed */
-					errormsg(WHERE,ERR_ALLOC,"local int var"
-						,sizeof(char *)*csi->int_vars);
-					if(csi->int_var_name) {
-						FREE(csi->int_var_name);
-						csi->int_var_name=0; }
-					if(csi->int_var) {
-						FREE(csi->int_var);
-						csi->int_var=0; }
-					csi->int_vars=0; }
-				else {
-					csi->int_var_name[csi->int_vars-1]=*(long *)csi->ip;
-					csi->int_var[csi->int_vars-1]=0; }
-				csi->ip+=4; /* Skip variable name */
-				return(0);
-			case DEFINE_GLOBAL_STR_VAR:
-				if(getstrvar(csi,*(long *)csi->ip)) {
-					csi->ip+=4;
-					return(0); }
-				global_str_vars++;
-				global_str_var=REALLOC(global_str_var
-					,sizeof(char *)*global_str_vars);
-				global_str_var_name=REALLOC(global_str_var_name
-					,sizeof(long)*global_str_vars);
-				if(global_str_var==NULL
-					|| global_str_var_name==NULL) { /* REALLOC failed */
-					errormsg(WHERE,ERR_ALLOC,"global str var"
-						,sizeof(char *)*global_str_vars);
-					if(global_str_var_name) {
-						FREE(global_str_var_name);
-						global_str_var_name=0; }
-					if(global_str_var) {
-						FREE(global_str_var);
-						global_str_var=0; }
-					global_str_vars=0; }
-				else {
-					global_str_var_name[global_str_vars-1]=
-						*(long *)csi->ip;
-					global_str_var[global_str_vars-1]=0; }
-				csi->ip+=4; /* Skip variable name */
-				return(0);
-			case DEFINE_GLOBAL_INT_VAR:
-				if(getintvar(csi,*(long *)csi->ip)) {
-					csi->ip+=4;
-					return(0); }
-				global_int_vars++;
-				global_int_var=REALLOC(global_int_var
-					,sizeof(char *)*global_int_vars);
-				global_int_var_name=REALLOC(global_int_var_name
-					,sizeof(long)*global_int_vars);
-				if(global_int_var==NULL
-					|| global_int_var_name==NULL) { /* REALLOC failed */
-					errormsg(WHERE,ERR_ALLOC,"local int var"
-						,sizeof(char *)*global_int_vars);
-					if(global_int_var_name) {
-						FREE(global_int_var_name);
-						global_int_var_name=0; }
-					if(global_int_var) {
-						FREE(global_int_var);
-						global_int_var=0; }
-					global_int_vars=0; }
-				else {
-					global_int_var_name[global_int_vars-1]
-						=*(long *)csi->ip;
-					global_int_var[global_int_vars-1]=0; }
-				csi->ip+=4; /* Skip variable name */
-				return(0);
-
-			case SET_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				if(pp)
-					*pp=copystrvar(csi,*pp
-						,cmdstr(csi->ip,path,csi->str,buf));
-				while(*(csi->ip++));	 /* Find NULL */
-				return(0);
-			case SET_INT_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				if(lp)
-					*lp=*(long *)csi->ip;
-				csi->ip+=4; /* Skip value */
-				return(0);
-			case COMPARE_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				if(pp)
-					csi->logic=stricmp(*pp
-						,cmdstr(csi->ip,path,csi->str,buf));
-				else {	/* Uninitialized str var */
-					if(*(csi->ip)==0)	 /* Blank static str */
-						csi->logic=LOGIC_TRUE;
-					else
-						csi->logic=LOGIC_FALSE; }
-				while(*(csi->ip++));	 /* Find NULL */
-				return(0);
-			case STRSTR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				if(pp && *pp && strstr(*pp
-					,cmdstr(csi->ip,path,csi->str,buf)))
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				while(*(csi->ip++));	 /* Find NULL */
-				return(0);
-			case STRNCMP_VAR:
-				i=*csi->ip++;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				if(pp && *pp)
-					csi->logic=strnicmp(*pp
-						,cmdstr(csi->ip,path,csi->str,buf),i);
-				else
-					csi->logic=LOGIC_FALSE;
-				while(*(csi->ip++));	 /* Find NULL */
-				return(0);
-			case STRNCMP_VARS:
-				i=*csi->ip++;
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp1 && *pp1 && pp2 && *pp2)
-					csi->logic=strnicmp(*pp1,*pp2,i);
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case STRSTR_VARS:
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp1 && *pp1 && pp2 && *pp2 && strstr(*pp1,*pp2))
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case COMPARE_INT_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				l=*(long *)csi->ip;
-				csi->ip+=4; /* Skip static value */
-				if(!lp) {	/* Unknown variable */
-					csi->logic=LOGIC_FALSE;
-					return(0); }
-				if(*lp>l)
-					csi->logic=LOGIC_GREATER;
-				else if(*lp<l)
-					csi->logic=LOGIC_LESS;
-				else
-					csi->logic=LOGIC_EQUAL;
-				return(0);
-			case COMPARE_VARS:
-				lp1=lp2=0;
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				if(!pp1)
-					lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				if(!pp2)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-
-				if(((!pp1 || !*pp1) && !lp1)
-					|| ((!pp2 || !*pp2) && !lp2)) {
-					if(pp1 && pp2)		/* Both unitialized or blank */
-						csi->logic=LOGIC_TRUE;
-					else
-						csi->logic=LOGIC_FALSE;
-					return(0); }
-
-				if(pp1) { /* ASCII */
-					if(!pp2) {
-						ltoa(*lp2,tmp,10);
-						csi->logic=stricmp(*pp1,tmp); }
-					else
-						csi->logic=stricmp(*pp1,*pp2);
-					return(0); }
-
-				/* Binary */
-				if(!lp2) {
-					l=strtol(*pp2,0,0);
-					if(*lp1>l)
-						csi->logic=LOGIC_GREATER;
-					else if(*lp1<l)
-						csi->logic=LOGIC_LESS;
-					else
-						csi->logic=LOGIC_EQUAL;
-					return(0); }
-				if(*lp1>*lp2)
-					csi->logic=LOGIC_GREATER;
-				else if(*lp1<*lp2)
-					csi->logic=LOGIC_LESS;
-				else
-					csi->logic=LOGIC_EQUAL;
-				return(0);
-			case COPY_VAR:
-				lp1=lp2=0;
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				if(!pp1)
-					lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				if(!pp2)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-
-				if((!pp1 && !lp1)
-					|| ((!pp2 || !*pp2) && !lp2)) {
-					csi->logic=LOGIC_FALSE;
-					return(0); }
-				csi->logic=LOGIC_TRUE;
-
-				if(pp1) {	/* ASCII */
-					if(!pp2)
-						ltoa(*lp2,tmp,10);
-					else
-						strcpy(tmp,*pp2);
-					*pp1=copystrvar(csi,*pp1,tmp);
-					return(0); }
-				if(!lp2)
-					*lp1=strtol(*pp2,0,0);
-				else
-					*lp1=*lp2;
-				return(0);
-			case SWAP_VARS:
-				lp1=lp2=0;
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				if(!pp1)
-					lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				if(!pp2)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-
-				if(((!pp1 || !*pp1) && !lp1)
-					|| ((!pp2 || !*pp2) && !lp2)) {
-					csi->logic=LOGIC_FALSE;
-					return(0); }
-
-				csi->logic=LOGIC_TRUE;
-
-				if(pp1) {	/* ASCII */
-					if(!pp2) {
-						if(!strnicmp(*pp2,"0x",2)) {
-							l=strtol((*pp1)+2,0,16);
-							ltoa(*lp2,tmp,16); }
-						else {
-							l=atol(*pp1);
-							ltoa(*lp2,tmp,10); }
-						*pp1=copystrvar(csi,*pp1,tmp);
-						*lp2=l; }
-					else {
-						p=*pp1;
-						*pp1=*pp2;
-						*pp2=p; }
-					return(0); }
-
-				/* Binary */
-				if(!lp2) {
-					if(!strnicmp(*pp2,"0x",2)) {
-						l=strtol((*pp2)+2,0,16);
-						ltoa(*lp1,tmp,16); }
-					else {
-						l=atol(*pp2);
-						ltoa(*lp1,tmp,10); }
-					*pp2=copystrvar(csi,*pp2,tmp);
-					*lp1=l; }
-				else {
-					l=*lp1;
-					*lp1=*lp2;
-					*lp2=l; }
-				return(0);
-			case CAT_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				strcpy(tmp,csi->ip);
-				while(*(csi->ip++));
-				if(pp && *pp)
-					for(i=0;i<MAX_SYSVARS;i++)
-						if(*pp==sysvar_p[i])
-							break;
-				if(pp && *pp!=csi->str && i==MAX_SYSVARS) {
-					if(*pp)
-						*pp=REALLOC(*pp,strlen(*pp)+strlen(tmp)+1);
-					else
-						*pp=REALLOC(*pp,strlen(tmp)+1); }
-				if(pp && *pp)
-					strcat(*pp,tmp);
-				return(0);
-			case CAT_STR_VARS:
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip dest variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip source variable name */
-				if(!pp1 || !pp2 || !*pp2) {
-					csi->logic=LOGIC_FALSE;
-					return(0); }
-				csi->logic=LOGIC_TRUE;
-				if(*pp1)
-					for(i=0;i<MAX_SYSVARS;i++)
-						if(*pp1==sysvar_p[i])
-							break;
-				if(*pp1!=csi->str && (!*pp1 || i==MAX_SYSVARS)) {
-					if(*pp1)
-						*pp1=REALLOC(*pp1,strlen(*pp1)+strlen(*pp2)+1);
-					else
-						*pp1=REALLOC(*pp1,strlen(*pp2)+1); }
-				strcat(*pp1,*pp2);
-				return(0);
-			case FORMAT_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				strcpy(str,csi->ip);
-				while(*(csi->ip++));	/* Find NULL */
-				j=*(csi->ip++); 		/* total args */
-				for(i=0;i<j;i++) {
-					vp=getstrvar(csi,*(long *)csi->ip);
-					if(!vp) {
-						lp=getintvar(csi,*(long *)csi->ip);
-						if(!lp)
-							arglist[i]=0;
-						else
-							arglist[i]=(void *)*lp; }
-					else
-						arglist[i]=*(char **)vp;
-					csi->ip+=4; }
-				vsprintf(tmp,str,arglist);
-				cmdstr(tmp,path,csi->str,str);
-				if(pp)
-					*pp=copystrvar(csi,*pp,str);
-				return(0);
-			case FORMAT_TIME_STR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				strcpy(str,csi->ip);
-				while(*(csi->ip++));	/* Find NULL */
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && lp) {
-					tm_p=gmtime(lp);
-					strftime(buf,128,str,tm_p);
-					*pp=copystrvar(csi,*pp,buf); }
-				return(0);
-			case TIME_STR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip str variable name */
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip int variable name */
-				if(pp && lp) {
-					strcpy(str,timestr(lp));
-					*pp=copystrvar(csi,*pp,str); }
-				return(0);
-			case DATE_STR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip str variable name */
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip int variable name */
-				if(pp && lp) {
-					unixtodstr(*lp,str);
-					*pp=copystrvar(csi,*pp,str); }
-				return(0);
-			case SECOND_STR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip str variable name */
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip int variable name */
-				if(pp && lp) {
-					sectostr(*lp,str);
-					*pp=copystrvar(csi,*pp,str); }
-				return(0);
-			case STRUPR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp)
-					strupr(*pp);
-				return(0);
-			case STRLWR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp)
-					strlwr(*pp);
-				return(0);
-			case TRUNCSP_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp)
-					truncsp(*pp);
-				return(0);
-			case STRIP_CTRL_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp)
-					strip_ctrl(*pp);
-				return(0);
-
-			case ADD_INT_VAR:
-			case SUB_INT_VAR:
-			case MUL_INT_VAR:
-			case DIV_INT_VAR:
-			case MOD_INT_VAR:
-			case AND_INT_VAR:
-			case OR_INT_VAR:
-			case NOT_INT_VAR:
-			case XOR_INT_VAR:
-				i=*(csi->ip-1);
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				l=*(long *)csi->ip;
-				csi->ip+=4;
-				if(!lp)
-					return(0);
-				switch(i) {
-					case ADD_INT_VAR:
-						*lp+=l;
-						break;
-					case SUB_INT_VAR:
-						*lp-=l;
-						break;
-					case MUL_INT_VAR:
-						*lp*=l;
-						break;
-					case DIV_INT_VAR:
-						*lp/=l;
-						break;
-					case MOD_INT_VAR:
-						*lp%=l;
-						break;
-					case AND_INT_VAR:
-						*lp&=l;
-						break;
-					case OR_INT_VAR:
-						*lp|=l;
-						break;
-					case NOT_INT_VAR:
-						*lp&=~l;
-						break;
-					case XOR_INT_VAR:
-						*lp^=l;
-						break; }
-				return(0);
-			case ADD_INT_VARS:
-			case SUB_INT_VARS:
-			case MUL_INT_VARS:
-			case DIV_INT_VARS:
-			case MOD_INT_VARS:
-			case AND_INT_VARS:
-			case OR_INT_VARS:
-			case NOT_INT_VARS:
-			case XOR_INT_VARS:
-				i=*(csi->ip-1);
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(!lp1)
-					return(0);
-				if(!lp2) {
-					(char **)pp=getstrvar(csi,*(long *)csi->ip);
-					if(!pp || !*pp)
-						return(0);
-					l=strtol(*pp,0,0); }
-				else
-					l=*lp2;
-				switch(i) {
-					case ADD_INT_VARS:
-						*lp1+=l;
-						break;
-					case SUB_INT_VARS:
-						*lp1-=l;
-						break;
-					case MUL_INT_VARS:
-						*lp1*=l;
-						break;
-					case DIV_INT_VARS:
-						*lp1/=l;
-						break;
-					case MOD_INT_VARS:
-						*lp1%=l;
-						break;
-					case AND_INT_VARS:
-						*lp1&=l;
-						break;
-					case OR_INT_VARS:
-						*lp1|=l;
-						break;
-					case NOT_INT_VARS:
-						*lp1&=~l;
-						break;
-					case XOR_INT_VARS:
-						*lp1^=l;
-						break; }
-				return(0);
-			case RANDOM_INT_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				l=*(long *)csi->ip;
-				csi->ip+=4;
-				if(lp)
-					*lp=random(l);
-				return(0);
-			case TIME_INT_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp)
-					*lp=time(NULL);
-				return(0);
-			case DATE_STR_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp && pp && *pp)
-					*lp=dstrtounix(*pp);
-				return(0);
-			case STRLEN_INT_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=strlen(*pp);
-					else
-						*lp=0; }
-				return(0);
-			case CRC16_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=crc16(*pp);
-					else
-						*lp=0; }
-				return(0);
-			case CRC32_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=crc32(*pp,strlen(*pp));
-					else
-						*lp=0; }
-				return(0);
-			case CHKSUM_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					*lp=0;
-					if(pp && *pp) {
-						i=0;
-						while(*((*pp)+i))
-							*lp+=(uchar)*((*pp)+(i++)); } }
-				return(0);
-			case FLENGTH_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=flength(*pp);
-					else
-						*lp=0; }
-				return(0);
-			case FTIME_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=fdate_dir(*pp);
-					else
-						*lp=0; }
-				return(0);
-			case CHARVAL_TO_INT:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					if(pp && *pp)
-						*lp=**pp;
-					else
-						*lp=0; }
-				return(0);
-			case GETSTR_VAR:
-			case GETLINE_VAR:
-			case GETNAME_VAR:
-			case GETSTRUPR_VAR:
-			case GETSTR_MODE:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				i=*(csi->ip++);
-				csi->logic=LOGIC_FALSE;
-				switch(*(csi->ip-6)) {
-					case GETNAME_VAR:
-						getstr(buf,i,K_UPRLWR);
-						break;
-					case GETSTRUPR_VAR:
-						getstr(buf,i,K_UPPER);
-						break;
-					case GETLINE_VAR:
-						getstr(buf,i,K_LINE);
-						break;
-					case GETSTR_MODE:
-						l=*(long *)csi->ip;
-						csi->ip+=4;
-						if(l&K_EDIT) {
-							if(pp && *pp)
-								strcpy(buf,*pp);
-							else
-								buf[0]=0; }
-						getstr(buf,i,l);
-						break;
-					default:
-						getstr(buf,i,0); }
-				if(sys_status&SS_ABORT)
-					return(0);
-				if(pp) {
-					*pp=copystrvar(csi,*pp,buf);
-					csi->logic=LOGIC_TRUE; }
-				return(0);
-			case GETNUM_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				if(!pp)
-					lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				i=*(short *)csi->ip;
-				csi->ip+=2;
-				csi->logic=LOGIC_FALSE;
-				l=getnum(i);
-				if(!pp && !lp)
-					return(0);
-				if(pp) {
-					if(l<=0)
-						str[0]=0;
-					else
-						ltoa(l,str,10);
-					*pp=copystrvar(csi,*pp,str);
-					csi->logic=LOGIC_TRUE;
-					return(0); }
-				if(lp) {
-					*lp=l;
-					csi->logic=LOGIC_TRUE; }
-				return(0);
-
-			case SHIFT_STR_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				i=*(csi->ip++);
-				if(!pp || !*pp)
-					return(0);
-				if(strlen(*pp)>=i)
-					memmove(*pp,*pp+i,strlen(*pp)+1);
-				return(0);
-
-			case CHKFILE_VAR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp && fexist(cmdstr(*pp,path,csi->str,buf)))
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case PRINTFILE_VAR_MODE:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				i=*(short *)(csi->ip);
-				csi->ip+=2;
-				if(pp && *pp)
-					printfile(*pp,i);
-				return(0);
-			case PRINTTAIL_VAR_MODE:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				i=*(short *)(csi->ip);
-				csi->ip+=2;
-				j=*csi->ip;
-				csi->ip++;
-				if(pp && *pp)
-					printtail(*pp,j,i);
-				return(0);
-			case SEND_FILE_VIA:
-			case RECEIVE_FILE_VIA:
-				j=*(csi->ip-1);
-				ch=*(csi->ip++);	/* Protocol */
-				cmdstr(csi->ip,csi->str,csi->str,str);
-				while(*(csi->ip++));	/* Find NULL */
-				for(i=0;i<total_prots;i++)
-					if(prot[i]->mnemonic==ch && chk_ar(prot[i]->ar,useron))
-						break;
-				csi->logic=LOGIC_FALSE;
-				if(i<total_prots)
-					if(external(cmdstr(j==SEND_FILE_VIA
-						? prot[i]->dlcmd : prot[i]->ulcmd,str,str,buf)
-						,EX_OUTL)==0)
-						csi->logic=LOGIC_TRUE;
-				return(0);
-			case SEND_FILE_VIA_VAR:
-			case RECEIVE_FILE_VIA_VAR:
-				j=*(csi->ip-1);
-				ch=*(csi->ip++);	/* Protocol */
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				for(i=0;i<total_prots;i++)
-					if(prot[i]->mnemonic==ch && chk_ar(prot[i]->ar,useron))
-						break;
-				csi->logic=LOGIC_FALSE;
-				if(!pp || !(*pp))
-					return(0);
-				if(i<total_prots)
-					if(external(cmdstr(j==SEND_FILE_VIA_VAR
-						 ? prot[i]->dlcmd : prot[i]->ulcmd,*pp,*pp,buf)
-						,EX_OUTL)==0)
-						csi->logic=LOGIC_TRUE;
-				return(0);
-
-			default:
-				errormsg(WHERE,ERR_CHK,"var sub-instruction",*(csi->ip-1));
-				return(0); }
-
-	case CS_FIO_FUNCTION:
-		switch(*(csi->ip++)) {	/* sub-op-code stored as next byte */
-			case FIO_OPEN:
-			case FIO_OPEN_VAR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				w=*(ushort *)csi->ip;
-				csi->ip+=2;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-7)==FIO_OPEN) {
-					cmdstr(csi->ip,path,csi->str,str);
-					while(*(csi->ip++)); }	 /* skip filename */
-				else {
-					(char **)pp=getstrvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!pp || !*pp)
-						return(0);
-					strcpy(str,*pp); }
-				if(csi->files>=MAX_FOPENS)
-					return(0);
-				if(lp) {
-					/* Access flags are not cross-platform, so convert */
-					i=0;
-					if(w&1) 	i|=O_RDONLY;
-					if(w&2) 	i|=O_WRONLY;
-					if(w&4) 	i|=O_RDWR;
-					if(w&0x040) i|=O_DENYNONE;
-					if(w&0x100) i|=O_CREAT;
-					if(w&0x200) i|=O_TRUNC;
-					if(w&0x400) i|=O_EXCL;
-					if(w&0x800) i|=O_APPEND;
-					*lp=(long)fnopen(&j,str,i);
-					if(*lp) {
-						for(i=0;i<csi->files;i++)
-							if(!csi->file[i])
-								break;
-						csi->file[i]=(FILE *)*lp;
-						if(i==csi->files)
-							csi->files++;
-						csi->logic=LOGIC_TRUE; } }
-				return(0);
-			case FIO_CLOSE:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp && *lp) {
-					csi->logic=fclose((FILE *)*lp);
-					for(i=0;i<csi->files;i++)
-						if(csi->file[i]==(FILE *)*lp)
-							csi->file[i]=0; }
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case FIO_FLUSH:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp && *lp)
-					csi->logic=fflush((FILE *)*lp);
-				else
-					csi->logic=LOGIC_FALSE;
-                return(0);
-			case FIO_READ:
-			case FIO_READ_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);		/* Handle */
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				if(!pp)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-9)==FIO_READ) {
-					i=*(short *)csi->ip;
-					csi->ip+=2; /* Length */ }
-				else {			/* FIO_READ_VAR */
-					vp=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!vp)
-						return(0);
-					i=*(short *)vp; }
-				if(i>1024)
-					i=1024;
-				if(!lp1 || !(*lp1) || (!pp && !lp2))
-					return(0);
-				if(pp) {
-					if(i<1) {
-						if(*pp && **pp)
-							i=strlen(*pp);
-						else
-							i=128; }
-					if((j=fread(buf,1,i,(FILE *)*lp1))==i)
-						csi->logic=LOGIC_TRUE;
-					buf[j]=0;
-					if(csi->etx) {
-						p=strchr(buf,csi->etx);
-						if(p) *p=0; }
-					*pp=copystrvar(csi,*pp,buf); }
-				else {
-					*lp2=0;
-					if(i>4 || i<1) i=4;
-					if(fread(lp2,1,i,(FILE *)*lp1)==i)
-						csi->logic=LOGIC_TRUE; }
-				return(0);
-			case FIO_READ_LINE:
-				lp1=getintvar(csi,*(long *)csi->ip);		/* Handle */
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				if(!pp)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(!lp1 || !(*lp1) || feof((FILE *)*lp1) || (!pp && !lp2))
-					return(0);
-				csi->logic=LOGIC_TRUE;
-				for(i=0;i<1024 /* && !eof(*lp1) removed 1/23/96 */;i++) {
-					if(!fread(buf+i,1,1,(FILE *)*lp1))
-						break;
-					if(*(buf+i)==LF) {
-						i++;
-						break; } }
-				buf[i]=0;
-				if(csi->etx) {
-					p=strchr(buf,csi->etx);
-					if(p) *p=0; }
-				if(pp)
-					*pp=copystrvar(csi,*pp,buf);
-				else
-					*lp2=strtol(buf,0,0);
-				return(0);
-			case FIO_WRITE:
-			case FIO_WRITE_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				if(!pp)
-					lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-9)==FIO_WRITE) {
-					i=*(short *)csi->ip;
-					csi->ip+=2; /* Length */ }
-				else {			/* FIO_WRITE_VAR */
-					vp=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!vp)
-						return(0);
-					i=*(short *)vp; }
-				if(i>1024)
-					i=1024;
-				if(!lp1 || !(*lp1) || (!pp && !lp2) || (pp && !*pp))
-					return(0);
-				if(pp) {
-					j=strlen(*pp);
-					if(i<1) i=j;
-					if(j>i) j=i;
-					j=fwrite(*pp,1,j,(FILE *)*lp1);
-					if(j<i) {
-						memset(buf,csi->etx,i-j);
-						fwrite(buf,1,i-j,(FILE *)*lp1); }
-					csi->logic=LOGIC_TRUE; }
-				else {
-					if(i<1 || i>4) i=4;
-					if(fwrite(lp2,1,i,(FILE *)*lp1)==i)
-						csi->logic=LOGIC_TRUE; }
-				return(0);
-			case FIO_GET_LENGTH:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp1 && *lp1 && lp2)
-					*lp2=filelength(fileno((FILE *)*lp1));
-				return(0);
-			case FIO_GET_TIME:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp1 && *lp1 && lp2) {
-					getftime(fileno((FILE *)*lp1),&ft);
-					*lp2=ftimetounix(ft); }
-				return(0);
-			case FIO_SET_TIME:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp1 && *lp1 && lp2) {
-					ft=unixtoftime(*lp2);
-					setftime(fileno((FILE *)*lp1),&ft); }
-				return(0);
-			case FIO_EOF:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(lp && *lp)
-					if(ftell((FILE *)*lp)>=filelength(fileno((FILE *)*lp)))
-						csi->logic=LOGIC_TRUE;
-				return(0);
-			case FIO_GET_POS:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				lp2=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp1 && *lp1 && lp2)
-					*lp2=ftell((FILE *)*lp1);
-				return(0);
-			case FIO_SEEK:
-			case FIO_SEEK_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-5)==FIO_SEEK) {
-					l=*(long *)csi->ip;
-					csi->ip+=4; }
-				else {
-					lp2=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!lp2) {
-						csi->ip+=2;
-						return(0); }
-					l=*lp2; }
-				i=*(short *)csi->ip;
-				csi->ip+=2;
-				if(lp1 && *lp1)
-					if(fseek((FILE *)*lp1,l,i)!=-1)
-						csi->logic=LOGIC_TRUE;
-				return(0);
-			case FIO_LOCK:
-			case FIO_LOCK_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-5)==FIO_LOCK) {
-					l=*(long *)csi->ip;
-					csi->ip+=4; }
-				else {
-					lp2=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!lp2)
-						return(0);
-					l=*lp2; }
-				if(lp1 && *lp1) {
-					fflush((FILE *)*lp1);
-					lseek(fileno((FILE *)*lp1),ftell((FILE *)*lp1),SEEK_SET);
-					csi->logic=locking(fileno((FILE *)*lp1),LK_LOCK,l); }
-				return(0);
-			case FIO_UNLOCK:
-			case FIO_UNLOCK_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-5)==FIO_UNLOCK) {
-					l=*(long *)csi->ip;
-					csi->ip+=4; }
-				else {
-					lp2=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!lp2)
-						return(0);
-					l=*lp2; }
-				if(lp1 && *lp1) {
-					fflush((FILE *)*lp1);
-					lseek(fileno((FILE *)*lp1),ftell((FILE *)*lp1),SEEK_SET);
-					csi->logic=locking(fileno((FILE *)*lp1),LK_UNLCK,l); }
-				return(0);
-			case FIO_SET_LENGTH:
-			case FIO_SET_LENGTH_VAR:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(*(csi->ip-5)==FIO_SET_LENGTH) {
-					l=*(long *)csi->ip;
-					csi->ip+=4; }
-				else {
-					lp2=getintvar(csi,*(long *)csi->ip);
-					csi->ip+=4;
-					if(!lp2)
-						return(0);
-					l=*lp2; }
-				if(lp1 && *lp1)
-					csi->logic=chsize(fileno((FILE *)*lp1),l);
-				return(0);
-			case FIO_PRINTF:
-				lp1=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				strcpy(str,csi->ip);
-				while(*(csi->ip++));	/* Find NULL */
-				j=*(csi->ip++); 		/* total args */
-				for(i=0;i<j;i++) {
-					vp=getstrvar(csi,*(long *)csi->ip);
-					if(!vp) {
-						lp2=getintvar(csi,*(long *)csi->ip);
-						if(!lp2)
-							arglist[i]=0;
-						else
-							arglist[i]=(void *)*lp2; }
-					else
-						arglist[i]=*(char **)vp;
-					csi->ip+=4; }
-				vsprintf(tmp,str,arglist);
-				if(lp1 && *lp1) {
-					cmdstr(tmp,path,csi->str,str);
-					fwrite(str,1,strlen(str),(FILE *)*lp1); }
-				return(0);
-			case FIO_SET_ETX:
-				csi->etx=*(csi->ip++);
-				return(0);
-			case REMOVE_FILE:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp && remove(*pp)==0)
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case RENAME_FILE:
-			case COPY_FILE:
-			case MOVE_FILE:
-				(char **)pp1=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4; /* Skip variable name */
-				(char **)pp2=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp1 && *pp1 && pp2 && *pp2)
-					switch(*(csi->ip-9)) {
-						case RENAME_FILE:
-							csi->logic=rename(*pp1,*pp2);
-							break;
-						case COPY_FILE:
-							csi->logic=mv(*pp1,*pp2,1);
-							break;
-						case MOVE_FILE:
-							csi->logic=mv(*pp1,*pp2,0);
-							break; }
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case GET_FILE_ATTRIB:
-			case SET_FILE_ATTRIB:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp && lp) {
-					if(*(csi->ip-9)==GET_FILE_ATTRIB)
-						*lp=_chmod(*pp,0,0);
-					else
-						*lp=_chmod(*pp,1,(int)*lp); }
-				return(0);
-			case MAKE_DIR:
-			case REMOVE_DIR:
-			case CHANGE_DIR:
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(pp && *pp)
-					switch(*(csi->ip-5)) {
-						case MAKE_DIR:
-							csi->logic=mkdir(*pp);
-							break;
-						case REMOVE_DIR:
-							csi->logic=rmdir(*pp);
-							break;
-						case CHANGE_DIR:
-							csi->logic=chdir(*pp);
-							break; }
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case OPEN_DIR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(pp && *pp && lp) {
-					*lp=(long)opendir((char *)*pp);
-					if(*lp)
-						csi->logic=LOGIC_TRUE; }
-				return(0);
-			case READ_DIR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				(char **)pp=getstrvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				csi->logic=LOGIC_FALSE;
-				if(pp && lp) {
-					de=readdir((DIR *)(*lp));
-					if(de!=NULL) {
-						csi->logic=LOGIC_TRUE;
-						*pp=copystrvar(csi,*pp,de->d_name); } }
-				return(0);
-			case REWIND_DIR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp) {
-					rewinddir((DIR *)(*lp));
-					csi->logic=LOGIC_TRUE; }
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			case CLOSE_DIR:
-				lp=getintvar(csi,*(long *)csi->ip);
-				csi->ip+=4;
-				if(lp && closedir((DIR *)(*lp))==0)
-					csi->logic=LOGIC_TRUE;
-				else
-					csi->logic=LOGIC_FALSE;
-				return(0);
-			default:
-				errormsg(WHERE,ERR_CHK,"fio sub-instruction",*(csi->ip-1));
-				return(0); }
-
-
-	case CS_SWITCH:
-		lp=getintvar(csi,*(long *)csi->ip);
-		csi->ip+=4;
-		if(!lp) {
-			skipto(csi,CS_END_SWITCH);
-			csi->ip++; }
-		else {
-			csi->misc|=CS_IN_SWITCH;
-			csi->switch_val=*lp; }
-		return(0);
-	case CS_CASE:
-		l=*(long *)csi->ip;
-		csi->ip+=4;
-		if(csi->misc&CS_IN_SWITCH && csi->switch_val!=l)
-			skipto(csi,CS_NEXTCASE);
-		else
-			csi->misc&=~CS_IN_SWITCH;
-		return(0);
-	case CS_COMPARE_ARS:
-		i=*(csi->ip++);  /* Length of ARS stored as byte before ARS */
-		csi->logic=!chk_ar(csi->ip,useron);
-		csi->ip+=i;
-		return(0);
-	case CS_TOGGLE_USER_MISC:
-		useron.misc^=*(long *)csi->ip;
-		putuserrec(useron.number,U_MISC,8,ultoa(useron.misc,tmp,16));
-		csi->ip+=4;
-		return(0);
-	case CS_COMPARE_USER_MISC:
-		if((useron.misc&*(long *)csi->ip)==*(long *)csi->ip)
-			csi->logic=LOGIC_TRUE;
-		else
-			csi->logic=LOGIC_FALSE;
-		csi->ip+=4;
-		return(0);
-	case CS_TOGGLE_USER_CHAT:
-		useron.chat^=*(long *)csi->ip;
-		putuserrec(useron.number,U_CHAT,8,ultoa(useron.chat,tmp,16));
-		csi->ip+=4;
-		return(0);
-	case CS_COMPARE_USER_CHAT:
-		if((useron.chat&*(long *)csi->ip)==*(long *)csi->ip)
-			csi->logic=LOGIC_TRUE;
-		else
-			csi->logic=LOGIC_FALSE;
-		csi->ip+=4;
-		return(0);
-	case CS_TOGGLE_USER_QWK:
-		useron.qwk^=*(long *)csi->ip;
-		putuserrec(useron.number,U_QWK,8,ultoa(useron.qwk,tmp,16));
-		csi->ip+=4;
-		return(0);
-	case CS_COMPARE_USER_QWK:
-		if((useron.qwk&*(long *)csi->ip)==*(long *)csi->ip)
-			csi->logic=LOGIC_TRUE;
-		else
-			csi->logic=LOGIC_FALSE;
-		csi->ip+=4;
-		return(0);
-	case CS_REPLACE_TEXT:
-		i=*(ushort *)csi->ip;
-		csi->ip+=2;
-		i--;
-		if(i>=TOTAL_TEXT) {
-			errormsg(WHERE,ERR_CHK,"replace text #",i);
-			while(*(csi->ip++));	 /* Find NULL */
-			return(0); }
-		if(text[i]!=text_sav[i] && text[i]!=nulstr)
-			FREE(text[i]);
-		j=strlen(cmdstr(csi->ip,path,csi->str,buf));
-		if(!j)
-			text[i]=nulstr;
-		else
-			text[i]=MALLOC(j+1);
-		if(!text[i]) {
-			errormsg(WHERE,ERR_ALLOC,"replacement text",j);
-			while(*(csi->ip++));	 /* Find NULL */
-			text[i]=text_sav[i];
-			return(0); }
-		if(j)
-			strcpy(text[i],buf);
-		while(*(csi->ip++));	 /* Find NULL */
-		return(0);
-	case CS_USE_INT_VAR:	// Self-modifying code!
-		(char **)pp=getstrvar(csi,*(long *)csi->ip);
-		if(pp && *pp)
-			l=strtol(*pp,0,0);
-		else {
-			lp=getintvar(csi,*(long *)csi->ip);
-			if(lp)
-				l=*lp;
-			else
-				l=0; }
-		csi->ip+=4; 			// Variable
-		i=*(csi->ip++); 		// Offset
-		if(i<1 || csi->ip+1+i>=csi->cs+csi->length) {
-			errormsg(WHERE,ERR_CHK,"offset",i);
-			csi->ip++;
-			return(0); }
-		switch(*(csi->ip++)) {	// Length
-			case sizeof(char):
-				*(csi->ip+i)=(char)l;
-				break;
-			case sizeof(short):
-				*((short *)(csi->ip+i))=(short)l;
-				break;
-			case sizeof(long):
-				*((long *)(csi->ip+i))=l;
-                break;
-			default:
-				errormsg(WHERE,ERR_CHK,"length",*(csi->ip-1));
-				break; }
-		return(0);
-	default:
-		errormsg(WHERE,ERR_CHK,"shell instruction",*(csi->ip-1));
-		return(0); }
-}
diff --git a/src/sbbs2/execmsg.c b/src/sbbs2/execmsg.c
deleted file mode 100644
index 510a24ce7342f77e58d883cffbbceb57e4495f6b..0000000000000000000000000000000000000000
--- a/src/sbbs2/execmsg.c
+++ /dev/null
@@ -1,301 +0,0 @@
-#line 1 "EXECMSG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-int execmsg(csi_t *csi)
-{
-	uchar	str[256],tmp2[128],*path,ch,*p;
-	int 	s,file,x,y;
-	long	i,j,k;		// Changes from ints - 03/25/96
-	long	l;
-	stats_t stats;
-	node_t	node;
-	file_t	f;
-	time_t	t;
-    csi_t   bin;
-
-
-switch(*(csi->ip++)) {
-
-	case CS_MSG_SELECT_AREA:
-		csi->logic=LOGIC_FALSE;
-		if(!usrgrps) return(0);
-		while(online) {
-			j=0;
-			if(usrgrps>1) {
-				sprintf(str,"%sMENU\\GRPS.*",text_dir);
-				if(fexist(str))
-					menu("GRPS");
-				else {
-					bputs(text[CfgGrpLstHdr]);
-					for(i=0;i<usrgrps && !msgabort();i++) {
-						if(i==curgrp)
-							outchar('*');
-						else outchar(SP);
-						if(i<9) outchar(SP);
-						if(i<99) outchar(SP);
-						bprintf(text[CfgGrpLstFmt]
-							,i+1,grp[usrgrp[i]]->lname); } }
-				sprintf(str,text[JoinWhichGrp],curgrp+1);
-				mnemonics(str);
-				j=getnum(usrgrps);
-				if((int)j==-1)
-					return(0);
-				if(!j)
-					j=curgrp;
-				else
-					j--; }
-			sprintf(str,"%sMENU\\SUBS%u.*",text_dir,usrgrp[j]+1);
-			if(fexist(str)) {
-				sprintf(str,"SUBS%u",usrgrp[j]+1);
-				menu(str); }
-			else {
-				CLS;
-				bprintf(text[SubLstHdr],grp[usrgrp[j]]->lname);
-				for(i=0;i<usrsubs[j] && !msgabort();i++) {
-					if(i==cursub[j]) outchar('*');
-					else outchar(SP);
-					sprintf(str,text[SubLstFmt],i+1
-						,sub[usrsub[j][i]]->lname,nulstr
-						,getposts(usrsub[j][i]));
-					if(i<9) outchar(SP);
-					if(i<99) outchar(SP);
-					bputs(str); } }
-			sprintf(str,text[JoinWhichSub],cursub[j]+1);
-			mnemonics(str);
-			i=getnum(usrsubs[j]);
-			if((int)i==-1) {
-				if(usrgrps==1)
-					return(0);
-				continue; }
-			if(!i)
-				i=cursub[j];
-			else
-				i--;
-			curgrp=j;
-			cursub[curgrp]=i;
-			csi->logic=LOGIC_TRUE;
-			return(0); }
-		return(0);
-
-	case CS_MSG_GET_SUB_NUM:
-
-		if(useron.misc&COLDKEYS) {
-			i=atoi(csi->str);
-			if(i && usrgrps && i<=usrsubs[curgrp])
-				cursub[curgrp]=i-1;
-			return(0); }
-
-		ch=getkey(K_UPPER);
-		outchar(ch);
-		if(usrgrps && (ch&0xf)*10<=usrsubs[curgrp] && (ch&0xf)) {
-			i=(ch&0xf)*10;
-			ch=getkey(K_UPPER);
-			if(!isdigit(ch) && ch!=CR) {
-				ungetkey(ch);
-				cursub[curgrp]=(i/10)-1;
-				return(0); }
-			outchar(ch);
-			if(ch==CR) {
-				cursub[curgrp]=(i/10)-1;
-				return(0); }
-			logch(ch,0);
-			i+=ch&0xf;
-			if(i*10<=usrsubs[curgrp]) { 	/* 100+ subs */
-				i*=10;
-				ch=getkey(K_UPPER);
-				if(!isdigit(ch) && ch!=CR) {
-					ungetkey(ch);
-					cursub[curgrp]=(i/10)-1;
-					return(0); }
-				outchar(ch);
-				if(ch==CR) {
-					cursub[curgrp]=(i/10)-1;
-					return(0); }
-				logch(ch,0);
-				i+=ch&0xf; }
-			if(i<=usrsubs[curgrp])
-				cursub[curgrp]=i-1;
-			return(0); }
-		if((ch&0xf)<=usrsubs[curgrp] && (ch&0xf) && usrgrps)
-			cursub[curgrp]=(ch&0xf)-1;
-		return(0);
-
-	case CS_MSG_GET_GRP_NUM:
-
-		if(useron.misc&COLDKEYS) {
-			i=atoi(csi->str);
-			if(i && i<=usrgrps)
-				curgrp=i-1;
-			return(0); }
-
-		ch=getkey(K_UPPER);
-		outchar(ch);
-		if((ch&0xf)*10<=usrgrps && (ch&0xf)) {
-			i=(ch&0xf)*10;
-			ch=getkey(K_UPPER);
-			if(!isdigit(ch) && ch!=CR) {
-				ungetkey(ch);
-				curgrp=(i/10)-1;
-				return(0); }
-			outchar(ch);
-			if(ch==CR) {
-				curgrp=(i/10)-1;
-				return(0); }
-			logch(ch,0);
-			i+=ch&0xf;
-			if(i<=usrgrps)
-				curgrp=i-1;
-			return(0); }
-		if((ch&0xf)<=usrgrps && (ch&0xf))
-			curgrp=(ch&0xf)-1;
-		return(0);
-
-	case CS_MSG_SET_GROUP:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<usrgrps;i++)
-			if(!stricmp(grp[usrgrp[i]]->sname,csi->str))
-				break;
-		if(i<usrgrps)
-			curgrp=i;
-		else
-			csi->logic=LOGIC_FALSE;
-		return(0);
-
-	case CS_MSG_SHOW_GROUPS:
-		if(!usrgrps) return(0);
-		sprintf(str,"%sMENU\\GRPS.*",text_dir);
-		if(fexist(str)) {
-			menu("GRPS");
-			return(0); }
-		bputs(text[GrpLstHdr]);
-		for(i=0;i<usrgrps && !msgabort();i++) {
-			if(i==curgrp)
-				outchar('*');
-			else outchar(SP);
-			if(i<9) outchar(SP);
-			bprintf(text[GrpLstFmt],i+1
-				,grp[usrgrp[i]]->lname,nulstr,usrsubs[i]); }
-		return(0);
-
-	case CS_MSG_SHOW_SUBBOARDS:
-		if(!usrgrps) return(0);
-		sprintf(str,"%sMENU\\SUBS%u.*",text_dir,usrgrp[curgrp]+1);
-		if(fexist(str)) {
-			sprintf(str,"SUBS%u",usrgrp[curgrp]+1);
-			menu(str);
-			return(0); }
-		CRLF;
-		bprintf(text[SubLstHdr],grp[usrgrp[curgrp]]->lname);
-		for(i=0;i<usrsubs[curgrp] && !msgabort();i++) {
-			if(i==cursub[curgrp]) outchar('*');
-			else outchar(SP);
-			sprintf(str,text[SubLstFmt],i+1
-				,sub[usrsub[curgrp][i]]->lname,nulstr
-				,getposts(usrsub[curgrp][i]));
-			if(i<9) outchar(SP);
-			if(i<99) outchar(SP);
-			bputs(str); }
-		return(0);
-
-	case CS_MSG_GROUP_UP:
-		curgrp++;
-		if(curgrp>=usrgrps)
-			curgrp=0;
-		return(0);
-	case CS_MSG_GROUP_DOWN:
-		if(!curgrp)
-			curgrp=usrgrps-1;
-		else curgrp--;
-		return(0);
-	case CS_MSG_SUBBOARD_UP:
-		if(!usrgrps) return(0);
-		cursub[curgrp]++;
-		if(cursub[curgrp]>=usrsubs[curgrp])
-			cursub[curgrp]=0;
-		return(0);
-	case CS_MSG_SUBBOARD_DOWN:
-		if(!usrgrps) return(0);
-		if(!cursub[curgrp])
-			cursub[curgrp]=usrsubs[curgrp]-1;
-		else cursub[curgrp]--;
-		return(0);
-	case CS_MSG_SET_AREA:
-		csi->logic=LOGIC_TRUE;
-		for(i=0;i<usrgrps;i++)
-			for(j=0;j<usrsubs[i];j++)
-				if(!stricmp(csi->str,sub[usrsub[i][j]]->code)) {
-					curgrp=i;
-					cursub[i]=j;
-					return(0); }
-		csi->logic=LOGIC_FALSE;
-		return(0);
-	case CS_MSG_READ:
-		if(!usrgrps) return(0);
-		csi->logic=scanposts(usrsub[curgrp][cursub[curgrp]],0,nulstr);
-		return(0);
-	case CS_MSG_POST:
-		if(!usrgrps) return(0);
-		csi->logic=LOGIC_FALSE;
-		if(!chk_ar(sub[usrsub[curgrp][cursub[curgrp]]]->post_ar,useron)) {
-			bputs(text[CantPostOnSub]);
-			return(0); }
-		csi->logic=!postmsg(usrsub[curgrp][cursub[curgrp]],0,0);
-		return(0);
-	case CS_MSG_QWK:
-		qwk_sec();
-		return(0);
-	case CS_MSG_PTRS_CFG:
-		new_scan_ptr_cfg();
-		return(0);
-	case CS_MSG_PTRS_REINIT:
-		for(i=0;i<total_subs;i++) {
-			sub[i]->ptr=sub_ptr[i];
-			sub[i]->last=sub_last[i]; }
-		bputs(text[MsgPtrsInitialized]);
-		return(0);
-	case CS_MSG_NEW_SCAN_CFG:
-		new_scan_cfg(SUB_NSCAN);
-		return(0);
-	case CS_MSG_NEW_SCAN:
-		scansubs(SCAN_NEW);
-		return(0);
-	case CS_MSG_NEW_SCAN_SUB:
-		csi->logic=scanposts(usrsub[curgrp][cursub[curgrp]],SCAN_NEW,nulstr);
-		return(0);
-	case CS_MSG_NEW_SCAN_ALL:
-		scanallsubs(SCAN_NEW);
-		return(0);
-	case CS_MSG_CONT_SCAN:
-		scansubs(SCAN_NEW|SCAN_CONST);
-		return(0);
-	case CS_MSG_CONT_SCAN_ALL:
-		scanallsubs(SCAN_NEW|SCAN_CONST);
-		return(0);
-	case CS_MSG_BROWSE_SCAN:
-		scansubs(SCAN_NEW|SCAN_BACK);
-		return(0);
-	case CS_MSG_BROWSE_SCAN_ALL:
-		scanallsubs(SCAN_BACK|SCAN_NEW);
-		return(0);
-	case CS_MSG_FIND_TEXT:
-		scansubs(SCAN_FIND);
-		return(0);
-	case CS_MSG_FIND_TEXT_ALL:
-		scanallsubs(SCAN_FIND);
-		return(0);
-	case CS_MSG_YOUR_SCAN_CFG:
-		new_scan_cfg(SUB_SSCAN);
-		return(0);
-	case CS_MSG_YOUR_SCAN:
-		scansubs(SCAN_TOYOU);
-		return(0);
-	case CS_MSG_YOUR_SCAN_ALL:
-		scanallsubs(SCAN_TOYOU);
-		return(0); }
-errormsg(WHERE,ERR_CHK,"shell function",*(csi->ip-1));
-return(0);
-}
diff --git a/src/sbbs2/execsbbs/execsbbs.c b/src/sbbs2/execsbbs/execsbbs.c
deleted file mode 100644
index 7c491cb17bc21a4643fbb0dde0b6ba76d5c5ef5c..0000000000000000000000000000000000000000
--- a/src/sbbs2/execsbbs/execsbbs.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* execbbs.c */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <dos.h>
-#include <dir.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <process.h>
-
-extern unsigned _heaplen=2048;
-
-/* usage: execsbbs start_dir "program parms" sbbspath [r] */
-
-int main(int argc, char *argv[])
-{
-	char path[129],*comspec,*p,*arg[30],c;
-	int disk;
-
-if(argc<4) {
-	printf("This program is for the internal use of Synchronet.\r\n");
-/***	Debug stuff
-	printf("argc=%d\r\n",argc);
-	for(c=0;c<argc;c++)
-		printf("argv[%d]='%s'\n",c,argv[c]);
-***/
-	return(0); }
-disk=getdisk();
-getcwd(path,128);
-comspec=getenv("COMSPEC");
-
-/***					/* Removed */
-strcpy(str,comspec);	/* save comspec */
-strcpy(comspec,"");     /* destroy comspec */
-***/
-
-if(argv[1][1]==':')                /* drive letter specified */
-	setdisk(toupper(argv[1][0])-'A');
-chdir(argv[1]);
-
-p=strchr(argv[2],' ');
-if(p)
-	p++;
-if(spawnlpe(P_WAIT,comspec,comspec,"/c",argv[2],NULL,environ))
-	printf("EXECSBBS: Error %d spawning %s\r\n",errno,argv[2]);
-/***
-strcpy(comspec,str);	/* restore comspec */
-***/
-setdisk(disk);
-if(chdir(path))
-	printf("\7\r\nEXECBBS: Error changing directory to %s\r\n",path);
-for(c=0;c<30;c++)
-	arg[c]=argv[c+3];
-if(execve(arg[0],arg,environ))
-	printf("EXECSBBS: Error %d executing %s\r\n",errno,arg[0]);
-return(1);
-}
diff --git a/src/sbbs2/execsbbs/make.bat b/src/sbbs2/execsbbs/make.bat
deleted file mode 100755
index a972501c137a79a5ec2d17e3cb12d39eca1849f5..0000000000000000000000000000000000000000
--- a/src/sbbs2/execsbbs/make.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-bcc -w-pro -C -mt -ndos execsbbs.c
-if errorlevel 1 goto end
-exe2bin dos\execsbbs.exe dos\execsbbs.com
-:end
diff --git a/src/sbbs2/execsbbs/make.cmd b/src/sbbs2/execsbbs/make.cmd
deleted file mode 100755
index 6791ea0b846a9001521fc8ec756736b96fe34a60..0000000000000000000000000000000000000000
--- a/src/sbbs2/execsbbs/make.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -C -nos2 execsbbs.c
diff --git a/src/sbbs2/fido.c b/src/sbbs2/fido.c
deleted file mode 100644
index eddef53a5873419c182ea91a4604252ddb8238be..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido.c
+++ /dev/null
@@ -1,818 +0,0 @@
-#line 1 "FIDO.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*********************************************/
-/* Functions that pertain solely to FidoNet  */
-/*********************************************/
-
-#include "sbbs.h"
-
-extern char *mon[];
-void inetmail(char *into, char *subj, char mode);
-void qnetmail(char *into, char *subj, char mode);
-int qwk_route(char *inaddr, char *fulladdr);
-
-void pt_zone_kludge(fmsghdr_t hdr,int fido)
-{
-	char str[256];
-
-sprintf(str,"\1INTL %u:%u/%u %u:%u/%u\r"
-	,hdr.destzone,hdr.destnet,hdr.destnode
-	,hdr.origzone,hdr.orignet,hdr.orignode);
-write(fido,str,strlen(str));
-
-if(hdr.destpoint) {
-    sprintf(str,"\1TOPT %u\r"
-		,hdr.destpoint);
-    write(fido,str,strlen(str)); }
-
-if(hdr.origpoint) {
-    sprintf(str,"\1FMPT %u\r"
-		,hdr.origpoint);
-    write(fido,str,strlen(str)); }
-}
-
-int lookup_netuser(char *into)
-{
-	char to[128],name[26],str[256],q[128];
-	int i;
-	FILE *stream;
-
-if(strchr(into,'@'))
-	return(0);
-strcpy(to,into);
-strupr(to);
-sprintf(str,"%sQNET\\USERS.DAT",data_dir);
-if((stream=fnopen(&i,str,O_RDONLY))==NULL)
-	return(0);
-while(!feof(stream)) {
-	if(!fgets(str,250,stream))
-		break;
-	str[25]=0;
-	truncsp(str);
-	strcpy(name,str);
-	strupr(name);
-	str[35]=0;
-	truncsp(str+27);
-	sprintf(q,"Do you mean %s @%s",str,str+27);
-	if(strstr(name,to) && yesno(q)) {
-		fclose(stream);
-		sprintf(into,"%s@%s",str,str+27);
-		return(0); }
-	if(sys_status&SS_ABORT)
-		break; }
-fclose(stream);
-return(1);
-}
-
-/****************************************************************************/
-/* Send FidoNet NetMail from BBS											*/
-/****************************************************************************/
-void netmail(char *into, char *title, char mode)
-{
-	char str[256],subj[128],to[256],fname[128],*buf,*p,ch;
-	int file,fido,x,cc_found,cc_sent;
-	uint i;
-	long length,l;
-	faddr_t addr;
-	fmsghdr_t hdr;
-
-sprintf(subj,"%.127s",title);
-
-
-strcpy(to,into);
-
-lookup_netuser(to);
-
-p=strrchr(to,'@');      /* Find '@' in name@addr */
-if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) {
-	mode&=~WM_FILE;
-	qnetmail(to,title,mode|WM_NETMAIL);
-	return; }
-if(p==NULL || !strchr(p+1,'/') || !total_faddrs) {
-	if(!p && dflt_faddr.zone)
-		addr=dflt_faddr;
-	else if(inetmail_misc&NMAIL_ALLOW) {
-		if(mode&WM_FILE && !SYSOP && !(inetmail_misc&NMAIL_FILE))
-			mode&=~WM_FILE;
-		inetmail(into,title,mode|WM_NETMAIL);
-		return; }
-	else if(dflt_faddr.zone)
-		addr=dflt_faddr;
-	else {
-		bprintf("\1n\r\nInvalid NetMail address.\r\n");
-		return; } }
-else {
-	addr=atofaddr(p+1); 	/* Get fido address */
-	*p=0;					/* Chop off address */
-	}
-
-if(mode&WM_FILE && !SYSOP && !(netmail_misc&NMAIL_FILE))
-	mode&=~WM_FILE;
-
-if((!SYSOP && !(netmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M')
-    || !total_faddrs) {
-    bputs(text[NoNetMailAllowed]);
-    return; }
-
-truncsp(to);				/* Truncate off space */
-
-memset(&hdr,0,sizeof(hdr));   /* Initialize header to null */
-strcpy(hdr.from,netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
-sprintf(hdr.to,"%.35s",to);
-
-/* Look-up in nodelist? */
-
-if(netmail_cost && !(useron.exempt&FLAG('S'))) {
-	if(useron.cdt+useron.freecdt<netmail_cost) {
-		bputs(text[NotEnoughCredits]);
-		return; }
-	sprintf(str,text[NetMailCostContinueQ],netmail_cost);
-	if(noyes(str))
-		return; }
-
-
-now=time(NULL);
-unixtodos(now,&date,&curtime);
-sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
-	,date.da_day,mon[date.da_mon-1],TM_YEAR(date.da_year-1900)
-	,curtime.ti_hour,curtime.ti_min,curtime.ti_sec);
-
-hdr.destzone	=addr.zone;
-hdr.destnet 	=addr.net;
-hdr.destnode	=addr.node;
-hdr.destpoint	=addr.point;
-
-for(i=0;i<total_faddrs;i++)
-	if(addr.zone==faddr[i].zone && addr.net==faddr[i].net)
-        break;
-if(i==total_faddrs) {
-	for(i=0;i<total_faddrs;i++)
-		if(addr.zone==faddr[i].zone)
-			break; }
-if(i==total_faddrs)
-	i=0;
-hdr.origzone	=faddr[i].zone;
-hdr.orignet 	=faddr[i].net;
-hdr.orignode	=faddr[i].node;
-hdr.origpoint	=faddr[i].point;
-
-strcpy(str,faddrtoa(faddr[i]));
-bprintf(text[NetMailing],hdr.to,faddrtoa(addr),hdr.from,str);
-
-hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
-
-if(netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
-if(netmail_misc&NMAIL_HOLD)  hdr.attr|=FIDO_HOLD;
-if(netmail_misc&NMAIL_KILL)  hdr.attr|=FIDO_KILLSENT;
-if(mode&WM_FILE) hdr.attr|=FIDO_FILE;
-
-sprintf(str,"%sNETMAIL.MSG",node_dir);
-remove(str);	/* Just incase it's already there */
-// mode&=~WM_FILE;
-if(!writemsg(str,nulstr,subj,WM_NETMAIL|mode,INVALID_SUB,into)) {
-	bputs(text[Aborted]);
-	return; }
-
-if(mode&WM_FILE) {
-	strcpy(fname,subj);
-	sprintf(str,"%sFILE\\%04u.OUT",data_dir,useron.number);
-	mkdir(str);
-	strcpy(tmp,data_dir);
-	if(tmp[0]=='.')    /* Relative path */
-		sprintf(tmp,"%s%s",node_dir,data_dir);
-	sprintf(str,"%sFILE\\%04u.OUT\\%s",tmp,useron.number,fname);
-	strcpy(subj,str);
-	if(fexist(str)) {
-		bputs(text[FileAlreadyThere]);
-		return; }
-	if(online==ON_LOCAL) {		/* Local upload */
-		bputs(text[EnterPath]);
-		if(!getstr(str,60,K_LINE|K_UPPER)) {
-			bputs(text[Aborted]);
-			return; }
-		backslash(str);
-		strcat(str,fname);
-		if(mv(str,subj,1))
-			return; }
-	else { /* Remote */
-		menu("ULPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(str,"Q");
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && chk_ar(prot[x]->ar,useron)) {
-				sprintf(tmp,"%c",prot[x]->mnemonic);
-				strcat(str,tmp); }
-		ch=getkeys(str,0);
-		if(ch=='Q' || sys_status&SS_ABORT) {
-			bputs(text[Aborted]);
-			return; }
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && prot[x]->mnemonic==ch
-				&& chk_ar(prot[x]->ar,useron))
-				break;
-		if(x<total_prots)	/* This should be always */
-			protocol(cmdstr(prot[x]->ulcmd,subj,nulstr,NULL),0); }
-	l=flength(subj);
-	if(l>0)
-		bprintf(text[FileNBytesReceived],fname,ultoac(l,tmp));
-	else {
-		bprintf(text[FileNotReceived],fname);
-        return; } }
-
-p=subj;
-if((SYSOP || useron.exempt&FLAG('F'))
-	&& !strncmpi(p,"CR:",3)) {     /* Crash over-ride by sysop */
-	p+=3;				/* skip CR: */
-	if(*p==SP) p++; 	/* skip extra space if it exists */
-	hdr.attr|=FIDO_CRASH; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-	&& !strncmpi(p,"FR:",3)) {     /* File request */
-	p+=3;				/* skip FR: */
-	if(*p==SP) p++;
-	hdr.attr|=FIDO_FREQ; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-	&& !strncmpi(p,"RR:",3)) {     /* Return receipt request */
-	p+=3;				/* skip RR: */
-	if(*p==SP) p++;
-	hdr.attr|=FIDO_RRREQ; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-	&& !strncmpi(p,"FA:",3)) {     /* File Attachment */
-	p+=3;				/* skip FA: */
-	if(*p==SP) p++;
-	hdr.attr|=FIDO_FILE; }
-
-sprintf(hdr.subj,"%.71s",p);
-
-sprintf(str,"%sNETMAIL.MSG",node_dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-    close(fido);
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    return; }
-length=filelength(file);
-if((buf=(char *)MALLOC(length))==NULL) {
-    close(fido);
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length);
-    return; }
-read(file,buf,length);
-close(file);
-
-cc_sent=0;
-while(1) {
-	for(i=1;i;i++) {
-		sprintf(str,"%s%u.MSG",netmail_dir,i);
-		if(!fexist(str))
-			break; }
-	if(!i) {
-		bputs(text[TooManyEmailsToday]);
-		return; }
-	if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
-		return; }
-	write(fido,&hdr,sizeof(hdr));
-
-	pt_zone_kludge(hdr,fido);
-
-	if(netmail_misc&NMAIL_DIRECT) {
-		sprintf(str,"\1FLAGS DIR\r\n");
-		write(fido,str,strlen(str)); }
-	if(mode&WM_FILE) {
-		sprintf(str,"\1FLAGS KFS\r\n");
-		write(fido,str,strlen(str)); }
-
-	if(cc_sent) {
-		sprintf(str,"* Originally to: %s\r\n\r\n",into);
-		write(fido,str,strlen(str)); }
-
-	l=0L;
-	while(l<length) {
-		if(buf[l]==1)	/* Ctrl-A, so skip it and the next char */
-			l++;
-		else if(buf[l]!=LF) {
-			if((uchar)buf[l]==0x8d)   /* r0dent i converted to normal i */
-				buf[l]='i';
-			write(fido,buf+l,1); }
-		l++; }
-	l=0;
-	write(fido,&l,1);	/* Null terminator */
-	close(fido);
-
-	if(!(useron.exempt&FLAG('S')))
-		subtract_cdt(netmail_cost);
-	if(mode&WM_FILE)
-		sprintf(str,"Sent NetMail file attachment to %s (%s)"
-			,hdr.to,faddrtoa(addr));
-	else
-		sprintf(str,"Sent NetMail to %s (%s)"
-			,hdr.to,faddrtoa(addr));
-	logline("EN",str);
-
-	cc_found=0;
-	for(l=0;l<length && cc_found<=cc_sent;l++)
-		if(l+3<length && !strnicmp(buf+l,"CC:",3)) {
-			cc_found++;
-			l+=2; }
-		else {
-			while(l<length && *(buf+l)!=LF)
-				l++; }
-	if(!cc_found)
-		break;
-	while(l<length && *(buf+l)==SP) l++;
-	for(i=0;l<length && *(buf+l)!=LF && i<128;i++,l++)
-		str[i]=buf[l];
-	if(!i)
-		break;
-	str[i]=0;
-	p=strrchr(str,'@');
-	if(p) {
-		addr=atofaddr(p+1);
-		*p=0;
-		sprintf(hdr.to,"%.35s",str); }
-	else {
-		atofaddr(str);
-		strcpy(hdr.to,"Sysop"); }
-	hdr.destzone	=addr.zone;
-	hdr.destnet 	=addr.net;
-	hdr.destnode	=addr.node;
-	hdr.destpoint	=addr.point;
-	cc_sent++; }
-
-if(netmail_sem[0])		/* update semaphore file */
-	if((file=nopen(netmail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-		close(file);
-
-FREE(buf);
-}
-
-/****************************************************************************/
-/* Send FidoNet NetMail from QWK REP Packet 								*/
-/****************************************************************************/
-void qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub)
-{
-	char	HUGE16 *qwkbuf,to[129],name[129],sender[129],senderaddr[129]
-		   ,str[256],*p,*cp,*addr,fulladdr[129],ch,buf[SDT_BLOCK_LEN];
-	int 	i,fido,inet=0,qnet=0,x;
-	ushort	net,xlat;
-	long	l,offset,length,m,n;
-	faddr_t fidoaddr;
-    fmsghdr_t hdr;
-	smbmsg_t msg;
-
-if(useron.rest&FLAG('M')) {
-    bputs(text[NoNetMailAllowed]);
-	return; }
-
-sprintf(str,"%.6s",block+116);
-n=atol(str);	  /* i = number of 128 byte records */
-
-if(n<2L || n>999999L) {
-	errormsg(WHERE,ERR_CHK,"QWK blocks",n);
-	return; }
-if((qwkbuf=MALLOC(n*128L))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,n*128L);
-	return; }
-memcpy((char *)qwkbuf,block,128);
-fread(qwkbuf+128,n-1,128,rep);
-
-if(into==NULL)
-	sprintf(to,"%-128.128s",(char *)qwkbuf+128);  /* To user on first line */
-else
-	strcpy(to,into);
-
-p=strchr(to,0xe3);		/* chop off at first CR */
-if(p) *p=0;
-
-strcpy(name,to);
-p=strchr(name,'@');
-if(p) *p=0;
-truncsp(name);
-
-
-p=strrchr(to,'@');       /* Find '@' in name@addr */
-if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { /* QWKnet */
-	qnet=1;
-	*p=0; }
-else if(p==NULL || !isdigit(*(p+1)) || !total_faddrs) {
-	if(p==NULL && dflt_faddr.zone)
-		fidoaddr=dflt_faddr;
-	else if(inetmail_misc&NMAIL_ALLOW) {	/* Internet */
-		inet=1;
-/*
-		if(p)
-			*p=0;				/* Chop off address */
-*/
-		}
-	else if(dflt_faddr.zone)
-		fidoaddr=dflt_faddr;
-	else {
-		bprintf("\1n\r\nInvalid NetMail address.\r\n");
-		FREE(qwkbuf);
-		return; } }
-else {
-	fidoaddr=atofaddr(p+1); 	/* Get fido address */
-	*p=0;					/* Chop off address */
-	}
-
-
-if(!inet && !qnet &&		/* FidoNet */
-	((!SYSOP && !(netmail_misc&NMAIL_ALLOW)) || !total_faddrs)) {
-    bputs(text[NoNetMailAllowed]);
-	FREE(qwkbuf);
-    return; }
-
-truncsp(to);			/* Truncate off space */
-
-if(!stricmp(to,"SBBS") && !SYSOP && qnet) {
-	FREE(qwkbuf);
-	return; }
-
-l=128;					/* Start of message text */
-
-if(qnet || inet) {
-
-	if(into==NULL) {	  /* If name@addr on first line, skip first line */
-		while(l<(n*128L) && (uchar)qwkbuf[l]!=0xe3) l++;
-        l++; }
-
-	memset(&msg,0,sizeof(smbmsg_t));
-    memcpy(msg.hdr.id,"SHD\x1a",4);
-    msg.hdr.version=smb_ver();
-    msg.hdr.when_imported.time=time(NULL);
-    msg.hdr.when_imported.zone=sys_timezone;
-
-	if(fromhub || useron.rest&FLAG('Q')) {
-		net=NET_QWK;
-		smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
-		if(!strncmp((uchar *)qwkbuf+l,"@VIA:",5)) {
-			sprintf(str,"%.128s",qwkbuf+l+5);
-			cp=strchr(str,0xe3);
-			if(cp) *cp=0;
-			l+=strlen(str)+1;
-			cp=str;
-			while(*cp && *cp<=SP) cp++;
-			sprintf(senderaddr,"%s/%s"
-				,fromhub ? qhub[fromhub-1]->id : useron.alias,cp);
-			strupr(senderaddr);
-			smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr); }
-		else {
-			if(fromhub)
-				strcpy(senderaddr,qhub[fromhub-1]->id);
-			else
-				strcpy(senderaddr,useron.alias);
-			strupr(senderaddr);
-			smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr); }
-		sprintf(sender,"%.25s",block+46); }    /* From name */
-	else {	/* Not Networked */
-		msg.hdr.when_written.zone=sys_timezone;
-		sprintf(str,"%u",useron.number);
-        smb_hfield(&msg,SENDEREXT,strlen(str),str);
-		strcpy(sender,(qnet || inetmail_misc&NMAIL_ALIAS)
-			? useron.alias : useron.name);
-		}
-	truncsp(sender);
-	smb_hfield(&msg,SENDER,strlen(sender),sender);
-    if(fromhub)
-        msg.idx.from=0;
-	else
-		msg.idx.from=useron.number;
-	if(!strncmp((uchar *)qwkbuf+l,"@TZ:",4)) {
-		sprintf(str,"%.128s",qwkbuf+l);
-		cp=strchr(str,0xe3);
-		if(cp) *cp=0;
-		l+=strlen(str)+1;
-		cp=str+4;
-		while(*cp && *cp<=SP) cp++;
-		msg.hdr.when_written.zone=(short)ahtoul(cp); }
-	else
-		msg.hdr.when_written.zone=sys_timezone;
-
-    date.da_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
-    date.da_day=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
-    date.da_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf);
-	if(date.da_year<Y2K_2DIGIT_WINDOW)
-		date.da_year+=100;
-	date.da_year+=1900;
-    curtime.ti_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
-    curtime.ti_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf);  /* From QWK time */
-    curtime.ti_sec=0;
-
-    msg.hdr.when_written.time=dostounix(&date,&curtime);
-
-	sprintf(str,"%.25s",block+71);              /* Title */
-	smb_hfield(&msg,SUBJECT,strlen(str),str);
-    strlwr(str);
-	msg.idx.subj=crc16(str); }
-
-if(qnet) {
-
-	p++;
-	addr=p;
-	msg.idx.to=qwk_route(addr,fulladdr);
-	if(!fulladdr[0]) {		/* Invalid address, so BOUNCE it */
-	/**
-		errormsg(WHERE,ERR_CHK,addr,0);
-		FREE(qwkbuf);
-		smb_freemsgmem(msg);
-		return;
-	**/
-		smb_hfield(&msg,SENDER,strlen(sys_id),sys_id);
-		msg.idx.from=0;
-		msg.idx.to=useron.number;
-		strcpy(to,sender);
-		strcpy(fulladdr,senderaddr);
-		sprintf(str,"BADADDR: %s",addr);
-		smb_hfield(&msg,SUBJECT,strlen(str),str);
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-		net=NET_NONE;
-        smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
-	}
-
-	smb_hfield(&msg,RECIPIENT,strlen(name),name);
-	net=NET_QWK;
-	smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
-
-	truncsp(fulladdr);
-	smb_hfield(&msg,RECIPIENTNETADDR,strlen(fulladdr),fulladdr);
-
-	bprintf(text[NetMailing],to,fulladdr,sender,sys_id); }
-
-if(inet) {				/* Internet E-mail */
-
-    if(inetmail_cost && !(useron.exempt&FLAG('S'))) {
-        if(useron.cdt+useron.freecdt<inetmail_cost) {
-            bputs(text[NotEnoughCredits]);
-            FREE(qwkbuf);
-			smb_freemsgmem(&msg);
-            return; }
-        sprintf(str,text[NetMailCostContinueQ],inetmail_cost);
-        if(noyes(str)) {
-            FREE(qwkbuf);
-			smb_freemsgmem(&msg);
-            return; } }
-
-	net=NET_INTERNET;
-	smb_hfield(&msg,RECIPIENT,strlen(name),name);
-    msg.idx.to=0;   /* Out-bound NetMail set to 0 */
-    smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
-	smb_hfield(&msg,RECIPIENTNETADDR,strlen(to),to);
-
-	bprintf(text[NetMailing],name,to
-        ,inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name
-		,sys_inetaddr); }
-
-if(qnet || inet) {
-
-    bputs(text[WritingIndx]);
-
-	if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-		errormsg(WHERE,ERR_OPEN,"MAIL",i);
-		FREE(qwkbuf);
-		smb_freemsgmem(&msg);
-		return; }
-	sprintf(smb.file,"%sMAIL",data_dir);
-	smb.retry_time=smb_retry_time;
-	if((i=smb_open(&smb))!=0) {
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		FREE(qwkbuf);
-		smb_freemsgmem(&msg);
-		return; }
-
-	if(filelength(fileno(smb.shd_fp))<1L) {   /* Create it if it doesn't exist */
-		smb.status.max_crcs=mail_maxcrcs;
-		smb.status.max_msgs=MAX_SYSMAIL;
-		smb.status.max_age=mail_maxage;
-		smb.status.attr=SMB_EMAIL;
-		if((i=smb_create(&smb))!=0) {
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-			errormsg(WHERE,ERR_CREATE,smb.file,i);
-			FREE(qwkbuf);
-			smb_freemsgmem(&msg);
-			return; } }
-
-	length=n*256L;	// Extra big for CRLF xlat, was (n-1L)*256L (03/16/96)
-
-
-	if(length&0xfff00000UL || !length) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		sprintf(str,"REP msg (%ld)",n);
-		errormsg(WHERE,ERR_LEN,str,length);
-		FREE(qwkbuf);
-		smb_freemsgmem(&msg);
-		return; }
-
-	if((i=smb_open_da(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		FREE(qwkbuf);
-		smb_freemsgmem(&msg);
-		return; }
-	if(sys_misc&SM_FASTMAIL)
-		offset=smb_fallocdat(&smb,length,1);
-	else
-		offset=smb_allocdat(&smb,length,1);
-	smb_close_da(&smb);
-
-	fseek(smb.sdt_fp,offset,SEEK_SET);
-	xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	m=2;
-	for(;l<n*128L && m<length;l++) {
-		if(qwkbuf[l]==0 || qwkbuf[l]==LF)
-			continue;
-		if((uchar)qwkbuf[l]==0xe3) {
-			fwrite(crlf,2,1,smb.sdt_fp);
-			m+=2;
-			continue; }
-		fputc(qwkbuf[l],smb.sdt_fp);
-		m++; }
-
-	for(ch=0;m<length;m++)			/* Pad out with NULLs */
-		fputc(ch,smb.sdt_fp);
-	fflush(smb.sdt_fp);
-
-	msg.hdr.offset=offset;
-
-	smb_dfield(&msg,TEXT_BODY,length);
-
-	i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-
-	smb_freemsgmem(&msg);
-	if(i) {
-		smb_freemsgdat(&smb,offset,length,1);
-		errormsg(WHERE,ERR_WRITE,smb.file,i); }
-	else {		/* Successful */
-		if(inet) {
-			if(inetmail_sem[0]) 	 /* update semaphore file */
-				if((fido=nopen(inetmail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-					close(fido);
-			if(!(useron.exempt&FLAG('S')))
-				subtract_cdt(inetmail_cost); }
-		sprintf(str,"Sent %s NetMail to %s (%s) via QWK"
-			,qnet ? "QWK":"Internet",name,qnet ? fulladdr : to);
-		logline("EN",str); }
-
-	FREE((char *)qwkbuf);
-	return; }
-
-
-/****************************** FidoNet **********************************/
-
-if(!fidoaddr.zone || !netmail_dir[0]) {  // No fido netmail allowed
-	bprintf("\1n\r\nInvalid NetMail address.\r\n");
-	FREE(qwkbuf);
-	return; }
-
-memset(&hdr,0,sizeof(hdr));   /* Initialize header to null */
-
-if(fromhub || useron.rest&FLAG('Q')) {
-	sprintf(str,"%.25s",block+46);              /* From */
-	truncsp(str);
-	sprintf(tmp,"@%s",fromhub ? qhub[fromhub-1]->id : useron.alias);
-	strupr(tmp);
-	strcat(str,tmp); }
-else
-	strcpy(str,netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
-sprintf(hdr.from,"%.35s",str);
-
-sprintf(hdr.to,"%.35s",to);
-
-/* Look-up in nodelist? */
-
-if(netmail_cost && !(useron.exempt&FLAG('S'))) {
-	if(useron.cdt+useron.freecdt<netmail_cost) {
-		bputs(text[NotEnoughCredits]);
-		FREE(qwkbuf);
-		return; }
-	sprintf(str,text[NetMailCostContinueQ],netmail_cost);
-	if(noyes(str)) {
-		FREE(qwkbuf);
-		return; } }
-
-hdr.destzone	=fidoaddr.zone;
-hdr.destnet 	=fidoaddr.net;
-hdr.destnode	=fidoaddr.node;
-hdr.destpoint	=fidoaddr.point;
-
-for(i=0;i<total_faddrs;i++)
-	if(fidoaddr.zone==faddr[i].zone && fidoaddr.net==faddr[i].net)
-        break;
-if(i==total_faddrs) {
-	for(i=0;i<total_faddrs;i++)
-		if(fidoaddr.zone==faddr[i].zone)
-			break; }
-if(i==total_faddrs)
-	i=0;
-hdr.origzone	=faddr[i].zone;
-hdr.orignet 	=faddr[i].net;
-hdr.orignode	=faddr[i].node;
-hdr.origpoint   =faddr[i].point;
-
-strcpy(str,faddrtoa(faddr[i]));
-bprintf(text[NetMailing],hdr.to,faddrtoa(fidoaddr),hdr.from,str);
-
-date.da_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
-date.da_day=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
-date.da_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf);
-if(date.da_year<Y2K_2DIGIT_WINDOW)
-	date.da_year+=100;
-date.da_year+=1900;
-curtime.ti_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
-curtime.ti_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf);		/* From QWK time */
-curtime.ti_sec=0;
-sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"          /* To FidoNet */
-	,date.da_day,mon[date.da_mon-1],TM_YEAR(date.da_year-1900)
-	,curtime.ti_hour,curtime.ti_min,curtime.ti_sec);
-
-hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
-
-if(netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
-if(netmail_misc&NMAIL_HOLD)  hdr.attr|=FIDO_HOLD;
-if(netmail_misc&NMAIL_KILL)  hdr.attr|=FIDO_KILLSENT;
-
-sprintf(str,"%.25s",block+71);      /* Title */
-truncsp(str);
-p=str;
-if((SYSOP || useron.exempt&FLAG('F'))
-    && !strncmpi(p,"CR:",3)) {     /* Crash over-ride by sysop */
-    p+=3;               /* skip CR: */
-    if(*p==SP) p++;     /* skip extra space if it exists */
-    hdr.attr|=FIDO_CRASH; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-    && !strncmpi(p,"FR:",3)) {     /* File request */
-    p+=3;               /* skip FR: */
-    if(*p==SP) p++;
-    hdr.attr|=FIDO_FREQ; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-    && !strncmpi(p,"RR:",3)) {     /* Return receipt request */
-    p+=3;               /* skip RR: */
-    if(*p==SP) p++;
-    hdr.attr|=FIDO_RRREQ; }
-
-if((SYSOP || useron.exempt&FLAG('F'))
-	&& !strncmpi(p,"FA:",3)) {     /* File attachment */
-	p+=3;				/* skip FA: */
-    if(*p==SP) p++;
-	hdr.attr|=FIDO_FILE; }
-
-sprintf(hdr.subj,"%.71s",p);
-
-for(i=1;i;i++) {
-	sprintf(str,"%s%u.MSG",netmail_dir,i);
-	if(!fexist(str))
-		break; }
-if(!i) {
-	bputs(text[TooManyEmailsToday]);
-	return; }
-if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
-	FREE(qwkbuf);
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
-	return; }
-write(fido,&hdr,sizeof(hdr));
-
-pt_zone_kludge(hdr,fido);
-
-if(netmail_misc&NMAIL_DIRECT) {
-	sprintf(str,"\1FLAGS DIR\r\n");
-    write(fido,str,strlen(str)); }
-
-l=128L;
-
-if(into==NULL) {	  /* If name@addr on first line, skip first line */
-	while(l<n*128L && (uchar)qwkbuf[l]!=0xe3) l++;
-	l++; }
-
-while(l<n*128L) {
-	if(qwkbuf[l]==1)   /* Ctrl-A, so skip it and the next char */
-		l++;
-	else if(qwkbuf[l]!=LF) {
-		if((uchar)qwkbuf[l]==0xe3) /* QWK cr/lf char converted to hard CR */
-			qwkbuf[l]=CR;
-		write(fido,(char *)qwkbuf+l,1); }
-	l++; }
-l=0;
-write(fido,&l,1);	/* Null terminator */
-close(fido);
-FREE((char *)qwkbuf);
-if(netmail_sem[0])		/* update semaphore file */
-	if((fido=nopen(netmail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-		close(fido);
-if(!(useron.exempt&FLAG('S')))
-	subtract_cdt(netmail_cost);
-sprintf(str,"Sent NetMail to %s @%s via QWK",hdr.to,faddrtoa(fidoaddr));
-logline("EN",str);
-}
-
diff --git a/src/sbbs2/fido/crc16.c b/src/sbbs2/fido/crc16.c
deleted file mode 100644
index dc899629401fb12ee443dd2dd22c36c65911c731..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/crc16.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* CRC16.C */
-
-/* 16-bit CRC routines */
-
-#include "smblib.h"
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
diff --git a/src/sbbs2/fido/crc32.h b/src/sbbs2/fido/crc32.h
deleted file mode 100644
index a5d5162fb2fbae6acfb7b5a18d0502d2d1339b93..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/crc32.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 32-bit CRC */
-
-long crc32tbl[]={	/* CRC polynomial 0xedb88320 */
-0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-#define ucrc32(ch,crc) (crc32tbl[(crc^ch)&0xff]^(crc>>8))
-
-
diff --git a/src/sbbs2/fido/file_id.diz b/src/sbbs2/fido/file_id.diz
deleted file mode 100644
index b03fe6269fbf1cc4ec9e84a572d384b69fd2df03..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/file_id.diz
+++ /dev/null
@@ -1,3 +0,0 @@
-SBBSFIDO v2.23 - Fixes 32-bit LZH decoding
-and OS/2 NOPEN error. No change for DOS16.
-Includes DOS, OS/2, and 32-bit DOS versions.
diff --git a/src/sbbs2/fido/lzh.c b/src/sbbs2/fido/lzh.c
deleted file mode 100644
index 2d21e4d55f31cdbac167a0d9f772f5d0d7d7ddbe..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/lzh.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/* LZH.C */
-
-/* Digital Dynamics conversion of 1988 LZH (LHarc) encoding functions	*/
-/* Based on Japanese version 29-NOV-1988								*/
-/* LZSS coded by Haruhiko Okumura										*/
-/* Adaptive Huffman Coding coded by Haruyasu Yoshizaki					*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifndef __WATCOMC__
-	#include <alloc.h>
-#endif
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-	#if defined(__TURBOC__)
-		#define REALLOC(x,y) farrealloc(x,y)
-		#define LMALLOC(x) farmalloc(x)
-		#define MALLOC(x) farmalloc(x)
-		#define LFREE(x) farfree(x)
-		#define FREE(x) farfree(x)
-	#elif defined(__WATCOMC__)
-		#define REALLOC realloc
-		#define LMALLOC(x) halloc(x,1)	/* far heap, but slow */
-		#define MALLOC malloc			/* far heap, but 64k max */
-		#define LFREE hfree
-		#define FREE free
-	#else	/* Other 16-bit Compiler */
-		#define REALLOC realloc
-		#define LMALLOC malloc
-		#define MALLOC malloc
-		#define LFREE free
-		#define FREE free
-	#endif
-#else		/* 32-bit Compiler or Small Memory Model */
-	#define REALLOC realloc
-	#define LMALLOC malloc
-	#define MALLOC malloc
-	#define LFREE free
-	#define FREE free
-#endif
-
-
-
-typedef unsigned char uchar;
-
-/* LZSS Parameters */
-
-#define LZH_N			4096	/* Size of string buffer */
-#define LZH_F			60		/* Size of look-ahead buffer */
-#define LZH_THRESHOLD	2
-#define LZH_NIL 		LZH_N	/* End of tree's node  */
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned char *lzh_text_buf;
-short int	lzh_match_position, lzh_match_length,
-	  *lzh_lson, *lzh_rson, *lzh_dad;
-
-#else
-
-unsigned char lzh_text_buf[LZH_N + LZH_F - 1];
-short int	  lzh_match_position, lzh_match_length,
-		lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
-
-#endif
-
-
-void lzh_init_tree(void)  /* Initializing tree */
-{
-	short int  i;
-
-	for (i = LZH_N + 1; i <= LZH_N + 256; i++)
-		lzh_rson[i] = LZH_NIL;			/* root */
-	for (i = 0; i < LZH_N; i++)
-		lzh_dad[i] = LZH_NIL;			/* node */
-}
-
-/******************************/
-/* Inserting node to the tree */
-/* Only used during encoding  */
-/******************************/
-void lzh_insert_node(short int r)
-{
-	short int  i, p, cmp;
-	unsigned char  *key;
-	unsigned c;
-
-	cmp = 1;
-	key = lzh_text_buf+r;
-	p = LZH_N + 1 + key[0];
-	lzh_rson[r] = lzh_lson[r] = LZH_NIL;
-	lzh_match_length = 0;
-	for ( ; ; ) {
-		if (cmp >= 0) {
-			if (lzh_rson[p] != LZH_NIL)
-				p = lzh_rson[p];
-			else {
-				lzh_rson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		} else {
-			if (lzh_lson[p] != LZH_NIL)
-				p = lzh_lson[p];
-			else {
-				lzh_lson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		}
-		for (i = 1; i < LZH_F; i++)
-			if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
-				break;
-		if (i > LZH_THRESHOLD) {
-			if (i > lzh_match_length) {
-				lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
-				if ((lzh_match_length = i) >= LZH_F)
-					break;
-			}
-			if (i == lzh_match_length) {
-				if ((c = ((r - p) & (LZH_N - 1)) - 1) < lzh_match_position) {
-					lzh_match_position = c;
-				}
-			}
-		}
-	}
-	lzh_dad[r] = lzh_dad[p];
-	lzh_lson[r] = lzh_lson[p];
-	lzh_rson[r] = lzh_rson[p];
-	lzh_dad[lzh_lson[p]] = r;
-	lzh_dad[lzh_rson[p]] = r;
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = r;
-	else
-		lzh_lson[lzh_dad[p]] = r;
-	lzh_dad[p] = LZH_NIL;  /* remove p */
-}
-
-void lzh_delete_node(short int p)  /* Deleting node from the tree */
-{
-	short int  q;
-
-	if (lzh_dad[p] == LZH_NIL)
-		return;			/* unregistered */
-	if (lzh_rson[p] == LZH_NIL)
-		q = lzh_lson[p];
-	else
-	if (lzh_lson[p] == LZH_NIL)
-		q = lzh_rson[p];
-	else {
-		q = lzh_lson[p];
-		if (lzh_rson[q] != LZH_NIL) {
-			do {
-				q = lzh_rson[q];
-			} while (lzh_rson[q] != LZH_NIL);
-			lzh_rson[lzh_dad[q]] = lzh_lson[q];
-			lzh_dad[lzh_lson[q]] = lzh_dad[q];
-			lzh_lson[q] = lzh_lson[p];
-			lzh_dad[lzh_lson[p]] = q;
-		}
-		lzh_rson[q] = lzh_rson[p];
-		lzh_dad[lzh_rson[p]] = q;
-	}
-	lzh_dad[q] = lzh_dad[p];
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = q;
-	else
-		lzh_lson[lzh_dad[p]] = q;
-	lzh_dad[p] = LZH_NIL;
-}
-
-/* Huffman coding parameters */
-
-#define LZH_N_CHAR		(256 - LZH_THRESHOLD + LZH_F)
-					/* character code (= 0..LZH_N_CHAR-1) */
-#define LZH_T		(LZH_N_CHAR * 2 - 1)	/* Size of table */
-#define LZH_R		(LZH_T - 1) 		/* root position */
-#define MAX_FREQ	0x8000
-					/* update when cumulative frequency */
-					/* reaches to this value */
-
-/*
- * Tables for encoding/decoding upper 6 bits of
- * sliding dictionary pointer
- */
-/* encoder table */
-uchar lzh_p_len[64] = {
-	0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-uchar lzh_p_code[64] = {
-	0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
-	0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
-	0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
-	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
-	0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
-	0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
-	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
-};
-
-/* decoder table */
-uchar lzh_d_code[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
-	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
-	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
-	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
-	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
-	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
-	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
-	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
-	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
-	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
-	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
-	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
-	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
-	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
-};
-
-uchar lzh_d_len[256] = {
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-};
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned short *lzh_freq=NULL;	 /* cumulative freq table */
-
-/*
- * pointing parent nodes.
- * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
- */
-short int *lzh_prnt=NULL;
-
-/* pointing children nodes (son[], son[] + 1)*/
-short int *lzh_son=NULL;
-
-#else	/* STATIC */
-
-unsigned short lzh_freq[LZH_T + 1];   /* cumulative freq table */
-short int lzh_prnt[LZH_T + LZH_N_CHAR];
-short int lzh_son[LZH_T + 1];		  /* bug fixed by Digital Dynamics */
-
-#endif
-
-
-unsigned short lzh_getbuf = 0;		/* Was just "unsigned" fixed 04/12/95 */
-uchar lzh_getlen = 0;
-
-int lzh_getbit(uchar *inbuf, long *incnt, long inlen)    /* get one bit */
-{
-	short int i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 1;
-	lzh_getlen--;
-	return (i < 0);
-}
-
-short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen)   /* get a byte */
-{
-	unsigned short i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 8;
-	lzh_getlen -= 8;
-	return i >> 8;
-}
-
-unsigned lzh_putbuf = 0;
-uchar lzh_putlen = 0;
-
-/* output c bits */
-void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen)
-{
-	lzh_putbuf |= c >> lzh_putlen;
-	if ((lzh_putlen += l) >= 8) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-		if ((lzh_putlen -= 8) >= 8) {
-			outbuf[(*outlen)++]=lzh_putbuf;
-			lzh_putlen -= 8;
-			lzh_putbuf = c << (l - lzh_putlen);
-		} else {
-			lzh_putbuf <<= 8;
-		}
-	}
-}
-
-
-/* initialize freq tree */
-
-void lzh_start_huff()
-{
-	short int i, j;
-
-lzh_getbuf = 0; 	/* Added by Digital Dynamics for repeating operations */
-lzh_getlen = 0;
-lzh_putbuf = 0;
-lzh_putlen = 0;
-
-	for (i = 0; i < LZH_N_CHAR; i++) {
-		lzh_freq[i] = 1;
-		lzh_son[i] = i + LZH_T;
-		lzh_prnt[i + LZH_T] = i;
-	}
-	i = 0; j = LZH_N_CHAR;
-	while (j <= LZH_R) {
-		lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
-		lzh_son[j] = i;
-		lzh_prnt[i] = lzh_prnt[i + 1] = j;
-		i += 2; j++;
-	}
-	lzh_freq[LZH_T] = 0xffff;
-    lzh_prnt[LZH_R] = 0;
-}
-
-
-/* reconstruct freq tree */
-
-void lzh_reconst()
-{
-	short int i, j, k;
-	unsigned short f, l;
-
-	/* halven cumulative freq for leaf nodes */
-	j = 0;
-	for (i = 0; i < LZH_T; i++) {
-		if (lzh_son[i] >= LZH_T) {
-			lzh_freq[j] = (lzh_freq[i] + 1) / 2;
-			lzh_son[j] = lzh_son[i];
-			j++;
-		}
-	}
-	/* make a tree : first, connect children nodes */
-	for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
-		k = i + 1;
-		f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
-		for (k = j - 1; f < lzh_freq[k]; k--);
-		k++;
-		l = (j - k) * 2;
-		
-		/* movmem() is Turbo-C dependent
-		   rewritten to memmove() by Kenji */
-		
-		/* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
-		(void)memmove(lzh_freq+k+1,lzh_freq+k, l);
-		lzh_freq[k] = f;
-		/* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
-		(void)memmove(lzh_son+k+1,lzh_son+k, l);
-		lzh_son[k] = i;
-	}
-	/* connect parent nodes */
-	for (i = 0; i < LZH_T; i++) {
-		if ((k = lzh_son[i]) >= LZH_T) {
-			lzh_prnt[k] = i;
-		} else {
-			lzh_prnt[k] = lzh_prnt[k + 1] = i;
-		}
-	}
-}
-
-/* update freq tree */
-
-void lzh_update(short int c)
-{
-	short int i, j, k, l;
-
-	if (lzh_freq[LZH_R] == MAX_FREQ) {
-		lzh_reconst();
-	}
-	c = lzh_prnt[c + LZH_T];
-	do {
-		k = ++lzh_freq[c];
-
-		/* swap nodes to keep the tree freq-ordered */
-		if (k > lzh_freq[l = c + 1]) {
-			while (k > lzh_freq[++l]);
-			l--;
-			lzh_freq[c] = lzh_freq[l];
-			lzh_freq[l] = k;
-
-			i = lzh_son[c];
-			lzh_prnt[i] = l;
-			if (i < LZH_T) lzh_prnt[i + 1] = l;
-
-			j = lzh_son[l];
-			lzh_son[l] = i;
-
-			lzh_prnt[j] = c;
-			if (j < LZH_T) lzh_prnt[j + 1] = c;
-			lzh_son[c] = j;
-
-			c = l;
-		}
-	} while ((c = lzh_prnt[c]) != 0);	/* do it until reaching the root */
-}
-
-unsigned short lzh_code, lzh_len;
-
-void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-	short int j, k;
-
-	i = 0;
-	j = 0;
-	k = lzh_prnt[c + LZH_T];
-
-	/* search connections from leaf node to the root */
-	do {
-		i >>= 1;
-
-		/*
-		if node's address is odd, output 1
-		else output 0
-		*/
-		if (k & 1) i += 0x8000;
-
-		j++;
-	} while ((k = lzh_prnt[k]) != LZH_R);
-	lzh_putcode(j, i, outbuf, outlen);
-	lzh_code = i;
-	lzh_len = j;
-	lzh_update(c);
-}
-
-void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-
-	/* output upper 6 bits with encoding */
-	i = c >> 6;
-	lzh_putcode(lzh_p_len[i], (unsigned)lzh_p_code[i] << 8, outbuf, outlen);
-
-	/* output lower 6 bits directly */
-	lzh_putcode(6, (c & 0x3f) << 10, outbuf, outlen);
-}
-
-void lzh_encode_end(uchar *outbuf, long *outlen)
-{
-	if (lzh_putlen) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-	}
-}
-
-short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short c;
-
-	c = lzh_son[LZH_R];
-
-	/*
-	 * start searching tree from the root to leaves.
-	 * choose node #(lzh_son[]) if input bit == 0
-	 * else choose #(lzh_son[]+1) (input bit == 1)
-	 */
-	while (c < LZH_T) {
-		c += lzh_getbit(inbuf,incnt,inlen);
-		c = lzh_son[c];
-	}
-	c -= LZH_T;
-	lzh_update(c);
-	return c;
-}
-
-short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short i, j, c;
-
-	/* decode upper 6 bits from given table */
-	i = lzh_getbyte(inbuf,incnt,inlen);
-	c = (unsigned)lzh_d_code[i] << 6;
-	j = lzh_d_len[i];
-
-	/* input lower 6 bits directly */
-	j -= 2;
-	while (j--) {
-		i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
-	}
-	return c | i & 0x3f;
-}
-
-/* Compression */
-
-/* Encoding/Compressing */
-/* Returns length of outbuf */
-long lzh_encode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, c, len, r, s, last_match_length;
-	long incnt,outlen; /* textsize=0; */
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		return(-1); }
-	if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		FREE(lzh_lson);
-		return(-1); }
-	if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-		FREE(lzh_rson);
-		return(-1); }
-#endif
-
-	incnt=0;
-	memcpy(outbuf,&inlen,sizeof(inlen));
-	outlen=sizeof(inlen);
-	if(!inlen) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-        FREE(lzh_rson);
-		FREE(lzh_dad);
-#endif
-		return(outlen); }
-	lzh_start_huff();
-	lzh_init_tree();
-	s = 0;
-	r = LZH_N - LZH_F;
-	for (i = s; i < r; i++)
-		lzh_text_buf[i] = ' ';
-	for (len = 0; len < LZH_F && incnt<inlen; len++)
-		lzh_text_buf[r + len] = inbuf[incnt++];
-	/* textsize = len; */
-	for (i = 1; i <= LZH_F; i++)
-		lzh_insert_node(r - i);
-	lzh_insert_node(r);
-	do {
-		if (lzh_match_length > len)
-			lzh_match_length = len;
-		if (lzh_match_length <= LZH_THRESHOLD) {
-			lzh_match_length = 1;
-			lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
-		} else {
-			lzh_encode_char(255 - LZH_THRESHOLD + lzh_match_length
-				,outbuf,&outlen);
-			lzh_encode_position(lzh_match_position
-				,outbuf,&outlen);
-		}
-		last_match_length = lzh_match_length;
-		for (i = 0; i < last_match_length && incnt<inlen; i++) {
-			lzh_delete_node(s);
-			c=inbuf[incnt++];
-			lzh_text_buf[s] = c;
-			if (s < LZH_F - 1)
-				lzh_text_buf[s + LZH_N] = c;
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			lzh_insert_node(r);
-		}
-/***
-		if ((textsize += i) > printcount) {
-			printf("%12ld\r", textsize);
-			printcount += 1024;
-		}
-***/
-		while (i++ < last_match_length) {
-			lzh_delete_node(s);
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			if (--len) lzh_insert_node(r);
-		}
-	} while (len > 0);
-	lzh_encode_end(outbuf,&outlen);
-/*
-	printf("input: %ld (%ld) bytes\n", inlen,textsize);
-	printf("output: %ld bytes\n", outlen);
-	printf("output/input: %.3f\n", (double)outlen / inlen);
-*/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-	FREE(lzh_lson);
-	FREE(lzh_rson);
-	FREE(lzh_dad);
-#endif
-
-	return(outlen);
-}
-
-/* Decoding/Uncompressing */
-/* Returns length of outbuf */
-long lzh_decode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, j, k, r, c;
-	unsigned long int  count;
-	long incnt,textsize;
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short)))
-		==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-
-#endif
-
-	incnt=0;
-	memcpy(&textsize,inbuf,sizeof(textsize));
-	incnt+=sizeof(textsize);
-	if (textsize == 0) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-#endif
-		return(textsize); }
-	lzh_start_huff();
-	for (i = 0; i < LZH_N - LZH_F; i++)
-		*(lzh_text_buf+i) = ' ';
-	r = LZH_N - LZH_F;
-    for (count = 0; count < textsize; ) {
-		c = lzh_decode_char(inbuf,&incnt,inlen);
-		if (c < 256) {
-			outbuf[count]=c;
-#if 0
-			if(r>(LZH_N + LZH_F - 1) || r<0) {
-				printf("Overflow! (%d)\n",r);
-				getch();
-				exit(-1); }
-#endif
-			*(lzh_text_buf+r) = c;
-			r++;
-			r &= (LZH_N - 1);
-			count++;
-		} else {
-			i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
-				& (LZH_N - 1);
-			j = c - 255 + LZH_THRESHOLD;
-			for (k = 0; k < j && count<textsize; k++) {
-				c = lzh_text_buf[(i + k) & (LZH_N - 1)];
-				outbuf[count]=c;
-#if 0
-				if(r>(LZH_N + LZH_F - 1) || r<0) {
-					printf("Overflow! (%d)\n",r);
-					exit(-1); }
-#endif
-				*(lzh_text_buf+r) = c;
-				r++;
-				r &= (LZH_N - 1);
-				count++;
-			}
-		}
-	}
-/***
-	printf("%12ld\n", count);
-***/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-#endif
-
-return(count);
-}
-
-
diff --git a/src/sbbs2/fido/lzh.h b/src/sbbs2/fido/lzh.h
deleted file mode 100644
index 68a71dd90c338ec888128735e99829fefdb02856..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/lzh.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* LZH.H */
-
-long lzh_encode(uchar *inbuf, long inlen, uchar *outbuf);
-long lzh_decode(uchar *inbuf, long inlen, uchar *outbuf);
-
diff --git a/src/sbbs2/fido/makeall.bat b/src/sbbs2/fido/makeall.bat
deleted file mode 100755
index d8896214fe42c6dd9a3c39b166e1b0aa63b5aa28..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/makeall.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-wmake
-if errorlevel 1 goto end
-wmake OS=DOSX
-if errorlevel 1 goto end
-wmake OS=OS2
-:end
diff --git a/src/sbbs2/fido/makefile b/src/sbbs2/fido/makefile
deleted file mode 100644
index 472e9e275db50858e572e2aca57851a93fd7b1ea..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/makefile
+++ /dev/null
@@ -1,78 +0,0 @@
-############################################
-# Makefile for Synchronet SBBSFIDO Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;..;..\smb
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -s -ml
-!else
-CFLAGS	= -I$(INCLUDE) -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -s
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\sbbsfido.exe
-OBJS	= $(OS)\sbbsfido.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\smblib.obj $(OS)\smbvars.obj $(OS)\ars.obj $(OS)\lzh.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-          ..\smb\smbdefs.h ..\smb\smblib.h ..\smb\smbvars.c
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-	@echo Linking $[@ ...
-        $(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-		    ..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\smbvars.obj: ..\smb\smbvars.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\lzh.obj: ..\smb\lzh.c ..\smb\lzh.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h 
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
diff --git a/src/sbbs2/fido/makefile.bc b/src/sbbs2/fido/makefile.bc
deleted file mode 100644
index 27f1c3e38755980d4b591cd192ae7b7bfbfa25e8..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/makefile.bc
+++ /dev/null
@@ -1,88 +0,0 @@
-############################################
-# Makefile for Synchronet SBBSFIDO Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC	= bcc
-LD	= tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE)
-LFLAGS  = -c
-!else
-OS      = DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -N -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-!endif
-MAIN	= $(OS)\sbbsfido.exe
-OBJS	= $(OS)\sbbsfido.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj\
-	  $(OS)\scfglib2.obj\
-	  $(OS)\smblib.obj $(OS)\smbvars.obj $(OS)\ars.obj $(OS)\lzh.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c \
-          ..\smb\smbdefs.h ..\smb\smblib.h ..\smb\smbvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS)   
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_FILE_CFG
--DNO_XTRN_CFG
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib2.c ..\scfgvars.c
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_FILE_CFG
--DNO_XTRN_CFG
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-#$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-#	@echo Compiling SMBLIB ...
-#	$(CC) $(CFLAGS) -n$(OS) -c ..\smb\smblib.c
-
-#$(OS)\smbvars.obj: ..\smb\smbvars.c ..\smb\smblib.h ..\smb\smbdefs.h
-#	@echo Compiling SMBVARS ...
-#	$(CC) $(CFLAGS) -n$(OS) -c ..\smb\smbvars.c
-
-#$(OS)\lzh.obj: ..\smb\lzh.c ..\smb\lzh.h
-#        @echo Compiling LZH ...
-#	$(CC) $(CFLAGS) -n$(OS) -c ..\smb\lzh.c
-
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h 
-        @echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -n$(OS) -c ..\ars.c
-
diff --git a/src/sbbs2/fido/sbbsfido.c b/src/sbbs2/fido/sbbsfido.c
deleted file mode 100644
index 35ed292f76675b28ec535b04bd29480d8c292712..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/sbbsfido.c
+++ /dev/null
@@ -1,1909 +0,0 @@
-/* SBBSFIDO.C */
-
-/* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
-
-#define VER "2.24"
-
-#include "sbbs.h"
-#include "crc32.h"
-#include "lzh.h"
-#include "post.h"
-#include "scfglib.h"
-
-#define IMPORT_NETMAIL	(1L<<0)
-#define IMPORT_ECHOMAIL (1L<<1)
-#define EXPORT_ECHOMAIL (1L<<2)
-#define DELETE_NETMAIL	(1L<<3)
-#define DELETE_ECHOMAIL (1L<<4)
-#define IGNORE_POINT	(1L<<5)
-#define IGNORE_ZONE 	(1L<<6)
-#define IGNORE_MSGPTRS	(1L<<7)
-#define UPDATE_MSGPTRS	(1L<<8)
-#define LEAVE_MSGPTRS	(1L<<9)
-#define KILL_ECHOMAIL	(1L<<10)
-#define ASCII_ONLY		(1L<<11)
-#define LOGFILE 		(1L<<12)
-#define REPORT			(1L<<13)
-#define EXPORT_ALL		(1L<<14)
-#define PURGE_ECHOMAIL	(1L<<15)
-#define UNKNOWN_NETMAIL (1L<<16)
-#define IGNORE_ADDRESS	(1L<<17)
-#define IMPORT_LOCAL	(1L<<18)
-#define IMPORT_NEW_ONLY (1L<<19)
-#define DONT_SET_RECV	(1L<<20)
-#define IGNORE_RECV 	(1L<<21)
-#define CONVERT_TEAR	(1L<<22)
-#define IMPORT_PRIVATE	(1L<<23)
-#define LOCAL_NETMAIL	(1L<<24)
-#define NOTIFY_RECEIPT	(1L<<25)
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-
-long misc=(IMPORT_NETMAIL|IMPORT_ECHOMAIL|EXPORT_ECHOMAIL
-			|DELETE_NETMAIL|DELETE_ECHOMAIL|KILL_ECHOMAIL);
-char tmp[256];
-
-FILE *fidologfile=NULL;
-#ifdef __TURBOC__
-	unsigned _stklen=20000;
-#endif
-int startmsg=1;
-int nodefile;
-
-#ifdef __WATCOMC__
-	#define O_DENYNONE SH_DENYNO
-#endif
-
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-if(misc&LOGFILE && fidologfile!=NULL)
-    fputs(str,fidologfile);
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-/******************************************/
-/* CRC-16 routines required for SMB index */
-/******************************************/
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(uint number, node_t *node, char lockit)
-{
-	char str[256];
-	int count=0;
-
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count==LOOP_NODEDAB)
-	lprintf("\7Error unlocking and reading NODE.DAB\r\n");
-}
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(uint number, node_t node)
-{
-	char str[256];
-	int count;
-
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	lprintf("\7Error writing NODE.DAB for node %u\r\n",number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-
-
-/****************************************************************************/
-/* Creates a short message for 'usernumber' than contains 'strin'			*/
-/****************************************************************************/
-void putsmsg(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-    node_t node;
-
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	lprintf("\7Error opening/creating %s for creat/append access\r\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-	close(file);
-	lprintf("\7Error writing %u bytes to %s\r\n",i,str);
-	return; }
-close(file);
-for(i=1;i<=sys_nodes;i++) {		/* flag node if user on that msg waiting */
-	getnodedat(i,&node,0);
-	if(node.useron==usernumber
-		&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
-		&& !(node.misc&NODE_MSGW)) {
-		getnodedat(i,&node,1);
-		node.misc|=NODE_MSGW;
-        putnodedat(i,node); } }
-}
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access&O_DENYNONE) {
-	share=SH_DENYNO;
-	access&=~O_DENYNONE; }
-else if(access==O_RDONLY) share=SH_DENYWR;
-else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-
-/****************************************************************************/
-/* Moves or copies a file from one dir to another                           */
-/* both 'src' and 'dest' must contain full path and filename                */
-/* returns 0 if successful, -1 if error                                     */
-/****************************************************************************/
-int mv(char *src, char *dest, char copy)
-{
-	char buf[4096],str[256];
-	int  ind,outd;
-	long length,chunk=4096,l;
-	ushort ftime,fdate;
-    FILE *inp,*outp;
-
-if(!strcmp(src,dest))	/* source and destination are the same! */
-	return(0);
-if(!fexist(src)) {
-	lprintf("\r\nMV ERROR: Source doesn't exist\r\n'%s'\r\n"
-		,src);
-	return(-1); }
-if(!copy && fexist(dest)) {
-	lprintf("\r\nMV ERROR: Destination already exists\r\n'%s'\r\n"
-		,dest);
-	return(-1); }
-if(!copy && ((src[1]!=':' && dest[1]!=':')
-	|| (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
-	if(rename(src,dest)) {						/* same drive, so move */
-		lprintf("\r\nMV ERROR: Error renaming '%s'"
-				"\r\n                      to '%s'\r\n",src,dest);
-		return(-1); }
-	return(0); }
-if((ind=nopen(src,O_RDONLY))==-1) {
-	lprintf("\r\nMV ERROR: ERR_OPEN %s\r\n",src);
-	return(-1); }
-if((inp=fdopen(ind,"rb"))==NULL) {
-	close(ind);
-	lprintf("\r\nMV ERROR: ERR_FDOPEN %s\r\n",str);
-	return(-1); }
-setvbuf(inp,NULL,_IOFBF,8*1024);
-if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-	fclose(inp);
-	lprintf("\r\nMV ERROR: ERR_OPEN %s\r\n",dest);
-	return(-1); }
-if((outp=fdopen(outd,"wb"))==NULL) {
-	close(outd);
-	fclose(inp);
-	lprintf("\r\nMV ERROR: ERR_FDOPEN %s\r\n",str);
-	return(-1); }
-setvbuf(outp,NULL,_IOFBF,8*1024);
-length=filelength(ind);
-l=0L;
-while(l<length) {
-	if(l+chunk>length)
-		chunk=length-l;
-	fread(buf,chunk,1,inp);
-	fwrite(buf,chunk,1,outp);
-	l+=chunk; }
-_dos_getftime(ind,&fdate,&ftime);
-_dos_setftime(outd,fdate,ftime);
-fclose(inp);
-fclose(outp);
-if(!copy && remove(src)) {
-	lprintf("MV ERROR: ERR_REMOVE %s\r\n",src);
-	return(-1); }
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the total number of msgs in the sub-board and sets 'ptr' to the  */
-/* date of the last message in the sub (0) if no messages.					*/
-/****************************************************************************/
-ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
-{
-	char str[256];
-	int i;
-	smbstatus_t status;
-
-sprintf(smb_file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-if((i=smb_open(10))!=0) {
-	lprintf("ERR_OPEN %s %d\r\n",smb_file,i);
-	return(0); }
-
-if(!filelength(fileno(shd_fp))) {			/* Empty base */
-	if(ptr) (*ptr)=0;
-	smb_close();
-	return(0); }
-if((i=smb_locksmbhdr(10))!=0) {
-	smb_close();
-	lprintf("ERR_LOCK %s %d\r\n",smb_file,i);
-	return(0); }
-if((i=smb_getstatus(&status))!=0) {
-	smb_unlocksmbhdr();
-	smb_close();
-	lprintf("ERR_READ %s %d\r\n",smb_file,i);
-	return(0); }
-smb_unlocksmbhdr();
-smb_close();
-if(ptr) (*ptr)=status.last_msg;
-return(status.total_msgs);
-}
-
-
-ulong loadmsgs(post_t HUGE16 **post, ulong ptr)
-{
-	int i;
-	long l=0;
-	idxrec_t idx;
-
-
-if((i=smb_locksmbhdr(10))!=0) { 				/* Be sure noone deletes or */
-	lprintf("ERR_LOCK %s %d\r\n",smb_file,i);   /* adds while we're reading */
-	return(0L); }
-
-fseek(sid_fp,0L,SEEK_SET);
-while(!feof(sid_fp)) {
-    if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
-        break;
-
-	if(idx.number<=ptr || idx.attr&MSG_DELETE)
-		continue;
-
-	if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED))
-		break;
-
-	if(((*post)=(post_t HUGE16 *)REALLOC((*post),sizeof(post_t)*(l+1)))
-        ==NULL) {
-		smb_unlocksmbhdr();
-		lprintf("ERR_ALLOC %s %lu\r\n",smb_file,sizeof(post_t *)*(l+1));
-		return(l); }
-	(*post)[l].offset=idx.offset;
-	(*post)[l].number=idx.number;
-	l++; }
-smb_unlocksmbhdr();
-return(l);
-}
-
-
-void allocfail(uint size)
-{
-lprintf("\7Error allocating %u bytes of memory.\r\n",size);
-bail(1);
-}
-
-void bail(int code)
-{
-exit(code);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct find_t f;
-
-if(!findfirst(filespec,&f,0))
-	return(f.size);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-
-if(!findfirst(filespec,&f,0))
-    return(1);
-return(0);
-}
-
-typedef struct {
-	ulong	alias,
-			real;
-			} username_t;
-
-/****************************************************************************/
-/* Note: Wrote another version of this function that read all userdata into */
-/****************************************************************************/
-/* Looks for a perfect match amoung all usernames (not deleted users)		*/
-/* Returns the number of the perfect matched username or 0 if no match		*/
-/* Called from functions waitforcall and newuser							*/
-/* memory then scanned it from memory... took longer - always.              */
-/****************************************************************************/
-ulong matchname(char *inname)
-{
-	static ulong total_users;
-	static username_t *username;
-	int userdat,file,i;
-	char str[256],c;
-	ulong l,crc;
-	FILE *namedat;
-
-if(!total_users) {		/* Load CRCs */
-	fprintf(stderr,"%-25s","Loading user names...");
-	sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-	if((namedat=fnopen(&file,str,O_RDONLY))==NULL)
-		return(0);
-	sprintf(str,"%sUSER\\USER.DAT",data_dir);
-	if((userdat=nopen(str,O_RDONLY|O_DENYNONE))==-1) {
-		fclose(namedat);
-		return(0); }
-	while(!feof(namedat) && !eof(userdat)) {
-		if(!fread(str,LEN_ALIAS+2,1,namedat))
-			break;
-		if((username=(username_t *)REALLOC(username
-			,(total_users+1)*sizeof(username_t)))==NULL)
-			break;
-
-		for(c=0;c<LEN_ALIAS;c++)
-			if(str[c]==ETX) break;
-		str[c]=0;
-		strlwr(str);
-		username[total_users].alias=crc32(str);
-		i=0;
-		while(i<LOOP_NODEDAB
-			&& lock(userdat,(long)((long)(total_users)*U_LEN)+U_NAME
-				,LEN_NAME)==-1) {
-			i++; }
-		if(i>=LOOP_NODEDAB) 	   /* Couldn't lock USER.DAT record */
-			continue;
-		lseek(userdat,(long)((long)(total_users)*U_LEN)+U_NAME,SEEK_SET);
-		read(userdat,str,LEN_NAME);
-		unlock(userdat,(long)((long)(total_users)*U_LEN)+U_NAME,LEN_NAME);
-		for(c=0;c<LEN_NAME;c++)
-			if(str[c]==ETX || str[c]==CR) break;
-		str[c]=0;
-		strlwr(str);
-		username[total_users].real=crc32(str);
-		total_users++; }
-	fclose(namedat);
-	close(userdat);
-	fprintf(stderr,
-		"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
-		"%25s"
-		"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
-		,""); }
-
-strcpy(str,inname);
-strlwr(str);
-crc=crc32(str);
-for(l=0;l<total_users;l++)
-	if(crc==username[l].alias || crc==username[l].real)
-		return(l+1);
-return(0);
-}
-
-/****************************************************************************/
-/* Converts goofy FidoNet time format into Unix format						*/
-/****************************************************************************/
-time_t fmsgtime(char *str)
-{
-	char month[4];
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-if(isdigit(str[1])) {	/* Regular format: "01 Jan 86  02:34:56" */
-	tm.tm_mday=atoi(str);
-	sprintf(month,"%3.3s",str+3);
-	if(!stricmp(month,"jan"))
-		tm.tm_mon=0;
-	else if(!stricmp(month,"feb"))
-		tm.tm_mon=1;
-	else if(!stricmp(month,"mar"))
-		tm.tm_mon=2;
-	else if(!stricmp(month,"apr"))
-		tm.tm_mon=3;
-	else if(!stricmp(month,"may"))
-		tm.tm_mon=4;
-	else if(!stricmp(month,"jun"))
-		tm.tm_mon=5;
-	else if(!stricmp(month,"jul"))
-		tm.tm_mon=6;
-	else if(!stricmp(month,"aug"))
-		tm.tm_mon=7;
-	else if(!stricmp(month,"sep"))
-		tm.tm_mon=8;
-	else if(!stricmp(month,"oct"))
-		tm.tm_mon=9;
-	else if(!stricmp(month,"nov"))
-		tm.tm_mon=10;
-	else
-		tm.tm_mon=11;
-	tm.tm_year=atoi(str+7);
-	tm.tm_hour=atoi(str+11);
-	tm.tm_min=atoi(str+14);
-	tm.tm_sec=atoi(str+17); }
-
-else {					/* SEAdog  format: "Mon  1 Jan 86 02:34" */
-	tm.tm_mday=atoi(str+4);
-	sprintf(month,"%3.3s",str+7);
-	if(!stricmp(month,"jan"))
-		tm.tm_mon=0;
-	else if(!stricmp(month,"feb"))
-		tm.tm_mon=1;
-	else if(!stricmp(month,"mar"))
-		tm.tm_mon=2;
-	else if(!stricmp(month,"apr"))
-		tm.tm_mon=3;
-	else if(!stricmp(month,"may"))
-		tm.tm_mon=4;
-	else if(!stricmp(month,"jun"))
-		tm.tm_mon=5;
-	else if(!stricmp(month,"jul"))
-		tm.tm_mon=6;
-	else if(!stricmp(month,"aug"))
-		tm.tm_mon=7;
-	else if(!stricmp(month,"sep"))
-		tm.tm_mon=8;
-	else if(!stricmp(month,"oct"))
-		tm.tm_mon=9;
-	else if(!stricmp(month,"nov"))
-		tm.tm_mon=10;
-	else
-		tm.tm_mon=11;
-	tm.tm_year=atoi(str+11);
-	tm.tm_hour=atoi(str+14);
-	tm.tm_min=atoi(str+17);
-	tm.tm_sec=0; }
-
-if(tm.tm_year<70)
-	tm.tm_year+=100;
-
-return(mktime(&tm));
-}
-
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-faddr_t atofaddr(char *str)
-{
-    char *p;
-    faddr_t addr;
-
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-    addr.zone=atoi(str);
-    addr.net=atoi(p+1); }
-else {
-    if(total_faddrs)
-		addr.zone=faddr[0].zone;
-    else
-        addr.zone=1;
-    addr.net=atoi(str); }
-if(!addr.zone)              /* no such thing as zone 0 */
-    addr.zone=1;
-if((p=strchr(str,'/'))!=NULL)
-    addr.node=atoi(p+1);
-else {
-    if(total_faddrs)
-		addr.net=faddr[0].net;
-    else
-        addr.net=1;
-    addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL)
-    addr.point=atoi(p+1);
-return(addr);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(faddr_t addr)
-{
-    static char str[25];
-    char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-    sprintf(point,".%u",addr.point);
-    strcat(str,point); }
-return(str);
-}
-
-#ifndef __OS2__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char HUGE16 *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-
-/****************************************************************************/
-/* Coverts a FidoNet message into a Synchronet message						*/
-/****************************************************************************/
-void fmsgtosmsg(int file, fmsghdr_t fmsghdr, smbstatus_t status, uint user
-	,uint subnum)
-{
-	uchar	ch,HUGE16 *fbuf,HUGE16 *sbody,HUGE16 *stail,HUGE16 *outbuf
-			,done,col,esc,cr,*p,str[128];
-	int 	i,chunk,lzh=0,storage;
-	ushort	xlat,net;
-	ulong	l,m,length,lzhlen,bodylen,taillen,crc;
-	faddr_t faddr,origaddr,destaddr;
-	smbmsg_t	msg;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=SMB_VERSION;
-if(fmsghdr.attr&FIDO_PRIVATE)
-	msg.idx.attr|=MSG_PRIVATE;
-msg.hdr.attr=msg.idx.attr;
-
-if(fmsghdr.attr&FIDO_FILE)
-	msg.hdr.auxattr|=MSG_FILEATTACH;
-
-msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_imported.zone=sys_timezone;
-msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
-
-origaddr.zone=fmsghdr.origzone; 	/* only valid if NetMail */
-origaddr.net=fmsghdr.orignet;
-origaddr.node=fmsghdr.orignode;
-origaddr.point=fmsghdr.origpoint;
-
-destaddr.zone=fmsghdr.destzone; 	/* only valid if NetMail */
-destaddr.net=fmsghdr.destnet;
-destaddr.node=fmsghdr.destnode;
-destaddr.point=fmsghdr.destpoint;
-
-smb_hfield(&msg,SENDER,strlen(fmsghdr.from),fmsghdr.from);
-strlwr(fmsghdr.from);
-msg.idx.from=crc16(fmsghdr.from);
-
-smb_hfield(&msg,RECIPIENT,strlen(fmsghdr.to),fmsghdr.to);
-strlwr(fmsghdr.to);
-msg.idx.to=crc16(fmsghdr.to);
-
-if(user) {
-	sprintf(str,"%u",user);
-	smb_hfield(&msg,RECIPIENTEXT,strlen(str),str);
-	msg.idx.to=user;
-	msg.idx.from=0; }
-
-smb_hfield(&msg,SUBJECT,strlen(fmsghdr.subj),fmsghdr.subj);
-remove_re(fmsghdr.subj);
-strlwr(fmsghdr.subj);
-msg.idx.subj=crc16(fmsghdr.subj);
-
-length=filelength(file)-sizeof(fmsghdr_t);
-if((fbuf=(char *)LMALLOC(length+1))==NULL) {
-	printf("alloc error\r\n");
-	smb_freemsgmem(msg);
-	return; }
-if((sbody=(char *)LMALLOC((length+1)*2L))==NULL) {
-	printf("alloc error\n");
-	LFREE((char *)fbuf);
-	smb_freemsgmem(msg);
-	return; }
-if((stail=(char *)LMALLOC((length+1)*2L))==NULL) {
-	printf("alloc error\n");
-	LFREE((char *)fbuf);
-	LFREE((char *)sbody);
-	smb_freemsgmem(msg);
-	return; }
-lread(file,fbuf,length);
-
-for(col=l=esc=done=bodylen=taillen=0,cr=1;l<length;l++) {
-	ch=fbuf[l];
-	if(ch==1 && cr) {	/* kludge line */
-
-		if(!strncmp((char *)fbuf+l+1,"TOPT ",5))
-			destaddr.point=atoi((char *)fbuf+l+6);
-
-		else if(!strncmp((char *)fbuf+l+1,"FMPT ",5))
-			origaddr.point=atoi((char *)fbuf+l+6);
-
-		else if(!strncmp((char *)fbuf+l+1,"INTL ",5)) {
-			faddr=atofaddr((char *)fbuf+l+6);
-			destaddr.zone=faddr.zone;
-			destaddr.net=faddr.net;
-			destaddr.node=faddr.node;
-			l+=6;
-			while(l<length && fbuf[l]!=SP) l++;
-			faddr=atofaddr((char *)fbuf+l+1);
-			origaddr.zone=faddr.zone;
-			origaddr.net=faddr.net;
-			origaddr.node=faddr.node; }
-
-		else if(!strncmp((char *)fbuf+l+1,"MSGID:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOMSGID,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"REPLY:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOREPLYID,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"FLAGS:",6)) {
-			l+=7;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOFLAGS,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"PATH:",5)) {
-			l+=6;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOPATH,m-l,fbuf+l); }
-
-		else if(!strncmp((char *)fbuf+l+1,"PID:",4)) {
-			l+=5;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOPID,m-l,fbuf+l); }
-
-		else {		/* Unknown kludge line */
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOCTRL,m-l,fbuf+l); }
-
-		while(l<length && fbuf[l]!=CR) l++;
-		continue; }
-
-	if(ch!=LF && ch!=0x8d) {	/* ignore LF and soft CRs */
-		if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
-			|| !strncmp((char *)fbuf+l,"---\r",4)))
-			done=1; 			/* tear line and down go into tail */
-		if(done && cr && !strncmp((char *)fbuf+l,"SEEN-BY:",8)) {
-			l+=8;
-			while(l<length && fbuf[l]<=SP) l++;
-			m=l;
-			while(m<length && fbuf[m]!=CR) m++;
-			while(m && fbuf[m-1]<=SP) m--;
-			if(m>l)
-				smb_hfield(&msg,FIDOSEENBY,m-l,fbuf+l);
-			while(l<length && fbuf[l]!=CR) l++;
-			continue; }
-		if(done)
-			stail[taillen++]=ch;
-		else
-			sbody[bodylen++]=ch;
-		col++;
-		if(ch==CR) {
-			cr=1;
-			col=0;
-			if(done)
-				stail[taillen++]=LF;
-			else
-				sbody[bodylen++]=LF; }
-		else {
-			cr=0;
-			if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
-				p=strchr((char *)fbuf+l+11,CR); 	 /* find carriage return */
-				while(p && *p!='(') p--;     /* rewind to '(' */
-				if(p)
-					origaddr=atofaddr(p+1); 	/* get orig address */
-				done=1; }
-			if(done)
-				continue;
-
-			if(ch==ESC) esc=1;		/* ANSI codes */
-			if(ch==SP && col>40 && !esc) {	/* word wrap */
-				for(m=l+1;m<length;m++) 	/* find next space */
-					if(fbuf[m]<=SP)
-						break;
-				if(m<length && m-l>80-col) {  /* if it's beyond the eol */
-					sbody[bodylen++]=CR;
-					sbody[bodylen++]=LF;
-					col=0; } }
-			} } }
-
-LFREE(fbuf);
-
-if(bodylen>=2 && sbody[bodylen-2]==CR && sbody[bodylen-1]==LF)
-	bodylen-=2; 						/* remove last CRLF if present */
-
-if(status.max_crcs) {
-	for(l=0,crc=0xffffffff;l<bodylen;l++)
-		crc=ucrc32(sbody[l],crc);
-	crc=~crc;
-
-	i=smb_addcrc(status.max_crcs,crc,10);
-	if(i) {
-		if(i==1)
-			lprintf("Duplicate message\r\n");
-		else
-			lprintf("smb_addcrc returned %d\r\n",i);
-		smb_freemsgmem(msg);
-		LFREE(sbody);
-		LFREE(stail);
-		return; } }
-
-while(taillen && stail[taillen-1]<=SP)	/* trim all garbage off the tail */
-	taillen--;
-
-net=NET_FIDO;	/* Record origin address */
-smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
-smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr);
-
-if(subnum==INVALID_SUB) { /* No origin line means NetMail, so add dest addr */
-	smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
-	smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr); }
-
-if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_LZH
-	&& bodylen+2+taillen+2>=SDT_BLOCK_LEN && bodylen) {
-	if((outbuf=(char *)LMALLOC(bodylen*2))==NULL) {
-		printf("alloc error for lzh: %lu\n",bodylen*2);
-		smb_freemsgmem(msg);
-		LFREE(sbody);
-		LFREE(stail);
-		return; }
-	lzhlen=lzh_encode((uchar *)sbody,bodylen,(uchar *)outbuf);
-	if(lzhlen>1 &&
-		smb_datblocks(lzhlen+4+taillen+2)<smb_datblocks(bodylen+2+taillen+2)) {
-		bodylen=lzhlen; 	/* Compressable */
-		l=bodylen+4;
-		LFREE(sbody);
-		lzh=1;
-		sbody=outbuf; }
-	else {					/* Uncompressable */
-		l=bodylen+2;
-		LFREE(outbuf); } }
-else
-	l=bodylen+2;
-
-if(taillen)
-	l+=(taillen+2);
-
-
-if(status.attr&SMB_HYPERALLOC) {
-	if((i=smb_locksmbhdr(10))!=0) {
-		printf("smb_locksmbhdr returned %d\n",i);
-		smb_freemsgmem(msg);
-		LFREE(sbody);
-		LFREE(stail);
-		return; }
-	msg.hdr.offset=smb_hallocdat();
-	storage=SMB_HYPERALLOC; }
-else {
-	if(smb_open_da(10)) {
-		smb_freemsgmem(msg);
-		printf("error opening %s.SDA\r\n",smb_file);
-		LFREE(sbody);
-		LFREE(stail);
-		return; }
-	if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_FAST) {
-		msg.hdr.offset=smb_fallocdat(l,1);
-		storage=SMB_FASTALLOC; }
-	else {
-		msg.hdr.offset=smb_allocdat(l,1);
-		storage=SMB_SELFPACK; }
-	fclose(sda_fp); }
-
-if(msg.hdr.offset && msg.hdr.offset<1L) {
-	smb_unlocksmbhdr();
-	smb_freemsgmem(msg);
-	LFREE(sbody);
-	LFREE(stail);
-	printf("error %ld allocating records\r\n",msg.hdr.offset);
-	return; }
-fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
-if(lzh) {
-	xlat=XLAT_LZH;
-	fwrite(&xlat,2,1,sdt_fp); }
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,sdt_fp);
-chunk=30000;
-for(l=0;l<bodylen;l+=chunk) {
-	if(l+chunk>bodylen)
-		chunk=bodylen-l;
-	fwrite(sbody+l,1,chunk,sdt_fp); }
-if(taillen) {
-	fwrite(&xlat,2,1,sdt_fp);
-	fwrite(stail,1,taillen,sdt_fp); }
-fflush(sdt_fp);
-LFREE(sbody);
-LFREE(stail);
-
-if(status.attr&SMB_HYPERALLOC)
-	smb_unlocksmbhdr();
-
-if(lzh)
-	bodylen+=2;
-bodylen+=2;
-smb_dfield(&msg,TEXT_BODY,bodylen);
-if(taillen)
-	smb_dfield(&msg,TEXT_TAIL,taillen+2);
-
-smb_addmsghdr(&msg,&status,storage,10);
-smb_freemsgmem(msg);
-}
-
-/****************************************************************/
-/* Get zone and point from kludge lines in 'file' if they exist */
-/****************************************************************/
-void getzpt(int file, fmsghdr_t *hdr)
-{
-	char buf[0x1000];
-	int i,len,cr=0;
-	faddr_t faddr;
-
-len=read(file,buf,0x1000);
-for(i=0;i<len;i++) {
-	if((!i || cr) && buf[i]==1) {	/* kludge */
-		if(!strncmp(buf+i+1,"TOPT ",5))
-			hdr->destpoint=atoi(buf+i+6);
-		else if(!strncmp(buf+i+1,"FMPT ",5))
-			hdr->origpoint=atoi(buf+i+6);
-		else if(!strncmp(buf+i+1,"INTL ",5)) {
-			faddr=atofaddr(buf+i+6);
-			hdr->destzone=faddr.zone;
-			hdr->destnet=faddr.net;
-			hdr->destnode=faddr.node;
-			i+=6;
-			while(buf[i] && buf[i]!=SP) i++;
-			faddr=atofaddr(buf+i+1);
-			hdr->origzone=faddr.zone;
-			hdr->orignet=faddr.net;
-			hdr->orignode=faddr.node; }
-		while(i<len && buf[i]!=CR) i++;
-		cr=1;
-		continue; }
-	if(buf[i]==CR)
-		cr=1;
-	else
-		cr=0; }
-lseek(file,sizeof(fmsghdr_t),SEEK_SET);
-}
-
-/***********************************/
-/* Synchronet/FidoNet Message util */
-/***********************************/
-int main(int argc, char **argv)
-{
-	char	ch,str[512],fname[256],touser[512],subj[512],path[512],sub_code[9]
-			,*p,*tp,*sp,*buf,*outbuf,cr,tear,lzh;
-	ushort	xlat;
-	int 	i,j,k,n,x,last,file,fmsg,nextmsg,g;
-	ulong	files,msgfiles,echomail=0,netmail=0,exported=0,crc,
-			l,m,length,lastmsg,posts,msgs,exp;
-	time_t	ptr,now,start,lastimport;
-	read_cfg_text_t txt;
-	struct	find_t ff;
-	struct	tm tm,*tm_p;
-	fmsghdr_t hdr;
-	faddr_t addr,sys_faddr;
-	post_t	HUGE16 *post;
-	FILE	*stream,*fstream;
-	smbstatus_t status;
-	smbmsg_t msg;
-
-lprintf("\nSynchronet <=> FidoNet Utility  Version %s  "
-	"Developed by Rob Swindell\n",VER);
-
-putenv("TZ=UCT0");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-txt.openerr="\7\r\nError opening %s for read.\r\n";
-txt.reading="\r\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
-txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
-
-node_dir[0]=sub_code[0]=0;
-for(i=1;i<argc;i++) {
-	if(argv[i][0]=='/') {
-		j=1;
-		while(argv[i][j]) {
-			switch(toupper(argv[i][j])) {
-				case 'A':
-                    misc|=ASCII_ONLY;
-                    break;
-				case 'B':
-					misc|=LOCAL_NETMAIL;
-					break;
-				case 'C':
-                    misc|=PURGE_ECHOMAIL;
-                    break;
-				case 'D':
-                    misc&=~DELETE_NETMAIL;
-                    break;
-				case 'E':
-                    misc&=~EXPORT_ECHOMAIL;
-                    break;
-				case 'F':
-                    misc|=IMPORT_LOCAL;
-                    break;
-				case 'G':
-                    misc|=IMPORT_NEW_ONLY;
-                    break;
-				case 'H':
-                    misc|=EXPORT_ALL;
-                    break;
-				case 'I':
-                    misc&=~IMPORT_ECHOMAIL;
-                    break;
-                case 'J':
-                    misc|=IGNORE_RECV;
-                    break;
-				case 'K':
-                    misc&=~KILL_ECHOMAIL;
-                    break;
-                case 'L':
-                    misc|=LOGFILE;
-                    break;
-				case 'M':
-                    misc|=IGNORE_MSGPTRS;
-                    break;
-				case 'N':
-					misc&=~IMPORT_NETMAIL;
-					break;
-				case 'O':
-                    misc|=IGNORE_ADDRESS;
-                    break;
-				case 'P':
-					misc|=IGNORE_POINT;
-					break;
-				case 'Q':
-					misc|=DONT_SET_RECV;
-					break;
-				case 'R':
-                    misc|=REPORT;
-                    break;
-				case 'S':
-                    misc|=IMPORT_PRIVATE;
-                    break;
-				case 'T':
-                    misc|=LEAVE_MSGPTRS;
-                    break;
-                case 'U':
-                    misc|=UPDATE_MSGPTRS;
-                    misc&=~EXPORT_ECHOMAIL;
-                    break;
-				case 'X':
-                    misc&=~DELETE_ECHOMAIL;
-                    break;
-                case 'Y':
-                    misc|=UNKNOWN_NETMAIL;
-                    break;
-				case 'Z':
-                    misc|=IGNORE_ZONE;
-                    break;
-
-				case '=':
-					misc|=CONVERT_TEAR;
-					break;
-				case '!':
-					misc|=NOTIFY_RECEIPT;
-					break;
-				case '2':
-					startmsg=2;
-					break;
-				default:
-					printf("\nusage: sbbsfido [sbbsnode] [/switches] "
-						"[sub_code]");
-					printf("\nwhere: sbbsnode is the path for your "
-						"NODE1 directory (example: c:\\sbbs\\node1)\n");
-					printf("       sub_code is the internal code for a "
-						"sub-board (default is ALL subs)\n");
-					printf("\nvalid switches:\n\n");
-					printf("n:do not import netmail               "
-						   "i:do not import echomail\n");
-					printf("p:ignore point in netmail address     "
-						   "e:do not export echomail\n");
-					printf("z:ignore zone in netmail address      "
-						   "h:export all echomail (hub rescan)\n");
-					printf("o:ignore entire netmail address       "
-						   "m:ignore message pointers (export all)\n");
-					printf("y:import netmail for unknown users    "
-						   "u:update message pointers (export none)\n");
-					printf("d:do not delete netmail after import  "
-						   "x:do not delete echomail after import\n");
-					printf("l:output to SBBSFIDO.LOG (verbose)    "
-						   "k:do not kill echomail after export\n");
-					printf("r:create report of import totals      "
-						   "t:do not update message pointers\n");
-					printf("a:export ASCII characters only        "
-						   "c:delete all messages (echomail purge)\n");
-					printf("j:ignore recieved bit on import       "
-						   "s:import private override (strip pvt)\n");
-					printf("q:do not set received bit on import   "
-                           "g:import new echomail only\n");
-					printf("b:import locally created netmail too  "
-                           "f:import locally created echomail too\n");
-					printf("=:change existing tear lines to ===   "
-                           "2:export/import/delete starting at 2.MSG\n");
-					printf("!:notify users of received echomail\n");
-					exit(0); }
-			j++; } }
-	else {
-		if(strchr(argv[i],'\\') || argv[i][1]==':')
-			sprintf(node_dir,"%.40s",argv[i]);
-		else
-			sprintf(sub_code,"%.8s",argv[i]); }  }
-
-if(!node_dir[0]) {
-	p=getenv("SBBSNODE");
-	if(p==NULL) {
-		printf("\7\nSBBSNODE environment variable not set.\n");
-		exit(1); }
-	strcpy(node_dir,p); }
-
-strupr(node_dir);
-
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,ctrl_dir,40))
-		strcpy(ctrl_dir,str); }
-backslash(ctrl_dir);
-
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,data_dir,40))
-		strcpy(data_dir,str); }
-backslash(data_dir);
-if(text_dir[0]=='.') {   /* Relative path */
-	strcpy(str,text_dir);
-	sprintf(text_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,text_dir,40))
-		strcpy(text_dir,str); }
-backslash(text_dir);
-read_msgs_cfg(txt);
-
-if(total_faddrs<1) {
-	sys_faddr.zone=sys_faddr.net=sys_faddr.node=1;
-	sys_faddr.point=0; }
-else
-	sys_faddr=faddr[0];
-
-
-if(misc&LOGFILE)
-	if((fidologfile=fnopen(&i,"SBBSFIDO.LOG"
-		,O_WRONLY|O_APPEND|O_CREAT))==NULL) {
-		lprintf("\7ERROR opening SBBSFIDO.LOG\r\n");
-		exit(1); }
-
-sprintf(str,"%s%s",ctrl_dir,"NODE.DAB");
-if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO))==-1) {
-	lprintf("\r\n\7Error opening %s\r\n",str);
-    exit(1); }
-
-if(misc&IMPORT_NETMAIL) {
-
-lputs("\r\n\r\nScanning for Inbound NetMail...\r\n");
-
-sprintf(smb_file,"%sMAIL",data_dir);
-if((i=smb_open(10))!=0) {
-	lprintf("Error %d opening %s\r\n",i,smb_file);
-	exit(1); }
-
-if(!filelength(fileno(shd_fp)))
-	if((i=smb_create(mail_maxcrcs,MAX_SYSMAIL,mail_maxage,SMB_EMAIL,10))!=0) {
-		lprintf("Error %d creating %s\r\n",i,smb_file);
-		exit(1); }
-
-if((i=smb_locksmbhdr(10))!=0) {
-	lprintf("Error %d locking %s\r\n",i,smb_file);
-	exit(1); }
-if((i=smb_getstatus(&status))!=0) {
-	lprintf("Error %d reading %s status header\r\n",i,smb_file);
-	exit(1); }
-smb_unlocksmbhdr();
-
-sprintf(str,"%s*.MSG",netmail_dir);
-
-for(last=findfirst(str,&ff,0);!last;last=findnext(&ff)) {
-	sprintf(path,"%s%s",netmail_dir,ff.name);
-	strupr(path);
-	lprintf("\r%s    ",path);
-	if((fmsg=nopen(path,O_RDWR))==-1) {
-		lprintf("\7ERROR opening");
-		continue; }
-	if(filelength(fmsg)<sizeof(fmsghdr_t)) {
-		lprintf("\7Invalid length of %u bytes\r\n",filelength(fmsg));
-		close(fmsg);
-		continue; }
-	if(read(fmsg,&hdr,sizeof(fmsghdr_t))!=sizeof(fmsghdr_t)) {
-		close(fmsg);
-		lprintf("\7ERROR reading %u bytes"
-			,sizeof(fmsghdr_t));
-		continue; }
-	if(hdr.attr&FIDO_ORPHAN) {
-		close(fmsg);
-		lprintf("Orphan (%s).\r\n",hdr.to);
-		continue; }
-	if(misc&IGNORE_ZONE)				/* default to system's zone */
-		hdr.destzone=hdr.origzone=sys_faddr.zone;
-	if(misc&IGNORE_POINT)				/* default to no point */
-		hdr.destpoint=hdr.origpoint=0;
-	getzpt(fmsg,&hdr);					/* use kludge if found */
-	for(i=0;i<total_faddrs;i++)
-		if(hdr.destzone==faddr[i].zone
-			&& hdr.destnet==faddr[i].net
-			&& hdr.destnode==faddr[i].node
-			&& hdr.destpoint==faddr[i].point)
-			break;
-	lprintf("%u:%u/%u.%u  "
-		,hdr.destzone,hdr.destnet,hdr.destnode,hdr.destpoint);
-	if(misc&IGNORE_ADDRESS || i<total_faddrs) {
-		if(!(misc&IGNORE_RECV) && hdr.attr&FIDO_RECV) {
-            close(fmsg);
-			lputs("Already received.\r\n");
-            continue; }
-		if(hdr.attr&FIDO_LOCAL && !(misc&LOCAL_NETMAIL)) {
-			close(fmsg);
-			lputs("Created locally.\r\n");
-			continue; }
-		i=atoi(hdr.to);
-		if(!stricmp(hdr.to,"SYSOP"))  /* NetMail to "sysop" goes to #1 */
-			i=1;
-		if(!i)
-			i=matchname(hdr.to);
-		if(!i) {
-			if(misc&UNKNOWN_NETMAIL)	/* receive unknown user mail to 1 */
-				i=1;
-			else {
-				lprintf("\7ERROR unknown user '%s'\r\n",hdr.to);
-				hdr.attr|=FIDO_ORPHAN;
-				lseek(fmsg,0L,SEEK_SET);
-				write(fmsg,&hdr,sizeof(fmsghdr_t));
-				close(fmsg);
-				continue; } }
-		lprintf("%s\r\n",hdr.to);
-
-		/*********************/
-		/* Importing NetMail */
-		/*********************/
-
-		fmsgtosmsg(fmsg,hdr,status,i,INVALID_SUB);
-
-		addr.zone=hdr.origzone;
-		addr.net=hdr.orignet;
-		addr.node=hdr.orignode;
-		addr.point=hdr.origpoint;
-		sprintf(str,"\7\1n\1hSBBSFIDO: \1m%.36s \1n\1msent you NetMail from "
-			"\1h%s\1n\r\n"
-			,hdr.from,faddrtoa(addr));
-		putsmsg(i,str);
-
-		if(hdr.attr&FIDO_FILE) {	/* File attachment */
-			strcpy(subj,hdr.subj);
-			tp=subj;
-			while(1) {
-				p=strchr(tp,SP);
-				if(p) *p=0;
-				sp=strrchr(tp,'/');              /* sp is slash pointer */
-				if(!sp) sp=strrchr(tp,'\\');
-				if(sp) tp=sp+1;
-				sprintf(str,"%s%s",fidofile_dir,tp);
-				sprintf(tmp,"%sFILE\\%04u.IN",data_dir,i);
-				mkdir(tmp);
-				strcat(tmp,"\\");
-				strcat(tmp,tp);
-				mv(str,tmp,0);
-				if(!p)
-					break;
-				tp=p+1; } }
-		netmail++;
-
-		/***************************/
-		/* Updating message header */
-		/***************************/
-		if(!(misc&DONT_SET_RECV)) {
-			hdr.attr|=FIDO_RECV;
-			lseek(fmsg,0L,SEEK_SET);
-			write(fmsg,&hdr,sizeof(fmsghdr_t)); }
-
-		/**************************************/
-		/* Delete source netmail if specified */
-		/**************************************/
-		close(fmsg);
-		if(misc&DELETE_NETMAIL)
-			remove(path); }
-	else
-		close(fmsg); }
-smb_close(); }
-
-
-if(misc&IMPORT_ECHOMAIL) {
-
-start=time(NULL);
-
-lputs("\r\n\r\nScanning for Inbound EchoMail...\r\n");
-
-sprintf(path,"%sSBBSFIDO.DAB",data_dir);
-if((file=nopen(path,O_RDWR|O_CREAT))==-1)
-	lastimport=0L;
-else {
-	read(file,&lastimport,4);
-	now=time(NULL);
-	lseek(file,0L,SEEK_SET);
-	write(file,&now,4);
-	close(file); }
-
-for(g=files=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		if(sub_code[0] && stricmp(sub_code,sub[i]->code))
-			continue;
-		if(!sub[i]->echopath[0])
-			sprintf(sub[i]->echopath,"%s%s\\",echomail_dir,sub[i]->code);
-		if(files) {
-			lputs("\r\n");
-			files=0; }
-		lprintf("\r\n%-15.15s %s\r\n"
-			,grp[sub[i]->grp]->sname,sub[i]->lname);
-
-		sprintf(path,"%s*.MSG",sub[i]->echopath);
-		l=findfirst(path,&ff,0);
-		if(startmsg==2 && !strcmp(ff.name,"1.MSG"))
-			l=findnext(&ff);
-		if(l)
-			continue;
-		lprintf("Counting %s",path);
-		msgfiles=0;
-		while(!l) {
-			memset(&tm,0,sizeof(tm));
-			tm.tm_mday=ff.wr_date&31;
-			tm.tm_mon=(ff.wr_date>>5)&15;
-			tm.tm_year=80+((ff.wr_date>>9)&127);
-			tm.tm_hour=(ff.wr_time>>11)&31;
-			tm.tm_min=(ff.wr_time>>5)&63;
-			tm.tm_sec=(ff.wr_time&0x1f)<<1;
-			if(isdigit(ff.name[0])
-				&& !(startmsg==2 && !strcmp(ff.name,"1.MSG"))
-				&& !(misc&IMPORT_NEW_ONLY && mktime(&tm)<=lastimport))
-				msgfiles++; 		/* msgfiles= messages to import */
-			l=findnext(&ff); }
-
-		lprintf("\r\n%u messages.\r\n",msgfiles);
-		if(!msgfiles)				/* no messages, so continue. */
-			continue;
-
-		sprintf(smb_file,"%s%s",sub[i]->data_dir,sub[i]->code);
-		if((j=smb_open(10))!=0) {
-			lprintf("Error %d opening %s\r\n",j,smb_file);
-			continue; }
-		if(!filelength(fileno(shd_fp)))
-			if((j=smb_create(sub[i]->maxcrcs,sub[i]->maxmsgs
-				,sub[i]->maxage
-				,sub[i]->misc&SUB_HYPER ? SMB_HYPERALLOC:0
-				,10))!=0) {
-				lprintf("Error %d creating %s\r\n",j,smb_file);
-				smb_close();
-				continue; }
-
-		if((j=smb_locksmbhdr(10))!=0) {
-			lprintf("Error %d locking SMB header\r\n",j);
-			smb_close();
-			continue; }
-		if((j=smb_getstatus(&status))!=0) {
-			lprintf("Error %d reading SMB header\r\n",j);
-			smb_close();
-			continue; }
-		smb_unlocksmbhdr();
-
-		for(l=startmsg;l<0x8000 && msgfiles;l++) {
-			sprintf(path,"%s%lu.MSG",sub[i]->echopath,l);
-			if(findfirst(path,&ff,0))	/* doesn't exist */
-				continue;				/* was break */
-			tm.tm_mday=ff.wr_date&31;
-			tm.tm_mon=(ff.wr_date>>5)&15;
-			tm.tm_year=80+((ff.wr_date>>9)&127);
-			tm.tm_hour=(ff.wr_time>>11)&31;
-			tm.tm_min=(ff.wr_time>>5)&63;
-			tm.tm_sec=(ff.wr_time&0x1f)<<1;
-			if(misc&IMPORT_NEW_ONLY && mktime(&tm)<=lastimport)
-				continue;
-			if(startmsg==2 && !strcmp(ff.name,"1.MSG"))
-				continue;
-			msgfiles--; 		/* so we only look for as many as are there */
-			strupr(path);
-			lprintf("\r%s    ",path);
-			files++;
-			if((fmsg=nopen(path,O_RDWR))==-1) {
-				lprintf("\7ERROR opening\r\n");
-				continue; }
-			if(filelength(fmsg)<sizeof(fmsghdr_t)) {
-				lprintf("\7Invalid length of %u bytes\r\n",filelength(fmsg));
-				close(fmsg);
-				continue; }
-			if(read(fmsg,&hdr,sizeof(fmsghdr_t))!=sizeof(fmsghdr_t)) {
-				close(fmsg);
-				lprintf("\7ERROR reading %u bytes\r\n"
-					,sizeof(fmsghdr_t));
-				continue; }
-			if(misc&IMPORT_LOCAL || !(hdr.attr&FIDO_LOCAL)) {
-
-				if(!(misc&IGNORE_RECV) && hdr.attr&FIDO_RECV) {
-					close(fmsg);
-					lputs("Already received.\r\n");
-					continue; }
-
-				if(hdr.attr&FIDO_SENT) {
-					close(fmsg);
-					lputs("Sent.");
-					if(hdr.attr&FIDO_KILLSENT)
-						if(!remove(path))
-							lputs(" Killed.");
-					lputs("\r\n");
-					continue; }
-
-				if(hdr.attr&FIDO_PRIVATE && !(sub[i]->misc&SUB_PRIV)) {
-					if(misc&IMPORT_PRIVATE)
-						hdr.attr&=~FIDO_PRIVATE;
-					else {
-						close(fmsg);
-						lputs("Private posts disallowed.\r\n");
-						continue; } }
-
-				if(!(hdr.attr&FIDO_PRIVATE) && sub[i]->misc&SUB_PONLY)
-					hdr.attr|=MSG_PRIVATE;
-
-				/**********************/
-				/* Importing EchoMail */
-				/**********************/
-
-				fmsgtosmsg(fmsg,hdr,status,0,i);
-
-				echomail++;
-
-				/* Updating message header */
-				if(!(misc&DONT_SET_RECV)) {
-					hdr.attr|=FIDO_RECV;
-					lseek(fmsg,0L,SEEK_SET);
-					write(fmsg,&hdr,sizeof(fmsghdr_t)); }
-
-				close(fmsg);
-				if(misc&NOTIFY_RECEIPT && (m=matchname(hdr.to))!=0) {
-					sprintf(str
-					,"\7\1n\1hSBBSFIDO: \1m%.36s \1n\1msent you EchoMail on "
-						"\1h%s \1n\1m%s\1n\r\n"
-						,hdr.from,grp[sub[i]->grp]->sname,sub[i]->sname);
-					putsmsg(m,str); }
-
-				/* Delete source EchoMail if specified */
-				if(misc&DELETE_ECHOMAIL)
-					remove(path); }
-			else
-				close(fmsg); }
-		smb_close();
-		}
-
-now=time(NULL);
-if(now-start)
-	lprintf("\r\nImported %lu EchoMail messages in %lu seconds "
-		"(%lu messages/second).\r\n"
-		,echomail,now-start,echomail/(now-start));
-}
-
-if(misc&EXPORT_ECHOMAIL) {
-
-start=time(NULL);
-
-lputs("\r\n\r\nScanning for Outbound EchoMail...\r\n");
-
-for(g=files=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		if(sub_code[0] && stricmp(sub_code,sub[i]->code))
-            continue;
-		if(!sub[i]->echopath[0])
-            sprintf(sub[i]->echopath,"%s%s\\",echomail_dir,sub[i]->code);
-		if(files) {
-			lputs("\r\n");
-			files=0; }
-		lprintf("\r\n%-15.15s %s\r\n"
-			,grp[sub[i]->grp]->sname,sub[i]->lname);
-		ptr=0;
-		if(!(misc&IGNORE_MSGPTRS)) {
-			sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-			if((file=nopen(str,O_RDONLY))!=-1) {
-				read(file,&ptr,sizeof(time_t));
-				close(file); } }
-
-		msgs=getlastmsg(i,&lastmsg,0);
-		if(!msgs || (!(misc&IGNORE_MSGPTRS) && ptr>=lastmsg)) {
-			if(ptr>lastmsg && !(misc&LEAVE_MSGPTRS)) {	/* fix ptr */
-                sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-				if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-					lprintf("\7ERROR opening/creating %s",str);
-				else {
-					write(file,&lastmsg,4);
-					close(file); } }
-			continue; }
-		nextmsg=startmsg;
-
-		sprintf(smb_file,"%s%s"
-			,sub[i]->data_dir,sub[i]->code);
-		if((j=smb_open(10))!=0) {
-			lprintf("Error %d opening %s\r\n",j,smb_file);
-			continue; }
-
-		post=NULL;
-		posts=loadmsgs(&post,ptr);
-
-		if(!posts)	{ /* no new messages */
-			smb_close();
-			if(post)
-				FREE(post);
-			continue; }
-
-		for(m=exp=0;m<posts;m++) {
-			printf("\rScanning: %lu of %lu     "
-				,m+1,posts);
-
-			msg.idx.offset=post[m].offset;
-			if((k=smb_lockmsghdr(msg,10))!=0) {
-				lprintf("ERR_LOCK %s %d\r\n",smb_file,k);
-				continue; }
-			k=smb_getmsghdr(&msg);
-			if(k || msg.hdr.number!=post[m].number) {
-				smb_unlockmsghdr(msg);
-				smb_freemsgmem(msg);
-
-				msg.hdr.number=post[m].number;
-				if((k=smb_getmsgidx(&msg))!=0) {
-					lprintf("ERR_READ %s %d\r\n",smb_file,k);
-					continue; }
-				if((k=smb_lockmsghdr(msg,10))!=0) {
-					lprintf("ERR_LOCK %s %d\r\n",smb_file,k);
-					continue; }
-				if((k=smb_getmsghdr(&msg))!=0) {
-					smb_unlockmsghdr(msg);
-					lprintf("ERR_READ %s %d\r\n",smb_file,k);
-					continue; } }
-
-			if((!(misc&EXPORT_ALL) && msg.from_net.type==NET_FIDO)
-				|| !strnicmp(msg.subj,"NE:",3)) {   /* no echo */
-				smb_unlockmsghdr(msg);
-				smb_freemsgmem(msg);
-				continue; }  /* From a Fido node, ignore it */
-
-			if(msg.from_net.type && msg.from_net.type!=NET_FIDO
-				&& !(sub[i]->misc&SUB_GATE)) {
-				smb_unlockmsghdr(msg);
-				smb_freemsgmem(msg);
-				continue; }
-
-			for(j=nextmsg;j;j++) {
-				sprintf(fname,"%s%u.MSG",sub[i]->echopath,j);
-				if(!fexist(fname))
-					break; }
-			if(!j) {
-				lputs("\7EchoMail dir full!");
-				smb_unlockmsghdr(msg);
-				smb_freemsgmem(msg);
-				continue; }
-			nextmsg=j+1;
-			strupr(fname);
-			if((fmsg=nopen(fname,O_WRONLY|O_CREAT))==-1) {
-				smb_unlockmsghdr(msg);
-				smb_freemsgmem(msg);
-				lprintf("\7ERROR creating %s\r\n",fname);
-				continue; }
-			if((fstream=fdopen(fmsg,"wb"))==NULL) {
-				close(fmsg);
-				smb_unlockmsghdr(msg);
-                smb_freemsgmem(msg);
-				lprintf("\7ERROR fdopen %s\r\n",fname);
-				continue; }
-			setvbuf(fstream,NULL,_IOFBF,2048);
-
-			files++;
-
-			memset(&hdr,0,sizeof(fmsghdr_t));	 /* Zero the header */
-			hdr.origzone=sub[i]->faddr.zone;
-			hdr.orignet=sub[i]->faddr.net;
-			hdr.orignode=sub[i]->faddr.node;
-			hdr.origpoint=sub[i]->faddr.point;
-
-			hdr.attr=FIDO_LOCAL;
-			if(misc&KILL_ECHOMAIL)
-				hdr.attr|=FIDO_KILLSENT;
-			if(msg.hdr.attr&MSG_PRIVATE)
-				hdr.attr|=FIDO_PRIVATE;
-
-			sprintf(hdr.from,"%.35s",msg.from);
-
-			tm_p=gmtime((time_t *)&msg.hdr.when_written.time);
-			sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
-				,tm_p->tm_mday,mon[tm_p->tm_mon],tm_p->tm_year%100
-				,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);
-
-			sprintf(hdr.to,"%.35s",msg.to);
-
-			sprintf(hdr.subj,"%.71s",msg.subj);
-
-			fwrite(&hdr,sizeof(fmsghdr_t),1,fstream);
-
-			for(j=0;j<msg.hdr.total_dfields;j++) {
-
-				if(msg.dfield[j].type!=TEXT_BODY
-					&& msg.dfield[j].type!=TEXT_TAIL)
-					continue;					/* skip non-text data fields */
-
-				if(msg.dfield[j].length<3)		/* need at least 3 bytes */
-					continue;
-
-				fseek(sdt_fp,msg.hdr.offset+msg.dfield[j].offset,SEEK_SET);
-
-				lzh=0;
-				fread(&xlat,2,1,sdt_fp);
-				if(xlat==XLAT_LZH) {
-					lzh=1;
-					fread(&xlat,2,1,sdt_fp); }
-				if(xlat!=XLAT_NONE) 	/* no other translations supported */
-					continue;
-
-				length=msg.dfield[j].length-2;
-				if(lzh)
-					length-=2;
-
-				if((buf=LMALLOC(length))==NULL) {
-					lprintf("Error allocating %lu bytes\r\n",length);
-					continue; }
-
-				fread(buf,length,1,sdt_fp);
-
-				if(lzh) {
-					l=*(long *)buf;
-					if((outbuf=LMALLOC(l))==NULL) {
-						lprintf("Error allocationg %lu for lzh\r\n",l);
-						LFREE(buf);
-						continue; }
-					length=lzh_decode(buf,length,outbuf);
-					LFREE(buf);
-					buf=outbuf; }
-
-				tear=0;
-				for(l=0,cr=1;l<length;l++) {
-					if(buf[l]==1) { /* Ctrl-A, so skip it and the next char */
-                        l++;
-						continue; }
-					if(buf[l]==LF || buf[l]==0)  /* Ignore line feeds */
-						continue;
-					if(cr) {
-						if(l+3<length && buf[l]=='-' && buf[l+1]=='-'
-							&& buf[l+2]=='-'
-							&& (buf[l+3]==SP || buf[l+3]==CR)) {
-							if(misc&CONVERT_TEAR)	/* Convert to === */
-								buf[l]=buf[l+1]=buf[l+2]='=';
-							else
-								tear=1; }
-						else if(l+10<length
-							&& !strncmp(buf+l," * Origin: ",11))
-							buf[l+1]='#'; } /* Convert * Origin into # Origin */
-
-					if(buf[l]==CR)
-						cr=1;
-					else
-						cr=0;
-					if(sub[i]->misc&SUB_ASCII || misc&ASCII_ONLY) {
-						if(buf[l]<SP && buf[l]!=CR) /* Ctrl ascii */
-							buf[l]='.';             /* converted to '.' */
-						if((uchar)buf[l]>0x7f)		/* extended ASCII */
-							buf[l]='*'; }           /* converted to '*' */
-					fputc(buf[l],fstream); }
-				fprintf(fstream,"\r\n");
-				LFREE(buf); }
-
-			if(!(sub[i]->misc&SUB_NOTAG)) {
-				if(!tear)	/* No previous tear line */
-					fprintf(fstream,"--- Synchronet+SBBSfido v%s\r\n"
-						,VER);	/* so add ours */
-				fprintf(fstream," * Origin: %s (%s)\r\n"
-					,sub[i]->origline[0] ? sub[i]->origline : origline
-					,faddrtoa(sub[i]->faddr)); }
-
-			fputc(0,fstream);	/* Null terminator */
-			fclose(fstream);
-			exported++;
-			exp++;
-			printf("Exported: %lu of %lu",exp,exported);
-			smb_unlockmsghdr(msg);
-			smb_freemsgmem(msg); }
-
-		smb_close();
-		FREE(post);
-
-		/***********************/
-		/* Update FIDO_PTR.DAB */
-		/***********************/
-		if(!(misc&LEAVE_MSGPTRS) && lastmsg>ptr) {
-			sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-			if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-				lprintf("\7ERROR opening/creating %s",str);
-			else {
-				write(file,&lastmsg,4);
-				close(file); } } }
-
-now=time(NULL);
-if(now-start)
-	lprintf("\r\nExported %lu EchoMail messages in %lu seconds "
-		"(%lu messages/second).\r\n"
-		,exported,now-start,exported/(now-start));
-
-}
-
-if(misc&UPDATE_MSGPTRS) {
-
-lputs("\r\n\r\nUpdating Message Pointers to Last Posted Message...\r\n");
-
-for(g=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		lprintf("\r\n%-15.15s %s\r\n"
-			,grp[sub[i]->grp]->sname,sub[i]->lname);
-		getlastmsg(i,&l,0);
-		sprintf(str,"%s%s.SFP",sub[i]->data_dir,sub[i]->code);
-		if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-			lprintf("\7ERROR opening/creating %s",str);
-		else {
-			write(file,&l,sizeof(time_t));
-			close(file); } } }
-
-if(misc&PURGE_ECHOMAIL) {
-
-lputs("\r\n\r\nPurging EchoMail...\r\n");
-
-for(g=0;g<total_grps;g++)
-for(i=0;i<total_subs;i++)
-	if(sub[i]->misc&SUB_FIDO && sub[i]->grp==g) {
-		if(sub_code[0] && stricmp(sub_code,sub[i]->code))
-            continue;
-		if(!sub[i]->echopath[0])
-            sprintf(sub[i]->echopath,"%s%s\\",echomail_dir,sub[i]->code);
-		sprintf(str,"%s*.MSG",sub[i]->echopath);
-		last=findfirst(str,&ff,0);
-		while(!last) {
-			sprintf(str,"%s%s",sub[i]->echopath,ff.name);
-			if(startmsg!=2 || strcmp(ff.name,"1.MSG")) {
-				lprintf("\r\nDeleting %s",str);
-				remove(str); }
-			last=findnext(&ff); } } }
-
-
-if(misc&(IMPORT_NETMAIL|IMPORT_ECHOMAIL) && misc&REPORT) {
-	sprintf(str,"%sSBBSFIDO.MSG",text_dir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		lprintf("Error opening %s\r\n",str);
-		exit(1); }
-	sprintf(fname,"\1c\1h               "
-		"���������������������������������������������������\r\n");
-	sprintf(path,"\1c\1h               "
-		"���������������������������������������������������\r\n");
-	write(file,fname,strlen(fname));
-	sprintf(str,"               \1n\1k\0016"
-		" Last FidoNet Transfer on %.24s \1n\r\n",ctime(&start));
-	write(file,str,strlen(str));
-	write(file,path,strlen(path));
-	write(file,fname,strlen(fname));
-	sprintf(subj,"Imported %lu EchoMail and %lu NetMail Messages"
-		,echomail,netmail);
-	sprintf(str,"               \1n\1k\0016 %-50.50s\1n\r\n",subj);
-	write(file,str,strlen(str));
-	write(file,path,strlen(path));
-	close(file); }
-
-return(0);
-}
-
diff --git a/src/sbbs2/fido/smbdefs.h b/src/sbbs2/fido/smbdefs.h
deleted file mode 100644
index 71791e69524fa58b43bf4ecbe9f495c6d237407e..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/smbdefs.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/* SMBDEFS.H */
-
-#ifndef _SMBDEFS_H
-#define _SMBDEFS_H
-
-/**********/
-/* Macros */
-/**********/
-
-#define SMB_VERSION 		0x0121		/* SMB format version */
-										/* High byte major, low byte minor */
-#define SMBLIB_VERSION		"1.21a"     /* SMB library version */
-
-										/* Control characters */
-#define TAB 				0x09		/* Horizontal tabulation	^I */
-#define LF					0x0a		/* Line feed				^J */
-#define FF					0x0c		/* Form feed				^L */
-#define CR					0x0d		/* Carriage return			^M */
-#define ESC 				0x1b		/* Escape					^[ */
-#define SP					0x20		/* Space					   */
-
-#define ulong				unsigned long
-#define ushort				unsigned short
-#define uchar				unsigned char
-#define uint				unsigned int
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-#	define HUGE16 huge
-#	define FAR16 far
-#	if defined(__TURBOC__)
-#		define REALLOC(x,y) farrealloc(x,y)
-#		define LMALLOC(x) farmalloc(x)
-#		define MALLOC(x) farmalloc(x)
-#		define LFREE(x) farfree(x)
-#		define FREE(x) farfree(x)
-#	elif defined(__WATCOMC__)
-#		define REALLOC realloc
-#		define LMALLOC(x) halloc(x,1)  /* far heap, but slow */
-#		define MALLOC malloc		   /* far heap, but 64k max */
-#		define LFREE hfree
-#		define FREE free
-#	else	/* Other 16-bit Compiler */
-#		define REALLOC realloc
-#		define LMALLOC malloc
-#		define MALLOC malloc
-#		define LFREE free
-#		define FREE free
-#	endif
-#else		/* 32-bit Compiler or Small Memory Model */
-#	define HUGE16
-#	define FAR16
-#	define REALLOC realloc
-#	define LMALLOC malloc
-#	define MALLOC malloc
-#	define LFREE free
-#	define FREE free
-#endif
-
-
-#define SDT_BLOCK_LEN		256 		/* Size of data blocks */
-#define SHD_BLOCK_LEN		256 		/* Size of header blocks */
-
-#define SMB_SELFPACK		0			/* Self-packing storage allocation */
-#define SMB_FASTALLOC		1			/* Fast allocation */
-#define SMB_HYPERALLOC		2			/* No allocation */
-
-#define SMB_EMAIL			1			/* User numbers stored in Indexes */
-
-										/* Time zone macros for when_t.zone */
-#define DAYLIGHT			0x8000		/* Daylight savings is active */
-#define US_ZONE 			0x4000		/* U.S. time zone */
-#define WESTERN_ZONE		0x2000		/* Non-standard zone west of UT */
-#define EASTERN_ZONE		0x1000		/* Non-standard zone east of UT */
-
-										/* US Time Zones (standard) */
-#define AST 				0x40F0		// Atlantic 			(-04:00)
-#define EST 				0x412C		// Eastern				(-05:00)
-#define CST 				0x4168		// Central				(-06:00)
-#define MST 				0x41A4		// Mountain 			(-07:00)
-#define PST 				0x41E0		// Pacific				(-08:00)
-#define YST 				0x421C		// Yukon				(-09:00)
-#define HST 				0x4258		// Hawaii/Alaska		(-10:00)
-#define BST 				0x4294		// Bering				(-11:00)
-
-										/* US Time Zones (daylight) */
-#define ADT 				0xC0F0		// Atlantic 			(-03:00)
-#define EDT 				0xC12C		// Eastern				(-04:00)
-#define CDT 				0xC168		// Central				(-05:00)
-#define MDT 				0xC1A4		// Mountain 			(-06:00)
-#define PDT 				0xC1E0		// Pacific				(-07:00)
-#define YDT 				0xC21C		// Yukon				(-08:00)
-#define HDT 				0xC258		// Hawaii/Alaska		(-09:00)
-#define BDT 				0xC294		// Bering				(-10:00)
-
-										/* Non-standard Time Zones */
-#define MID 				0x2294		// Midway				(-11:00)
-#define VAN 				0x21E0		// Vancouver			(-08:00)
-#define EDM 				0x21A4		// Edmonton 			(-07:00)
-#define WIN 				0x2168		// Winnipeg 			(-06:00)
-#define BOG 				0x212C		// Bogota				(-05:00)
-#define CAR 				0x20F0		// Caracas				(-04:00)
-#define RIO 				0x20B4		// Rio de Janeiro		(-03:00)
-#define FER 				0x2078		// Fernando de Noronha	(-02:00)
-#define AZO 				0x203C		// Azores				(-01:00)
-#define LON 				0x1000		// London				(+00:00)
-#define BER 				0x103C		// Berlin				(+01:00)
-#define ATH 				0x1078		// Athens				(+02:00)
-#define MOS 				0x10B4		// Moscow				(+03:00)
-#define DUB 				0x10F0		// Dubai				(+04:00)
-#define KAB 				0x110E		// Kabul				(+04:30)
-#define KAR 				0x112C		// Karachi				(+05:00)
-#define BOM 				0x114A		// Bombay				(+05:30)
-#define KAT 				0x1159		// Kathmandu			(+05:45)
-#define DHA 				0x1168		// Dhaka				(+06:00)
-#define BAN 				0x11A4		// Bangkok				(+07:00)
-#define HON 				0x11E0		// Hong Kong			(+08:00)
-#define TOK 				0x121C		// Tokyo				(+09:00)
-#define SYD 				0x1258		// Sydney				(+10:00)
-#define NOU 				0x1294		// Noumea				(+11:00)
-#define WEL 				0x12D0		// Wellington			(+12:00)
-
-										/* Valid hfield_t.types */
-#define SENDER				0x00
-#define SENDERAGENT 		0x01
-#define SENDERNETTYPE		0x02
-#define SENDERNETADDR		0x03
-#define SENDEREXT			0x04
-#define SENDERPOS			0x05
-#define SENDERORG			0x06
-
-#define AUTHOR				0x10
-#define AUTHORAGENT 		0x11
-#define AUTHORNETTYPE		0x12
-#define AUTHORNETADDR		0x13
-#define AUTHOREXT			0x14
-#define AUTHORPOS			0x15
-#define AUTHORORG			0x16
-
-#define REPLYTO 			0x20
-#define REPLYTOAGENT		0x21
-#define REPLYTONETTYPE		0x22
-#define REPLYTONETADDR		0x23
-#define REPLYTOEXT			0x24
-#define REPLYTOPOS			0x25
-#define REPLYTOORG			0x26
-
-#define RECIPIENT			0x30
-#define RECIPIENTAGENT		0x31
-#define RECIPIENTNETTYPE	0x32
-#define RECIPIENTNETADDR	0x33
-#define RECIPIENTEXT		0x34
-#define RECIPIENTPOS		0x35
-#define RECIPIENTORG		0x36
-
-#define FORWARDTO			0x40
-#define FORWARDTOAGENT		0x41
-#define FORWARDTONETTYPE	0x42
-#define FORWARDTONETADDR	0x43
-#define FORWARDTOEXT		0x44
-#define FORWARDTOPOS		0x45
-#define FORWARDTOORG		0x46
-
-#define FORWARDED			0x48
-
-#define RECEIVEDBY			0x50
-#define RECEIVEDBYAGENT 	0x51
-#define RECEIVEDBYNETTYPE	0x52
-#define RECEIVEDBYNETADDR	0x53
-#define RECEIVEDBYEXT		0x54
-#define RECEIVEDBYPOS		0x55
-#define RECEIVEDBYORG		0x56
-
-#define RECEIVED			0x58
-
-#define SUBJECT 			0x60
-#define SUMMARY 			0x61
-#define COMMENT 			0x62
-#define CARBONCOPY			0x63
-#define GROUP				0x64
-#define EXPIRATION			0x65
-#define PRIORITY			0x66
-
-#define FILEATTACH			0x70
-#define DESTFILE			0x71
-#define FILEATTACHLIST		0x72
-#define DESTFILELIST		0x73
-#define FILEREQUEST 		0x74
-#define FILEPASSWORD		0x75
-#define FILEREQUESTLIST 	0x76
-#define FILEPASSWORDLIST	0x77
-
-#define IMAGEATTACH 		0x80
-#define ANIMATTACH			0x81
-#define FONTATTACH			0x82
-#define SOUNDATTACH 		0x83
-#define PRESENTATTACH		0x84
-#define VIDEOATTACH 		0x85
-#define APPDATAATTACH		0x86
-
-#define IMAGETRIGGER		0x90
-#define ANIMTRIGGER 		0x91
-#define FONTTRIGGER 		0x92
-#define SOUNDTRIGGER		0x93
-#define PRESENTTRIGGER		0x94
-#define VIDEOTRIGGER		0x95
-#define APPDATATRIGGER		0x96
-
-#define FIDOCTRL			0xa0
-#define FIDOAREA			0xa1
-#define FIDOSEENBY			0xa2
-#define FIDOPATH			0xa3
-#define FIDOMSGID			0xa4
-#define FIDOREPLYID 		0xa5
-#define FIDOPID 			0xa6
-#define FIDOFLAGS			0xa7
-
-#define RFC822HEADER		0xb0
-#define RFC822MSGID 		0xb1
-#define RFC822REPLYID		0xb2
-
-#define UNKNOWN 			0xf1
-#define UNKNOWNASCII		0xf2
-#define UNUSED				0xff
-
-										/* Valid dfield_t.types */
-#define TEXT_BODY			0x00
-#define TEXT_SOUL			0x01
-#define TEXT_TAIL			0x02
-#define TEXT_WING			0x03
-#define IMAGEEMBED			0x20
-#define ANIMEMBED			0x21
-#define FONTEMBED			0x22
-#define SOUNDEMBED			0x23
-#define PRESENTEMBED		0x24
-#define VIDEOEMBED			0x25
-#define APPDATAEMBED		0x26
-#define UNUSED				0xff
-
-
-										/* Message attributes */
-#define MSG_PRIVATE 		(1<<0)
-#define MSG_READ			(1<<1)
-#define MSG_PERMANENT		(1<<2)
-#define MSG_LOCKED			(1<<3)
-#define MSG_DELETE			(1<<4)
-#define MSG_ANONYMOUS		(1<<5)
-#define MSG_KILLREAD		(1<<6)
-#define MSG_MODERATED		(1<<7)
-#define MSG_VALIDATED		(1<<8)
-
-										/* Auxillary header attributes */
-#define MSG_FILEREQUEST 	(1<<0)		// File request
-#define MSG_FILEATTACH		(1<<1)		// File(s) attached to Msg
-#define MSG_TRUNCFILE		(1<<2)		// Truncate file(s) when sent
-#define MSG_KILLFILE		(1<<3)		// Delete file(s) when sent
-#define MSG_RECEIPTREQ		(1<<4)		// Return receipt requested
-#define MSG_CONFIRMREQ		(1<<5)		// Confirmation receipt requested
-#define MSG_NODISP			(1<<6)		// Msg may not be displayed to user
-
-										/* Message network attributes */
-#define MSG_LOCAL			(1<<0)		// Msg created locally
-#define MSG_INTRANSIT		(1<<1)		// Msg is in-transit
-#define MSG_SENT			(1<<2)		// Sent to remote
-#define MSG_KILLSENT		(1<<3)		// Kill when sent
-#define MSG_ARCHIVESENT 	(1<<4)		// Archive when sent
-#define MSG_HOLD			(1<<5)		// Hold for pick-up
-#define MSG_CRASH			(1<<6)		// Crash
-#define MSG_IMMEDIATE		(1<<7)		// Send Msg now, ignore restrictions
-#define MSG_DIRECT			(1<<8)		// Send directly to destination
-#define MSG_GATE			(1<<9)		// Send via gateway
-#define MSG_ORPHAN			(1<<10) 	// Unknown destination
-#define MSG_FPU 			(1<<11) 	// Force pickup
-#define MSG_TYPELOCAL		(1<<12) 	// Msg is for local use only
-#define MSG_TYPEECHO		(1<<13) 	// Msg is for conference distribution
-#define MSG_TYPENET 		(1<<14) 	// Msg is direct network mail
-
-
-enum {
-     NET_NONE
-    ,NET_UNKNOWN
-    ,NET_FIDO
-    ,NET_POSTLINK
-    ,NET_QWK
-	,NET_INTERNET
-	,NET_WWIV
-	,NET_MHS
-
-/* Add new ones here */
-
-    ,NET_TYPES
-    };
-
-enum {
-     AGENT_PERSON
-    ,AGENT_PROCESS
-
-/* Add new ones here */
-
-    ,AGENT_TYPES
-    };
-
-enum {
-     XLAT_NONE              // No translation/End of translation list
-    ,XLAT_ENCRYPT           // Encrypted data
-    ,XLAT_ESCAPED           // 7-bit ASCII escaping for ctrl and 8-bit data
-    ,XLAT_HUFFMAN           // Static and adaptive Huffman coding compression
-    ,XLAT_LZW               // Limpel/Ziv/Welch compression
-    ,XLAT_MLZ78             // Modified LZ78 compression
-    ,XLAT_RLE               // Run length encoding compression
-    ,XLAT_IMPLODE           // Implode compression (PkZIP)
-    ,XLAT_SHRINK            // Shrink compression (PkZIP)
-	,XLAT_LZH				// LHarc (LHA) Dynamic Huffman coding
-
-/* Add new ones here */
-
-    ,XLAT_TYPES
-    };
-
-
-/************/
-/* Typedefs */
-/************/
-
-typedef struct {
-
-	ulong	time;			// Local time (unix format)
-	short	zone;			// Time zone
-
-	} when_t;
-
-typedef struct {
-
-	ushort	to; 			// 16-bit CRC of recipient name (lower case)
-	ushort	from;			// 16-bit CRC of sender name (lower case)
-	ushort	subj;			// 16-bit CRC of subject (lower case, w/o RE:)
-	ushort	attr;			// attributes (read, permanent, etc.)
-	ulong	offset; 		// offset into header file
-	ulong	number; 		// number of message (1 based)
-	ulong	time;			// time/date message was imported/posted
-
-	} idxrec_t;
-
-typedef struct {
-
-    uchar   id[4];          // text or binary unique hdr ID
-    ushort  version;        // version number (initially 100h for 1.00)
-    ushort  length;         // length including this struct
-
-	} smbhdr_t;
-
-typedef struct {
-
-	ulong	last_msg;		// last message number
-	ulong	total_msgs; 	// total messages
-	ulong	header_offset;	// byte offset to first header record
-	ulong	max_crcs;		// Maximum number of CRCs to keep in history
-    ulong   max_msgs;       // Maximum number of message to keep in sub
-    ushort  max_age;        // Maximum age of message to keep in sub (in days)
-	ushort	attr;			// Attributes for this message base (SMB_HYPER,etc)
-
-	} smbstatus_t;
-
-typedef struct {
-
-	uchar	id[4];			// SHD<^Z>
-    ushort  type;           // Message type (normally 0)
-    ushort  version;        // Version of type (initially 100h for 1.00)
-    ushort  length;         // Total length of fixed record + all fields
-	ushort	attr;			// Attributes (bit field) (duped in SID)
-	ulong	auxattr;		// Auxillary attributes (bit field)
-    ulong   netattr;        // Network attributes
-	when_t	when_written;	// Time message was written (unix format)
-	when_t	when_imported;	// Time message was imported
-    ulong   number;         // Message number
-    ulong   thread_orig;    // Original message number in thread
-    ulong   thread_next;    // Next message in thread
-    ulong   thread_first;   // First reply to this message
-	uchar	reserved[16];	// Reserved for future use
-    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-	ushort	total_dfields;	// Total number of data fields
-
-	} msghdr_t;
-
-typedef struct {
-
-	ushort	type;			// Type of data field
-    ulong   offset;         // Offset into buffer 
-    ulong   length;         // Length of data field
-
-    } dfield_t;
-
-typedef struct {
-
-	ushort	type;
-	ushort	length; 		// Length of buffer
-
-	} hfield_t;
-
-typedef struct {
-
-	ushort	zone;
-	ushort	net;
-	ushort	node;
-	ushort	point;
-
-    } fidoaddr_t;
-
-typedef struct {
-
-    ushort  type;
-	void	*addr;
-
-	} net_t;
-
-typedef struct {
-
-	idxrec_t	idx;			// Index
-	msghdr_t	hdr;			// Header record (fixed portion)
-	uchar		*to,			// To name
-				*to_ext,		// To extension
-				*from,			// From name
-				*from_ext,		// From extension
-				*replyto,		// Reply-to name
-				*replyto_ext,	// Reply-to extension */
-				*subj;			// Subject
-	ushort		to_agent,		// Type of agent message is to
-				from_agent, 	// Type of agent message is from
-				replyto_agent;	// Type of agent replies should be sent to
-	net_t		to_net, 		// Destination network type and address
-                from_net,       // Origin network address
-                replyto_net;    // Network type and address for replies
-	ushort		total_hfields;	// Total number of header fields
-	hfield_t	*hfield;		// Header fields (fixed length portion)
-	void		**hfield_dat;	// Header fields (variable length portion)
-	dfield_t	*dfield;		// Data fields (fixed length portion)
-	ulong		offset; 		// Offset (number of records) into index
-	uchar		forwarded;		// Forwarded from agent to another
-
-	} smbmsg_t;
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/fido/smblib.c b/src/sbbs2/fido/smblib.c
deleted file mode 100644
index e2d8a474b875feec0a6efaa1f49a01650ab396a9..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/smblib.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-/* SMBLIB.C */
-
-#include "smblib.h"
-
-/****************************************************************************/
-/* Open a message base of name 'smb_file'                                   */
-/* If retry_time is 0, fast open method (no compatibility/validity check)	*/
-/* Opens files for READing messages or updating message indices only        */
-/****************************************************************************/
-int smb_open(int retry_time)
-{
-    int file;
-    char str[128];
-	smbhdr_t hdr;
-
-shd_fp=sdt_fp=sid_fp=NULL;
-sprintf(str,"%s.SHD",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (shd_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-    return(2); }
-
-if(retry_time && filelength(file)>=sizeof(smbhdr_t)) {
-	setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
-    if(smb_locksmbhdr(retry_time)) {
-		smb_close();
-        return(-1); }
-	memset(&hdr,0,sizeof(smbhdr_t));
-    fread(&hdr,sizeof(smbhdr_t),1,shd_fp);
-    if(memcmp(hdr.id,"SMB\x1a",4)) {
-		smb_close();
-        return(-2); }
-    if(hdr.version<0x110) {         /* Compatibility check */
-		smb_close();
-        return(-3); }
-    smb_unlocksmbhdr();
-	rewind(shd_fp); }
-
-setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
-
-sprintf(str,"%s.SDT",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (sdt_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close();
-	return(1); }
-setvbuf(sdt_fp,NULL,_IOFBF,2*1024);
-
-sprintf(str,"%s.SID",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (sid_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close();
-	return(3); }
-setvbuf(sid_fp,NULL,_IOFBF,2*1024);
-
-return(0);
-}
-
-/****************************************************************************/
-/* Closes the currently open message base									*/
-/****************************************************************************/
-void smb_close(void)
-{
-if(shd_fp!=NULL) {
-	smb_unlocksmbhdr(); 			/* In case it's been locked */
-	fclose(shd_fp); }
-if(sid_fp!=NULL)
-	fclose(sid_fp);
-if(sdt_fp!=NULL)
-	fclose(sdt_fp);
-sid_fp=shd_fp=sdt_fp=NULL;
-}
-
-/****************************************************************************/
-/* Opens the data block allocation table message base 'smb_file'            */
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_open_da(int retry_time)
-{
-    int file;
-    char str[128];
-	long start;
-
-start=time(NULL);
-sprintf(str,"%s.SDA",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-		return(-2); }
-if((sda_fp=fdopen(file,"r+b"))==NULL)
-	return(-3);
-setvbuf(sda_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-/****************************************************************************/
-/* Opens the header block allocation table for message base 'smb_file'      */
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_open_ha(int retry_time)
-{
-    int file;
-    char str[128];
-	long start;
-
-start=time(NULL);
-sprintf(str,"%s.SHA",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-		return(-2); }
-if((sha_fp=fdopen(file,"r+b"))==NULL)
-	return(-3);
-setvbuf(sha_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-/****************************************************************************/
-/* If the parameter 'push' is non-zero, this function stores the currently  */
-/* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
-/* message bases may be stored (defined in SMBDEFS.H).						*/
-/* The parameter 'op' is the operation to perform on the stack. Either      */
-/* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG						*/
-/* If the operation is SMB_STACK_POP, this function restores a message base */
-/* previously saved with a SMB_STACK_PUSH call to this same function.		*/
-/* If the operation is SMB_STACK_XCHNG, then the current message base is	*/
-/* exchanged with the message base on the top of the stack (most recently	*/
-/* pushed.																	*/
-/* If the current message base is not open, the SMB_STACK_PUSH and			*/
-/* SMB_STACK_XCHNG operations do nothing									*/
-/* Returns 0 on success, non-zero if stack full.                            */
-/* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.	*/
-/****************************************************************************/
-int smb_stack(int op)
-{
-	static char stack_file[SMB_STACK_LEN][128];
-	static FILE *stack_sdt[SMB_STACK_LEN],
-				*stack_shd[SMB_STACK_LEN],
-				*stack_sid[SMB_STACK_LEN],
-				*stack_sda[SMB_STACK_LEN],
-				*stack_sha[SMB_STACK_LEN];
-	static int	stack_idx;
-	char		tmp_file[128];
-	FILE		*tmp_sdt,
-				*tmp_shd,
-				*tmp_sid,
-				*tmp_sda,
-				*tmp_sha;
-
-if(op==SMB_STACK_PUSH) {
-	if(stack_idx>=SMB_STACK_LEN)
-		return(1);
-	if(shd_fp==NULL || sdt_fp==NULL || sid_fp==NULL) /* Msg base not open */
-		return(0);
-	memcpy(stack_file[stack_idx],smb_file,128);
-	stack_sdt[stack_idx]=sdt_fp;
-	stack_shd[stack_idx]=shd_fp;
-	stack_sid[stack_idx]=sid_fp;
-	stack_sda[stack_idx]=sda_fp;
-	stack_sha[stack_idx]=sha_fp;
-	stack_idx++;
-	return(0); }
-/* pop or xchng */
-if(!stack_idx)	/* Nothing on the stack, so do nothing */
-	return(0);
-if(op==SMB_STACK_XCHNG) {
-	if(!shd_fp)
-		return(0);
-	memcpy(tmp_file,smb_file,128);
-	tmp_sdt=sdt_fp;
-	tmp_shd=shd_fp;
-	tmp_sid=sid_fp;
-	tmp_sda=sda_fp;
-	tmp_sha=sha_fp; }
-
-stack_idx--;
-memcpy(smb_file,stack_file[stack_idx],128);
-sdt_fp=stack_sdt[stack_idx];
-shd_fp=stack_shd[stack_idx];
-sid_fp=stack_sid[stack_idx];
-sda_fp=stack_sda[stack_idx];
-sha_fp=stack_sha[stack_idx];
-if(op==SMB_STACK_XCHNG) {
-	stack_idx++;
-	memcpy(stack_file[stack_idx-1],tmp_file,128);
-	stack_sdt[stack_idx-1]=tmp_sdt;
-	stack_shd[stack_idx-1]=tmp_shd;
-	stack_sid[stack_idx-1]=tmp_sid;
-	stack_sda[stack_idx-1]=tmp_sda;
-	stack_sha[stack_idx-1]=tmp_sha; }
-return(0);
-}
-
-/****************************************************************************/
-/* Truncates header file													*/
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_trunchdr(int retry_time)
-{
-	long start;
-
-start=time(NULL);
-rewind(shd_fp);
-while(1) {
-	if(!chsize(fileno(shd_fp),0L))
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)		/* Time-out */
-		return(-2); }
-return(0);
-}
-
-/*********************************/
-/* Message Base Header Functions */
-/*********************************/
-
-/****************************************************************************/
-/* Attempts for retry_time number of seconds to lock the message base hdr	*/
-/****************************************************************************/
-int smb_locksmbhdr(int retry_time)
-{
-	ulong start;
-
-start=time(NULL);
-while(1) {
-	if(!lock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
-		return(0);
-	if(time(NULL)-start>=retry_time)
-		break;							/* Incase we've already locked it */
-	unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Read the SMB header from the header file and place into "status"         */
-/****************************************************************************/
-int smb_getstatus(smbstatus_t *status)
-{
-    char    str[128];
-	int 	i;
-
-setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
-clearerr(shd_fp);
-fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fread(status,1,sizeof(smbstatus_t),shd_fp);
-setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Writes message base header												*/
-/****************************************************************************/
-int smb_putstatus(smbstatus_t status)
-{
-	int i;
-
-clearerr(shd_fp);
-fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
-fflush(shd_fp);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Unlocks previously locks message base header 							*/
-/****************************************************************************/
-int smb_unlocksmbhdr()
-{
-return(unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
-}
-
-/********************************/
-/* Individual Message Functions */
-/********************************/
-
-/****************************************************************************/
-/* Attempts for retry_time number of seconds to lock the header for 'msg'   */
-/****************************************************************************/
-int smb_lockmsghdr(smbmsg_t msg, int retry_time)
-{
-    ulong start;
-
-start=time(NULL);
-while(1) {
-	if(!lock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)))
-        return(0);
-    if(time(NULL)-start>=retry_time)
-		break;
-	unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Fills msg->idx with message index based on msg->hdr.number				*/
-/* OR if msg->hdr.number is 0, based on msg->offset (record offset).		*/
-/* if msg.hdr.number does not equal 0, then msg->offset is filled too.		*/
-/* Either msg->hdr.number or msg->offset must be initialized before 		*/
-/* calling this function													*/
-/* Returns 1 if message number wasn't found, 0 if it was                    */
-/****************************************************************************/
-int smb_getmsgidx(smbmsg_t *msg)
-{
-	idxrec_t idx;
-	ulong	 l,length,total,bot,top;
-
-clearerr(sid_fp);
-if(!msg->hdr.number) {
-	fseek(sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&msg->idx,sizeof(idxrec_t),1,sid_fp))
-		return(1);
-	return(0); }
-
-length=filelength(fileno(sid_fp));
-if(!length)
-	return(1);
-total=length/sizeof(idxrec_t);
-if(!total)
-	return(1);
-
-bot=0;
-top=total;
-l=total/2; /* Start at middle index */
-while(1) {
-	fseek(sid_fp,l*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
-		return(1);
-	if(bot==top-1 && idx.number!=msg->hdr.number)
-        return(1);
-	if(idx.number>msg->hdr.number) {
-		top=l;
-		l=bot+((top-bot)/2);
-		continue; }
-	if(idx.number<msg->hdr.number) {
-		bot=l;
-		l=top-((top-bot)/2);
-		continue; }
-	break; }
-msg->idx=idx;
-msg->offset=l;
-return(0);
-}
-
-/****************************************************************************/
-/* Reads the last index record in the open message base 					*/
-/****************************************************************************/
-int smb_getlastidx(idxrec_t *idx)
-{
-	long length;
-
-clearerr(sid_fp);
-length=filelength(fileno(sid_fp));
-if(length<sizeof(idxrec_t))
-	return(-1);
-fseek(sid_fp,length-sizeof(idxrec_t),SEEK_SET);
-if(!fread(idx,sizeof(idxrec_t),1,sid_fp))
-	return(-2);
-return(0);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the header record for 'msg'              */
-/* Returns length															*/
-/****************************************************************************/
-uint smb_getmsghdrlen(smbmsg_t msg)
-{
-	int i;
-
-/* fixed portion */
-msg.hdr.length=sizeof(msghdr_t);
-/* data fields */
-msg.hdr.length+=msg.hdr.total_dfields*sizeof(dfield_t);
-/* header fields */
-for(i=0;i<msg.total_hfields;i++) {
-	msg.hdr.length+=sizeof(hfield_t);
-	msg.hdr.length+=msg.hfield[i].length; }
-return(msg.hdr.length);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the data buffer for 'msg'                */
-/* Returns length															*/
-/****************************************************************************/
-ulong smb_getmsgdatlen(smbmsg_t msg)
-{
-	int i;
-	ulong length=0L;
-
-for(i=0;i<msg.hdr.total_dfields;i++)
-	length+=msg.dfield[i].length;
-return(length);
-}
-
-/****************************************************************************/
-/* Read header information into 'msg' structure                             */
-/* msg->idx.offset must be set before calling this function 				*/
-/* Must call smb_freemsgmem() to free memory allocated for var len strs 	*/
-/* Returns 0 on success, non-zero if error									*/
-/****************************************************************************/
-int smb_getmsghdr(smbmsg_t *msg)
-{
-	ushort	i;
-	ulong	l,offset;
-	idxrec_t idx;
-
-rewind(shd_fp);
-fseek(shd_fp,msg->idx.offset,SEEK_SET);
-idx=msg->idx;
-offset=msg->offset;
-memset(msg,0,sizeof(smbmsg_t));
-msg->idx=idx;
-msg->offset=offset;
-if(!fread(&msg->hdr,sizeof(msghdr_t),1,shd_fp))
-	return(-1);
-if(memcmp(msg->hdr.id,"SHD\x1a",4))
-	return(-2);
-if(msg->hdr.version<0x110)
-	return(-9);
-l=sizeof(msghdr_t);
-if(msg->hdr.total_dfields && (msg->dfield
-	=(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
-	smb_freemsgmem(*msg);
-	return(-3); }
-i=0;
-while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
-	if(!fread(&msg->dfield[i],sizeof(dfield_t),1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-4); }
-	i++;
-	l+=sizeof(dfield_t); }
-if(i<msg->hdr.total_dfields) {
-	smb_freemsgmem(*msg);
-	return(-8); }
-
-while(l<msg->hdr.length) {
-	i=msg->total_hfields;
-	if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
-		==NULL) {
-		smb_freemsgmem(*msg);
-		return(-3); }
-	if((msg->hfield=(hfield_t *)REALLOC(msg->hfield
-		,sizeof(hfield_t)*(i+1)))==NULL) {
-		smb_freemsgmem(*msg);
-		return(-3); }
-	msg->total_hfields++;
-	if(!fread(&msg->hfield[i],sizeof(hfield_t),1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-5); }
-	l+=sizeof(hfield_t);
-	if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
-		==NULL) {			/* Allocate 1 extra for NULL terminator */
-		smb_freemsgmem(*msg);  /* or 0 length field */
-		return(-3); }
-	memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
-	if(msg->hfield[i].length
-		&& !fread(msg->hfield_dat[i],msg->hfield[i].length,1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-6); }
-
-	switch(msg->hfield[i].type) {	/* convenience variables */
-		case SENDER:
-			if(!msg->from) {
-				msg->from=msg->hfield_dat[i];
-				break; }
-		case FORWARDED: 	/* fall through */
-			msg->forwarded=1;
-			break;
-		case SENDERAGENT:
-			if(!msg->forwarded)
-				msg->from_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDEREXT:
-			if(!msg->forwarded)
-				msg->from_ext=msg->hfield_dat[i];
-			break;
-		case SENDERNETTYPE:
-			if(!msg->forwarded)
-				msg->from_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDERNETADDR:
-			if(!msg->forwarded)
-				msg->from_net.addr=msg->hfield_dat[i];
-            break;
-		case REPLYTO:
-			msg->replyto=msg->hfield_dat[i];
-            break;
-		case REPLYTOEXT:
-			msg->replyto_ext=msg->hfield_dat[i];
-			break;
-		case REPLYTOAGENT:
-			msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETTYPE:
-			msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETADDR:
-			msg->replyto_net.addr=msg->hfield_dat[i];
-            break;
-		case RECIPIENT:
-			msg->to=msg->hfield_dat[i];
-            break;
-		case RECIPIENTEXT:
-			msg->to_ext=msg->hfield_dat[i];
-			break;
-		case RECIPIENTAGENT:
-			msg->to_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETTYPE:
-			msg->to_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETADDR:
-			msg->to_net.addr=msg->hfield_dat[i];
-            break;
-		case SUBJECT:
-			msg->subj=msg->hfield_dat[i];
-			break; }
-	l+=msg->hfield[i].length; }
-
-if(!msg->from || !msg->to || !msg->subj) {
-	smb_freemsgmem(*msg);
-	return(-7); }
-return(0);
-}
-
-/****************************************************************************/
-/* Frees memory allocated for 'msg'                                         */
-/****************************************************************************/
-void smb_freemsgmem(smbmsg_t msg)
-{
-	ushort	i;
-
-if(msg.dfield)
-	FREE(msg.dfield);
-for(i=0;i<msg.total_hfields;i++)
-	if(msg.hfield_dat[i])
-		FREE(msg.hfield_dat[i]);
-if(msg.hfield)
-	FREE(msg.hfield);
-if(msg.hfield_dat)
-	FREE(msg.hfield_dat);
-}
-
-/****************************************************************************/
-/* Unlocks header for 'msg'                                                 */
-/****************************************************************************/
-int smb_unlockmsghdr(smbmsg_t msg)
-{
-return(unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)));
-}
-
-
-/****************************************************************************/
-/* Adds a header field to the 'msg' structure (in memory only)              */
-/****************************************************************************/
-int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
-{
-	int i;
-
-i=msg->total_hfields;
-if((msg->hfield=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))
-	==NULL)
-	return(1);
-if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
-	==NULL)
-	return(2);
-msg->total_hfields++;
-msg->hfield[i].type=type;
-msg->hfield[i].length=length;
-if(length) {
-	if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
-		return(4);
-	memcpy(msg->hfield_dat[i],data,length); }
-else
-	msg->hfield_dat[i]=NULL;
-return(0);
-}
-
-/****************************************************************************/
-/* Adds a data field to the 'msg' structure (in memory only)                */
-/* Automatically figures out the offset into the data buffer from existing	*/
-/* dfield lengths															*/
-/****************************************************************************/
-int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
-{
-	int i,j;
-
-i=msg->hdr.total_dfields;
-if((msg->dfield=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))
-	==NULL)
-	return(1);
-msg->hdr.total_dfields++;
-msg->dfield[i].type=type;
-msg->dfield[i].length=length;
-for(j=msg->dfield[i].offset=0;j<i;j++)
-	msg->dfield[i].offset+=msg->dfield[j].length;
-return(0);
-}
-
-/****************************************************************************/
-/* Checks CRC history file for duplicate crc. If found, returns 1.			*/
-/* If no dupe, adds to CRC history and returns 0, or negative if error. 	*/
-/****************************************************************************/
-int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
-{
-	char	str[128];
-	int 	file;
-	long	length;
-	ulong	l,*buf;
-	time_t	start;
-
-if(!max_crcs)
-	return(0);
-start=time(NULL);
-sprintf(str,"%s.SCH",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-        return(-2); }
-length=filelength(file);
-if(length<0L) {
-	close(file);
-	return(-4); }
-if((buf=(ulong *)MALLOC(max_crcs*4))==NULL) {
-	close(file);
-	return(-3); }
-if(length>=max_crcs*4) {			/* Reached or exceeds max crcs */
-	read(file,buf,max_crcs*4);
-	for(l=0;l<max_crcs;l++)
-		if(crc==buf[l])
-			break;
-	if(l<max_crcs) {				/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); }
-	chsize(file,0L);				/* truncate it */
-	lseek(file,0L,SEEK_SET);
-	write(file,buf+4,(max_crcs-1)*4); }
-
-else if(length/4) { 						/* Less than max crcs */
-	read(file,buf,length);
-	for(l=0;l<length/4;l++)
-		if(crc==buf[l])
-			break;
-	if(l<length/4) {					/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); } }
-
-lseek(file,0L,SEEK_END);
-write(file,&crc,4); 			   /* Write to the end */
-FREE(buf);
-close(file);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Creates a new message header record in the header file.					*/
-/* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
-/* If storage is SMB_FASTALLOC, fast allocation is used 					*/
-/* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)	*/
-/****************************************************************************/
-int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
-	,int retry_time)
-{
-	int i;
-	long l;
-
-if(smb_locksmbhdr(retry_time))
-    return(1);
-if(smb_getstatus(status))
-    return(2);
-
-if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(retry_time))!=0)
-    return(i);
-
-msg->hdr.length=smb_getmsghdrlen(*msg);
-if(storage==SMB_HYPERALLOC)
-	l=smb_hallochdr(status->header_offset);
-else if(storage==SMB_FASTALLOC)
-    l=smb_fallochdr(msg->hdr.length);
-else
-    l=smb_allochdr(msg->hdr.length);
-if(l==-1L) {
-	smb_unlocksmbhdr();
-	fclose(sha_fp);
-	return(-1); }
-
-status->last_msg++;
-msg->idx.number=msg->hdr.number=status->last_msg;
-msg->idx.offset=status->header_offset+l;
-msg->idx.time=msg->hdr.when_imported.time;
-msg->idx.attr=msg->hdr.attr;
-msg->offset=status->total_msgs;
-status->total_msgs++;
-smb_putstatus(*status);
-
-if(storage!=SMB_HYPERALLOC)
-	fclose(sha_fp);
-i=smb_putmsg(*msg);
-smb_unlocksmbhdr();
-return(i);
-}
-
-/****************************************************************************/
-/* Writes both header and index information for msg 'msg'                   */
-/****************************************************************************/
-int smb_putmsg(smbmsg_t msg)
-{
-	int i;
-
-i=smb_putmsghdr(msg);
-if(i)
-	return(i);
-return(smb_putmsgidx(msg));
-}
-
-/****************************************************************************/
-/* Writes index information for 'msg'                                       */
-/* msg.idx																	*/
-/* and msg.offset must be set prior to calling to this function             */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int smb_putmsgidx(smbmsg_t msg)
-{
-
-clearerr(sid_fp);
-fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-if(!fwrite(&msg.idx,sizeof(idxrec_t),1,sid_fp))
-	return(1);
-fflush(sid_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Writes header information for 'msg'                                      */
-/* msg.hdr.length                                                           */
-/* msg.idx.offset                                                           */
-/* and msg.offset must be set prior to calling to this function             */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int smb_putmsghdr(smbmsg_t msg)
-{
-	ushort	i;
-	ulong	l;
-
-clearerr(shd_fp);
-if(fseek(shd_fp,msg.idx.offset,SEEK_SET))
-	return(-1);
-
-/************************************************/
-/* Write the fixed portion of the header record */
-/************************************************/
-if(!fwrite(&msg.hdr,sizeof(msghdr_t),1,shd_fp))
-	return(-2);
-
-/************************************************/
-/* Write the data fields (each is fixed length) */
-/************************************************/
-for(i=0;i<msg.hdr.total_dfields;i++)
-	if(!fwrite(&msg.dfield[i],sizeof(dfield_t),1,shd_fp))
-		return(-3);
-
-/*******************************************/
-/* Write the variable length header fields */
-/*******************************************/
-for(i=0;i<msg.total_hfields;i++) {
-	if(!fwrite(&msg.hfield[i],sizeof(hfield_t),1,shd_fp))
-		return(-4);
-	if(msg.hfield[i].length 					/* more then 0 bytes long */
-		&& !fwrite(msg.hfield_dat[i],msg.hfield[i].length,1,shd_fp))
-		return(-5); }
-
-l=smb_getmsghdrlen(msg);
-while(l%SHD_BLOCK_LEN) {
-	if(fputc(0,shd_fp)==EOF)
-		return(-6); 			   /* pad block with NULL */
-	l++; }
-fflush(shd_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Creates a sub-board's initial header file                                */
-/* Truncates and deletes other associated SMB files 						*/
-/****************************************************************************/
-int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-	,int retry_time)
-{
-    char        str[128];
-	smbhdr_t	hdr;
-	smbstatus_t status;
-
-if(filelength(fileno(shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
-	&& smb_locksmbhdr(retry_time))	/* header exists, so lock it */
-	return(1);
-memset(&hdr,0,sizeof(smbhdr_t));
-memset(&status,0,sizeof(smbstatus_t));
-memcpy(hdr.id,"SMB\x1a",4);     /* <S> <M> <B> <^Z> */
-hdr.version=SMB_VERSION;
-hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-status.last_msg=status.total_msgs=0;
-status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-status.max_crcs=max_crcs;
-status.max_msgs=max_msgs;
-status.max_age=max_age;
-status.attr=attr;
-rewind(shd_fp);
-fwrite(&hdr,1,sizeof(smbhdr_t),shd_fp);
-fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
-rewind(shd_fp);
-chsize(fileno(shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
-fflush(shd_fp);
-
-rewind(sdt_fp);
-chsize(fileno(sdt_fp),0L);
-rewind(sid_fp);
-chsize(fileno(sid_fp),0L);
-
-sprintf(str,"%s.SDA",smb_file);
-remove(str);						/* if it exists, delete it */
-sprintf(str,"%s.SHA",smb_file);
-remove(str);                        /* if it exists, delete it */
-sprintf(str,"%s.SCH",smb_file);
-remove(str);
-smb_unlocksmbhdr();
-return(0);
-}
-
-/****************************************************************************/
-/* Returns number of data blocks required to store "length" amount of data  */
-/****************************************************************************/
-ulong smb_datblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SDT_BLOCK_LEN;
-if(length%SDT_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Returns number of header blocks required to store "length" size header   */
-/****************************************************************************/
-ulong smb_hdrblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SHD_BLOCK_LEN;
-if(length%SHD_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Finds unused space in data file based on block allocation table and		*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of data (in bytes, not blocks)				*/
-/* Assumes smb_open_da() has been called									*/
-/* fclose(sda_fp) should be called after									*/
-/* Returns negative on error												*/
-/****************************************************************************/
-long smb_allocdat(ulong length, ushort headers)
-{
-    ushort  i,j;
-	ulong	l,blocks,offset=0L;
-
-blocks=smb_datblocks(length);
-j=0;	/* j is consecutive unused block counter */
-fflush(sda_fp);
-rewind(sda_fp);
-while(!feof(sda_fp)) {
-	if(!fread(&i,2,1,sda_fp))
-        break;
-	offset+=SDT_BLOCK_LEN;
-    if(!i) j++;
-    else   j=0;
-	if(j==blocks) {
-		offset-=(blocks*SDT_BLOCK_LEN);
-        break; } }
-clearerr(sda_fp);
-fseek(sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,sda_fp))
-		return(-1);
-fflush(sda_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for data, but doesn't search for unused blocks           */
-/* Returns negative on error												*/
-/****************************************************************************/
-long smb_fallocdat(ulong length, ushort headers)
-{
-	ulong	l,blocks,offset;
-
-fflush(sda_fp);
-clearerr(sda_fp);
-blocks=smb_datblocks(length);
-fseek(sda_fp,0L,SEEK_END);
-offset=(ftell(sda_fp)/2L)*SDT_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,sda_fp))
-        break;
-fflush(sda_fp);
-if(l<blocks)
-	return(-1L);
-return(offset);
-}
-
-/****************************************************************************/
-/* De-allocates space for data												*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_freemsgdat(ulong offset, ulong length, ushort headers)
-{
-	ushort	i;
-	ulong	l,blocks;
-
-blocks=smb_datblocks(length);
-
-clearerr(sda_fp);
-for(l=0;l<blocks;l++) {
-	if(fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
-		return(1);
-	if(!fread(&i,2,1,sda_fp))
-		return(2);
-	if(headers>i)
-		i=0;			/* don't want to go negative */
-	else
-		i-=headers;
-	if(fseek(sda_fp,-2L,SEEK_CUR))
-		return(3);
-	if(!fwrite(&i,2,1,sda_fp))
-		return(4); }
-fflush(sda_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Adds to data allocation records for blocks starting at 'offset'          */
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_incdat(ulong offset, ulong length, ushort headers)
-{
-	ushort	i;
-	ulong	l,blocks;
-
-clearerr(sda_fp);
-blocks=smb_datblocks(length);
-for(l=0;l<blocks;l++) {
-	fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
-	if(!fread(&i,2,1,sda_fp))
-		return(1);
-	i+=headers;
-	fseek(sda_fp,-2L,SEEK_CUR);
-	if(!fwrite(&i,2,1,sda_fp))
-		return(2); }
-fflush(sda_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* De-allocates blocks for header record									*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_freemsghdr(ulong offset, ulong length)
-{
-	uchar	c=0;
-	ulong	l,blocks;
-
-clearerr(sha_fp);
-blocks=smb_hdrblocks(length);
-fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(1);
-fflush(sha_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Frees all allocated header and data blocks for 'msg'                     */
-/****************************************************************************/
-int smb_freemsg(smbmsg_t msg, smbstatus_t status)
-{
-	int 	i;
-	ushort	x;
-
-if(status.attr&SMB_HYPERALLOC)	/* Nothing to do */
-	return(0);
-
-for(x=0;x<msg.hdr.total_dfields;x++) {
-	if((i=smb_freemsgdat(msg.hdr.offset+msg.dfield[x].offset
-		,msg.dfield[x].length,1))!=0)
-		return(i); }
-return(smb_freemsghdr(msg.idx.offset-status.header_offset,msg.hdr.length));
-}
-
-/****************************************************************************/
-/* Finds unused space in header file based on block allocation table and	*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of header (in bytes, not blocks) 			*/
-/* Assumes smb_open_ha() has been called									*/
-/* fclose(sha_fp) should be called after									*/
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long smb_allochdr(ulong length)
-{
-	uchar	c;
-	ushort	i;
-	ulong	l,blocks,offset=0;
-
-blocks=smb_hdrblocks(length);
-i=0;	/* i is consecutive unused block counter */
-fflush(sha_fp);
-rewind(sha_fp);
-while(!feof(sha_fp)) {
-	if(!fread(&c,1,1,sha_fp))
-        break;
-	offset+=SHD_BLOCK_LEN;
-	if(!c) i++;
-	else   i=0;
-	if(i==blocks) {
-		offset-=(blocks*SHD_BLOCK_LEN);
-        break; } }
-clearerr(sha_fp);
-fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-c=1;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(-1L);
-fflush(sha_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for index, but doesn't search for unused blocks          */
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long smb_fallochdr(ulong length)
-{
-	uchar	c=1;
-	ulong	l,blocks,offset;
-
-blocks=smb_hdrblocks(length);
-fflush(sha_fp);
-clearerr(sha_fp);
-fseek(sha_fp,0L,SEEK_END);
-offset=ftell(sha_fp)*SHD_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(-1L);
-fflush(sha_fp);
-return(offset);
-}
-
-/************************************************************************/
-/* Allocate header blocks using Hyper Allocation						*/
-/* this function should be most likely not be called from anywhere but	*/
-/* smb_addmsghdr()														*/
-/************************************************************************/
-long smb_hallochdr(ulong header_offset)
-{
-	long l;
-
-fflush(shd_fp);
-fseek(shd_fp,0L,SEEK_END);
-l=ftell(shd_fp);
-if(l<header_offset) 					/* Header file truncated?!? */
-	return(header_offset);
-while((l-header_offset)%SHD_BLOCK_LEN)	/* Make sure even block boundry */
-	l++;
-return(l-header_offset);
-}
-
-/************************************************************************/
-/* Allocate data blocks using Hyper Allocation							*/
-/* smb_locksmbhdr() should be called before this function and not		*/
-/* unlocked until all data fields for this message have been written	*/
-/* to the SDT file														*/
-/************************************************************************/
-long smb_hallocdat()
-{
-	long l;
-
-fflush(sdt_fp);
-fseek(sdt_fp,0L,SEEK_END);
-l=ftell(sdt_fp);
-if(l<=0)
-	return(l);
-while(l%SDT_BLOCK_LEN)					/* Make sure even block boundry */
-	l++;
-return(l);
-}
-
-/* End of SMBLIB.C */
diff --git a/src/sbbs2/fido/smblib.h b/src/sbbs2/fido/smblib.h
deleted file mode 100644
index b682f74f039574009cd3ef2e0a77204231e8e5b7..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/smblib.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* SMBLIB.H */
-
-#ifndef _SMBLIB_H
-#define _SMBLIB_H
-
-#if defined(__WATCOMC__) || defined(__TURBOC__)
-#	include <io.h>
-#	include <mem.h>
-#	include <share.h>
-#else
-#	include <memory.h>
-#endif
-
-#ifdef __WATCOMC__
-#	include <dos.h>
-#elif defined(__TURBOC__)
-#	include <dir.h>
-#endif
-
-#include <malloc.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define GLOBAL extern	/* turn smbvars.c files into header */
-
-#include "smbvars.c"
-
-#define SMB_STACK_LEN		4			/* Max msg bases in smb_stack() 	*/
-#define SMB_STACK_POP       0           /* Pop a msg base off of smb_stack() */
-#define SMB_STACK_PUSH      1           /* Push a msg base onto smb_stack() */
-#define SMB_STACK_XCHNG     2           /* Exchange msg base w/last pushed */
-
-int 	smb_open(int retry_time);
-void	smb_close(void);
-int 	smb_open_da(int retry_time);
-int 	smb_open_ha(int retry_time);
-int 	smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-				  ,int retry_time);
-int 	smb_stack(int op);
-int 	smb_trunchdr(int retry_time);
-int 	smb_locksmbhdr(int retry_time);
-int 	smb_getstatus(smbstatus_t *status);
-int 	smb_putstatus(smbstatus_t status);
-int 	smb_unlocksmbhdr(void);
-int 	smb_getmsgidx(smbmsg_t *msg);
-int 	smb_getlastidx(idxrec_t *idx);
-uint	smb_getmsghdrlen(smbmsg_t msg);
-ulong	smb_getmsgdatlen(smbmsg_t msg);
-int 	smb_lockmsghdr(smbmsg_t msg, int retry_time);
-int 	smb_getmsghdr(smbmsg_t *msg);
-int 	smb_unlockmsghdr(smbmsg_t msg);
-int 	smb_addcrc(ulong max_crcs, ulong crc, int retry_time);
-int 	smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data);
-int 	smb_dfield(smbmsg_t *msg, ushort type, ulong length);
-int 	smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
-				,int retry_time);
-int 	smb_putmsg(smbmsg_t msg);
-int 	smb_putmsgidx(smbmsg_t msg);
-int 	smb_putmsghdr(smbmsg_t msg);
-void	smb_freemsgmem(smbmsg_t msg);
-ulong	smb_hdrblocks(ulong length);
-ulong	smb_datblocks(ulong length);
-long	smb_allochdr(ulong length);
-long	smb_fallochdr(ulong length);
-long	smb_hallochdr(ulong header_offset);
-long	smb_allocdat(ulong length, ushort headers);
-long	smb_fallocdat(ulong length, ushort headers);
-long	smb_hallocdat(void);
-int 	smb_incdat(ulong offset, ulong length, ushort headers);
-int 	smb_freemsg(smbmsg_t msg, smbstatus_t status);
-int 	smb_freemsgdat(ulong offset, ulong length, ushort headers);
-int 	smb_freemsghdr(ulong offset, ulong length);
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/fido/smbvars.c b/src/sbbs2/fido/smbvars.c
deleted file mode 100644
index 9b80d699e636c3dcc01d5f15c464c5b544bcf47a..0000000000000000000000000000000000000000
--- a/src/sbbs2/fido/smbvars.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SMBVARS.C */
-
-/*************************************************************************/
-/* Global variables for SMBLIB. Same file used for both header and code. */
-/*************************************************************************/
-
-#ifndef GLOBAL
-#define GLOBAL
-#endif
-
-#include "smbdefs.h"
-#include <stdio.h>
-
-GLOBAL char 	smb_file[128];	/* path and filename for SMB file (no ext) */
-GLOBAL char 	shd_buf[SHD_BLOCK_LEN];
-GLOBAL FILE 	*sdt_fp;
-GLOBAL FILE 	*shd_fp;
-GLOBAL FILE 	*sid_fp;
-GLOBAL FILE 	*sda_fp;
-GLOBAL FILE 	*sha_fp;
-GLOBAL FILE 	*sch_fp;
-
diff --git a/src/sbbs2/file.c b/src/sbbs2/file.c
deleted file mode 100644
index 2ae1b479dd8cae25b7822ce66aeb25c0c2733f81..0000000000000000000000000000000000000000
--- a/src/sbbs2/file.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#line 1 "FILE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*************************************************************************/
-/* Add/delete/edit/view/retrieve the file information for struct file_t  */
-/* Called only from functions within xfer.c								 */
-/*************************************************************************/
-
-#include "sbbs.h"
-
-long fdate_dir(char *filespec);
-
-void getextdesc(uint dirnum, ulong datoffset, char *ext)
-{
-	char str[256];
-	int file;
-
-memset(ext,0,513);
-sprintf(str,"%s%s.EXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1)
-	return;
-lseek(file,(datoffset/F_LEN)*512L,SEEK_SET);
-read(file,ext,512);
-close(file);
-}
-
-void putextdesc(uint dirnum, ulong datoffset, char *ext)
-{
-	char str[256],nulbuf[512];
-	int file;
-
-memset(nulbuf,0,512);
-sprintf(str,"%s%s.EXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-	return;
-lseek(file,0L,SEEK_END);
-while(filelength(file)<(datoffset/F_LEN)*512L)
-	write(file,nulbuf,512);
-lseek(file,(datoffset/F_LEN)*512L,SEEK_SET);
-write(file,ext,512);
-close(file);
-}
-
-/****************************************************************************/
-/* Prints all information of file in file_t structure 'f'					*/
-/****************************************************************************/
-void fileinfo(file_t f)
-{
-	char str[256],fname[13],ext[513];
-	uint i,j;
-	long t;
-
-for(i=0;i<usrlibs;i++)
-	if(usrlib[i]==dir[f.dir]->lib)
-		break;
-for(j=0;j<usrdirs[i];j++)
-	if(usrdir[i][j]==f.dir)
-		break;
-unpadfname(f.name,fname);
-bprintf(text[FiLib],i+1,lib[dir[f.dir]->lib]->lname);
-bprintf(text[FiDir],j+1,dir[f.dir]->lname);
-bprintf(text[FiFilename],fname);
-if(f.size!=-1L)
-	bprintf(text[FiFileSize],ultoac(f.size,tmp));
-bprintf(text[FiCredits]
-	,(dir[f.dir]->misc&DIR_FREE || !f.cdt) ? "FREE" : ultoac(f.cdt,tmp));
-bprintf(text[FiDescription],f.desc);
-bprintf(text[FiUploadedBy],f.misc&FM_ANON ? text[UNKNOWN_USER] : f.uler);
-if(f.date)
-	bprintf(text[FiFileDate],timestr(&f.date));
-bprintf(text[FiDateUled],timestr(&f.dateuled));
-bprintf(text[FiDateDled],f.datedled ? timestr(&f.datedled) : "Never");
-bprintf(text[FiTimesDled],f.timesdled);
-if(f.size!=-1L)
-	bprintf(text[FiTransferTime],sectostr(f.timetodl,tmp));
-if(f.altpath) {
-	if(f.altpath<=altpaths) {
-		if(SYSOP)
-			bprintf(text[FiAlternatePath],altpath[f.altpath-1]); }
-	else
-		bprintf(text[InvalidAlternatePathN],f.altpath); }
-CRLF;
-if(f.misc&FM_EXTDESC) {
-	getextdesc(f.dir,f.datoffset,ext);
-	CRLF;
-	putmsg(ext,P_NOATCODES);
-	CRLF; }
-if(f.size==-1L)
-	bprintf(text[FileIsNotOnline],f.name);
-if(f.opencount)
-	bprintf(text[FileIsOpen],f.opencount,f.opencount>1 ? "s" : nulstr);
-
-}
-
-/****************************************************************************/
-/* Gets file data from dircode.IXB file										*/
-/* Need fields .name and .dir filled.                                       */
-/* only fills .offset, .dateuled, and .datedled                             */
-/****************************************************************************/
-void getfileixb(file_t *f)
-{
-	uchar HUGE16 *ixbbuf,str[256],fname[13];
-	int file;
-	ulong l,length;
-
-sprintf(str,"%s%s.IXB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-	close(file);
-	errormsg(WHERE,ERR_LEN,str,length);
-	return; }
-if((ixbbuf=MALLOC(length))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length);
-	return; }
-if(lread(file,ixbbuf,length)!=length) {
-	close(file);
-	FREE((char *)ixbbuf);
-	errormsg(WHERE,ERR_READ,str,length);
-	return; }
-close(file);
-strcpy(fname,f->name);
-for(l=8;l<12;l++)	/* Turn FILENAME.EXT into FILENAMEEXT */
-	fname[l]=fname[l+1];
-for(l=0;l<length;l+=F_IXBSIZE) {
-	sprintf(str,"%11.11s",ixbbuf+l);
-	if(!strcmp(str,fname))
-		break; }
-if(l>=length) {
-	errormsg(WHERE,ERR_CHK,str,0);
-	FREE((char *)ixbbuf);
-	return; }
-l+=11;
-f->datoffset=ixbbuf[l]|((long)ixbbuf[l+1]<<8)|((long)ixbbuf[l+2]<<16);
-f->dateuled=ixbbuf[l+3]|((long)ixbbuf[l+4]<<8)
-	|((long)ixbbuf[l+5]<<16)|((long)ixbbuf[l+6]<<24);
-f->datedled=ixbbuf[l+7]|((long)ixbbuf[l+8]<<8)
-	|((long)ixbbuf[l+9]<<16)|((long)ixbbuf[l+10]<<24);
-FREE((char *)ixbbuf);
-}
-
-/****************************************************************************/
-/* Gets filedata from dircode.DAT file										*/
-/* Need fields .name ,.dir and .offset to get other info    				*/
-/* Does not fill .dateuled or .datedled fields.                             */
-/****************************************************************************/
-void getfiledat(file_t *f)
-{
-	char buf[F_LEN+1],str[256];
-	int file;
-	long length;
-
-sprintf(str,"%s%s.DAT",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-length=filelength(file);
-if(f->datoffset>length) {
-	close(file);
-	errormsg(WHERE,ERR_LEN,str,length);
-	return; }
-if(length%F_LEN) {
-	close(file);
-	errormsg(WHERE,ERR_LEN,str,length);
-	return; }
-lseek(file,f->datoffset,SEEK_SET);
-if(read(file,buf,F_LEN)!=F_LEN) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str,F_LEN);
-	return; }
-close(file);
-getrec(buf,F_ALTPATH,2,str);
-f->altpath=hptoi(str);
-getrec(buf,F_CDT,LEN_FCDT,str);
-f->cdt=atol(str);
-
-if(!f->size) {					/* only read disk if this is null */
-//	  if(dir[f->dir]->misc&DIR_FCHK) {
-		sprintf(str,"%s%s"
-			,f->altpath>0 && f->altpath<=altpaths ? altpath[f->altpath-1]
-			: dir[f->dir]->path,unpadfname(f->name,tmp));
-		f->size=flength(str);
-		f->date=fdate_dir(str);
-/*
-		}
-	else {
-		f->size=f->cdt;
-		f->date=0; }
-*/
-		}
-if((f->size>0L) && cur_cps)
-	f->timetodl=(f->size/(ulong)cur_cps);
-else
-	f->timetodl=0;
-
-getrec(buf,F_DESC,LEN_FDESC,f->desc);
-getrec(buf,F_ULER,LEN_ALIAS,f->uler);
-getrec(buf,F_TIMESDLED,5,str);
-f->timesdled=atoi(str);
-getrec(buf,F_OPENCOUNT,3,str);
-f->opencount=atoi(str);
-if(buf[F_MISC]!=ETX)
-	f->misc=buf[F_MISC]-SP;
-else
-	f->misc=0;
-}
-
-/****************************************************************************/
-/* Increments the opencount on the file data 'f' and adds the transaction 	*/
-/* to the backout.dab														*/
-/****************************************************************************/
-void openfile(file_t f)
-{
-	char str1[256],str2[4],str3[4],ch;
-	int file;
-
-/************************************/
-/* Increment open count in dat file */
-/************************************/
-sprintf(str1,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str1,O_RDWR))==-1) {
-	errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
-	return; }
-lseek(file,f.datoffset+F_OPENCOUNT,SEEK_SET);
-if(read(file,str2,3)!=3) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str1,3);
-	return; }
-str2[3]=0;
-itoa(atoi(str2)+1,str3,10);
-putrec(str2,0,3,str3);
-lseek(file,f.datoffset+F_OPENCOUNT,SEEK_SET);
-if(write(file,str2,3)!=3) {
-	close(file);
-	errormsg(WHERE,ERR_WRITE,str1,3);
-	return; }
-close(file);
-/**********************************/
-/* Add transaction to BACKOUT.DAB */
-/**********************************/
-sprintf(str1,"%sBACKOUT.DAB",node_dir);
-if((file=nopen(str1,O_WRONLY|O_APPEND|O_CREAT))==-1) {
-	errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_APPEND|O_CREAT);
-	return; }
-ch=BO_OPENFILE;
-write(file,&ch,1);				/* backout type */
-write(file,dir[f.dir]->code,8); /* directory code */
-write(file,&f.datoffset,4);		/* offset into .dat file */
-write(file,&ch,BO_LEN-(1+8+4)); /* pad it */
-close(file);
-}
-
-/****************************************************************************/
-/* Decrements the opencount on the file data 'f' and removes the backout  	*/
-/* from the backout.dab														*/
-/****************************************************************************/
-void closefile(file_t f)
-{
-	uchar str1[256],str2[4],str3[4],ch,*buf;
-	int file;
-	long length,l,offset;
-
-/************************************/
-/* Decrement open count in dat file */
-/************************************/
-sprintf(str1,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str1,O_RDWR))==-1) {
-	errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
-	return; }
-lseek(file,f.datoffset+F_OPENCOUNT,SEEK_SET);
-if(read(file,str2,3)!=3) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str1,3);
-	return; }
-str2[3]=0;
-ch=atoi(str2);
-if(ch) ch--;
-itoa(ch,str3,10);
-putrec(str2,0,3,str3);
-lseek(file,f.datoffset+F_OPENCOUNT,SEEK_SET);
-if(write(file,str2,3)!=3) {
-	close(file);
-	errormsg(WHERE,ERR_WRITE,str1,3);
-	return; }
-close(file);
-/*****************************************/
-/* Removing transaction from BACKOUT.DAB */
-/*****************************************/
-sprintf(str1,"%sBACKOUT.DAB",node_dir);
-if(flength(str1)<1L)	/* file is not there or empty */
-	return;
-if((file=nopen(str1,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str1,O_RDONLY);
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str1,length);
-	return; }
-if(read(file,buf,length)!=length) {
-	close(file);
-	FREE(buf);
-	errormsg(WHERE,ERR_READ,str1,length);
-	return; }
-close(file);
-if((file=nopen(str1,O_WRONLY|O_TRUNC))==-1) {
-	errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_TRUNC);
-	return; }
-ch=0;								/* 'ch' is a 'file already removed' flag */
-for(l=0;l<length;l+=BO_LEN) {       /* in case file is in backout.dab > 1 */
-	if(!ch && buf[l]==BO_OPENFILE) {
-		memcpy(str1,buf+l+1,8);
-		str1[8]=0;
-		memcpy(&offset,buf+l+9,4);
-		if(!stricmp(str1,dir[f.dir]->code) && offset==f.datoffset) {
-			ch=1;
-			continue; } }
-	write(file,buf+l,BO_LEN); }
-FREE(buf);
-close(file);
-}
diff --git a/src/sbbs2/file_ovl.c b/src/sbbs2/file_ovl.c
deleted file mode 100644
index aa7eb5963c7c56972386bbb974572142343bcd38..0000000000000000000000000000000000000000
--- a/src/sbbs2/file_ovl.c
+++ /dev/null
@@ -1,580 +0,0 @@
-#line 1 "FILE_OVL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Adds file data in 'f' to DIR#.DAT and DIR#.IXB   and updates user        */
-/* info for uploader. Must have .name, .desc and .dir fields filled prior   */
-/* to a call to this function.                                              */
-/* Returns 1 if file uploaded sucessfully, 0 if not.                        */
-/****************************************************************************/
-char uploadfile(file_t *f)
-{
-	uchar path[256],str[256],fname[25],ext[513],desc[513],tmp[128],*p;
-	static uchar sbbsfilename[128],sbbsfiledesc[128];
-	int  file;
-    uint i;
-    long length;
-	FILE *stream;
-
-f->misc=0;
-curdirnum=f->dir;
-if(findfile(f->dir,f->name)) {
-	errormsg(WHERE,ERR_CHK,f->name,f->dir);
-    return(0); }
-sprintf(path,"%s%s",f->altpath>0 && f->altpath<=altpaths
-	? altpath[f->altpath-1]
-	: dir[f->dir]->path,unpadfname(f->name,fname));
-if(!fexist(path)) {
-	bprintf(text[FileNotReceived],f->name);
-	sprintf(str,"Attempted to upload %s to %s %s (Not received)",f->name
-		,lib[dir[f->dir]->lib]->sname,dir[f->dir]->sname);
-    logline("U!",str);
-    return(0); }
-strcpy(tmp,f->name);
-truncsp(tmp);
-for(i=0;i<total_ftests;i++)
-	if(ftest[i]->ext[0]=='*' || !strcmp(tmp+9,ftest[i]->ext)) {
-		if(!chk_ar(ftest[i]->ar,useron))
-			continue;
-		attr(LIGHTGRAY);
-        bputs(ftest[i]->workstr);
-
-		sprintf(sbbsfilename,"SBBSFILENAME=%.12s",unpadfname(f->name,fname));
-		putenv(sbbsfilename);
-		sprintf(sbbsfiledesc,"SBBSFILEDESC=%.*s",LEN_FDESC,f->desc);
-		putenv(sbbsfiledesc);
-		sprintf(str,"%sSBBSFILE.NAM",node_dir);
-        if((stream=fopen(str,"w"))!=NULL) {
-			fwrite(fname,1,strlen(fname),stream);
-			fclose(stream); }
-        sprintf(str,"%sSBBSFILE.DES",node_dir);
-		if((stream=fopen(str,"w"))!=NULL) {
-			fwrite(f->desc,1,strlen(f->desc),stream);
-            fclose(stream); }
-		if(external(cmdstr(ftest[i]->cmd,path,f->desc,NULL),0)) { /* EX_OUTL */
-			bprintf(text[FileHadErrors],f->name,ftest[i]->ext);
-            if(SYSOP) {
-                if(!yesno(text[DeleteFileQ])) return(0); }
-            remove(path);
-			sprintf(str,"Attempted to upload %s to %s %s (%s Errors)",f->name
-				,lib[dir[f->dir]->lib]->sname,dir[f->dir]->sname,ftest[i]->ext);
-            logline("U!",str);
-            return(0); }
-        else {
-			sprintf(str,"%sSBBSFILE.NAM",node_dir);
-			if((stream=fopen(str,"r"))!=NULL) {
-				if(fgets(str,128,stream)) {
-					truncsp(str);
-					strupr(str);
-					padfname(str,f->name);
-					strcpy(tmp,f->name);
-					truncsp(tmp);
-					sprintf(path,"%s%s",f->altpath>0 && f->altpath<=altpaths
-						? altpath[f->altpath-1] : dir[f->dir]->path
-						,unpadfname(f->name,fname)); }
-                fclose(stream);
-				}
-			sprintf(str,"%sSBBSFILE.DES",node_dir);
-			if((stream=fopen(str,"r"))!=NULL) {
-				if(fgets(str,128,stream)) {
-					truncsp(str);
-					sprintf(f->desc,"%.*s",LEN_FDESC,str); }
-				fclose(stream); }
-            CRLF; } }
-
-if((length=flength(path))<=0L) {
-	bprintf(text[FileZeroLength],f->name);
-    remove(path);
-	sprintf(str,"Attempted to upload %s to %s %s (Zero length)",f->name
-		,lib[dir[f->dir]->lib]->sname,dir[f->dir]->sname);
-    logline("U!",str);
-    return(0); }
-if(dir[f->dir]->misc&DIR_DIZ) {
-	for(i=0;i<total_fextrs;i++)
-		if(!stricmp(fextr[i]->ext,tmp+9) && chk_ar(fextr[i]->ar,useron))
-			break;
-	if(i<total_fextrs) {
-		sprintf(str,"%sFILE_ID.DIZ",temp_dir);
-		remove(str);
-		external(cmdstr(fextr[i]->cmd,path,"FILE_ID.DIZ",NULL),EX_OUTL);
-		if(!fexist(str)) {
-			sprintf(str,"%sDESC.SDI",temp_dir);
-			remove(str);
-			external(cmdstr(fextr[i]->cmd,path,"DESC.SDI",NULL),EX_OUTL); }
-		if((file=nopen(str,O_RDONLY))!=-1) {
-			memset(ext,0,513);
-			read(file,ext,512);
-			for(i=512;i;i--)
-				if(ext[i-1]>SP)
-					break;
-			ext[i]=0;
-			if(!f->desc[0]) {
-				strcpy(desc,ext);
-				strip_exascii(desc);
-				strip_ctrl(desc);
-				for(i=0;desc[i];i++)
-					if(isalnum(desc[i]))
-						break;
-				sprintf(f->desc,"%.*s",LEN_FDESC,desc+i); }
-			close(file);
-			remove(str);
-			f->misc|=FM_EXTDESC; } } }
-
-logon_ulb+=length;  /* Update 'this call' stats */
-logon_uls++;
-if(dir[f->dir]->misc&DIR_AONLY)  /* Forced anonymous */
-	f->misc|=FM_ANON;
-f->cdt=length;
-f->dateuled=time(NULL);
-f->timesdled=0;
-f->datedled=0L;
-f->opencount=0;
-strcpy(f->uler,useron.alias);
-bprintf(text[FileNBytesReceived],f->name,ultoac(length,tmp));
-if(!f->desc[0])
-	sprintf(f->desc,"%.*s",LEN_FDESC,text[NoDescription]);
-if(!addfiledat(f))
-	return(0);
-
-if(f->misc&FM_EXTDESC)
-	putextdesc(f->dir,f->datoffset,ext);
-
-sprintf(str,"Uploaded %s to %s %s",f->name,lib[dir[f->dir]->lib]->sname
-	,dir[f->dir]->sname);
-if(dir[f->dir]->upload_sem[0])
-	if((file=nopen(dir[f->dir]->upload_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-        close(file);
-logline("U+",str);
-/**************************/
-/* Update Uploader's Info */
-/**************************/
-useron.uls=adjustuserrec(useron.number,U_ULS,5,1);
-useron.ulb=adjustuserrec(useron.number,U_ULB,10,length);
-if(dir[f->dir]->up_pct && dir[f->dir]->misc&DIR_CDTUL) { /* credit for upload */
-	if(dir[f->dir]->misc&DIR_CDTMIN && cur_cps)    /* Give min instead of cdt */
-		useron.min=adjustuserrec(useron.number,U_MIN,10
-			,((ulong)(length*(dir[f->dir]->up_pct/100.0))/cur_cps)/60);
-	else
-		useron.cdt=adjustuserrec(useron.number,U_CDT,10
-			,(ulong)(f->cdt*(dir[f->dir]->up_pct/100.0))); }
-return(1);
-}
-
-
-/****************************************************************************/
-/* Updates downloader, uploader and downloaded file data                    */
-/* Must have offset, dir and name fields filled prior to call.              */
-/****************************************************************************/
-void downloadfile(file_t f)
-{
-    char str[256],str2[256],fname[13];
-    int i,file;
-	long length,mod;
-    ulong l;
-	user_t uploader;
-
-getfiledat(&f); /* Get current data - right after download */
-if((length=f.size)<0L)
-    length=0L;
-logon_dlb+=length;  /* Update 'this call' stats */
-logon_dls++;
-bprintf(text[FileNBytesSent],f.name,ultoac(length,tmp));
-sprintf(str,"Downloaded %s from %s %s",f.name,lib[dir[f.dir]->lib]->sname
-    ,dir[f.dir]->sname);
-logline("D-",str);
-/****************************/
-/* Update Downloader's Info */
-/****************************/
-useron.dls=adjustuserrec(useron.number,U_DLS,5,1);
-useron.dlb=adjustuserrec(useron.number,U_DLB,10,length);
-if(!(dir[f.dir]->misc&DIR_FREE) && !(useron.exempt&FLAG('D')))
-	subtract_cdt(f.cdt);
-/**************************/
-/* Update Uploader's Info */
-/**************************/
-i=matchuser(f.uler);
-uploader.number=i;
-getuserdat(&uploader);
-if(i && i!=useron.number && uploader.firston<f.dateuled) {
-	l=f.cdt;
-	if(!(dir[f.dir]->misc&DIR_CDTDL))	/* Don't give credits on d/l */
-		l=0;
-	if(dir[f.dir]->misc&DIR_CDTMIN && cur_cps) { /* Give min instead of cdt */
-		mod=((ulong)(l*(dir[f.dir]->dn_pct/100.0))/cur_cps)/60;
-		adjustuserrec(i,U_MIN,10,mod);
-		sprintf(tmp,"%lu minute",mod);
-		sprintf(str,text[DownloadUserMsg]
-			,!strcmp(dir[f.dir]->code,"TEMP") ? temp_file : f.name
-			,!strcmp(dir[f.dir]->code,"TEMP") ? text[Partially] : nulstr
-			,useron.alias,tmp); }
-	else {
-		mod=(ulong)(l*(dir[f.dir]->dn_pct/100.0));
-		adjustuserrec(i,U_CDT,10,mod);
-		ultoac(mod,tmp);
-		sprintf(str,text[DownloadUserMsg]
-			,!strcmp(dir[f.dir]->code,"TEMP") ? temp_file : f.name
-			,!strcmp(dir[f.dir]->code,"TEMP") ? text[Partially] : nulstr
-			,useron.alias,tmp); }
-    putsmsg(i,str); }
-/*******************/
-/* Update IXB File */
-/*******************/
-f.datedled=time(NULL);
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDWR))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-    return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-    close(file);
-    errormsg(WHERE,ERR_LEN,str,length);
-    return; }
-strcpy(fname,f.name);
-for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[i]=fname[i+1];
-for(l=0;l<length;l+=F_IXBSIZE) {
-    read(file,str,F_IXBSIZE);      /* Look for the filename in the IXB file */
-    str[11]=0;
-    if(!strcmp(fname,str)) break; }
-if(l>=length) {
-    close(file);
-    errormsg(WHERE,ERR_CHK,f.name,0);
-    return; }
-lseek(file,l+18,SEEK_SET);
-write(file,&f.datedled,4);  /* Write the current time stamp for datedled */
-close(file);
-/*******************/
-/* Update DAT File */
-/*******************/
-f.timesdled++;
-putfiledat(f);
-/******************************************/
-/* Update User to User index if necessary */
-/******************************************/
-if(f.dir==user_dir) {
-    rmuserxfers(0,useron.number,f.name);
-    if(!getuserxfers(0,0,f.name)) { /* check if any ixt entries left */
-        sprintf(str,"%s%s",f.altpath>0 && f.altpath<=altpaths ?
-            altpath[f.altpath-1] : dir[f.dir]->path,unpadfname(f.name,tmp));
-        remove(str);
-        removefiledat(f); } }
-}
-
-/****************************************************************************/
-/* Removes DAT and IXB entries for the file in the struct 'f'               */
-/****************************************************************************/
-void removefiledat(file_t f)
-{
-	char c,str[256],ixbname[12],HUGE16 *ixbbuf,fname[13];
-    int file;
-    ulong l,length;
-
-strcpy(fname,f.name);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    return; }
-length=filelength(file);
-if(!length) {
-	close(file);
-	return; }
-if((ixbbuf=(char *)MALLOC(length))==0) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length);
-    return; }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-    errormsg(WHERE,ERR_READ,str,length);
-	FREE((char *)ixbbuf);
-    return; }
-close(file);
-if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
-    return; }
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        ixbname[c]=ixbbuf[l+c];
-    ixbname[c]=0;
-    if(strcmp(ixbname,fname))
-		if(lwrite(file,&ixbbuf[l],F_IXBSIZE)!=F_IXBSIZE) {
-            close(file);
-            errormsg(WHERE,ERR_WRITE,str,F_IXBSIZE);
-			FREE((char *)ixbbuf);
-            return; } }
-FREE((char *)ixbbuf);
-close(file);
-sprintf(str,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-    return; }
-lseek(file,f.datoffset,SEEK_SET);
-c=ETX;          /* If first char of record is ETX, record is unused */
-if(write(file,&c,1)!=1) { /* So write a D_T on the first byte of the record */
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,1);
-    return; }
-close(file);
-if(f.dir==user_dir)  /* remove file from index */
-    rmuserxfers(0,0,f.name);
-
-}
-
-/****************************************************************************/
-/* Puts filedata into DIR_code.DAT file                                     */
-/* Called from removefiles                                                  */
-/****************************************************************************/
-void putfiledat(file_t f)
-{
-    char buf[F_LEN+1],str[256];
-    int file;
-    long length;
-
-putrec(buf,F_CDT,LEN_FCDT,ultoa(f.cdt,tmp,10));
-putrec(buf,F_DESC,LEN_FDESC,f.desc);
-putrec(buf,F_DESC+LEN_FDESC,2,crlf);
-putrec(buf,F_ULER,LEN_ALIAS+5,f.uler);
-putrec(buf,F_ULER+LEN_ALIAS+5,2,crlf);
-putrec(buf,F_TIMESDLED,5,itoa(f.timesdled,tmp,10));
-putrec(buf,F_TIMESDLED+5,2,crlf);
-putrec(buf,F_OPENCOUNT,3,itoa(f.opencount,tmp,10));
-putrec(buf,F_OPENCOUNT+3,2,crlf);
-buf[F_MISC]=f.misc+SP;
-putrec(buf,F_ALTPATH,2,hexplus(f.altpath,tmp));
-putrec(buf,F_ALTPATH+2,2,crlf);
-sprintf(str,"%s%s.DAT",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-    return; }
-length=filelength(file);
-if(length%F_LEN) {
-    close(file);
-    errormsg(WHERE,ERR_LEN,str,length);
-    return; }
-if(f.datoffset>length) {
-    close(file);
-    errormsg(WHERE,ERR_LEN,str,length);
-    return; }
-lseek(file,f.datoffset,SEEK_SET);
-if(write(file,buf,F_LEN)!=F_LEN) {
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,F_LEN);
-    return; }
-length=filelength(file);
-close(file);
-if(length%F_LEN)
-    errormsg(WHERE,ERR_LEN,str,length);
-}
-
-/****************************************************************************/
-/* Adds the data for struct filedat to the directory's data base.           */
-/* changes the .datoffset field only                                        */
-/* returns 1 if added successfully, 0 if not.								*/
-/****************************************************************************/
-char addfiledat(file_t *f)
-{
-	uchar str[256],fdat[F_LEN+1],fname[13],idx[3],c,HUGE16 *ixbbuf;
-    int i,file;
-	ulong length,l;
-	time_t uldate;
-
-/************************/
-/* Add data to DAT File */
-/************************/
-sprintf(str,"%s%s.DAT",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_CREAT);
-	return(0); }
-length=filelength(file);
-if(length==0L)
-    l=0L;
-else {
-    if(length%F_LEN) {
-        close(file);
-        errormsg(WHERE,ERR_LEN,str,length);
-		return(0); }
-    for(l=0;l<length;l+=F_LEN) {    /* Find empty slot */
-        lseek(file,l,SEEK_SET);
-        read(file,&c,1);
-		if(c==ETX) break; }
-	if(l/F_LEN>=MAX_FILES || l/F_LEN>=dir[f->dir]->maxfiles) {
-		bputs(text[DirFull]);
-		close(file);
-		sprintf(str,"Directory Full: %s %s"
-			,lib[dir[f->dir]->lib]->sname,dir[f->dir]->sname);
-		logline("U!",str);
-		return(0); } }
-putrec(fdat,F_CDT,LEN_FCDT,ultoa(f->cdt,tmp,10));
-putrec(fdat,F_DESC,LEN_FDESC,f->desc);
-putrec(fdat,F_DESC+LEN_FDESC,2,crlf);
-putrec(fdat,F_ULER,LEN_ALIAS+5,f->uler);
-putrec(fdat,F_ULER+LEN_ALIAS+5,2,crlf);
-putrec(fdat,F_TIMESDLED,5,ultoa(f->timesdled,tmp,10));
-putrec(fdat,F_TIMESDLED+5,2,crlf);
-putrec(fdat,F_OPENCOUNT,3,itoa(f->opencount,tmp,10));
-putrec(fdat,F_OPENCOUNT+3,2,crlf);
-fdat[F_MISC]=f->misc+SP;
-putrec(fdat,F_ALTPATH,2,hexplus(f->altpath,tmp));
-putrec(fdat,F_ALTPATH+2,2,crlf);
-f->datoffset=l;
-idx[0]=l&0xff;          /* Get offset within DAT file for IXB file */
-idx[1]=(l>>8)&0xff;
-idx[2]=(l>>16)&0xff;
-lseek(file,l,SEEK_SET);
-if(write(file,fdat,F_LEN)!=F_LEN) {
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,F_LEN);
-	return(0); }
-length=filelength(file);
-close(file);
-if(length%F_LEN)
-    errormsg(WHERE,ERR_LEN,str,length);
-
-/*******************************************/
-/* Update last upload date/time stamp file */
-/*******************************************/
-sprintf(str,"%s%s.DAB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-else {
-    now=time(NULL);
-    write(file,&now,4);
-    close(file); }
-
-/************************/
-/* Add data to IXB File */
-/************************/
-strcpy(fname,f->name);
-for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[i]=fname[i+1];
-sprintf(str,"%s%s.IXB",dir[f->dir]->data_dir,dir[f->dir]->code);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_CREAT);
-	return(0); }
-length=filelength(file);
-if(length) {    /* IXB file isn't empty */
-    if(length%F_IXBSIZE) {
-        close(file);
-        errormsg(WHERE,ERR_LEN,str,length);
-		return(0); }
-	if((ixbbuf=(char *)MALLOC(length))==NULL) {
-        close(file);
-        errormsg(WHERE,ERR_ALLOC,str,length);
-		return(0); }
-	if(lread(file,ixbbuf,length)!=length) {
-        close(file);
-        errormsg(WHERE,ERR_READ,str,length);
-		FREE((char *)ixbbuf);
-		return(0); }
-/************************************************/
-/* Sort by Name or Date, Assending or Decending */
-/************************************************/
-    if(dir[f->dir]->sort==SORT_NAME_A || dir[f->dir]->sort==SORT_NAME_D) {
-        for(l=0;l<length;l+=F_IXBSIZE) {
-            for(i=0;i<12 && fname[i]==ixbbuf[l+i];i++);
-            if(i==12) {     /* file already in directory index */
-                close(file);
-                errormsg(WHERE,ERR_CHK,str,0);
-				FREE((char *)ixbbuf);
-				return(0); }
-            if(dir[f->dir]->sort==SORT_NAME_A && fname[i]<ixbbuf[l+i])
-                break;
-            if(dir[f->dir]->sort==SORT_NAME_D && fname[i]>ixbbuf[l+i])
-                break; } }
-    else {  /* sort by date */
-        for(l=0;l<length;l+=F_IXBSIZE) {
-			uldate=(ixbbuf[l+14]|((long)ixbbuf[l+15]<<8)
-				|((long)ixbbuf[l+16]<<16)|((long)ixbbuf[l+17]<<24));
-			if(dir[f->dir]->sort==SORT_DATE_A && f->dateuled<uldate)
-                break;
-			if(dir[f->dir]->sort==SORT_DATE_D && f->dateuled>uldate)
-                break; } }
-    lseek(file,l,SEEK_SET);
-    if(write(file,fname,11)!=11) {  /* Write filename to IXB file */
-        close(file);
-        errormsg(WHERE,ERR_WRITE,str,11);
-		FREE((char *)ixbbuf);
-		return(0); }
-    if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
-        close(file);
-        errormsg(WHERE,ERR_WRITE,str,3);
-		FREE((char *)ixbbuf);
-		return(0); }
-    write(file,&f->dateuled,sizeof(time_t));
-    write(file,&f->datedled,4);              /* Write 0 for datedled */
-	if(lwrite(file,&ixbbuf[l],length-l)!=length-l) { /* Write rest of IXB */
-        close(file);
-        errormsg(WHERE,ERR_WRITE,str,length-l);
-		FREE((char *)ixbbuf);
-		return(0); }
-	FREE((char *)ixbbuf); }
-else {              /* IXB file is empty... No files */
-    if(write(file,fname,11)!=11) {  /* Write filename it IXB file */
-        close(file);
-        errormsg(WHERE,ERR_WRITE,str,11);
-		return(0); }
-    if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
-        close(file);
-        errormsg(WHERE,ERR_WRITE,str,3);
-		return(0); }
-    write(file,&f->dateuled,sizeof(time_t));
-    write(file,&f->datedled,4); }
-length=filelength(file);
-close(file);
-if(length%F_IXBSIZE)
-    errormsg(WHERE,ERR_LEN,str,length);
-return(1);
-}
-
-/****************************************************************************/
-/* Update the upload date for the file 'f'                                  */
-/****************************************************************************/
-void update_uldate(file_t f)
-{
-	char str[256],fname[13];
-	int i,file;
-	long l,length;
-
-/*******************/
-/* Update IXB File */
-/*******************/
-sprintf(str,"%s%s.IXB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_RDWR))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-    return; }
-length=filelength(file);
-if(length%F_IXBSIZE) {
-    close(file);
-	errormsg(WHERE,ERR_LEN,str,length);
-    return; }
-strcpy(fname,f.name);
-for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[i]=fname[i+1];
-for(l=0;l<length;l+=F_IXBSIZE) {
-    read(file,str,F_IXBSIZE);      /* Look for the filename in the IXB file */
-    str[11]=0;
-    if(!strcmp(fname,str)) break; }
-if(l>=length) {
-    close(file);
-	errormsg(WHERE,ERR_CHK,f.name,length);
-    return; }
-lseek(file,l+14,SEEK_SET);
-write(file,&f.dateuled,4);
-close(file);
-
-/*******************************************/
-/* Update last upload date/time stamp file */
-/*******************************************/
-sprintf(str,"%s%s.DAB",dir[f.dir]->data_dir,dir[f.dir]->code);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-else {
-	write(file,&f.dateuled,4);
-    close(file); }
-
-}
-
diff --git a/src/sbbs2/filelist/filelist.c b/src/sbbs2/filelist/filelist.c
deleted file mode 100644
index 01eba9d9126840b15cb4fb91245e7c988bc639d3..0000000000000000000000000000000000000000
--- a/src/sbbs2/filelist/filelist.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/* FILELIST.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Utility to create list of files from Synchronet file directories */
-/* Default list format is FILES.BBS, but file size, uploader, upload date */
-/* and other information can be included. */
-
-#include "sbbs.h"
-
-#define FILELIST_VER "2.12"
-
-#define MAX_NOTS 25
-
-#ifdef lputs
-#undef lputs
-#endif
-
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/****************************************************************************/
-/* Turns FILE    .EXT into FILE.EXT                                         */
-/* Called from upload                                                       */
-/****************************************************************************/
-char *unpadfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0,d=0;c<strlen(filename);c++)
-    if(filename[c]!=SP) str[d++]=filename[c];
-str[d]=0;
-return(str);
-}
-
-#ifndef __FLAT__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char huge *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-	uint i;
-
-i=_dos_findfirst(filespec,_A_NORMAL,&f);
-#ifdef __WATCOMC__
-_dos_findclose(&f);
-#endif
-if(!i)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the time/date of the file in 'filespec' in time_t (unix) format  */
-/****************************************************************************/
-long fdate(char *filespec)
-{
-	int 	file;
-	ushort	fd,ft;
-	struct	tm t;
-
-if((file=nopen(filespec,O_RDONLY))==-1)
-	return(0);
-_dos_getftime(file,&fd,&ft);
-close(file);
-memset(&t,0,sizeof(t));
-t.tm_year=((fd&0xfe00)>>9)+80;
-t.tm_mon=((fd&0x01e0)>>5)-1;
-t.tm_mday=fd&0x1f;
-t.tm_hour=(ft&0xf800)>>11;
-t.tm_min=(ft&0x07e0)>>5;
-t.tm_sec=(ft&0x001f)<<1;
-return(mktime(&t));
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	int c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-void stripctrlz(char *str)
-{
-	char tmp[1024];
-	int i,j,k;
-
-k=strlen(str);
-for(i=j=0;i<k;i++)
-	if(str[i]!=0x1a)
-		tmp[j++]=str[i];
-tmp[j]=0;
-strcpy(str,tmp);
-}
-
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-
-/****************************************************************************/
-/* Places into 'strout' CR or ETX terminated string starting at 			*/
-/* 'start' and ending at 'start'+'length' or terminator from 'strin'		*/
-/****************************************************************************/
-void getrec(char *strin,int start,int length,char *strout)
-{
-	int i=0,stop;
-
-stop=start+length;
-while(start<stop) {
-	if(strin[start]==ETX)
-		break;
-	strout[i++]=strin[start++]; }
-strout[i]=0;
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(access&O_WRONLY) access|=O_RDWR; 	/* fdopen can't open WRONLY */
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&(O_RDONLY|O_RDWR))
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&(O_WRONLY|O_RDWR))
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-void allocfail(uint size)
-{
-lprintf("\7Error allocating %u bytes of memory.\r\n",size);
-bail(1);
-}
-
-void bail(int code)
-{
-exit(code);
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct tm *t;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	t=gmtime(&unix);
-	sprintf(str,"%02u/%02u/%02u",t->tm_mon+1,t->tm_mday
-		,t->tm_year%100); }
-return(str);
-}
-
-#define ALL 	(1L<<0)
-#define PAD 	(1L<<1)
-#define HDR 	(1L<<2)
-#define CDT_	(1L<<3)
-#define EXT 	(1L<<4)
-#define ULN 	(1L<<5)
-#define ULD 	(1L<<6)
-#define DLS 	(1L<<7)
-#define DLD 	(1L<<8)
-#define NOD 	(1L<<9)
-#define PLUS	(1L<<10)
-#define MINUS	(1L<<11)
-#define JST 	(1L<<12)
-#define NOE 	(1L<<13)
-#define DFD 	(1L<<14)
-#define TOT 	(1L<<15)
-#define AUTO	(1L<<16)
-
-/*********************/
-/* Entry point (duh) */
-/*********************/
-int main(int argc, char **argv)
-{
-	char	*p,str[256],fname[256],ext,not[MAX_NOTS][9],nots=0;
-	uchar	HUGE16 *datbuf,HUGE16 *ixbbuf;
-	int 	i,j,file,dirnum,libnum,desc_off,lines
-			,omode=O_WRONLY|O_CREAT|O_TRUNC;
-	ulong	l,m,n,cdt,misc=0,total_cdt=0,total_files=0,datbuflen;
-	time_t	uld,dld;
-	read_cfg_text_t txt;
-	FILE	*in,*out=NULL;
-
-putenv("TZ=UCT0");
-_fmode=O_BINARY;
-setvbuf(stdout,NULL,_IONBF,0);
-
-fprintf(stderr,"\nFILELIST Version %s (%s) - Generate Synchronet File "
-	"Directory Lists\n"
-	,FILELIST_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-    ,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	);
-
-if(argc<2) {
-	printf("\n   usage: FILELIST <dir_code or * for ALL> [switches] [outfile]\n");
-	printf("\nswitches: /LIB name All directories of specified library\n");
-	printf("          /NOT code Exclude specific directory\n");
-	printf("          /CAT      Concatenate to existing outfile\n");
-	printf("          /PAD      Pad filename with spaces\n");
-	printf("          /HDR      Include directory headers\n");
-	printf("          /CDT      Include credit value\n");
-	printf("          /TOT      Include credit totals\n");
-	printf("          /ULN      Include uploader's name\n");
-	printf("          /ULD      Include upload date\n");
-	printf("          /DFD      Include DOS file date\n");
-	printf("          /DLD      Include download date\n");
-	printf("          /DLS      Include total downloads\n");
-	printf("          /NOD      Exclude normal descriptions\n");
-	printf("          /NOE      Exclude normal descriptions, if extended "
-		"exists\n");
-	printf("          /EXT      Include extended descriptions\n");
-	printf("          /JST      Justify extended descriptions under normal\n");
-	printf("          /+        Include extended description indicator (+)\n");
-	printf("          /-        Include offline file indicator (-)\n");
-	printf("          /*        Short-hand for /PAD /HDR /CDT /+ /-\n");
-	exit(0); }
-
-p=getenv("SBBSNODE");
-if(p==NULL) {
-	printf("\nSBBSNODE environment variable not set.\n");
-	printf("\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-	exit(1); }
-
-strcpy(node_dir,p);
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-txt.openerr="\7\nError opening %s for read.\n";
-txt.reading="\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\nError allocating %u bytes of memory\n";
-txt.error="\7\nERROR: Offset %lu in %s\r\n\n";
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str); }
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str); }
-read_file_cfg(txt);
-printf("\n");
-
-
-dirnum=libnum=-1;
-if(argv[1][0]=='*')
-	misc|=ALL;
-else if(argv[1][0]!='/') {
-	strupr(argv[1]);
-	for(i=0;i<total_dirs;i++)
-		if(!stricmp(argv[1],dir[i]->code))
-			break;
-	if(i>=total_dirs) {
-		printf("\nDirectory code '%s' not found.\n",argv[1]);
-		exit(1); }
-	dirnum=i; }
-for(i=1;i<argc;i++) {
-	if(!stricmp(argv[i],"/LIB")) {
-		if(dirnum!=-1) {
-			printf("\nBoth directory code and /LIB parameters were used.\n");
-			exit(1); }
-		i++;
-		if(i>=argc) {
-			printf("\nLibrary short name must follow /LIB parameter.\n");
-			exit(1); }
-		strupr(argv[i]);
-		for(j=0;j<total_libs;j++)
-			if(!stricmp(lib[j]->sname,argv[i]))
-				break;
-		if(j>=total_libs) {
-			printf("\nLibrary short name '%s' not found.\n",argv[i]);
-			exit(1); }
-		libnum=j; }
-	else if(!stricmp(argv[i],"/NOT")) {
-		if(nots>=MAX_NOTS) {
-			printf("\nMaximum number of /NOT options (%u) exceeded.\n"
-				,MAX_NOTS);
-			exit(1); }
-		i++;
-		if(i>=argc) {
-			printf("\nDirectory internal code must follow /NOT parameter.\n");
-            exit(1); }
-		sprintf(not[nots++],"%.8s",argv[i]); }
-	else if(!stricmp(argv[i],"/ALL")) {
-		if(dirnum!=-1) {
-			printf("\nBoth directory code and /ALL parameters were used.\n");
-            exit(1); }
-		if(libnum!=-1) {
-			printf("\nBoth library name and /ALL parameters were used.\n");
-			exit(1); }
-		misc|=ALL; }
-	else if(!stricmp(argv[i],"/PAD"))
-		misc|=PAD;
-	else if(!stricmp(argv[i],"/CAT"))
-		omode=O_WRONLY|O_CREAT|O_APPEND;
-	else if(!stricmp(argv[i],"/HDR"))
-		misc|=HDR;
-	else if(!stricmp(argv[i],"/CDT"))
-		misc|=CDT_;
-	else if(!stricmp(argv[i],"/TOT"))
-		misc|=TOT;
-	else if(!stricmp(argv[i],"/EXT"))
-		misc|=EXT;
-	else if(!stricmp(argv[i],"/ULN"))
-		misc|=ULN;
-	else if(!stricmp(argv[i],"/ULD"))
-		misc|=ULD;
-	else if(!stricmp(argv[i],"/DLD"))
-		misc|=DLD;
-	else if(!stricmp(argv[i],"/DFD"))
-		misc|=DFD;
-	else if(!stricmp(argv[i],"/DLS"))
-		misc|=DLS;
-	else if(!stricmp(argv[i],"/NOD"))
-		misc|=NOD;
-	else if(!stricmp(argv[i],"/JST"))
-		misc|=(EXT|JST);
-	else if(!stricmp(argv[i],"/NOE"))
-		misc|=(EXT|NOE);
-	else if(!stricmp(argv[i],"/+"))
-		misc|=PLUS;
-	else if(!stricmp(argv[i],"/-"))
-		misc|=MINUS;
-	else if(!stricmp(argv[i],"/*"))
-		misc|=(HDR|PAD|CDT_|PLUS|MINUS);
-
-	else if(i!=1) {
-		if(argv[i][0]=='*') {
-			misc|=AUTO;
-			continue; }
-		if((j=nopen(argv[i],omode))==-1) {
-			printf("\nError opening/creating %s for output.\n",argv[i]);
-			exit(1); }
-		out=fdopen(j,"wb"); } }
-
-if(!out && !(misc&AUTO)) {
-	printf("\nOutput file not specified, using FILES.BBS in each "
-		"directory.\n");
-	misc|=AUTO; }
-
-for(i=0;i<total_dirs;i++) {
-	if(!(misc&ALL) && i!=dirnum && dir[i]->lib!=libnum)
-		continue;
-	for(j=0;j<nots;j++)
-		if(!stricmp(not[j],dir[i]->code))
-			break;
-	if(j<nots)
-		continue;
-	if(misc&AUTO && dir[i]->seqdev) 	/* CD-ROM */
-		continue;
-	printf("\n%-*s %s",LEN_GSNAME,lib[dir[i]->lib]->sname,dir[i]->lname);
-	sprintf(str,"%s%s.IXB",dir[i]->data_dir,dir[i]->code);
-	if((file=nopen(str,O_RDONLY))==-1)
-		continue;
-	l=filelength(file);
-	if(misc&AUTO) {
-		sprintf(str,"%sFILES.BBS",dir[i]->path);
-		if((j=nopen(str,omode))==-1) {
-			printf("\nError opening/creating %s for output.\n",str);
-			exit(1); }
-		out=fdopen(j,"wb"); }
-	if(misc&HDR) {
-		sprintf(fname,"%-*s      %-*s       Files: %4u"
-			,LEN_GSNAME,lib[dir[i]->lib]->sname
-			,LEN_SLNAME,dir[i]->lname,l/F_IXBSIZE);
-		fprintf(out,"%s\r\n",fname);
-		strset(fname,'-');
-		fprintf(out,"%s\r\n",fname); }
-	if(!l) {
-		close(file);
-		if(misc&AUTO) fclose(out);
-		continue; }
-	if((ixbbuf=(char *)MALLOC(l))==NULL) {
-		close(file);
-		if(misc&AUTO) fclose(out);
-		printf("\7ERR_ALLOC %s %lu\n",str,l);
-		continue; }
-	if(read(file,ixbbuf,l)!=l) {
-		close(file);
-		if(misc&AUTO) fclose(out);
-		printf("\7ERR_READ %s %lu\n",str,l);
-		FREE((char *)ixbbuf);
-		continue; }
-	close(file);
-	sprintf(str,"%s%s.DAT",dir[i]->data_dir,dir[i]->code);
-	if((file=nopen(str,O_RDONLY))==-1) {
-		printf("\7ERR_OPEN %s %lu\n",str,O_RDONLY);
-		FREE((char *)ixbbuf);
-		if(misc&AUTO) fclose(out);
-		continue; }
-	datbuflen=filelength(file);
-	if((datbuf=MALLOC(datbuflen))==NULL) {
-		close(file);
-		printf("\7ERR_ALLOC %s %lu\n",str,datbuflen);
-		FREE((char *)ixbbuf);
-		if(misc&AUTO) fclose(out);
-		continue; }
-	if(lread(file,datbuf,datbuflen)!=datbuflen) {
-		close(file);
-		printf("\7ERR_READ %s %lu\n",str,datbuflen);
-		FREE((char *)datbuf);
-		FREE((char *)ixbbuf);
-		if(misc&AUTO) fclose(out);
-		continue; }
-	close(file);
-	m=0L;
-	while(m<l && !ferror(out)) {
-		for(j=0;j<12 && m<l;j++)
-			if(j==8)
-				str[j]='.';
-			else
-				str[j]=ixbbuf[m++]; /* Turns FILENAMEEXT into FILENAME.EXT */
-		str[j]=0;
-		unpadfname(str,fname);
-		fprintf(out,"%-12.12s",misc&PAD ? str : fname);
-		total_files++;
-		n=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
-		uld=(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)|((long)ixbbuf[m+5]<<16)
-			|((long)ixbbuf[m+6]<<24));
-		dld=(ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)|((long)ixbbuf[m+9]<<16)
-			|((long)ixbbuf[m+10]<<24));
-		m+=11;
-
-		if(n>=datbuflen 							/* index out of bounds */
-			|| datbuf[n+F_DESC+LEN_FDESC]!=CR) {	/* corrupted data */
-			fprintf(stderr,"\n\7%s%s is corrupted!\n"
-				,dir[i]->data_dir,dir[i]->code);
-			exit(-1); }
-
-
-		if(misc&PLUS && datbuf[n+F_MISC]!=ETX
-			&& (datbuf[n+F_MISC]-SP)&FM_EXTDESC)
-			fputc('+',out);
-		else
-			fputc(SP,out);
-
-		desc_off=12;
-		if(misc&(CDT_|TOT)) {
-			getrec((char *)&datbuf[n],F_CDT,LEN_FCDT,str);
-			cdt=atol(str);
-			total_cdt+=cdt;
-			if(misc&CDT_) {
-				fprintf(out,"%7lu",cdt);
-				desc_off+=7; } }
-
-		if(misc&MINUS) {
-			sprintf(str,"%s%s",dir[i]->path,fname);
-			if(!fexist(str))
-				fputc('-',out);
-			else
-				fputc(SP,out); }
-		else
-			fputc(SP,out);
-		desc_off++;
-
-		if(misc&DFD) {
-			sprintf(str,"%s%s",dir[i]->path,fname);
-			fprintf(out,"%s ",unixtodstr(fdate(str),str));
-			desc_off+=9; }
-
-		if(misc&ULD) {
-			fprintf(out,"%s ",unixtodstr(uld,str));
-            desc_off+=9; }
-
-		if(misc&ULN) {
-			getrec((char *)&datbuf[n],F_ULER,25,str);
-			fprintf(out,"%-25s ",str);
-			desc_off+=26; }
-
-		if(misc&DLD) {
-			fprintf(out,"%s ",unixtodstr(dld,str));
-			desc_off+=9; }
-
-		if(misc&DLS) {
-			getrec((char *)&datbuf[n],F_TIMESDLED,5,str);
-			j=atoi(str);
-			fprintf(out,"%5u ",j);
-			desc_off+=6; }
-
-		if(datbuf[n+F_MISC]!=ETX && (datbuf[n+F_MISC]-SP)&FM_EXTDESC)
-			ext=1;	/* extended description exists */
-		else
-			ext=0;	/* it doesn't */
-
-		if(!(misc&NOD) && !(misc&NOE && ext)) {
-			getrec((char *)&datbuf[n],F_DESC,LEN_FDESC,str);
-			fprintf(out,"%s",str); }
-
-		if(misc&EXT && ext) {							/* Print ext desc */
-
-			sprintf(str,"%s%s.EXB",dir[i]->data_dir,dir[i]->code);
-			if(!fexist(str))
-				continue;
-			if((j=nopen(str,O_RDONLY))==-1) {
-				printf("\7ERR_OPEN %s %lu\n",str,O_RDONLY);
-				continue; }
-			if((in=fdopen(j,"rb"))==NULL) {
-				close(j);
-				continue; }
-			fseek(in,(n/F_LEN)*512L,SEEK_SET);
-			lines=0;
-			if(!(misc&NOE)) {
-				fprintf(out,"\r\n");
-				lines++; }
-			while(!feof(in) && !ferror(in)
-				&& ftell(in)<((n/F_LEN)+1)*512L) {
-				if(!fgets(str,128,in) || !str[0])
-					break;
-				stripctrlz(str);
-				if(lines) {
-					if(misc&JST)
-						fprintf(out,"%*s",desc_off,"");
-					fputc(SP,out);				/* indent one character */ }
-				fprintf(out,"%s",str);
-				lines++; }
-			fclose(in); }
-		fprintf(out,"\r\n"); }
-	FREE((char *)datbuf);
-	FREE((char *)ixbbuf);
-	fprintf(out,"\r\n"); /* blank line at end of dir */
-	if(misc&AUTO) fclose(out); }
-
-if(misc&TOT && !(misc&AUTO))
-	fprintf(out,"TOTALS\n------\n%lu credits/bytes in %lu files.\r\n"
-		,total_cdt,total_files);
-printf("\nDone.\n");
-return(0);
-}
diff --git a/src/sbbs2/filelist/makeall.bat b/src/sbbs2/filelist/makeall.bat
deleted file mode 100755
index d68900c3d3397527fe45f8723f77457287880eda..0000000000000000000000000000000000000000
--- a/src/sbbs2/filelist/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOSX %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/filelist/makefile b/src/sbbs2/filelist/makefile
deleted file mode 100644
index 3621cb7c947dee31cbe46a367e18ce4bd0f7a139..0000000000000000000000000000000000000000
--- a/src/sbbs2/filelist/makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-############################################
-# Makefile for Synchronet FILELIST Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..;..\smb;..\rio
-
-
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml
-!else
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-!ifeq OS NT
-SYSTEM	= NT
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\filelist.exe
-OBJS	= $(OS)\filelist.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\ars.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_MSGS_CFG &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
diff --git a/src/sbbs2/filelist/makefile.bc b/src/sbbs2/filelist/makefile.bc
deleted file mode 100644
index accee0fd8e9879c9126cfa1e37ec5c29275f6cae..0000000000000000000000000000000000000000
--- a/src/sbbs2/filelist/makefile.bc
+++ /dev/null
@@ -1,76 +0,0 @@
-############################################
-# Makefile for Synchronet FILELIST Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC      = bcc
-LD      = tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE)
-LFLAGS  = -c
-!else
-OS	= DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL   = l
-CFLAGS  = -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS  = -n -c
-!endif
-MAIN    = $(OS)\filelist.exe
-OBJS    = $(OS)\filelist.obj $(OS)\scfgvars.obj $(OS)\ars.obj \
-	  $(OS)\scfglib1.obj $(OS)\scfglib2.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-        @echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $< 
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL).obj $(OBJS)   
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Global Variables
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c \
-	..\scfglib.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_XTRN_CFG 
--DNO_TEXT_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib2.c ..\scfgvars.c \
-	..\scfglib.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_MSGS_CFG
--DNO_XTRN_CFG 
--DNO_TEXT_CFG
--DNO_CHAT_CFG
-! ..\$&.c
diff --git a/src/sbbs2/gen_defs.h b/src/sbbs2/gen_defs.h
deleted file mode 100644
index 48f343082f7b5a99b9d58bcc496605be90d1073f..0000000000000000000000000000000000000000
--- a/src/sbbs2/gen_defs.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* GEN_DEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _GEN_DEFS_H
-#define _GEN_DEFS_H
-
-/************************************************************************/
-/* General (application independant) type definitions and macros		*/
-/* tabstop: 4 (as usual)												*/
-/************************************************************************/
-
-									/* Control characters */
-#define STX 	0x02				/* Start of text			^B	*/
-#define ETX 	0x03				/* End of text				^C	*/
-#define BS		0x08				/* Back space				^H	*/
-#define TAB 	0x09				/* Horizontal tabulation	^I	*/
-#define LF		0x0a				/* Line feed				^J	*/
-#define FF		0x0c				/* Form feed				^L	*/
-#define CR		0x0d				/* Carriage return			^M	*/
-#define ESC 	0x1b				/* Escape					^[	*/
-#define SP		0x20				/* Space						*/
-
-									/* Unsigned type short-hands	*/
-#define uchar	unsigned char
-#define ushort  unsigned short
-#define uint    unsigned int
-#define ulong   unsigned long
-
-/****************************************************************************/
-/* MALLOC/FREE Macros for various compilers and environments				*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/* FAR16 is used to create a far (32-bit) pointer in 16-bit compilers		*/
-/* HUGE16 is used to create a huge (32-bit) pointer in 16-bit compilers 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-	#define HUGE16 huge
-	#define FAR16 far
-	#if defined(__TURBOC__)
-		#define REALLOC(x,y) farrealloc(x,y)
-		#define LMALLOC(x) farmalloc(x)
-		#define MALLOC(x) farmalloc(x)
-		#define LFREE(x) farfree(x)
-		#define FREE(x) farfree(x)
-	#elif defined(__WATCOMC__)
-		#define REALLOC realloc
-		#define LMALLOC(x) halloc(x,1)	/* far heap, but slow */
-		#define MALLOC malloc			/* far heap, but 64k max */
-		#define LFREE hfree
-		#define FREE free
-	#else	/* Other 16-bit Compiler */
-		#define REALLOC realloc
-		#define LMALLOC malloc
-		#define MALLOC malloc
-		#define LFREE free
-		#define FREE free
-	#endif
-#else		/* 32-bit Compiler or Small Memory Model */
-	#define HUGE16
-	#define FAR16
-	#define REALLOC realloc
-	#define LMALLOC malloc
-	#define MALLOC malloc
-	#define LFREE free
-	#define FREE free
-#endif
-
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/genetext.c b/src/sbbs2/genetext.c
deleted file mode 100644
index 4f2b8e928ea968f90a354bd37bac65322887e3b5..0000000000000000000000000000000000000000
--- a/src/sbbs2/genetext.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* GENETEXT.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Creates the file ETEXT.C which has the encrypted text strings for use in */
-/* Synchronet */
-
-#include <stdio.h>
-
-void cvtusc(char *str)
-{
-    int i;
-
-for(i=0;str[i];i++)
-	if(str[i]=='_')
-		str[i]=' ';
-}
-
-void main()
-{
-	unsigned char str[129],bits,len;
-	unsigned int i,j;
-    unsigned long l,m;
-	FILE *in,*cout,*hout;
-
-if((in=fopen("ETEXT.DAT","rb"))==NULL) {
-	printf("can't open ETEXT.DAT\n");
-	return; }
-
-if((cout=fopen("ETEXT.C","wb"))==NULL) {
-	printf("can't create ETEXT.C\n");
-	return; }
-
-if((hout=fopen("ETEXT.H","wb"))==NULL) {
-	printf("can't create ETEXT.H\n");
-    return; }
-
-fprintf(cout,"/* ETEXT.C */\r\n\r\n#include \"etext.h\"\r\n\r\n");
-fprintf(hout,"/* ETEXT.H */\r\n\r\n");
-while(!feof(in)) {
-	if(!fgets(str,127,in))
-		break;
-	str[strlen(str)-3]=0;	/* chop off :crlf */
-	if(!str[0])
-		break;
-	fprintf(hout,"extern unsigned long %s[];\r\n",str);
-	fprintf(cout,"unsigned long %s[]={ ",str);
-	if(!fgets(str,127,in))
-		break;
-	str[strlen(str)-2]=0;	/* chop off crlf */
-	if(!str[0])
-        break;
-	cvtusc(str);
-	len=strlen(str);
-	l=len^0x49;
-	bits=7;
-	for(i=0,j=1;i<len;i++) {
-		m=(unsigned long)(str[i]^(i^0x2c));
-		l|=(m<<bits);
-		bits+=7;
-		if(bits>=32) {
-			fprintf(cout,"%luUL,",l);
-			j++;
-			l=0UL;
-			bits-=32;
-			if(bits)
-				l=(unsigned long)(str[i]^(i^0x2c))>>(7-bits); } }
-	fprintf(cout,"%luUL };\r\n",l); }
-}
diff --git a/src/sbbs2/genetext.exe b/src/sbbs2/genetext.exe
deleted file mode 100755
index c32166f2a87e36f619d76773a88708fe7ab01ebc..0000000000000000000000000000000000000000
Binary files a/src/sbbs2/genetext.exe and /dev/null differ
diff --git a/src/sbbs2/getnode.c b/src/sbbs2/getnode.c
deleted file mode 100644
index fdfb3be4dc5a35a198f15cabd4b0146859adf6be..0000000000000000000000000000000000000000
--- a/src/sbbs2/getnode.c
+++ /dev/null
@@ -1,248 +0,0 @@
-#line 1 "GETNODE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(uint number, node_t *node, char lockit)
-{
-	char str[256];
-	int count=0;
-
-if(!(sys_status&SS_NODEDAB))
-	return;
-if(!number || number>sys_nodes) {
-	errormsg(WHERE,ERR_CHK,"node number",number);
-	return; }
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	if(count>10)
-		mswait(55);
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count>(LOOP_NODEDAB/2) && count!=LOOP_NODEDAB) {
-	sprintf(str,"NODE.DAB COLLISION - Count: %d",count);
-	logline("!!",str); }
-if(count==LOOP_NODEDAB) {
-	errormsg(WHERE,ERR_READ,"NODE.DAB",number+1);
-	return; }
-}
-
-/****************************************************************************/
-/* Synchronizes all the nodes knowledge of the other nodes' actions, mode,  */
-/* status and other flags.                                                  */
-/* Assumes that getnodedat(node_num,&thisnode,0) was called right before it */
-/* is called.  																*/
-/****************************************************************************/
-void nodesync()
-{
-	static user_t user;
-	static int inside;
-	char str[256],today[32];
-	int i,j,atr=curatr; /* was lclatr(-1) 01/29/96 */
-	node_t node;
-
-if(inside) return;
-inside=1;
-
-if(thisnode.action!=action) {
-	getnodedat(node_num,&thisnode,1);
-	thisnode.action=action;
-	putnodedat(node_num,thisnode); }
-
-criterrs=thisnode.errors;
-
-if(sys_status&SS_USERON) {
-	if(!(sys_status&SS_NEWDAY)) {
-		now=time(NULL);
-		unixtodstr(logontime,str);
-		unixtodstr(now,today);
-		if(strcmp(str,today)) { /* New day, clear "today" user vars */
-			sys_status|=SS_NEWDAY;	// So we don't keep doing this over&over
-			putuserrec(useron.number,U_ETODAY,5,"0");
-			putuserrec(useron.number,U_PTODAY,5,"0");
-			putuserrec(useron.number,U_TTODAY,5,"0");
-			putuserrec(useron.number,U_LTODAY,5,"0");
-			putuserrec(useron.number,U_TEXTRA,5,"0");
-			putuserrec(useron.number,U_FREECDT,10
-				,ultoa(level_freecdtperday[useron.level],str,10));
-			getuserdat(&useron); } }
-	if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) {   /* not guest */
-		getuserdat(&useron);
-		getnodedat(node_num,&thisnode,1);
-		thisnode.misc&=~NODE_UDAT;
-		putnodedat(node_num,thisnode); }
-	if(thisnode.misc&NODE_MSGW)
-		getsmsg(useron.number); 	/* getsmsg clears MSGW flag */
-	if(thisnode.misc&NODE_NMSG)
-		getnmsg(); }				/* getnmsg clears NMSG flag */
-
-if(sync_mod[0])
-	exec_bin(sync_mod,&main_csi);
-
-if(thisnode.misc&NODE_INTR) {
-    bputs(text[NodeLocked]);
-	logline(nulstr,"Interrupted");
-    hangup();
-	inside=0;
-    return; }
-
-if(sys_status&SS_USERON && memcmp(&user,&useron,sizeof(user_t))) {
-//	  lputc(7);
-    getusrdirs();
-    getusrsubs();
-    user=useron; }
-
-if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn)
-	&& !SYSOP) {
-	timeleft_warn=5-(timeleft/60);
-	attr(LIGHTGRAY);
-	bprintf(text[OnlyXminutesLeft]
-		,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr); }
-
-attr(atr);	/* replace original attributes */
-inside=0;
-}
-
-/****************************************************************************/
-/* Prints short messages waiting for this node, if any...                   */
-/****************************************************************************/
-void getnmsg()
-{
-	char str[256], HUGE16 *buf;
-	int file;
-	long length;
-
-getnodedat(node_num,&thisnode,1);
-thisnode.misc&=~NODE_NMSG;          /* clear the NMSG flag */
-putnodedat(node_num,thisnode);
-
-#if 0
-/* Only for v1b rev 2-5 and XSDK v2.1x compatibility */
-sprintf(str,"%sMSGS\\N%3.3u.IXB",data_dir,node_num);
-if((ixb=nopen(str,O_RDONLY))!=-1) {
-    read(ixb,&offset,4);
-    chsize(ixb,0L);
-    close(ixb);
-    remove(str); }
-#endif
-
-sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,node_num);
-if(flength(str)<1L)
-	return;
-if((file=nopen(str,O_RDWR))==-1) {
-	/**
-		errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-	**/
-    return; }
-length=filelength(file);
-if(!length) {
-	close(file);
-	return; }
-if((buf=LMALLOC(length+1))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length+1);
-    return; }
-if(lread(file,buf,length)!=length) {
-    close(file);
-    FREE(buf);
-    errormsg(WHERE,ERR_READ,str,length);
-    return; }
-chsize(file,0L);
-close(file);
-buf[length]=0;
-
-if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
-    || sys_status&SS_IN_CTRLP) {
-    CRLF; }
-putmsg(buf,P_NOATCODES);
-LFREE(buf);
-}
-
-/****************************************************************************/
-/* 'ext' must be at least 128 bytes!                                        */
-/****************************************************************************/
-void getnodeext(uint number, char *ext)
-{
-    char str[256];
-    int count=0;
-
-if(!(sys_status&SS_NODEDAB))
-    return;
-if(!number || number>sys_nodes) {
-    errormsg(WHERE,ERR_CHK,"node number",number);
-    return; }
-number--;   /* make zero based */
-while(count<LOOP_NODEDAB) {
-    if(count>10)
-        mswait(55);
-    if(lock(node_ext,(long)number*128L,128)==-1) {
-        count++;
-        continue; }
-    lseek(node_ext,(long)number*128L,SEEK_SET);
-    if(read(node_ext,ext,128)==128)
-        break;
-    count++; }
-unlock(node_ext,(long)number*128L,128);
-if(count>(LOOP_NODEDAB/2) && count!=LOOP_NODEDAB) {
-    sprintf(str,"NODE.EXB COLLISION - Count: %d",count);
-    logline("!!",str); }
-if(count==LOOP_NODEDAB) {
-    errormsg(WHERE,ERR_READ,"NODE.EXB",number+1);
-    return; }
-}
-
-
-/****************************************************************************/
-/* Prints short messages waiting for 'usernumber', if any...                */
-/* then deletes them.                                                       */
-/****************************************************************************/
-void getsmsg(int usernumber)
-{
-	char str[256], HUGE16 *buf;
-    int file;
-    long length;
-
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if(flength(str)<1L)
-    return;
-if((file=nopen(str,O_RDWR))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-    return; }
-length=filelength(file);
-if((buf=LMALLOC(length+1))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length+1);
-    return; }
-if(lread(file,buf,length)!=length) {
-    close(file);
-    FREE(buf);
-    errormsg(WHERE,ERR_READ,str,length);
-    return; }
-chsize(file,0L);
-close(file);
-buf[length]=0;
-getnodedat(node_num,&thisnode,0);
-if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
-    || sys_status&SS_IN_CTRLP) {
-    CRLF; }
-if(thisnode.misc&NODE_MSGW) {
-    getnodedat(node_num,&thisnode,1);
-    thisnode.misc&=~NODE_MSGW;
-    putnodedat(node_num,thisnode); }
-putmsg(buf,P_NOATCODES);
-LFREE(buf);
-}
-
diff --git a/src/sbbs2/getuser.c b/src/sbbs2/getuser.c
deleted file mode 100644
index 313dbce0b025213694dedf3254dc7ba49b2ef5c5..0000000000000000000000000000000000000000
--- a/src/sbbs2/getuser.c
+++ /dev/null
@@ -1,429 +0,0 @@
-#line 1 "GETUSER.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-/****************************************************************************/
-/* Fills the structure 'user' with info for user.number	from USER.DAT		*/
-/* Called from functions useredit, waitforcall and main_sec					*/
-/****************************************************************************/
-void getuserdat(user_t *user)
-{
-	uchar userdat[U_LEN+1],str[U_LEN+1];
-	int i,file;
-
-if(!user->number || user->number>lastuser()) {
-	memset(user,0L,sizeof(user_t));
-	user->number=0;
-	return; }
-sprintf(userdat,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(userdat,O_RDONLY|O_DENYNONE))==-1) {
-	close(file);
-	memset(user,0L,sizeof(user_t));
-	user->number=0;
-	return; }
-lseek(file,(long)((long)(user->number-1)*U_LEN),SEEK_SET);
-i=0;
-while(i<LOOP_NODEDAB
-	&& lock(file,(long)((long)(user->number-1)*U_LEN),U_LEN)==-1) {
-	if(i>10)
-		mswait(55);
-	i++; }
-
-if(i>=LOOP_NODEDAB) {
-	close(file);
-	errormsg(WHERE,ERR_LOCK,"USER.DAT",user->number);
-	memset(user,0L,sizeof(user_t));
-	user->number=0;
-    return; }
-
-if(read(file,userdat,U_LEN)!=U_LEN) {
-	unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
-	close(file);
-	errormsg(WHERE,ERR_READ,"USER.DAT",U_LEN);
-	memset(user,0L,sizeof(user_t));
-	user->number=0;
-	return; }
-
-unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
-close(file);
-getrec(userdat,U_ALIAS,LEN_ALIAS,user->alias);
-/* order of these function	*/
-getrec(userdat,U_NAME,LEN_NAME,user->name);
-/* calls is irrelevant */
-getrec(userdat,U_HANDLE,LEN_HANDLE,user->handle);
-getrec(userdat,U_NOTE,LEN_NOTE,user->note);
-getrec(userdat,U_COMP,LEN_COMP,user->comp);
-getrec(userdat,U_COMMENT,LEN_COMMENT,user->comment);
-getrec(userdat,U_NETMAIL,LEN_NETMAIL,user->netmail);
-getrec(userdat,U_ADDRESS,LEN_ADDRESS,user->address);
-getrec(userdat,U_LOCATION,LEN_LOCATION,user->location);
-getrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user->zipcode);
-getrec(userdat,U_PASS,LEN_PASS,user->pass);
-getrec(userdat,U_PHONE,LEN_PHONE,user->phone);
-getrec(userdat,U_BIRTH,LEN_BIRTH,user->birth);
-getrec(userdat,U_MODEM,LEN_MODEM,user->modem);
-getrec(userdat,U_LASTON,8,str); user->laston=ahtoul(str);
-getrec(userdat,U_FIRSTON,8,str); user->firston=ahtoul(str);
-getrec(userdat,U_EXPIRE,8,str); user->expire=ahtoul(str);
-getrec(userdat,U_PWMOD,8,str); user->pwmod=ahtoul(str);
-getrec(userdat,U_NS_TIME,8,str);
-user->ns_time=ahtoul(str);
-if(user->ns_time<0x20000000L)
-	user->ns_time=user->laston;  /* Fix for v2.00->v2.10 */
-
-getrec(userdat,U_LOGONS,5,str); user->logons=atoi(str);
-getrec(userdat,U_LTODAY,5,str); user->ltoday=atoi(str);
-getrec(userdat,U_TIMEON,5,str); user->timeon=atoi(str);
-getrec(userdat,U_TEXTRA,5,str); user->textra=atoi(str);
-getrec(userdat,U_TTODAY,5,str); user->ttoday=atoi(str);
-getrec(userdat,U_TLAST,5,str); user->tlast=atoi(str);
-getrec(userdat,U_POSTS,5,str); user->posts=atoi(str);
-getrec(userdat,U_EMAILS,5,str); user->emails=atoi(str);
-getrec(userdat,U_FBACKS,5,str); user->fbacks=atoi(str);
-getrec(userdat,U_ETODAY,5,str); user->etoday=atoi(str);
-getrec(userdat,U_PTODAY,5,str); user->ptoday=atoi(str);
-getrec(userdat,U_ULB,10,str); user->ulb=atol(str);
-getrec(userdat,U_ULS,5,str); user->uls=atoi(str);
-getrec(userdat,U_DLB,10,str); user->dlb=atol(str);
-getrec(userdat,U_DLS,5,str); user->dls=atoi(str);
-getrec(userdat,U_CDT,10,str); user->cdt=atol(str);
-getrec(userdat,U_MIN,10,str); user->min=atol(str);
-getrec(userdat,U_LEVEL,2,str); user->level=atoi(str);
-getrec(userdat,U_FLAGS1,8,str); user->flags1=ahtoul(str); /***
-getrec(userdat,U_TL,2,str); user->tl=atoi(str); ***/
-getrec(userdat,U_FLAGS2,8,str); user->flags2=ahtoul(str);
-getrec(userdat,U_FLAGS3,8,str); user->flags3=ahtoul(str);
-getrec(userdat,U_FLAGS4,8,str); user->flags4=ahtoul(str);
-getrec(userdat,U_EXEMPT,8,str); user->exempt=ahtoul(str);
-getrec(userdat,U_REST,8,str); user->rest=ahtoul(str);
-getrec(userdat,U_ROWS,2,str); user->rows=atoi(str);
-if(user->rows && user->rows<10)
-	user->rows=10;
-user->sex=userdat[U_SEX];
-if(!user->sex)
-	user->sex=SP;	 /* fix for v1b04 that could save as 0 */
-user->prot=userdat[U_PROT];
-if(user->prot<SP)
-	user->prot=SP;
-getrec(userdat,U_MISC,8,str); user->misc=ahtoul(str);
-if(user->rest&FLAG('Q'))
-	user->misc&=~SPIN;
-
-getrec(userdat,U_LEECH,2,str);
-user->leech=(uchar)ahtoul(str);
-getrec(userdat,U_CURSUB,8,useron.cursub);
-getrec(userdat,U_CURDIR,8,useron.curdir);
-
-getrec(userdat,U_FREECDT,10,str);
-user->freecdt=atol(str);
-
-getrec(userdat,U_XEDIT,8,str);
-for(i=0;i<total_xedits;i++)
-	if(!stricmp(str,xedit[i]->code) && chk_ar(xedit[i]->ar,*user))
-		break;
-user->xedit=i+1;
-if(user->xedit>total_xedits)
-    user->xedit=0;
-
-getrec(userdat,U_SHELL,8,str);
-for(i=0;i<total_shells;i++)
-	if(!stricmp(str,shell[i]->code))
-		break;
-if(i==total_shells)
-	i=0;
-user->shell=i;
-
-getrec(userdat,U_QWK,8,str);
-if(str[0]<SP) { 			   /* v1c, so set defaults */
-	if(user->rest&FLAG('Q'))
-		user->qwk=(QWK_RETCTLA);
-	else
-		user->qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL); }
-else
-	user->qwk=ahtoul(str);
-
-getrec(userdat,U_TMPEXT,3,user->tmpext);
-if((!user->tmpext[0] || !strcmp(user->tmpext,"0")) && total_fcomps)
-	strcpy(user->tmpext,fcomp[0]->ext);  /* For v1x to v2x conversion */
-
-getrec(userdat,U_CHAT,8,str);
-user->chat=ahtoul(str);
-
-if(useron.number==user->number) {
-	useron=*user;
-
-	if(online) {
-
-#if 0
-		getusrdirs();
-		getusrsubs();
-#endif
-		if(useron.misc&AUTOTERM) {
-			useron.misc&=~(ANSI|RIP|WIP);
-			useron.misc|=autoterm; }
-		statusline(); } }
-}
-
-
-/****************************************************************************/
-/* Returns the username in 'str' that corresponds to the 'usernumber'       */
-/* Called from functions everywhere                                         */
-/****************************************************************************/
-char *username(int usernumber,char *strin)
-{
-    char str[256];
-    char c;
-    int file;
-
-if(usernumber<1) {
-    strin[0]=0;
-    return(strin); }
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if(flength(str)<1L) {
-    strin[0]=0;
-    return(strin); }
-if((file=nopen(str,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    strin[0]=0;
-    return(strin); }
-if(filelength(file)<(long)((long)usernumber*(LEN_ALIAS+2))) {
-    close(file);
-    strin[0]=0;
-    return(strin); }
-lseek(file,(long)((long)(usernumber-1)*(LEN_ALIAS+2)),SEEK_SET);
-read(file,strin,LEN_ALIAS);
-close(file);
-for(c=0;c<LEN_ALIAS;c++)
-    if(strin[c]==ETX) break;
-strin[c]=0;
-if(!c)
-    strcpy(strin,"DELETED USER");
-return(strin);
-}
-
-/****************************************************************************/
-/* Fills the timeleft variable with the correct value. Hangs up on the      */
-/* user if their time is up.                                                */
-/* Called from functions main_sec and xfer_sec                              */
-/****************************************************************************/
-void gettimeleft(void)
-{
-    static  inside;
-    char    str[128];
-    int     i;
-    time_t  eventtime=0,thisevent;
-    long    tleft;
-    struct  date lastdate;
-    struct  tm *gm;
-
-now=time(NULL);
-
-gm=localtime(&now);
-if(useron.exempt&FLAG('T')) {   /* Time online exemption */
-    timeleft=level_timepercall[useron.level]*60;
-    if(timeleft<10)             /* never get below 10 for exempt users */
-        timeleft=10; }
-else {
-    tleft=(((long)level_timeperday[useron.level]-useron.ttoday)
-        +useron.textra)*60L;
-    if(tleft<0) tleft=0;
-    if(tleft>level_timepercall[useron.level]*60)
-        tleft=level_timepercall[useron.level]*60;
-    tleft+=useron.min*60L;
-    tleft-=now-starttime;
-    if(tleft>0x7fffL)
-        timeleft=0x7fff;
-    else
-        timeleft=tleft; }
-
-/* Timed event time reduction handler */
-
-for(i=0;i<total_events;i++) {
-    if(!event[i]->node || event[i]->node>sys_nodes)
-        continue;
-    if(!(event[i]->misc&EVENT_FORCE)
-        || (!(event[i]->misc&EVENT_EXCL) && event[i]->node!=node_num)
-        || !(event[i]->days&(1<<gm->tm_wday)))
-        continue;
-    unixtodos(event[i]->last,&lastdate,&curtime);
-    unixtodos(now,&date,&curtime);
-    curtime.ti_hour=event[i]->time/60;   /* hasn't run yet today */
-    curtime.ti_min=event[i]->time-(curtime.ti_hour*60);
-    curtime.ti_sec=0;
-    thisevent=dostounix(&date,&curtime);
-    if(date.da_day==lastdate.da_day && date.da_mon==lastdate.da_mon)
-        thisevent+=24L*60L*60L;     /* already ran today, so add 24hrs */
-    if(!eventtime || thisevent<eventtime)
-        eventtime=thisevent; }
-if(eventtime && now+timeleft>eventtime) {    /* less time, set flag */
-    sys_status|=SS_EVENT;
-    timeleft=eventtime-now; }
-
-/* Event time passed by front-end */
-if(next_event && (next_event<now || next_event-now<timeleft)) {
-    timeleft=next_event-now;
-    sys_status|=SS_EVENT; }
-
-if(timeleft<0)  /* timeleft can't go negative */
-    timeleft=0;
-if(thisnode.status==NODE_NEWUSER) {
-    timeleft=level_timepercall[new_level];
-    if(timeleft<10*60L)
-        timeleft=10*60L; }
-
-if(inside)			/* The following code is not recursive */
-    return;
-inside=1;
-
-if(!timeleft && !SYSOP && !(sys_status&SS_LCHAT)) {
-    logline(nulstr,"Ran out of time");
-    SAVELINE;
-    bputs(text[TimesUp]);
-    if(!(sys_status&(SS_EVENT|SS_USERON)) && useron.cdt>=100L*1024L
-		&& !(sys_misc&SM_NOCDTCVT)) {
-        sprintf(tmp,text[Convert100ktoNminQ],cdt_min_value);
-        if(yesno(tmp)) {
-			logline("  ","Credit to Minute Conversion");
-            useron.min=adjustuserrec(useron.number,U_MIN,10,cdt_min_value);
-			useron.cdt=adjustuserrec(useron.number,U_CDT,10,-(102400L));
-			sprintf(str,"Credit Adjustment: %ld",-(102400L));
-			logline("$-",str);
-			sprintf(str,"Minute Adjustment: %u",cdt_min_value);
-			logline("*+",str);
-            RESTORELINE;
-            gettimeleft();
-            inside=0;
-            return; } }
-	if(sys_misc&SM_TIME_EXP && !(sys_status&SS_EVENT)
-		&& !(useron.exempt&FLAG('E'))) {
-                                        /* set to expired values */
-		bputs(text[AccountHasExpired]);
-		sprintf(str,"%s Expired",useron.alias);
-		logentry("!%",str);
-		if(level_misc[useron.level]&LEVEL_EXPTOVAL
-			&& level_expireto[useron.level]<10) {
-			useron.flags1=val_flags1[level_expireto[useron.level]];
-			useron.flags2=val_flags2[level_expireto[useron.level]];
-			useron.flags3=val_flags3[level_expireto[useron.level]];
-			useron.flags4=val_flags4[level_expireto[useron.level]];
-			useron.exempt=val_exempt[level_expireto[useron.level]];
-			useron.rest=val_rest[level_expireto[useron.level]];
-			if(val_expire[level_expireto[useron.level]])
-				useron.expire=now
-					+(val_expire[level_expireto[useron.level]]*24*60*60);
-			else
-				useron.expire=0;
-			useron.level=val_level[level_expireto[useron.level]]; }
-		else {
-			if(level_misc[useron.level]&LEVEL_EXPTOLVL)
-				useron.level=level_expireto[useron.level];
-			else
-				useron.level=expired_level;
-			useron.flags1&=~expired_flags1; /* expired status */
-			useron.flags2&=~expired_flags2; /* expired status */
-			useron.flags3&=~expired_flags3; /* expired status */
-			useron.flags4&=~expired_flags4; /* expired status */
-			useron.exempt&=~expired_exempt;
-			useron.rest|=expired_rest;
-			useron.expire=0; }
-        putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,str,10));
-        putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,str,16));
-        putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,str,16));
-        putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,str,16));
-        putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,str,16));
-        putuserrec(useron.number,U_EXPIRE,8,ultoa(useron.expire,str,16));
-        putuserrec(useron.number,U_EXEMPT,8,ultoa(useron.exempt,str,16));
-        putuserrec(useron.number,U_REST,8,ultoa(useron.rest,str,16));
-		if(expire_mod[0])
-			exec_bin(expire_mod,&main_csi);
-        RESTORELINE;
-        gettimeleft();
-        inside=0;
-        return; }
-    SYNC;
-    hangup(); }
-inside=0;
-}
-
-/****************************************************************************/
-/* Places into 'strout' CR or ETX terminated string starting at             */
-/* 'start' and ending at 'start'+'length' or terminator from 'strin'        */
-/****************************************************************************/
-void getrec(char *strin,int start,int length,char *strout)
-{
-    int i=0,stop;
-
-stop=start+length;
-while(start<stop) {
-	if(strin[start]==ETX || strin[start]==CR || strin[start]==LF)
-        break;
-    strout[i++]=strin[start++]; }
-strout[i]=0;
-}
-
-/****************************************************************************/
-/* Places into 'strout', 'strin' starting at 'start' and ending at          */
-/* 'start'+'length'                                                         */
-/****************************************************************************/
-void putrec(char *strout,int start,int length,char *strin)
-{
-    int i=0,j;
-
-j=strlen(strin);
-while(i<j && i<length)
-    strout[start++]=strin[i++];
-while(i++<length)
-    strout[start++]=ETX;
-}
-
-
-/****************************************************************************/
-/* Returns the age derived from the string 'birth' in the format MM/DD/YY	*/
-/* Called from functions statusline, main_sec, xfer_sec, useredit and 		*/
-/* text files																*/
-/****************************************************************************/
-char getage(char *birth)
-{
-	char age;
-
-if(!atoi(birth) || !atoi(birth+3))	/* Invalid */
-	return(0);
-getdate(&date);
-age=(date.da_year-1900)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
-if(age>90)
-	age-=90;
-if(sys_misc&SM_EURODATE) {		/* DD/MM/YY format */
-	if(atoi(birth)>31 || atoi(birth+3)>12)
-		return(0);
-	if(((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_mon ||
-		(((birth[3]&0xf)*10)+(birth[4]&0xf)==date.da_mon &&
-		((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_day))
-		age--; }
-else {							/* MM/DD/YY format */
-	if(atoi(birth)>12 || atoi(birth+3)>31)
-		return(0);
-	if(((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_mon ||
-		(((birth[0]&0xf)*10)+(birth[1]&0xf)==date.da_mon &&
-		((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_day))
-		age--; }
-if(age<0)
-	return(0);
-return(age);
-}
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                               */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-    ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-    val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
diff --git a/src/sbbs2/initdata.c b/src/sbbs2/initdata.c
deleted file mode 100644
index c02305fd6d17cf0962718dc1caefd4fc9907b712..0000000000000000000000000000000000000000
--- a/src/sbbs2/initdata.c
+++ /dev/null
@@ -1,239 +0,0 @@
-#line 1 "INITDATA.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/**************************************************************************/
-/* This file contains the function initdata() and its exclusive functions */
-/**************************************************************************/
-
-#include "sbbs.h"
-
-/****************************************************************/
-/* Prototypes of functions that are called only by initdata()	*/
-/****************************************************************/
-void md(char *path);
-char *readtext(long *line, FILE *stream);
-
-/****************************************************************************/
-/* Initializes system and node configuration information and data variables */
-/****************************************************************************/
-void initdata()
-{
-	char	str[256],str2[LEN_ALIAS+1],fname[13];
-	int 	file;
-	uint 	i,j;
-	long	l,line=0L;
-	FILE 	*instream;
-	read_cfg_text_t txt;
-
-txt.openerr="\7\r\nError opening %s for read.\r\n";
-txt.reading="\r\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
-txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
-
-read_node_cfg(txt);
-read_main_cfg(txt);
-read_msgs_cfg(txt);
-read_file_cfg(txt);
-read_xtrn_cfg(txt);
-read_chat_cfg(txt);
-read_attr_cfg(txt);
-
-strcpy(fname,"TEXT.DAT");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-lprintf(txt.reading,fname);
-for(i=0;i<TOTAL_TEXT && !feof(instream) && !ferror(instream);i++)
-	if((text[i]=text_sav[i]=readtext(&line,instream))==NULL)
-		i--;
-if(i<TOTAL_TEXT) {
-	lprintf(txt.error,line,fname);
-	lprintf("Less than TOTAL_TEXT (%u) strings defined in %s\r\n"
-		,TOTAL_TEXT,fname);
-	bail(1); }
-/****************************/
-/* Read in static text data */
-/****************************/
-fclose(instream);
-lprintf(txt.readit,fname);
-
-strcpy(str,temp_dir);
-if(strcmp(str+1,":\\"))     /* not root directory */
-    str[strlen(str)-1]=0;   /* chop off '\' */
-md(str);
-
-for(i=0;i<=sys_nodes;i++) {
-	sprintf(str,"%sDSTS.DAB",i ? node_path[i-1] : ctrl_dir);
-	if(flength(str)<DSTSDABLEN) {
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-			lprintf("\7\r\nError creating %s\r\n",str);
-			bail(1); }
-		while(filelength(file)<DSTSDABLEN)
-			if(write(file,"\0",1)!=1)
-				break;				/* Create NULL system dsts.dab */
-		close(file); } }
-
-j=0;
-sprintf(str,"%sUSER\\USER.DAT",data_dir);
-if((l=flength(str))>0L) {
-	if(l%U_LEN) {
-		lprintf("\7\r\n%s is not evenly divisable by U_LEN (%d)\r\n"
-			,str,U_LEN);
-		bail(1); }
-	j=lastuser(); }
-if(node_valuser>j)	/* j still equals last user */
-	node_valuser=1;
-sys_status|=SS_INITIAL;
-#ifdef __MSDOS__
-freedosmem=farcoreleft();
-#endif
-}
-
-/****************************************************************************/
-/* If the directory 'path' doesn't exist, create it.                      	*/
-/****************************************************************************/
-void md(char *path)
-{
-	struct ffblk ff;
-
-if(findfirst(path,&ff,FA_DIREC)) {
-	lprintf("\r\nCreating Directory %s... ",path);
-	if(mkdir(path)) {
-		lprintf("\7failed!\r\nFix configuration or make directory by "
-			"hand.\r\n");
-		bail(1); }
-	lputs(crlf); }
-}
-
-/****************************************************************************/
-/* Reads special TEXT.DAT printf style text lines, splicing multiple lines, */
-/* replacing escaped characters, and allocating the memory					*/
-/****************************************************************************/
-char *readtext(long *line,FILE *stream)
-{
-	char buf[2048],str[2048],*p,*p2;
-	int i,j,k;
-
-if(!fgets(buf,256,stream))
-	return(NULL);
-if(line)
-	(*line)++;
-if(buf[0]=='#')
-	return(NULL);
-p=strrchr(buf,'"');
-if(!p) {
-	if(line) {
-		lprintf("\7\r\nNo quotation marks in line %d of TEXT.DAT\r\n",*line);
-		bail(1); }
-	return(NULL); }
-if(*(p+1)=='\\')	/* merge multiple lines */
-	while(strlen(buf)<2000) {
-		if(!fgets(str,255,stream))
-			return(NULL);
-		if(line)
-			(*line)++;
-		p2=strchr(str,'"');
-		if(!p2)
-			continue;
-		strcpy(p,p2+1);
-		p=strrchr(p,'"');
-		if(p && *(p+1)=='\\')
-			continue;
-		break; }
-*(p)=0;
-k=strlen(buf);
-for(i=1,j=0;i<k;j++) {
-	if(buf[i]=='\\')	{ /* escape */
-		i++;
-		if(isdigit(buf[i])) {
-			str[j]=atoi(buf+i); 	/* decimal, NOT octal */
-			if(isdigit(buf[++i]))	/* skip up to 3 digits */
-				if(isdigit(buf[++i]))
-					i++;
-			continue; }
-		switch(buf[i++]) {
-			case '\\':
-				str[j]='\\';
-				break;
-			case '?':
-				str[j]='?';
-				break;
-			case 'x':
-                tmp[0]=buf[i++];        /* skip next character */
-                tmp[1]=0;
-                if(isxdigit(buf[i])) {  /* if another hex digit, skip too */
-                    tmp[1]=buf[i++];
-                    tmp[2]=0; }
-				str[j]=(char)ahtoul(tmp);
-				break;
-			case '\'':
-				str[j]='\'';
-				break;
-			case '"':
-				str[j]='"';
-				break;
-			case 'r':
-				str[j]=CR;
-				break;
-			case 'n':
-				str[j]=LF;
-				break;
-			case 't':
-				str[j]=TAB;
-				break;
-			case 'b':
-				str[j]=BS;
-				break;
-			case 'a':
-				str[j]=7;	/* BEL */
-				break;
-			case 'f':
-				str[j]=FF;
-				break;
-			case 'v':
-				str[j]=11;	/* VT */
-				break;
-			default:
-				str[j]=buf[i];
-				break; }
-		continue; }
-	str[j]=buf[i++]; }
-str[j]=0;
-if((p=(char *)MALLOC(j+1))==NULL) {
-	lprintf("\7\r\nError allocating %u bytes of memory from TEXT.DAT\r\n",j);
-	bail(1); }
-strcpy(p,str);
-return(p);
-}
-
-/****************************************************************************/
-/* Reads in ATTR.CFG and initializes the associated variables               */
-/****************************************************************************/
-void read_attr_cfg(read_cfg_text_t txt)
-{
-    char    str[256],fname[13];
-    int     file,i;
-	long	offset=0;
-    FILE    *instream;
-
-strcpy(fname,"ATTR.CFG");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-    lprintf(txt.openerr,str);
-    bail(1); }
-lprintf(txt.reading,fname);
-for(i=0;i<TOTAL_COLORS && !feof(instream) && !ferror(instream);i++) {
-	readline(&offset,str,4,instream);
-    color[i]=attrstr(str); }
-if(i<TOTAL_COLORS) {
-	lprintf(txt.error,offset,fname);
-    lprintf("Less than TOTAL_COLORS (%u) defined in %s\r\n"
-        ,TOTAL_COLORS,fname);
-    bail(1); }
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
diff --git a/src/sbbs2/install/install.c b/src/sbbs2/install/install.c
deleted file mode 100644
index bb24972c0346ae124a915fd36b6307941c5b5388..0000000000000000000000000000000000000000
--- a/src/sbbs2/install/install.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/* install.c */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet BBS Installation program */
-
-unsigned int _stklen=0x8000;
-
-#include <io.h>
-#include <dir.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <process.h>
-#include <errno.h>
-#include "uifc.h"
-
-/* OS Specific */
-#if defined(__FLAT__)	// 32-bit
-	#define FAR16
-	#define HUGE16
-	#define lread(f,b,l) read(f,b,l)
-	#define lfread(b,l,f) fread(b,l,f)
-	#define lwrite(f,b,l) write(f,b,l)
-	#define lfwrite(b,l,f) fwrite(b,l,f)
-#else					// 16-bit
-	#define FAR16 far
-	#define HUGE16 huge
-#endif
-
-void bail(int code);
-
-char **opt;
-
-#define EXEC		(1<<1)
-#define CFGS		(1<<2)
-#define TEXT		(1<<3)
-#define DOCS		(1<<4)
-
-#define DISK1		(EXEC|CFGS|TEXT|DOCS)
-
-#define UTIL		(1<<10)
-#define XTRN		(1<<11)
-#define XSDK		(1<<12)
-
-#define DISK2		(UTIL|XTRN|XSDK)
-
-#define UPGRADE 	(1<<13)
-
-#define LOOP_NOPEN 100
-
-int mode=(DISK1|DISK2);
-
-enum {				/* Upgrade FROM version */
-	 NONE
-	,SBBS20
-	,SBBS21
-	,SBBS22
-	,SBBS23
-	};
-
-char tmp[256];
-char install_to[129],install_from[256];
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-
-/****************************************************************************/
-/* If the directory 'path' doesn't exist, create it.                      	*/
-/* returns 1 if successful, 0 otherwise 									*/
-/****************************************************************************/
-int md(char *path)
-{
-	char str[128];
-	struct ffblk ff;
-
-if(strlen(path)<2) {
-	umsg("Invalid path");
-	return(0); }
-strcpy(str,path);
-if(strcmp(str+1,":\\") && str[strlen(str)-1]=='\\')
-	str[strlen(str)-1]=0;	/* Chop of \ if not root directory */
-if(findfirst(str,&ff,FA_DIREC)) {
-	if(mkdir(str)) {
-		sprintf(str,"Unable to Create Directory '%s'",path);
-		umsg(str);
-		return(0); } }
-return(1);
-}
-
-long fdate_dir(char *filespec)
-{
-    struct ffblk f;
-    struct date fd;
-    struct time ft;
-
-if(findfirst(filespec,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC)==0) {
-	fd.da_day=f.ff_fdate&0x1f;
-	fd.da_mon=(f.ff_fdate>>5)&0xf;
-	fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
-	ft.ti_hour=0;
-	ft.ti_min=0;
-	ft.ti_sec=0;
-    return(dostounix(&fd,&ft)); }
-else return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-	return(f.ff_fsize);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC)==0)
-    return(1);
-return(0);
-}
-
-#ifndef __OS2__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char huge *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-
-/****************************************************************************/
-/* This function writes files that are potentially larger than 32767 bytes  */
-/* Up to one megabytes of data can be written with each call.				*/
-/****************************************************************************/
-long lwrite(int file, char huge *buf, long bytes)
-{
-
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(write(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(write(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-	else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	cputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-int copy(char *src, char *dest)
-{
-	char c,HUGE16 *buf,str[256],str2[128],*scrnsave;
-	int in,out;
-	long length,chunk,l;
-	struct ftime ftime;
-
-if(!strcmp(src,dest))	/* copy from and to are same, so return */
-	return(0);
-
-if((scrnsave=MALLOC(scrn_len*80*2))==NULL)
-	return(-1);
-hidemouse();
-gettext(1,1,80,scrn_len,scrnsave);
-
-#define width 72
-#define top 10
-#define left 0
-
-sprintf(str2,"Copying %s to %s...",src,dest);
-sprintf(str," %-64.64s",str2); /* Make sure it's no more than 60 */
-
-gotoxy(SCRN_LEFT+left,SCRN_TOP+top);
-textattr(hclr|(bclr<<4));
-putch('�');
-for(c=1;c<width-1;c++)
-	putch('�');
-putch('�');
-gotoxy(SCRN_LEFT+left,SCRN_TOP+top+1);
-putch('�');
-textattr(lclr|(bclr<<4));
-cprintf("%-*.*s",width-2,width-2,str);
-gotoxy(SCRN_LEFT+left+(width-1),SCRN_TOP+top+1);
-textattr(hclr|(bclr<<4));
-putch('�');
-gotoxy(SCRN_LEFT+left,SCRN_TOP+top+2);
-putch('�');
-for(c=1;c<width-1;c++)
-	putch('�');
-putch('�');
-gotoxy(SCRN_LEFT+left+(width-5),SCRN_TOP+top+1);
-textattr(lclr|(bclr<<4));
-
-if((in=nopen(src,O_RDONLY))==-1) {
-	cprintf("\r\nERR_OPEN %s",src);
-	getch();
-	puttext(1,1,80,scrn_len,scrnsave);
-	FREE(scrnsave);
-	showmouse();
-    return(-1); }
-if((out=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-	close(in);
-	sprintf(str,"ERROR OPENING %s",dest);
-	umsg(str);
-	puttext(1,1,80,scrn_len,scrnsave);
-	FREE(scrnsave);
-	showmouse();
-	return(-1); }
-length=filelength(in);
-if(!length) {
-	close(in);
-	close(out);
-	sprintf(str,"ZERO LENGTH %s",src);
-	umsg(str);
-	puttext(1,1,80,scrn_len,scrnsave);
-	showmouse();
-	FREE(scrnsave);
-	return(-1); }
-#if __OS2__
-chunk=1000000;
-#else
-chunk=0x8000; /* use 32k chunks */
-#endif
-if(chunk>length)			/* leave space for stack expansion */
-	chunk=length;
-if((buf=MALLOC(chunk))==NULL) {
-	close(in);
-	close(out);
-	sprintf(str,"ERROR ALLOC %s %lu",src,chunk);
-	umsg(str);
-	puttext(1,1,80,scrn_len,scrnsave);
-    FREE(scrnsave);
-	showmouse();
-    return(-1); }
-l=0L;
-while(l<length) {
-	cprintf("%2lu%%",l ? (long)(100.0/((float)length/l)) : 0L);
-	if(l+chunk>length)
-		chunk=length-l;
-	lread(in,buf,chunk);
-	lwrite(out,buf,chunk);
-	l+=chunk;
-	cputs("\b\b\b");
-	}
-// cputs("   \b\b\b");  /* erase it */
-FREE((char *)buf);
-getftime(in,&ftime);
-setftime(out,&ftime);
-close(in);
-close(out);
-puttext(1,1,80,scrn_len,scrnsave);
-FREE(scrnsave);
-showmouse();
-return(0);
-}
-
-int unarc(int timestamp, char *src, char *dir, char *arg)
-{
-	int i,atr;
-	char str[128],cmd[128],*scrnsave;
-
-if((scrnsave=MALLOC((scrn_len+1)*80*2))==NULL)
-	return(-1);
-hidemouse();
-gettext(1,1,80,scrn_len+1,scrnsave);
-//lclini(scrn_len+1);
-textattr(LIGHTGRAY);
-clrscr();
-sprintf(cmd,"%sLHA.EXE",install_from);
-sprintf(str,"/c%d",timestamp);
-i=spawnlp(P_WAIT,cmd,cmd,"x",str,"/s","/m1",src,dir,arg,NULL);
-if(i==-1) {
-	printf("\r\nCannot execute %s.  Hit any key to continue.",cmd);
-	getch(); }
-else if(i) {
-	printf("\r\n%s returned error level %d.  Hit any key to continue.",cmd,i);
-	getch(); }
-clrscr();
-puttext(1,1,80,scrn_len+1,scrnsave);
-showmouse();
-FREE(scrnsave);
-//lclini(scrn_len);
-//textattr(atr);
-return(i);
-}
-
-
-void main(int argc, char **argv)
-{
-	int i,j,k,ver;
-	long l;
-	char str[128],*p;
-	char text_dir[64],docs_dir[64],exec_dir[64],ctrl_dir[64];
-	struct text_info txt;
-	struct ffblk ff;
-
-timezone=0;
-daylight=0;
-uifcini();
-if(argc>1) {	/* user specified install path */
-	sprintf(install_to,"%.20s",argv[1]);
-	strupr(install_to);
-	if(strlen(install_to)==1) {
-		if(!isalpha(install_to[0])) {
-			cprintf("\7\r\nInvalid install path - '%s'\r\n",install_to);
-			bail(1); }
-		strcat(install_to,":"); }
-	backslash(install_to);
-	if(strlen(install_to)<4)	/* user says C, C:, or C:\, make C:\SBBS */
-		strcat(install_to,"SBBS\\"); }
-else
-	strcpy(install_to,"C:\\SBBS\\");
-
-strcpy(install_from,argv[0]);
-strupr(install_from);
-p=strrchr(install_from,'\\');
-if(p)
-	*(p+1)=0;
-else {				/* incase of A:INSTALL */
-	p=strchr(install_from,':');
-	if(p)
-		*(p+1)=0; }
-
-if((opt=(char **)MALLOC(sizeof(char *)*MAX_OPTS))==NULL) {
-	cputs("memory allocation error\r\n");
-	bail(1); }
-for(i=0;i<MAX_OPTS;i++)
-	if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL) {
-		cputs("memory allocation error\r\n");
-		bail(1); }
-
-/***
-if(findfirst("MENU.ZIP",&ff,0)) {
-	cprintf("\7\r\nCan't find MENU.ZIP\r\n");
-	bail(1); }
-if(findfirst("TEXT.ZIP",&ff,0)) {
-	cprintf("\7\r\nCan't find TEXT.ZIP\r\n");
-	bail(1); }
-if(findfirst("DOCS.ZIP",&ff,0)) {
-	cprintf("\7\r\nCan't find DOCS.ZIP\r\n");
-	bail(1); }
-if(findfirst("EXEC.ZIP",&ff,0)) {
-	cprintf("\7\r\nCan't find EXEC.ZIP\r\n");
-	bail(1); }
-if(findfirst("PKUNZIP.EXE",&ff,0)) {
-	cprintf("\7\r\nCan't find PKUNZIP.EXE\r\n");
-	bail(1); }
-***/
-uscrn("Synchronet Installation Utility  Version 2.3");
-
-i=0;
-while(1) {
-
-	helpbuf=
-" Synchronet Installation \r\n\r\n"
-"If you are installing Synchronet for evaluation or demonstration\r\n"
-"purposes, be sure to set Install Registration Key to No.\r\n\r\n"
-"If do not have the Synchronet Utilities Disk (Distribution Disk 2), be\r\n"
-"sure to set Install Distribution Disk 2 to None.\r\n\r\n"
-"When you are happy with the installation settings and the destination\r\n"
-"path, select Start Installation to continue or hit  ESC  to abort.";
-
-	j=0;
-	str[0]=0;
-	if((mode&DISK1)==DISK1)
-		strcpy(str,"All");
-	else {
-		if(!(mode&DISK1))
-			strcpy(str,"None");
-		else {
-			strcat(str,"Selected: ");
-			if(mode&EXEC)
-				strcat(str,"EXEC ");
-			if(mode&CFGS)
-				strcat(str,"CFGS ");
-			if(mode&TEXT)
-				strcat(str,"TEXT ");
-			if(mode&DOCS)
-				strcat(str,"DOCS "); } }
-	sprintf(opt[j++],"%-30.30s%s","Install Distribution Disk 1",str);
-	str[0]=0;
-	if((mode&DISK2)==DISK2)
-		strcpy(str,"All");
-	else {
-		if(!(mode&DISK2))
-			strcpy(str,"None");
-		else {
-			strcat(str,"Selected: ");
-			if(mode&UTIL)
-				strcat(str,"UTIL ");
-			if(mode&XTRN)
-				strcat(str,"XTRN ");
-			if(mode&XSDK)
-				strcat(str,"XSDK "); } }
-	sprintf(opt[j++],"%-30.30s%s","Install Distribution Disk 2",str);
-	sprintf(opt[j++],"%-30.30s%s","Source Path",install_from);
-	sprintf(opt[j++],"%-30.30s%s","Target Path",install_to);
-	strcpy(opt[j++],"Start Installation");
-	opt[j][0]=0;
-	switch(ulist(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,60,&i,0
-		,"Synchronet Multinode BBS Installation",opt)) {
-		case 0:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-30.30s%3s","Main Executables"
-					,mode&EXEC ? "Yes":"No");
-				sprintf(opt[k++],"%-30.30s%3s","Default Configuration"
-					,mode&CFGS ? "Yes":"No");
-				sprintf(opt[k++],"%-30.30s%3s","Text and Menus"
-					,mode&TEXT ? "Yes":"No");
-				sprintf(opt[k++],"%-30.30s%3s","Documentation"
-					,mode&DOCS ? "Yes":"No");
-				strcpy(opt[k++],"All");
-				strcpy(opt[k++],"None");
-				opt[k][0]=0;
-helpbuf=
-" Distribution Disk 1 \r\n\r\n"
-"If you are a installing Synchronet for the first time, it is suggested\r\n"
-"that you install All of Disk 1.\r\n\r\n"
-"If for some reason, you wish to partially install Synchronet or update\r\n"
-"a previously installed version, you can toggle the installation of the\r\n"
-"following file sets:\r\n\r\n"
-"EXEC: Main executable files necessary for Synchronet to run\r\n\r\n"
-"CFGS: Default configuration files\r\n\r\n"
-"TEXT: Text and menu files\r\n\r\n"
-"DOCS: Online ASCII documentation for the system operator";
-				j=ulist(0,0,0,0,&j,0,"Distribution Disk 1",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-						mode^=EXEC;
-						break;
-					case 1:
-						mode^=CFGS;
-						break;
-					case 2:
-						mode^=TEXT;
-						break;
-					case 3:
-						mode^=DOCS;
-						break;
-					case 4:
-						mode|=DISK1;
-						break;
-					case 5:
-						mode&=~DISK1;
-						break; } }
-			break;
-		case 1:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-30.30s%3s","Utilities"
-					,mode&UTIL ? "Yes":"No");
-				sprintf(opt[k++],"%-30.30s%3s","Online External Programs"
-					,mode&XTRN ? "Yes":"No");
-				sprintf(opt[k++],"%-30.30s%3s","External Program SDK"
-					,mode&XSDK ? "Yes":"No");
-				strcpy(opt[k++],"All");
-				strcpy(opt[k++],"None");
-				opt[k][0]=0;
-helpbuf=
-" Distribution Disk 2 \r\n\r\n"
-"This disk is optional for the execution of Synchronet. This disk is\r\n"
-"also referred to as the Synchronet Utilities Disk.\r\n\r\n"
-"If for some reason, you wish to partially install Synchronet or update\r\n"
-"a previously installed version, you can toggle the installation of the\r\n"
-"following file sets:\r\n\r\n"
-"UTIL: Utilities to enhance the operation of Synchronet\r\n\r\n"
-"XTRN: Online External Program Samples\r\n\r\n"
-"XSDK: External Program Software Development Kit (for programmers)";
-				j=ulist(WIN_RHT,0,0,0,&j,0,"Distribution Disk 2",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-						mode^=UTIL;
-						break;
-					case 1:
-						mode^=XTRN;
-						break;
-					case 2:
-						mode^=XSDK;
-						break;
-					case 3:
-						mode|=DISK2;
-						break;
-					case 4:
-						mode&=~DISK2;
-                        break; } }
-			break;
-		case 2:
-helpbuf=
-" Source Path \r\n\r\n"
-"This is the complete path (drive and directory) to install Synchronet\r\n"
-"from. The suggested path is A:\\, but any valid DOS drive and\r\n"
-"directory may be used.";
-			uinput(WIN_L2R,0,0,"Source Path",install_from
-				,30,K_EDIT|K_UPPER);
-			backslash(install_from);
-            break;
-		case 3:
-helpbuf=
-" Target Path \r\n\r\n"
-"This is the complete path (drive and directory) to install Synchronet\r\n"
-"to. The suggested path is C:\\SBBS\\, but any valid DOS drive and\r\n"
-"directory may be used.";
-			uinput(WIN_L2R|WIN_BOT,0,0,"Target Path",install_to
-				,20,K_EDIT|K_UPPER);
-			backslash(install_to);
-			break;
-		case 4:
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			j=1;
-			j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-				,"Are you upgrading from an older version (already installed)"
-				,opt);
-			if(j==-1)
-				break;
-			if(j==0) {
-				helpbuf=
-" Upgrade Back-up \r\n"
-"\r\n"
-"INSTALL will take care to only overwrite files that have been changed\r\n"
-"in this new version, but it is always a good idea to do a complete\r\n"
-"system back-up before upgrading, just to be safe.\r\n"
-"\r\n"
-"If you have customized (with an editor) any of the following files, you\r\n"
-"will want to back them up (copy to another disk or directory) before\r\n"
-"you begin the upgrade procedure:\r\n"
-"\r\n"
-"TEXT.DAT (CTRL\\TEXT.DAT)\r\n"
-"Command Shells and Loadable Modules (EXEC\\*.SRC)\r\n"
-"Menus (TEXT\\MENU\\*.ASC)\r\n"
-"Match Maker Questionnaires (XTRN\\SMM\\*.QUE)\r\n"
-"External Program Menus (XTRN\\SMM\\*.ASC, XTRN\\SCB\\*.ASC, etc)\r\n";
-				help();
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				j=0;
-				j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-					,"Continue with upgrade"
-					,opt);
-				if(j)
-					break;
-				mode|=UPGRADE;
-				mode&=~CFGS; }
-			else
-				mode&=~UPGRADE;
-			strcpy(str,install_to);
-			if(str[1]==':')                /* drive letter specified */
-				setdisk(toupper(str[0])-'A');
-			if(!md(str))
-				break;
-			sprintf(exec_dir,"%sEXEC\\",install_to);
-			if(mode&UPGRADE)
-				if(uinput(WIN_L2R|WIN_SAV,0,0,"EXEC Directory",exec_dir
-					,30,K_EDIT|K_UPPER)<1)
-					break;
-			backslash(exec_dir);
-			if(!md(exec_dir))
-				break;
-			if(mode&UPGRADE) {
-				sprintf(str,"%sSBBS.EXE",exec_dir);
-				l=fdate_dir(str);
-				ver=NONE;
-				switch(l) {
-					case 0x3044fb80:	/* 08/31/95 v2.20a */
-						ver=SBBS22;
-						break;
-					case 0x2f6a2280:	/* 03/18/95 v2.11a */
-					case 0x2f43e700:	/* 02/17/95 v2.10a */
-						ver=SBBS21;
-						break;
-					case 0x2e6fa580:	/* 09/09/94 v2.00g */
-					case 0x2e627680:	/* 08/30/94 v2.00f */
-					case 0x2e5a8d80:	/* 08/24/94 v2.00e */
-					case 0x2e569900:	/* 08/21/94 v2.00d */
-					case 0x2e554780:	/* 08/20/94 v2.00c */
-					case 0x2e0b7380:	/* 06/25/94 v2.00b */
-					case 0x2ded2100:	/* 06/02/94 v2.00a */
-						ver=SBBS20;
-						break; }
-				if(ver==NONE && flength(str)==642448UL)
-					ver=SBBS22; /* v2.20b - possibly patched */
-				if(ver==NONE) {
-					strcpy(opt[0],"Version 1");
-					strcpy(opt[1],"Version 2.0");
-					strcpy(opt[2],"Version 2.1");
-					strcpy(opt[3],"Version 2.2");
-					strcpy(opt[4],"Version 2.3 beta");
-					opt[5][0]=0;
-					j=0;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Which version are you upgrading from?"
-						,opt);
-					if(j<0)
-						break;
-					ver=j;
-					if(ver==NONE) { // Version 1
-						umsg("INSTALL can only upgrade from Version 2.0 or later");
-						umsg("See the file UPGRADE.DOC for UPGRADE instructions");
-						break; } } }
-
-			if(mode&EXEC) {
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-				opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sEXEC.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 1",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK1;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-
-				/* If they already exist, flag as read/write */
-				if(mode&DISK1) {
-					sprintf(str,"%sSBBS.EXE",exec_dir);
-					chmod(str,S_IREAD|S_IWRITE);
-					sprintf(str,"%sSCFG.EXE",exec_dir);
-					chmod(str,S_IREAD|S_IWRITE);
-
-					sprintf(str,"%sEXEC.LZH",install_from);
-					sprintf(tmp,"%sEXEC.LZH",exec_dir);
-					if(copy(str,tmp))
-						break;
-					if(mode&UPGRADE) {
-						sprintf(str,"@%sEXEC.UPG",install_from);
-						if(fexist(str+1))
-							if(unarc(1,tmp,exec_dir,str)) {
-								remove(tmp);
-								break; }
-						if(unarc(0,tmp,exec_dir,NULL)) {
-                            remove(tmp);
-							break; } }
-                    else
-						if(unarc(1,tmp,exec_dir,NULL)) {
-							remove(tmp);
-							break; }
-					remove(tmp);
-
-					/* now set to READ ONLY */
-					sprintf(str,"%sSBBS.EXE",exec_dir);
-					if(chmod(str,S_IREAD))
-						umsg("Error setting SBBS.EXE to READ ONLY");
-					sprintf(str,"%sSCFG.EXE",exec_dir);
-					if(chmod(str,S_IREAD))
-						umsg("Error setting SCFG.EXE to READ ONLY"); } }
-
-			if(mode&CFGS) {
-				sprintf(str,"%sCTRL",install_to);
-				if(!md(str))
-					break;
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sCFGS.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 1",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK1;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-				if(mode&DISK1) {	 /* not skip */
-					sprintf(str,"%sCFGS.LZH",install_from);
-					sprintf(tmp,"%sCFGS.LZH",install_to);
-					if(copy(str,tmp))
-						break;
-					sprintf(str,"%sCTRL",install_to);
-					if(unarc(1,tmp,install_to,NULL)) {
-						remove(tmp);
-						break; }
-					remove(tmp); } }
-
-			if(mode&TEXT) {
-				sprintf(ctrl_dir,"%sCTRL\\",install_to);
-				if(!md(ctrl_dir))
-					break;
-				sprintf(text_dir,"%sTEXT\\",install_to);
-				if(!md(text_dir))
-                    break;
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sTEXT.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 1",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK1;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-				if(mode&DISK1) {
-					sprintf(str,"%sTEXT.LZH",install_from);
-					sprintf(tmp,"%sTEXT.LZH",install_to);
-					if(copy(str,tmp))
-						break;
-					if(mode&UPGRADE) {
-						sprintf(str,"@%sTEXT.UPG",install_from);
-						if(fexist(str+1))
-							if(unarc(1,tmp,install_to,str)) {
-								remove(tmp);
-								break; }
-						if(unarc(0,tmp,install_to,NULL)) {
-                            remove(tmp);
-							break; } }
-					else
-						if(unarc(1,tmp,install_to,NULL)) {
-							remove(tmp);
-							break; }
-					remove(tmp); } }
-
-			if(mode&DOCS) {
-				sprintf(docs_dir,"%sDOCS\\",install_to);
-				if(mode&UPGRADE)
-					if(uinput(WIN_L2R|WIN_SAV,0,0,"DOCS Directory",docs_dir
-						,30,K_EDIT|K_UPPER)<1)
-                        break;
-				backslash(docs_dir);
-				if(!md(docs_dir))
-					break;
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sDOCS.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 1",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK1;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-				if(mode&DISK1) {
-					sprintf(str,"%sDOCS.LZH",install_from);
-					sprintf(tmp,"%sDOCS.LZH",install_to);
-					if(copy(str,tmp))
-						break;
-					if(unarc(1,tmp,docs_dir,NULL)) {
-						remove(tmp);
-						break; }
-					remove(tmp); } }
-
-			if(mode&UTIL) {
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sUTIL.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 2 (Utilities Disk)",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK2;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-
-				if(mode&DISK2) {
-					sprintf(str,"%sUTIL.LZH",install_from);
-					sprintf(tmp,"%sUTIL.LZH",exec_dir);
-					if(copy(str,tmp))
-						break;
-					if(mode&UPGRADE) {
-						sprintf(str,"@%sUTIL.UPG",install_from);
-						if(fexist(str+1))
-							if(unarc(1,tmp,exec_dir,str)) {
-								remove(tmp);
-								break; }
-						if(unarc(0,tmp,exec_dir,NULL)) {
-                            remove(tmp);
-							break; } }
-                    else
-						if(unarc(1,tmp,exec_dir,NULL)) {
-							remove(tmp);
-							break; }
-					remove(tmp); } }
-
-			if(mode&XTRN) {
-				sprintf(str,"%sXTRN",install_to);
-				if(!md(str))
-					break;
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sXTRN.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 2 (Utilities Disk)",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK2;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-
-				if(mode&DISK2) {
-					sprintf(str,"%sXTRN.LZH",install_from);
-					sprintf(tmp,"%sXTRN.LZH",install_to);
-					if(copy(str,tmp))
-						break;
-					if(mode&UPGRADE) {
-						sprintf(str,"@%sXTRN.UPG",install_from);
-						if(fexist(str+1))
-							if(unarc(1,tmp,install_to,str)) {
-								remove(tmp);
-								break; }
-						if(unarc(0,tmp,install_to,NULL)) {
-                            remove(tmp);
-							break; } }
-					else
-						if(unarc(1,tmp,install_to,NULL)) {
-							remove(tmp);
-                            break; }
-					remove(tmp); } }
-
-			if(mode&XSDK) {
-				sprintf(str,"%sXTRN",install_to);
-				if(!md(str))
-					break;
-				sprintf(str,"%sXTRN\\SDK",install_to);
-				if(!md(str))
-                    break;
-				strcpy(opt[0],"Skip This Disk");
-				strcpy(opt[1],"Okay, Try Again");
-                strcpy(opt[2],"Change Source Path...");
-                opt[3][0]=0;
-				j=1;
-				while(1) {
-					sprintf(str,"%sXSDK.LZH",install_from);
-					if(!findfirst(str,&ff,0))
-						break;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Insert Distribution Disk 2 (Utilities Disk)",opt);
-					if(j==-1)
-						break;
-					if(j==0) {
-						mode&=~DISK2;
-						break; }
-					if(j==2) {
-						uinput(WIN_L2R|WIN_SAV,0,0,"Source Path",install_from
-							,30,K_EDIT|K_UPPER);
-						backslash(install_from); } }
-				if(j==-1)
-					break;
-
-				if(mode&DISK2) {
-					sprintf(str,"%sXSDK.LZH",install_from);
-					sprintf(tmp,"%sXTRN\\XSDK.LZH",install_to);
-					if(copy(str,tmp))
-						break;
-					sprintf(str,"%sXTRN\\SDK\\",install_to);
-					if(unarc(1,tmp,str,NULL)) {
-						remove(tmp);
-						break; }
-					remove(tmp); } }
-			sprintf(str,"%sNODE1",install_to);
-			chdir(str);
-			if(mode&UPGRADE) {
-				helpbuf=
-" Additional Upgrade Instructions \r\n"
-"\r\n"
-"If you were previously running version 1.1 of SyncEdit, you'll need to\r\n"
-"change your command lines and toggle options in SCFG for this new\r\n"
-"version (2.0). See DOCS\\SYNCEDIT.DOC for details.\r\n"
-"\r\n"
-"Make sure you have SCFG->System->Loadable Modules->Login set to LOGIN\r\n"
-"and SCFG->System->Loadable Modules->Logon set to LOGON.\r\n"
-"\r\n"
-"If you want your users to be able to use WIP compatible terminals with\r\n"
-"your BBS, add WIPSHELL to SCFG->Command Shells with an Access\r\n"
-"Requirement String of \"WIP\".";
-				help(); }
-			uifcbail();
-			if(mode&UPGRADE) {
-				cprintf("Synchronet Upgrade Complete.\r\n");
-				exit(0); }
-			if(mode&CFGS)
-				p="/F";
-			else
-				p=NULL;
-			spawnl(P_WAIT,"..\\EXEC\\SCFG.EXE"
-				,"..\\EXEC\\SCFG","..\\CTRL",p,NULL);
-			textattr(LIGHTGRAY);
-			cprintf(
-"Synchronet BBS and its utilities use file and record locking to maintain\r\n"
-"data integrity in a multinode environment. File and record locking under DOS\r\n"
-"requires the use of SHARE.\r\n"
-"\r\n"
-			);
-			cprintf(
-"SHARE is a program that is distributed with MS-DOS and PC-DOS v3.0 and higher\r\n"
-"and must be executed prior to running SBBS. SHARE.EXE should be located in the\r\n"
-"DOS directory of your hard disk.\r\n"
-"\r\n"
-			);
-			cprintf(
-"If you are running Microsoft Windows, you must exit Windows and load SHARE\r\n"
-"before reloading Windows.\r\n"
-"\r\n"
-			);
-			cprintf(
-"It is not necessary to run SHARE if using a single node on a Novell NetWare\r\n"
-"workstation or in an OS/2 DOS window.\r\n"
-"\r\n"
-			);
-			cprintf(
-"SHARE.EXE can be automatically loaded in your AUTOEXEC.BAT or CONFIG.SYS.\r\n"
-"\r\n"
-			);
-			textattr(WHITE);
-			cprintf(
-"After you have loaded SHARE, type SBBS from THIS directory.\r\n"
-			);
-			textattr(LIGHTGRAY);
-			exit(0);
-		case -1:
-			j=0;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			if(!(ulist(WIN_MID,0,0,20,&j,0,"Abort Installation",opt)))
-				bail(0);
-			break; } }
-}
-
-void bail(int code)
-{
-
-if(code)
-	getch();
-uifcbail();
-exit(code);
-}
diff --git a/src/sbbs2/install/makefile b/src/sbbs2/install/makefile
deleted file mode 100644
index f277d18b8b1a3dc5b888f597cf7ebe7283049405..0000000000000000000000000000000000000000
--- a/src/sbbs2/install/makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-###############################################
-# Makefile for Synchronet BBS Install Program #
-# For use with Borland C++ for DOS or OS/2    #
-###############################################
-
-# Macros
-CC	= bcc
-LD	= tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\..\uifc
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE) -w-pro
-LFLAGS  = -c
-!else
-OS      = DOS
-INCLUDE = \bc45\include;..;..\..\uifc
-LIB	= \bc45\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LFLAGS	= -n -c
-OBJS	= ..\..\mswait\$(OS)\mswait.obj
-!endif
-MAIN	= $(OS)\install.exe
-OBJS	= $(OBJS) $(OS)\uifc.obj $(OS)\install.obj
-HEADERS = ..\..\uifc\uifc.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL).obj $(OBJS)
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib\
-	$(LIB)\emu.lib
-!endif
-
-# Local Menu Routines
-$(OS)\uifc.obj: ..\..\uifc\uifc.c ..\..\uifc\uifc.h
-	@echo Compiling ..\..\uifc\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\..\uifc\$&.c
-
-install.obj: 	$(HEADERS)
diff --git a/src/sbbs2/listfile.c b/src/sbbs2/listfile.c
deleted file mode 100644
index d0c4582032342bdcfaf06c2bd95ef387b0cec8eb..0000000000000000000000000000000000000000
--- a/src/sbbs2/listfile.c
+++ /dev/null
@@ -1,782 +0,0 @@
-#line 1 "LISTFILE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-int listfile(char *fname, char HUGE16 *buf, uint dirnum
-	, char *search, char letter, ulong datoffset);
-
-void clearline(void)
-{
-	int i;
-
-outchar(CR);
-if(useron.misc&ANSI)
-	bputs("\x1b[K");
-else {
-	for(i=0;i<79;i++)
-		outchar(SP);
-	outchar(CR); }
-}
-
-/****************************************************************************/
-/* Remove credits from uploader of file 'f'                                 */
-/****************************************************************************/
-void removefcdt(file_t f)
-{
-	char str[128];
-	int u;
-	long cdt;
-
-if((u=matchuser(f.uler))==0) {
-   bputs(text[UnknownUser]);
-   return; }
-cdt=0L;
-if(dir[f.dir]->misc&DIR_CDTMIN && cur_cps) {
-	if(dir[f.dir]->misc&DIR_CDTUL)
-		cdt=((ulong)(f.cdt*(dir[f.dir]->up_pct/100.0))/cur_cps)/60;
-	if(dir[f.dir]->misc&DIR_CDTDL
-		&& f.timesdled)  /* all downloads */
-		cdt+=((ulong)((long)f.timesdled
-			*f.cdt*(dir[f.dir]->dn_pct/100.0))/cur_cps)/60;
-	adjustuserrec(u,U_MIN,10,-cdt);
-	sprintf(str,"%lu minute",cdt);
-	sprintf(tmp,text[FileRemovedUserMsg]
-		,f.name,cdt ? str : text[No]);
-	putsmsg(u,tmp); }
-else {
-	if(dir[f.dir]->misc&DIR_CDTUL)
-		cdt=(ulong)(f.cdt*(dir[f.dir]->up_pct/100.0));
-	if(dir[f.dir]->misc&DIR_CDTDL
-		&& f.timesdled)  /* all downloads */
-		cdt+=(ulong)((long)f.timesdled
-			*f.cdt*(dir[f.dir]->dn_pct/100.0));
-	adjustuserrec(u,U_CDT,10,-cdt);
-	sprintf(tmp,text[FileRemovedUserMsg]
-		,f.name,cdt ? ultoac(cdt,str) : text[No]);
-    putsmsg(u,tmp); }
-
-adjustuserrec(u,U_ULB,10,-f.size);
-adjustuserrec(u,U_ULS,5,-1);
-}
-
-/****************************************************************************/
-/* Move file 'f' from f.dir to newdir                                       */
-/****************************************************************************/
-void movefile(file_t f, int newdir)
-{
-	char str[256],path[256],fname[128],ext[1024];
-	int olddir=f.dir;
-
-if(findfile(newdir,f.name)) {
-	bprintf(text[FileAlreadyThere],f.name);
-	return; }
-getextdesc(olddir,f.datoffset,ext);
-if(dir[olddir]->misc&DIR_MOVENEW)
-	f.dateuled=time(NULL);
-unpadfname(f.name,fname);
-removefiledat(f);
-f.dir=newdir;
-addfiledat(&f);
-bprintf(text[MovedFile],f.name
-	,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-sprintf(str,"Moved %s to %s %s",f.name
-	,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-logline(nulstr,str);
-if(!f.altpath) {	/* move actual file */
-	sprintf(str,"%s%s",dir[olddir]->path,fname);
-	if(fexist(str)) {
-		sprintf(path,"%s%s",dir[f.dir]->path,fname);
-		mv(str,path,0); } }
-if(f.misc&FM_EXTDESC)
-	putextdesc(f.dir,f.datoffset,ext);
-}
-
-/****************************************************************************/
-/* Batch flagging prompt for download, extended info, and archive viewing	*/
-/* Returns -1 if 'Q' or Ctrl-C, 0 if skip, 1 if [Enter], 2 otherwise        */
-/* or 3, backwards. 														*/
-/****************************************************************************/
-char batchflagprompt(int dirnum, file_t bf[26], char total, long totalfiles)
-{
-	char ch,c,d,str[256],fname[128],*p,remcdt,remfile;
-	int i,j,u,ml,md,udir,ulib;
-	long cdt;
-	file_t f;
-
-for(ulib=0;ulib<usrlibs;ulib++)
-	if(usrlib[ulib]==dir[dirnum]->lib)
-		break;
-for(udir=0;udir<usrdirs[ulib];udir++)
-	if(usrdir[ulib][udir]==dirnum)
-		break;
-
-CRLF;
-while(online) {
-	bprintf(text[BatchFlagPrompt]
-		,ulib+1
-		,lib[dir[dirnum]->lib]->sname
-		,udir+1
-		,dir[dirnum]->sname
-		,totalfiles);
-	ch=getkey(K_UPPER);
-	clearline();
-	if(ch=='?') {
-		menu("BATFLAG");
-		if(lncntr)
-			pause();
-		return(2); }
-	if(ch=='Q' || sys_status&SS_ABORT)
-		return(-1);
-	if(ch=='S')
-		return(0);
-	if(ch=='P')
-		return(3);
-	if(ch=='B') {    /* Flag for batch download */
-		if(useron.rest&FLAG('D')) {
-			bputs(text[R_Download]);
-			return(2); }
-		if(total==1) {
-			f.dir=dirnum;
-			strcpy(f.name,bf[0].name);
-			f.datoffset=bf[0].datoffset;
-			f.size=0;
-			getfiledat(&f);
-			addtobatdl(f);
-			CRLF;
-			return(2); }
-		bputs(text[BatchDlFlags]);
-		d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF);
-		lncntr=0;
-		if(sys_status&SS_ABORT)
-			return(-1);
-		if(d) { 	/* d is string length */
-			CRLF;
-			lncntr=0;
-			for(c=0;c<d;c++) {
-				if(batdn_total>=max_batdn) {
-					bprintf(text[BatchDlQueueIsFull],str+c);
-					break; }
-				if(strchr(str+c,'.')) {     /* filename or spec given */
-					f.dir=dirnum;
-					p=strchr(str+c,SP);
-					if(!p) p=strchr(str+c,',');
-					if(p) *p=0;
-					for(i=0;i<total;i++) {
-						if(batdn_total>=max_batdn) {
-							bprintf(text[BatchDlQueueIsFull],str+c);
-							break; }
-						padfname(str+c,tmp);
-						if(filematch(bf[i].name,tmp)) {
-							strcpy(f.name,bf[i].name);
-							f.datoffset=bf[i].datoffset;
-							f.size=0;
-							getfiledat(&f);
-							addtobatdl(f); } } }
-				if(strchr(str+c,'.'))
-					c+=strlen(str+c);
-				else if(str[c]<'A'+total && str[c]>='A') {
-					f.dir=dirnum;
-					strcpy(f.name,bf[str[c]-'A'].name);
-					f.datoffset=bf[str[c]-'A'].datoffset;
-					f.size=0;
-					getfiledat(&f);
-					addtobatdl(f); } }
-			CRLF;
-			return(2); }
-		clearline();
-		continue; }
-
-	if(ch=='E' || ch=='V') {    /* Extended Info */
-		if(total==1) {
-			f.dir=dirnum;
-			strcpy(f.name,bf[0].name);
-			f.datoffset=bf[0].datoffset;
-			f.dateuled=bf[0].dateuled;
-			f.datedled=bf[0].datedled;
-			f.size=0;
-            getfiledat(&f);
-			if(!viewfile(f,ch=='E'))
-				return(-1);
-			return(2); }
-		bputs(text[BatchDlFlags]);
-		d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF);
-		lncntr=0;
-		if(sys_status&SS_ABORT)
-			return(-1);
-		if(d) { 	/* d is string length */
-			CRLF;
-			lncntr=0;
-			for(c=0;c<d;c++) {
-				if(strchr(str+c,'.')) {     /* filename or spec given */
-					f.dir=dirnum;
-					p=strchr(str+c,SP);
-					if(!p) p=strchr(str+c,',');
-					if(p) *p=0;
-					for(i=0;i<total;i++) {
-						padfname(str+c,tmp);
-						if(filematch(bf[i].name,tmp)) {
-							strcpy(f.name,bf[i].name);
-							f.datoffset=bf[i].datoffset;
-							f.dateuled=bf[i].dateuled;
-							f.datedled=bf[i].datedled;
-							f.size=0;
-							getfiledat(&f);
-							if(!viewfile(f,ch=='E'))
-								return(-1); } } }
-				if(strchr(str+c,'.'))
-					c+=strlen(str+c);
-				else if(str[c]<'A'+total && str[c]>='A') {
-					f.dir=dirnum;
-					strcpy(f.name,bf[str[c]-'A'].name);
-					f.datoffset=bf[str[c]-'A'].datoffset;
-					f.dateuled=bf[str[c]-'A'].dateuled;
-					f.datedled=bf[str[c]-'A'].datedled;
-					f.size=0;
-					getfiledat(&f);
-					if(!viewfile(f,ch=='E'))
-						return(-1); } }
-			return(2); }
-		clearline();
-		continue; }
-
-	if((ch=='D' || ch=='M')     /* Delete or Move */
-		&& !(useron.rest&FLAG('R'))
-		&& (dir_op(dirnum) || useron.exempt&FLAG('R'))) {
-		if(total==1) {
-			strcpy(str,"A");
-			d=1; }
-		else {
-			bputs(text[BatchDlFlags]);
-			d=getstr(str,26,K_UPPER|K_LOWPRIO|K_NOCRLF); }
-		lncntr=0;
-		if(sys_status&SS_ABORT)
-			return(-1);
-		if(d) { 	/* d is string length */
-			CRLF;
-			if(ch=='D') {
-				if(noyes(text[AreYouSureQ]))
-					return(2);
-				remcdt=remfile=1;
-				if(dir_op(dirnum)) {
-					remcdt=!noyes(text[RemoveCreditsQ]);
-					remfile=!noyes(text[DeleteFileQ]); } }
-			else if(ch=='M') {
-				CRLF;
-				for(i=0;i<usrlibs;i++)
-                    bprintf(text[MoveToLibLstFmt],i+1,lib[usrlib[i]]->lname);
-                SYNC;
-                bprintf(text[MoveToLibPrompt],dir[dirnum]->lib+1);
-				if((ml=getnum(usrlibs))==-1)
-					return(2);
-				if(!ml)
-					ml=dir[dirnum]->lib;
-                else
-					ml--;
-                CRLF;
-				for(j=0;j<usrdirs[ml];j++)
-                    bprintf(text[MoveToDirLstFmt]
-						,j+1,dir[usrdir[ml][j]]->lname);
-                SYNC;
-				bprintf(text[MoveToDirPrompt],usrdirs[ml]);
-				if((md=getnum(usrdirs[ml]))==-1)
-					return(2);
-				if(!md)
-					md=usrdirs[ml]-1;
-				else md--;
-				CRLF; }
-			lncntr=0;
-			for(c=0;c<d;c++) {
-				if(strchr(str+c,'.')) {     /* filename or spec given */
-					f.dir=dirnum;
-					p=strchr(str+c,SP);
-					if(!p) p=strchr(str+c,',');
-					if(p) *p=0;
-					for(i=0;i<total;i++) {
-						padfname(str+c,tmp);
-						if(filematch(bf[i].name,tmp)) {
-							strcpy(f.name,bf[i].name);
-							unpadfname(f.name,fname);
-							f.datoffset=bf[i].datoffset;
-							f.dateuled=bf[i].dateuled;
-							f.datedled=bf[i].datedled;
-							f.size=0;
-							getfiledat(&f);
-							if(f.opencount) {
-								bprintf(text[FileIsOpen]
-									,f.opencount,f.opencount>1 ? "s":nulstr);
-								continue; }
-							if(ch=='D') {
-								removefiledat(f);
-								if(remfile) {
-									sprintf(tmp,"%s%s",dir[f.dir]->path,fname);
-									remove(tmp); }
-								if(remcdt)
-									removefcdt(f); }
-							else if(ch=='M')
-								movefile(f,usrdir[ml][md]); } } }
-				if(strchr(str+c,'.'))
-					c+=strlen(str+c);
-				else if(str[c]<'A'+total && str[c]>='A') {
-					f.dir=dirnum;
-					strcpy(f.name,bf[str[c]-'A'].name);
-					unpadfname(f.name,fname);
-					f.datoffset=bf[str[c]-'A'].datoffset;
-					f.dateuled=bf[str[c]-'A'].dateuled;
-					f.datedled=bf[str[c]-'A'].datedled;
-					f.size=0;
-					getfiledat(&f);
-					if(f.opencount) {
-						bprintf(text[FileIsOpen]
-							,f.opencount,f.opencount>1 ? "s":nulstr);
-						continue; }
-					if(ch=='D') {
-						removefiledat(f);
-						if(remfile) {
-							sprintf(tmp,"%s%s",dir[f.dir]->path,fname);
-							remove(tmp); }
-						if(remcdt)
-							removefcdt(f); }
-					else if(ch=='M')
-						movefile(f,usrdir[ml][md]); } }
-			return(2); }
-		clearline();
-        continue; }
-
-	return(1); }
-
-return(-1);
-}
-
-/*****************************************************************************/
-/* List files in directory 'dir' that match 'filespec'. Filespec must be 	 */
-/* padded. ex: FILE*   .EXT, not FILE*.EXT. 'mode' determines other critiria */
-/* the files must meet before they'll be listed. 'mode' bit FL_NOHDR doesn't */
-/* list the directory header.                                                */
-/* Returns -1 if the listing was aborted, otherwise total files listed		 */
-/*****************************************************************************/
-int listfiles(uint dirnum, char *filespec, int tofile, char mode)
-{
-	uchar str[256],hdr[256],cmd[129],c,d,letter='A',*buf,*p,ext[513];
-	uchar HUGE16 *datbuf,HUGE16 *ixbbuf,flagprompt=0;
-	int i,j,file,found=0,lastbat=0,disp;
-	ulong l,m=0,n,length,anchor,next,datbuflen;
-	file_t f,bf[26];	/* bf is batch flagged files */
-
-if(mode&FL_ULTIME) {
-	last_ns_time=now;
-    sprintf(str,"%s%s.DAB",dir[dirnum]->data_dir,dir[dirnum]->code);
-	if((file=nopen(str,O_RDONLY))!=-1) {
-		read(file,&l,4);
-		close(file);
-		if(ns_time>l)
-			return(0); } }
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1)
-	return(0);
-l=filelength(file);
-if(!l) {
-	close(file);
-	return(0); }
-if((ixbbuf=(char *)MALLOC(l))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,l);
-	return(0); }
-if(lread(file,ixbbuf,l)!=l) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str,l);
-	FREE((char *)ixbbuf);
-	return(0); }
-close(file);
-sprintf(str,"%s%s.DAT",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	FREE((char *)ixbbuf);
-	return(0); }
-datbuflen=filelength(file);
-if((datbuf=MALLOC(datbuflen))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,datbuflen);
-	FREE((char *)ixbbuf);
-	return(0); }
-if(lread(file,datbuf,datbuflen)!=datbuflen) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str,datbuflen);
-	FREE((char *)datbuf);
-	FREE((char *)ixbbuf);
-	return(0); }
-close(file);
-if(!tofile) {
-	action=NODE_LFIL;
-	getnodedat(node_num,&thisnode,0);
-	if(thisnode.action!=NODE_LFIL) {	/* was a sync */
-		getnodedat(node_num,&thisnode,1);
-		thisnode.action=NODE_LFIL;
-		putnodedat(node_num,thisnode); } }
-while(online && found<MAX_FILES) {
-	if(found<0)
-		found=0;
-	if(m>=l || flagprompt) {		  /* End of list */
-		if(useron.misc&BATCHFLAG && !tofile && found && found!=lastbat
-			&& !(mode&(FL_EXFIND|FL_VIEW))) {
-			flagprompt=0;
-			lncntr=0;
-			if((i=batchflagprompt(dirnum,bf,letter-'A',l/F_IXBSIZE))==2) {
-				m=anchor;
-				found-=letter-'A';
-				letter='A'; }
-			else if(i==3) {
-				if((long)anchor-((letter-'A')*F_IXBSIZE)<0) {
-					m=0;
-					found=0; }
-				else {
-					m=anchor-((letter-'A')*F_IXBSIZE);
-					found-=letter-'A'; }
-				letter='A'; }
-			else if(i==-1) {
-				FREE((char *)ixbbuf);
-				FREE((char *)datbuf);
-				return(-1); }
-			else
-				break;
-			getnodedat(node_num,&thisnode,0);
-			nodesync(); }
-		else
-			break; }
-
-	if(letter>'Z')
-		letter='A';
-	if(letter=='A')
-		anchor=m;
-
-	if(msgabort()) {		 /* used to be !tofile && msgabort() */
-		FREE((char *)ixbbuf);
-		FREE((char *)datbuf);
-		return(-1); }
-	for(j=0;j<12 && m<l;j++)
-		if(j==8)
-			str[j]='.';
-		else
-			str[j]=ixbbuf[m++];		/* Turns FILENAMEEXT into FILENAME.EXT */
-	str[j]=0;
-	if(!(mode&(FL_FINDDESC|FL_EXFIND)) && filespec[0]
-		&& !filematch(str,filespec)) {
-		m+=11;
-		continue; }
-	n=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
-	if(n>=datbuflen) {	/* out of bounds */
-		m+=11;
-		continue; }
-	if(mode&(FL_FINDDESC|FL_EXFIND)) {
-		getrec((char *)&datbuf[n],F_DESC,LEN_FDESC,tmp);
-		strupr(tmp);
-		p=strstr(tmp,filespec);
-		if(!(mode&FL_EXFIND) && p==NULL) {
-			m+=11;
-			continue; }
-		getrec((char *)&datbuf[n],F_MISC,1,tmp);
-		j=tmp[0];  /* misc bits */
-		if(j) j-=SP;
-		if(mode&FL_EXFIND && j&FM_EXTDESC) { /* search extended description */
-			getextdesc(dirnum,n,ext);
-			strupr(ext);
-			if(!strstr(ext,filespec) && !p) {	/* not in description or */
-				m+=11;						 /* extended description */
-				continue; } }
-		else if(!p) {			 /* no extended description and not in desc */
-			m+=11;
-			continue; } }
-	if(mode&FL_ULTIME) {
-		if(ns_time>(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)|((long)ixbbuf[m+5]<<16)
-			|((long)ixbbuf[m+6]<<24))) {
-			m+=11;
-			continue; } }
-	if(useron.misc&BATCHFLAG && letter=='A' && found && !tofile
-		&& !(mode&(FL_EXFIND|FL_VIEW))
-		&& (!mode || !(useron.misc&EXPERT)))
-        bputs(text[FileListBatchCommands]);
-	m+=11;
-	if(!found && !(mode&(FL_EXFIND|FL_VIEW))) {
-		for(i=0;i<usrlibs;i++)
-			if(usrlib[i]==dir[dirnum]->lib)
-				break;
-		for(j=0;j<usrdirs[i];j++)
-			if(usrdir[i][j]==dirnum)
-				break;						/* big header */
-		if((!mode || !(useron.misc&EXPERT)) && !tofile && (!filespec[0]
-			|| (strchr(filespec,'*') || strchr(filespec,'?')))) {
-			sprintf(hdr,"%s%s.HDR",dir[dirnum]->data_dir,dir[dirnum]->code);
-			if(fexist(hdr))
-				printfile(hdr,0);	/* Use DATA\DIRS\<CODE>.HDR */
-			else {
-				if(useron.misc&BATCHFLAG)
-					bputs(text[FileListBatchCommands]);
-				else {
-					CLS;
-					d=strlen(lib[usrlib[i]]->lname)>strlen(dir[dirnum]->lname) ?
-						strlen(lib[usrlib[i]]->lname)+17
-						: strlen(dir[dirnum]->lname)+17;
-					if(i>8 || j>8) d++;
-					attr(color[clr_filelsthdrbox]);
-					bputs("��");            /* use to start with \r\n */
-					for(c=0;c<d;c++)
-						outchar('�');
-					bputs("�\r\n� ");
-					sprintf(hdr,text[BoxHdrLib],i+1,lib[usrlib[i]]->lname);
-					bputs(hdr);
-					for(c=bstrlen(hdr);c<d;c++)
-						outchar(SP);
-					bputs("�\r\n� ");
-					sprintf(hdr,text[BoxHdrDir],j+1,dir[dirnum]->lname);
-					bputs(hdr);
-					for(c=bstrlen(hdr);c<d;c++)
-						outchar(SP);
-					bputs("�\r\n� ");
-					sprintf(hdr,text[BoxHdrFiles],l/F_IXBSIZE);
-					bputs(hdr);
-					for(c=bstrlen(hdr);c<d;c++)
-						outchar(SP);
-					bputs("�\r\n��");
-					for(c=0;c<d;c++)
-						outchar('�');
-					bputs("�\r\n"); } } }
-		else {					/* short header */
-			if(tofile) {
-				sprintf(hdr,"(%u) %s ",i+1,lib[usrlib[i]]->sname);
-				write(tofile,crlf,2);
-				write(tofile,hdr,strlen(hdr)); }
-			else {
-				sprintf(hdr,text[ShortHdrLib],i+1,lib[usrlib[i]]->sname);
-				bputs("\r\1>\r\n");
-				bputs(hdr); }
-			c=bstrlen(hdr);
-			if(tofile) {
-				sprintf(hdr,"(%u) %s",j+1,dir[dirnum]->lname);
-				write(tofile,hdr,strlen(hdr)); }
-			else {
-				sprintf(hdr,text[ShortHdrDir],j+1,dir[dirnum]->lname);
-				bputs(hdr); }
-			c+=bstrlen(hdr);
-			if(tofile) {
-				write(tofile,crlf,2);
-				sprintf(hdr,"%*s",c,nulstr);
-				strset(hdr,'�');
-				strcat(hdr,crlf);
-				write(tofile,hdr,strlen(hdr)); }
-			else {
-				CRLF;
-				attr(color[clr_filelstline]);
-				while(c--)
-					outchar('�');
-				CRLF; } } }
-	next=m;
-	disp=1;
-	if(mode&(FL_EXFIND|FL_VIEW)) {
-		f.dir=dirnum;
-		strcpy(f.name,str);
-		m-=11;
-		f.datoffset=n;
-		f.dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
-			|((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
-		f.datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
-			|((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24);
-		m+=11;
-		f.size=0;
-		getfiledat(&f);
-		if(!found)
-			bputs("\r\1>");
-		if(mode&FL_EXFIND) {
-			if(!viewfile(f,1)) {
-				FREE((char *)ixbbuf);
-				FREE((char *)datbuf);
-				return(-1); } }
-		else {
-			if(!viewfile(f,0)) {
-				FREE((char *)ixbbuf);
-				FREE((char *)datbuf);
-				return(-1); } } }
-
-	else if(tofile)
-		listfiletofile(str,&datbuf[n],dirnum,tofile);
-	else if(mode&FL_FINDDESC)
-		disp=listfile(str,&datbuf[n],dirnum,filespec,letter,n);
-	else
-		disp=listfile(str,&datbuf[n],dirnum,nulstr,letter,n);
-	if(!disp && letter>'A') {
-		next=m-F_IXBSIZE;
-		letter--; }
-	else {
-		disp=1;
-		found++; }
-	if(sys_status&SS_ABORT) {
-		FREE((char *)ixbbuf);
-		FREE((char *)datbuf);
-		return(-1); }
-	if(mode&(FL_EXFIND|FL_VIEW))
-		continue;
-	if(useron.misc&BATCHFLAG && !tofile) {
-		if(disp) {
-			strcpy(bf[letter-'A'].name,str);
-			m-=11;
-			bf[letter-'A'].datoffset=n;
-			bf[letter-'A'].dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
-				|((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
-			bf[letter-'A'].datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
-				|((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24); }
-        m+=11;
-		if(flagprompt || letter=='Z' || !disp ||
-			(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?')
-			&& !(mode&FL_FINDDESC))
-			|| (useron.misc&BATCHFLAG && !tofile && lncntr>=rows-2)
-			) {
-			flagprompt=0;
-			lncntr=0;
-			lastbat=found;
-			if((i=batchflagprompt(dirnum,bf,letter-'A'+1,l/F_IXBSIZE))<1) {
-				FREE((char *)ixbbuf);
-				FREE((char *)datbuf);
-				if(i==-1)
-					return(-1);
-				else
-					return(found); }
-			if(i==2) {
-				next=anchor;
-				found-=(letter-'A')+1; }
-			else if(i==3) {
-				if((long)anchor-((letter-'A'+1)*F_IXBSIZE)<0) {
-					next=0;
-					found=0; }
-				else {
-					next=anchor-((letter-'A'+1)*F_IXBSIZE);
-					found-=letter-'A'+1; } }
-			getnodedat(node_num,&thisnode,0);
-			nodesync();
-			letter='A';	}
-		else letter++; }
-	if(useron.misc&BATCHFLAG && !tofile
-		&& lncntr>=rows-2) {
-		lncntr=0;		/* defeat pause() */
-		flagprompt=1; }
-	m=next;
-	if(mode&FL_FINDDESC) continue;
-	if(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?') && m)
-		break; }
-
-FREE((char *)ixbbuf);
-FREE((char *)datbuf);
-return(found);
-}
-
-int cntlines(char *str)
-{
-	int i,lc,last;
-
-for(i=lc=last=0;str[i];i++)
-	if(str[i]==LF || i-last>LEN_FDESC) {
-		lc++;
-		last=i; }
-return(lc);
-}
-
-/****************************************************************************/
-/* Prints one file's information on a single line                           */
-/* Return 1 if displayed, 0 otherwise										*/
-/****************************************************************************/
-int listfile(char *fname, char HUGE16 *buf, uint dirnum
-	, char *search, char letter, ulong datoffset)
-{
-	char str[256],ext[513]="",*ptr,*cr,*lf,exist=1;
-    uchar alt;
-    int i,j;
-    ulong cdt;
-
-if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC && useron.misc&EXTDESC) {
-	getextdesc(dirnum,datoffset,ext);
-	if(useron.misc&BATCHFLAG && lncntr+cntlines(ext)>=rows-2 && letter!='A')
-		return(0); }
-attr(color[clr_filename]);
-bputs(fname);
-if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC) {
-	if(!(useron.misc&EXTDESC))
-		outchar('+');
-	else
-		outchar(SP); }
-else
-    outchar(SP);
-if(useron.misc&BATCHFLAG) {
-    attr(color[clr_filedesc]);
-    bprintf("%c",letter); }
-getrec((char *)buf,F_ALTPATH,2,str);
-alt=(uchar)ahtoul(str);
-sprintf(str,"%s%s",alt>0 && alt<=altpaths ? altpath[alt-1]:dir[dirnum]->path
-    ,unpadfname(fname,tmp));
-if(dir[dirnum]->misc&DIR_FCHK && !fexist(str)) {
-    exist=0;
-    attr(color[clr_err]); }
-else
-    attr(color[clr_filecdt]);
-getrec((char *)buf,F_CDT,LEN_FCDT,str);
-cdt=atol(str);
-if(useron.misc&BATCHFLAG) {
-    if(!cdt) {
-        attr(curatr^(HIGH|BLINK));
-        bputs("  FREE"); }
-    else {
-        if(cdt<1024)    /* 1k is smallest size */
-            cdt=1024;
-		bprintf("%5luk",cdt/1024L); } }
-else {
-    if(!cdt) {  /* FREE file */
-        attr(curatr^(HIGH|BLINK));
-        bputs("   FREE"); }
-	else if(cdt>9999999L)
-		bprintf("%6luk",cdt/1024L);
-	else
-        bprintf("%7lu",cdt); }
-if(exist)
-    outchar(SP);
-else
-    outchar('-');
-getrec((char *)buf,F_DESC,LEN_FDESC,str);
-attr(color[clr_filedesc]);
-if(!ext[0]) {
-	if(search[0]) { /* high-light string in string */
-		strcpy(tmp,str);
-		strupr(tmp);
-		ptr=strstr(tmp,search);
-		i=strlen(search);
-		j=ptr-tmp;
-		bprintf("%.*s",j,str);
-		attr(color[clr_filedesc]^HIGH);
-		bprintf("%.*s",i,str+j);
-		attr(color[clr_filedesc]);
-		bprintf("%.*s",strlen(str)-(j+i),str+j+i); }
-	else
-		bputs(str);
-	CRLF; }
-ptr=ext;
-while(*ptr && ptr<ext+512 && !msgabort()) {
-	cr=strchr(ptr,CR);
-	lf=strchr(ptr,LF);
-	if(lf && (lf<cr || !cr)) cr=lf;
-	if(cr>ptr+LEN_FDESC)
-		cr=ptr+LEN_FDESC;
-	else if(cr)
-		*cr=0;
-//	  bprintf("%.*s\r\n",LEN_FDESC,ptr);
-	sprintf(str,"%.*s\r\n",LEN_FDESC,ptr);
-	putmsg(str,P_NOATCODES|P_SAVEATR);
-	if(!cr) {
-		if(strlen(ptr)>LEN_FDESC)
-			cr=ptr+LEN_FDESC;
-		else
-			break; }
-	if(!(*(cr+1)) || !(*(cr+2)))
-		break;
-	bprintf("%21s",nulstr);
-	ptr=cr;
-	if(!(*ptr)) ptr++;
-	while(*ptr==LF || *ptr==CR) ptr++; }
-return(1);
-}
diff --git a/src/sbbs2/login.c b/src/sbbs2/login.c
deleted file mode 100644
index 7a5c2de012ea7ec3059f815c8e65cd6d5384058f..0000000000000000000000000000000000000000
--- a/src/sbbs2/login.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#line 1 "LOGIN.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-extern char qwklogon;
-
-int login(char *str, char *pw)
-{
-	long useron_misc=useron.misc;
-
-useron.number=0;
-if(node_dollars_per_call && noyes(text[AreYouSureQ]))
-	return(LOGIC_FALSE);
-
-if(str[0]=='*') {
-	memmove(str,str+1,strlen(str));
-	qwklogon=1; }
-else
-	qwklogon=0;
-
-if(!(node_misc&NM_NO_NUM) && isdigit(str[0])) {
-	useron.number=atoi(str);
-	getuserdat(&useron);
-	if(useron.number && useron.misc&(DELETED|INACTIVE))
-		useron.number=0; }
-
-if(!useron.number) {
-	useron.number=matchuser(str);
-	if(!useron.number && (uchar)str[0]<0x7f && str[1]
-		&& isalpha(str[0]) && strchr(str,SP) && node_misc&NM_LOGON_R)
-		useron.number=userdatdupe(0,U_NAME,LEN_NAME,str,0);
-	if(useron.number) {
-		getuserdat(&useron);
-		if(useron.number && useron.misc&(DELETED|INACTIVE))
-			useron.number=0; } }
-
-if(!useron.number) {
-	if(node_misc&NM_LOGON_P) {
-        strcpy(useron.alias,str);
-		bputs(pw);
-		console|=CON_R_ECHOX;
-		if(!(sys_misc&SM_ECHO_PW))
-			console|=CON_L_ECHOX;
-		getstr(str,LEN_PASS,K_UPPER|K_LOWPRIO);
-		console&=~(CON_R_ECHOX|CON_L_ECHOX);
-		bputs(text[InvalidLogon]);
-		sprintf(tmp,"(%04u)  %-25s  Password: '%s'"
-			,0,useron.alias,str);
-		logline("+!",tmp); }
-	else {
-		bputs(text[UnknownUser]);
-		sprintf(tmp,"Unknown User '%s'",str);
-		logline("+!",tmp); }
-	useron.misc=useron_misc;
-	return(LOGIC_FALSE); }
-
-if(!online) {
-	useron.number=0;
-	return(LOGIC_FALSE); }
-statline=0;
-statusline();
-if((online==ON_REMOTE || sys_misc&SM_REQ_PW || node_misc&NM_SYSPW)
-	&& (useron.pass[0] || REALSYSOP)
-	&& (!node_dollars_per_call || sys_misc&SM_REQ_PW)) {
-	bputs(pw);
-	console|=CON_R_ECHOX;
-	if(!(sys_misc&SM_ECHO_PW))
-		console|=CON_L_ECHOX;
-	getstr(str,LEN_PASS,K_UPPER|K_LOWPRIO);
-	console&=~(CON_R_ECHOX|CON_L_ECHOX);
-	if(!online) {
-		useron.number=0;
-		return(LOGIC_FALSE); }
-	if(stricmp(useron.pass,str)) {
-		bputs(text[InvalidLogon]);
-		sprintf(tmp,"(%04u)  %-25s  Password: '%s' Attempt: '%s'"
-			,useron.number,useron.alias,useron.pass,str);
-		logline("+!",tmp);
-		useron.number=0;
-		useron.misc=useron_misc;
-		return(LOGIC_FALSE); }
-	if(REALSYSOP && !chksyspass(0)) {
-		bputs(text[InvalidLogon]);
-		useron.number=0;
-		useron.misc=useron_misc;
-		return(LOGIC_FALSE); } }
-
-return(LOGIC_TRUE);
-}
diff --git a/src/sbbs2/logio.c b/src/sbbs2/logio.c
deleted file mode 100644
index 37bb5562a4a230682b8223266af49edb15d42aeb..0000000000000000000000000000000000000000
--- a/src/sbbs2/logio.c
+++ /dev/null
@@ -1,81 +0,0 @@
-#line 1 "LOGIO.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/********************************/
-/* Log file reading and writing */
-/********************************/
-
-#include "sbbs.h"
-
-void logentry(char *code, char *entry)
-{
-	char str[512];
-
-now=time(NULL);
-sprintf(str,"Node %2d  %s\r\n   %s",node_num,timestr(&now),entry);
-logline(code,str);
-}
-
-/****************************************************************************/
-/* Writes 'str' verbatim into node.log 										*/
-/****************************************************************************/
-void log(char *str)
-{
-if(!(sys_status&SS_LOGOPEN) || online==ON_LOCAL) return;
-if(logcol>=78 || (78-logcol)<strlen(str)) {
-	write(logfile,crlf,2);
-	logcol=1; }
-if(logcol==1) {
-	write(logfile,"   ",3);
-	logcol=4; }
-write(logfile,str,strlen(str));
-if(str[strlen(str)-1]==LF)
-	logcol=1;
-else
-	logcol+=strlen(str);
-}
-
-/****************************************************************************/
-/* Writes 'str' on it's own line in node.log								*/
-/****************************************************************************/
-void logline(char *code, char *str)
-{
-	char line[1024];
-
-if(!(sys_status&SS_LOGOPEN) || (online==ON_LOCAL && strcmp(code,"!!"))) return;
-if(logcol!=1)
-	write(logfile,crlf,2);
-sprintf(line,"%-2.2s %s\r\n",code,str);
-write(logfile,line,strlen(line));
-logcol=1;
-}
-
-/****************************************************************************/
-/* Writes a comma then 'ch' to log, tracking column.						*/
-/****************************************************************************/
-void logch(char ch, char comma)
-{
-	char slash='/';
-
-if(!(sys_status&SS_LOGOPEN) || (online==ON_LOCAL)) return;
-if((uchar)ch<SP)	/* Don't log control chars */
-	return;
-if(logcol==1) {
-	logcol=4;
-	write(logfile,"   ",3); }
-else if(logcol>=78) {
-	logcol=4;
-	write(logfile,"\r\n   ",5); }
-if(comma && logcol!=4) {
-	write(logfile,",",1);
-	logcol++; }
-if(ch&0x80) {
-	ch&=0x7f;
-	if(ch<SP)
-		return;
-	write(logfile,&slash,1); }
-write(logfile,&ch,1);
-logcol++;
-}
-
diff --git a/src/sbbs2/logon.c b/src/sbbs2/logon.c
deleted file mode 100644
index 47e6d7afc43c85391d12943d51d6cf7182667750..0000000000000000000000000000000000000000
--- a/src/sbbs2/logon.c
+++ /dev/null
@@ -1,569 +0,0 @@
-#line 1 "LOGON.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************************************/
-/* Functions pertaining to the logging on and off of a user					*/
-/****************************************************************************/
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-extern char qwklogon,onquiet;
-
-/****************************************************************************/
-/* Called once upon each user logging on the board							*/
-/* Returns 1 if user passed logon, 0 if user failed.						*/
-/****************************************************************************/
-char logon()
-{
-	char	str[256],c;
-	int 	file;
-	uint	i,j,k,mailw;
-	ulong	totallogons;
-	node_t	node;
-	FILE	*stream;
-	struct tm *gm;
-
-now=time(NULL);
-gm=localtime(&now);
-if(!useron.number)
-	return(0);
-
-if(useron.rest&FLAG('Q'))
-    qwklogon=1;
-if(SYSOP && ((online==ON_REMOTE && !(sys_misc&SM_R_SYSOP))
-    || (online==ON_LOCAL && !(sys_misc&SM_L_SYSOP))))
-	return(0);
-if(cur_rate<node_minbps && !(useron.exempt&FLAG('M'))) {
-    bprintf(text[MinimumModemSpeed],node_minbps);
-    sprintf(str,"%sTOOSLOW.MSG",text_dir);
-    if(fexist(str))
-        printfile(str,0);
-    sprintf(str,"(%04u)  %-25s  Modem speed: %u<%u"
-        ,useron.number,useron.alias,cur_rate,node_minbps);
-    logline("+!",str);
-	return(0); }
-
-if(useron.rest&FLAG('G')) {     /* Guest account */
-    useron.misc=(new_misc&(~ASK_NSCAN));
-	useron.rows=0;
-	useron.misc&=~(ANSI|RIP|WIP|NO_EXASCII|COLOR);
-    useron.misc|=autoterm;
-    if(!(useron.misc&ANSI) && yesno(text[AnsiTerminalQ]))
-        useron.misc|=ANSI;
-	if(useron.misc&(RIP|WIP)
-		|| (useron.misc&ANSI && yesno(text[ColorTerminalQ])))
-        useron.misc|=COLOR;
-	if(!yesno(text[ExAsciiTerminalQ]))
-		useron.misc|=NO_EXASCII;
-    for(i=0;i<total_xedits;i++)
-        if(!stricmp(xedit[i]->code,new_xedit)
-            && chk_ar(xedit[i]->ar,useron))
-            break;
-    if(i<total_xedits)
-        useron.xedit=i+1;
-    else
-        useron.xedit=0;
-	useron.prot=new_prot;
-    useron.shell=new_shell; }
-
-if(node_dollars_per_call) {
-    adjustuserrec(useron.number,U_CDT,10
-        ,cdt_per_dollar*node_dollars_per_call);
-    bprintf(text[CreditedAccount]
-        ,cdt_per_dollar*node_dollars_per_call);
-    sprintf(str,"%s #%u was billed $%d T: %u seconds"
-        ,useron.alias,useron.number
-        ,node_dollars_per_call,(uint)now-answertime);
-    logline("$+",str);
-    hangup();
-	return(0); }
-
-//lclini(node_scrnlen-1);
-
-if(!chk_ar(node_ar,useron)) {
-    bputs(text[NoNodeAccess]);
-    sprintf(str,"(%04u)  %-25s  Insufficient node access"
-        ,useron.number,useron.alias);
-    logline("+!",str);
-	return(0); }
-
-getnodedat(node_num,&thisnode,1);
-if(thisnode.misc&NODE_LOCK) {
-	putnodedat(node_num,thisnode);	/* must unlock! */
-    if(!SYSOP && !(useron.exempt&FLAG('N'))) {
-        bputs(text[NodeLocked]);
-        sprintf(str,"(%04u)  %-25s  Locked node logon attempt"
-            ,useron.number,useron.alias);
-        logline("+!",str);
-		return(0); }
-    if(yesno(text[RemoveNodeLockQ])) {
-		getnodedat(node_num,&thisnode,1);
-        logline("S-","Removed Node Lock");
-		thisnode.misc&=~NODE_LOCK; }
-	else
-		getnodedat(node_num,&thisnode,1); }
-
-if(onquiet || (useron.exempt&FLAG('Q') && useron.misc&QUIET))
-    thisnode.status=NODE_QUIET;
-else
-    thisnode.status=NODE_INUSE;
-onquiet=0;
-action=thisnode.action=NODE_LOGN;
-if(online==ON_LOCAL)
-    thisnode.connection=0;
-else
-    thisnode.connection=cur_rate;
-thisnode.misc&=~(NODE_ANON|NODE_INTR|NODE_MSGW|NODE_POFF|NODE_AOFF);
-if(useron.chat&CHAT_NOACT)
-    thisnode.misc|=NODE_AOFF;
-if(useron.chat&CHAT_NOPAGE)
-    thisnode.misc|=NODE_POFF;
-thisnode.useron=useron.number;
-putnodedat(node_num,thisnode);
-
-getusrsubs();
-getusrdirs();
-
-if(useron.misc&CURSUB && !(useron.rest&FLAG('G'))) {
-    for(i=0;i<usrgrps;i++) {
-		for(j=0;j<usrsubs[i];j++) {
-			if(!strcmp(sub[usrsub[i][j]]->code,useron.cursub))
-				break; }
-        if(j<usrsubs[i]) {
-            curgrp=i;
-            cursub[i]=j;
-            break; } }
-	for(i=0;i<usrlibs;i++) {
-        for(j=0;j<usrdirs[i];j++)
-			if(!strcmp(dir[usrdir[i][j]]->code,useron.curdir))
-                break;
-        if(j<usrdirs[i]) {
-            curlib=i;
-            curdir[i]=j;
-            break; } } }
-
-
-if(useron.misc&AUTOTERM) {
-    useron.misc&=~(ANSI|RIP|WIP);
-    useron.misc|=autoterm; }
-
-if(!chk_ar(shell[useron.shell]->ar,useron)) {
-    useron.shell=new_shell;
-    if(!chk_ar(shell[useron.shell]->ar,useron)) {
-        for(i=0;i<total_shells;i++)
-            if(chk_ar(shell[i]->ar,useron))
-                break;
-        if(i==total_shells)
-            useron.shell=0; } }
-
-statline=sys_def_stat;
-statusline();
-logon_ml=useron.level;
-logontime=time(NULL);
-starttime=logontime;
-last_ns_time=ns_time=useron.ns_time;
-// ns_time-=(useron.tlast*60); /* file newscan time == last logon time */
-delfiles(temp_dir,"*.*");
-sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,node_num);
-remove(str);            /* remove any pending node messages */
-sprintf(str,"%sMSGS\\N%3.3u.IXB",data_dir,node_num);
-remove(str);			/* remove any pending node message indices */
-
-if(!SYSOP && online==ON_REMOTE) {
-	rioctl(IOCM|ABORT);	/* users can't abort anything */
-	rioctl(IOCS|ABORT); }
-
-CLS;
-if(useron.rows)
-	rows=useron.rows;
-else if(online==ON_LOCAL)
-	rows=node_scrnlen-1;
-unixtodstr(logontime,str);
-if(!strncmp(str,useron.birth,5) && !(useron.rest&FLAG('Q'))) {
-	bputs(text[HappyBirthday]);
-	pause();
-	CLS;
-	user_event(EVENT_BIRTHDAY); }
-unixtodstr(useron.laston,tmp);
-if(strcmp(str,tmp)) {			/* str still equals logon time */
-	useron.ltoday=1;
-	useron.ttoday=useron.etoday=useron.ptoday=useron.textra=0;
-	useron.freecdt=level_freecdtperday[useron.level]; }
-else
-	useron.ltoday++;
-
-gettimeleft();
-sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
-batch_add_list(str);
-if(!qwklogon) { 	 /* QWK Nodes don't go through this */
-
-	if(sys_pwdays
-		&& logontime>(useron.pwmod+((ulong)sys_pwdays*24UL*60UL*60UL))) {
-		bprintf(text[TimeToChangePw],sys_pwdays);
-
-		c=0;
-		while(c<LEN_PASS) { 				/* Create random password */
-			str[c]=random(43)+48;
-			if(isalnum(str[c]))
-				c++; }
-		str[c]=0;
-		bprintf(text[YourPasswordIs],str);
-
-		if(sys_misc&SM_PWEDIT && yesno(text[NewPasswordQ]))
-			while(online) {
-				bputs(text[NewPassword]);
-				getstr(str,LEN_PASS,K_UPPER|K_LINE);
-				truncsp(str);
-				if(chkpass(str,useron))
-					break;
-				CRLF; }
-
-		while(online) {
-			if(sys_misc&SM_PWEDIT) {
-				CRLF;
-				bputs(text[VerifyPassword]); }
-			else
-				bputs(text[NewUserPasswordVerify]);
-			console|=CON_R_ECHOX;
-			if(!(sys_misc&SM_ECHO_PW))
-				console|=CON_L_ECHOX;
-			getstr(tmp,LEN_PASS,K_UPPER);
-			console&=~(CON_R_ECHOX|CON_L_ECHOX);
-			if(strcmp(str,tmp)) {
-				bputs(text[Wrong]);
-				continue; }
-			break; }
-		strcpy(useron.pass,str);
-		useron.pwmod=time(NULL);
-		putuserrec(useron.number,U_PWMOD,8,ultoa(useron.pwmod,str,16));
-		bputs(text[PasswordChanged]);
-		pause(); }
-	if(useron.ltoday>level_callsperday[useron.level]
-		&& !(useron.exempt&FLAG('L'))) {
-		bputs(text[NoMoreLogons]);
-		sprintf(str,"(%04u)  %-25s  Out of logons"
-			,useron.number,useron.alias);
-		logline("+!",str);
-		hangup();
-		return(0); }
-	if(useron.rest&FLAG('L') && useron.ltoday>1) {
-		bputs(text[R_Logons]);
-		sprintf(str,"(%04u)  %-25s  Out of logons"
-			,useron.number,useron.alias);
-		logline("+!",str);
-		hangup();
-		return(0); }
-	if(!useron.name[0] && ((uq&UQ_ALIASES && uq&UQ_REALNAME)
-		|| uq&UQ_COMPANY))
-		while(online) {
-			if(uq&UQ_ALIASES && uq&UQ_REALNAME)
-				bputs(text[EnterYourRealName]);
-			else
-				bputs(text[EnterYourCompany]);
-			getstr(useron.name,LEN_NAME,K_UPRLWR|(uq&UQ_NOEXASC));
-			if(uq&UQ_ALIASES && uq&UQ_REALNAME) {
-				if(trashcan(useron.name,"NAME") || !useron.name[0]
-					|| !strchr(useron.name,SP)
-					|| strchr(useron.name,0xff)
-					|| (uq&UQ_DUPREAL
-						&& userdatdupe(useron.number,U_NAME,LEN_NAME
-						,useron.name,0)))
-					bputs(text[YouCantUseThatName]);
-				else
-					break; }
-			else
-				break; }
-	if(uq&UQ_HANDLE && !useron.handle[0]) {
-		sprintf(useron.handle,"%.*s",LEN_HANDLE,useron.alias);
-		while(online) {
-			bputs(text[EnterYourHandle]);
-			if(!getstr(useron.handle,LEN_HANDLE
-				,K_LINE|K_EDIT|K_AUTODEL|(uq&UQ_NOEXASC))
-				|| strchr(useron.handle,0xff)
-				|| (uq&UQ_DUPHAND
-					&& userdatdupe(useron.number,U_HANDLE,LEN_HANDLE
-					,useron.handle,0))
-				|| trashcan(useron.handle,"NAME"))
-				bputs(text[YouCantUseThatName]);
-			else
-				break; } }
-	if(uq&UQ_LOCATION && !useron.location[0])
-		while(online) {
-			bputs(text[EnterYourCityState]);
-			if(getstr(useron.location,LEN_LOCATION,K_UPRLWR|(uq&UQ_NOEXASC)))
-				break; }
-	if(uq&UQ_ADDRESS && !useron.address[0])
-		while(online) {
-			bputs(text[EnterYourAddress]);
-			if(getstr(useron.address,LEN_ADDRESS,K_UPRLWR|(uq&UQ_NOEXASC)))
-				break; }
-	if(uq&UQ_ADDRESS && !useron.zipcode[0])
-		while(online) {
-			bputs(text[EnterYourZipCode]);
-			if(getstr(useron.zipcode,LEN_ZIPCODE,K_UPPER|(uq&UQ_NOEXASC)))
-				break; }
-	if(uq&UQ_PHONE && !useron.phone[0]) {
-		i=yesno(text[CallingFromNorthAmericaQ]);
-		while(online) {
-			bputs(text[EnterYourPhoneNumber]);
-			if(i) {
-				if(gettmplt(useron.phone,sys_phonefmt
-					,K_LINE|(uq&UQ_NOEXASC))<strlen(sys_phonefmt))
-                     continue; }
-			else {
-				if(getstr(useron.phone,LEN_PHONE
-					,K_UPPER|(uq&UQ_NOEXASC))<5)
-					continue; }
-			if(!trashcan(useron.phone,"PHONE"))
-				break; } }
-	if(uq&UQ_COMP && !useron.comp[0])
-		getcomputer(useron.comp);
-	if(new_sif[0]) {
-		sprintf(str,"%sUSER\\%4.4u.DAT",data_dir,useron.number);
-		if(flength(str)<1L)
-			create_sif_dat(new_sif,str); } }
-if(!online) {
-	sprintf(str,"(%04u)  %-25s  Unsuccessful logon"
-		,useron.number,useron.alias);
-    logline("+!",str);
-	return(0); }
-strcpy(useron.modem,connection);
-useron.logons++;
-putuserdat(useron);
-getmsgptrs();
-sys_status|=SS_USERON;          /* moved from further down */
-
-if(useron.rest&FLAG('Q')) {
-	sprintf(str,"(%04u)  %-25s  QWK Network Connection"
-		,useron.number,useron.alias);
-	logline("++",str);
-	return(1); }
-
-/********************/
-/* SUCCESSFUL LOGON */
-/********************/
-totallogons=logonstats();
-sprintf(str,"(%04u)  %-25s  Logon %lu - %u"
-	,useron.number,useron.alias,totallogons,useron.ltoday);
-logline("++",str);
-
-if(!qwklogon && logon_mod[0])
-	exec_bin(logon_mod,&main_csi);
-
-if(thisnode.status!=NODE_QUIET) {
-    sprintf(str,"%sLOGON.LST",data_dir);
-    if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-        errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_CREAT|O_APPEND);
-        return(0); }
-    sprintf(str,text[LastFewCallersFmt],node_num
-        ,totallogons,useron.alias
-        ,sys_misc&SM_LISTLOC ? useron.location : useron.note
-        ,gm->tm_hour,gm->tm_min
-        ,connection,useron.ltoday);
-    write(file,str,strlen(str));
-    close(file); }
-
-if(sys_logon[0])				/* execute system logon event */
-	external(cmdstr(sys_logon,nulstr,nulstr,NULL),EX_OUTR|EX_OUTL); /* EX_CC */
-
-if(qwklogon)
-    return(1);
-
-sys_status|=SS_PAUSEON;	/* always force pause on during this section */
-main_cmds=xfer_cmds=posts_read=0;
-mailw=getmail(useron.number,0);
-bprintf(text[SiSysName],sys_name);
-bprintf(text[SiNodeNumberName],node_num,node_name);
-bprintf(text[LiUserNumberName],useron.number,useron.alias);
-bprintf(text[LiLogonsToday],useron.ltoday
-	,level_callsperday[useron.level]);
-bprintf(text[LiTimeonToday],useron.ttoday
-	,level_timeperday[useron.level]+useron.min);
-bprintf(text[LiMailWaiting],mailw);
-strcpy(str,text[LiSysopIs]);
-i=kbd_state();		 /* Check scroll lock */
-if(i&16 || (sys_chat_ar[0] && chk_ar(sys_chat_ar,useron)))
-	strcat(str,text[LiSysopAvailable]);
-else
-	strcat(str,text[LiSysopNotAvailable]);
-bprintf("%s\r\n\r\n",str);
-if(sys_status&SS_EVENT)
-	bputs(text[ReducedTime]);
-getnodedat(node_num,&thisnode,1);
-thisnode.misc&=~(NODE_AOFF|NODE_POFF);
-if(useron.chat&CHAT_NOACT)
-    thisnode.misc|=NODE_AOFF;
-if(useron.chat&CHAT_NOPAGE)
-    thisnode.misc|=NODE_POFF;
-putnodedat(node_num,thisnode);
-getsmsg(useron.number); 		/* Moved from further down */
-SYNC;
-c=0;
-for(i=1;i<=sys_nodes;i++)
-	if(i!=node_num) {
-		getnodedat(i,&node,0);
-		if(node.status==NODE_INUSE
-			|| ((node.status==NODE_QUIET || node.errors) && SYSOP)) {
-			if(!c)
-				bputs(text[NodeLstHdr]);
-			printnodedat(i,node);
-			c=1; }
-		if(node.status==NODE_INUSE && i!=node_num && node.useron==useron.number
-			&& !SYSOP && !(useron.exempt&FLAG('G'))) {
-			strcpy(tmp,"On two nodes at the same time");
-			sprintf(str,"(%04u)  %-25s  %s"
-				,useron.number,useron.alias,tmp);
-			logline("+!",str);
-			errorlog(tmp);
-			bputs(text[UserOnTwoNodes]);
-			hangup();
-			return(0); }
-		if(thisnode.status!=NODE_QUIET
-			&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
-			&& !(node.misc&NODE_AOFF) && node.useron!=useron.number) {
-			sprintf(str,text[NodeLoggedOnAtNbps]
-				,node_num
-				,thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias
-				,connection);
-			putnmsg(i,str); } }
-
-if(sys_exp_warn && useron.expire && useron.expire>now /* Warn user of coming */
-	&& (useron.expire-now)/(1440L*60L)<=sys_exp_warn) /* expiration */
-	bprintf(text[AccountWillExpireInNDays],(useron.expire-now)/(1440L*60L));
-
-if(criterrs && SYSOP)
-	bprintf(text[CriticalErrors],criterrs);
-if((i=getuserxfers(0,useron.number,0))!=0) {
-	bprintf(text[UserXferForYou],i,i>1 ? "s" : nulstr); }
-if((i=getuserxfers(useron.number,0,0))!=0) {
-	bprintf(text[UnreceivedUserXfer],i,i>1 ? "s" : nulstr); }
-SYNC;
-sys_status&=~SS_PAUSEON;	/* Turn off the pause override flag */
-if(online==ON_REMOTE)
-	rioctl(IOSM|ABORT);		/* Turn abort ability on */
-if(mailw) {
-	if(yesno(text[ReadYourMailNowQ]))
-		readmail(useron.number,MAIL_YOUR); }
-lastnodemsg=0;
-if(useron.misc&ASK_NSCAN && yesno(text[NScanAllGrpsQ]))
-    scanallsubs(SCAN_NEW);
-if(useron.misc&ASK_SSCAN && yesno(text[SScanAllGrpsQ]))
-    scanallsubs(SCAN_TOYOU);
-return(1);
-}
-
-/****************************************************************************/
-/* Checks the system DSTS.DAB to see if it is a new day, if it is, all the  */
-/* nodes' and the system's CSTS.DAB are added to, and the DSTS.DAB's daily  */
-/* stats are cleared. Also increments the logon values in DSTS.DAB if       */
-/* applicable.                                                              */
-/****************************************************************************/
-ulong logonstats()
-{
-    char str[256];
-    int dsts,csts;
-    uint i;
-    struct date update;
-    time_t update_t;
-    stats_t stats;
-    node_t node;
-
-sprintf(str,"%sDSTS.DAB",ctrl_dir);
-if((dsts=nopen(str,O_RDWR))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-    return(0L); }
-read(dsts,&update_t,4);         /* Last updated         */
-read(dsts,&stats.logons,4);     /* Total number of logons on system */
-close(dsts);
-if(update_t>now+(24L*60L*60L)) /* More than a day in the future? */
-    errormsg(WHERE,ERR_CHK,"Daily stats time stamp",update_t);
-unixtodos(update_t,&update,&curtime);
-unixtodos(now,&date,&curtime);
-if((date.da_day>update.da_day && date.da_mon==update.da_mon)
-    || date.da_mon>update.da_mon || date.da_year>update.da_year) {
-
-    sprintf(str,"New Day - Prev: %s ",timestr(&update_t));
-    logentry("!=",str);
-
-    sys_status|=SS_DAILY;       /* New Day !!! */
-    sprintf(str,"%sLOGON.LST",data_dir);    /* Truncate logon list */
-    if((dsts=nopen(str,O_TRUNC|O_CREAT|O_WRONLY))==-1) {
-        errormsg(WHERE,ERR_OPEN,str,O_TRUNC|O_CREAT|O_WRONLY);
-        return(0L); }
-    close(dsts);
-    for(i=0;i<=sys_nodes;i++) {
-        if(i) {     /* updating a node */
-            getnodedat(i,&node,1);
-            node.misc|=NODE_EVENT;
-            putnodedat(i,node); }
-        sprintf(str,"%sDSTS.DAB",i ? node_path[i-1] : ctrl_dir);
-        if((dsts=nopen(str,O_RDWR))==-1) /* node doesn't have stats yet */
-            continue;
-        sprintf(str,"%sCSTS.DAB",i ? node_path[i-1] : ctrl_dir);
-        if((csts=nopen(str,O_WRONLY|O_APPEND|O_CREAT))==-1) {
-            close(dsts);
-            errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_APPEND|O_CREAT);
-            continue; }
-        lseek(dsts,8L,SEEK_SET);        /* Skip time and logons */
-        write(csts,&now,4);
-        read(dsts,&stats.ltoday,4);
-        write(csts,&stats.ltoday,4);
-        lseek(dsts,4L,SEEK_CUR);        /* Skip total time on */
-        read(dsts,&stats.ttoday,4);
-        write(csts,&stats.ttoday,4);
-        read(dsts,&stats.uls,4);
-        write(csts,&stats.uls,4);
-        read(dsts,&stats.ulb,4);
-        write(csts,&stats.ulb,4);
-        read(dsts,&stats.dls,4);
-        write(csts,&stats.dls,4);
-        read(dsts,&stats.dlb,4);
-        write(csts,&stats.dlb,4);
-        read(dsts,&stats.ptoday,4);
-        write(csts,&stats.ptoday,4);
-        read(dsts,&stats.etoday,4);
-        write(csts,&stats.etoday,4);
-        read(dsts,&stats.ftoday,4);
-        write(csts,&stats.ftoday,4);
-        close(csts);
-        lseek(dsts,0L,SEEK_SET);        /* Go back to beginning */
-        write(dsts,&now,4);             /* Update time stamp  */
-        lseek(dsts,4L,SEEK_CUR);        /* Skip total logons */
-        stats.ltoday=0;
-        write(dsts,&stats.ltoday,4);  /* Logons today to 0 */
-        lseek(dsts,4L,SEEK_CUR);     /* Skip total time on */
-        stats.ttoday=0;              /* Set all other today variables to 0 */
-        write(dsts,&stats.ttoday,4);        /* Time on today to 0 */
-        write(dsts,&stats.ttoday,4);        /* Uploads today to 0 */
-        write(dsts,&stats.ttoday,4);        /* U/L Bytes today    */
-        write(dsts,&stats.ttoday,4);        /* Download today     */
-        write(dsts,&stats.ttoday,4);        /* Download bytes     */
-        write(dsts,&stats.ttoday,4);        /* Posts today        */
-        write(dsts,&stats.ttoday,4);        /* Emails today       */
-        write(dsts,&stats.ttoday,4);        /* Feedback today     */
-        write(dsts,&stats.ttoday,2);        /* New users Today    */
-        close(dsts); } }
-
-if(thisnode.status==NODE_QUIET)       /* Quiet users aren't counted */
-    return(0L);
-
-for(i=0;i<2;i++) {
-    sprintf(str,"%sDSTS.DAB",i ? ctrl_dir : node_dir);
-    if((dsts=nopen(str,O_RDWR))==-1) {
-        errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-        return(0L); }
-    lseek(dsts,4L,SEEK_SET);        /* Skip time stamp */
-    read(dsts,&stats.logons,4);
-    read(dsts,&stats.ltoday,4);
-    stats.logons++;
-    stats.ltoday++;
-    lseek(dsts,4L,SEEK_SET);        /* Rewind back and overwrite */
-    write(dsts,&stats.logons,4);
-    write(dsts,&stats.ltoday,4);
-    close(dsts); }
-return(stats.logons);
-}
-
-
diff --git a/src/sbbs2/logout.c b/src/sbbs2/logout.c
deleted file mode 100644
index e3c2ddf10b32d66a6f09228d2df786fc2dca30be..0000000000000000000000000000000000000000
--- a/src/sbbs2/logout.c
+++ /dev/null
@@ -1,245 +0,0 @@
-#line 1 "LOGOUT.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-/****************************************************************************/
-/* Function that is called after a user hangs up or logs off				*/
-/****************************************************************************/
-void logout()
-{
-	char	str[256];
-	int 	done,i,j;
-	ushort	ttoday;
-	file_t	f;
-	node_t	node;
-	struct	date logondate;
-	struct	time lt;
-	FILE	*stream;
-
-now=time(NULL);
-unixtodos(now,&date,&curtime);
-
-if(!useron.number) {				 /* Not logged in, so do nothing */
-	if(!online) {
-		sprintf(str,"%02d:%02d%c  T:%3u sec\r\n"
-			,curtime.ti_hour>12 ? curtime.ti_hour-12
-			: curtime.ti_hour==0 ? 12 : curtime.ti_hour, curtime.ti_min
-			, curtime.ti_hour>=12 ? 'p' : 'a'
-			,(uint)(now-answertime));
-		logline("@-",str); }
-	return; }
-
-strcpy(lastuseron,useron.alias);	/* for use with WFC status display */
-
-if(useron.rest&FLAG('G')) {        /* Reset guest's msg scan cfg */
-	putuserrec(useron.number,U_NAME,LEN_NAME,nulstr);
-	for(i=0;i<total_subs;i++) {
-		if(sub[i]->misc&SUB_NSDEF)
-			sub[i]->misc|=SUB_NSCAN;
-		else
-			sub[i]->misc&=~SUB_NSCAN;
-		if(sub[i]->misc&SUB_SSDEF)
-			sub[i]->misc|=SUB_SSCAN;
-		else
-			sub[i]->misc&=~SUB_SSCAN; }
-	batdn_total=0; }
-
-if(batdn_total) {
-	sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
-	if((stream=fnopen(&i,str,O_WRONLY|O_TRUNC|O_CREAT))!=NULL) {
-		for(i=0;i<batdn_total;i++)
-			fprintf(stream,"%s\r\n",batdn_name[i]);
-		fclose(stream); } }
-	
-if(sys_status&SS_USERON && thisnode.status!=NODE_QUIET 
-	&& !(useron.rest&FLAG('Q')))
-	for(i=1;i<=sys_nodes;i++)
-		if(i!=node_num) {
-			getnodedat(i,&node,0);
-			if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-				&& !(node.misc&NODE_AOFF) && node.useron!=useron.number) {
-				sprintf(str,text[NodeLoggedOff],node_num
-					,thisnode.misc&NODE_ANON
-					? text[UNKNOWN_USER] : useron.alias);
-				putnmsg(i,str); } }
-
-if(!online) {		/* NOT re-login */
-
-	getnodedat(node_num,&thisnode,1);
-	thisnode.status=NODE_WFC;
-	thisnode.misc&=~(NODE_INTR|NODE_MSGW|NODE_NMSG
-		|NODE_UDAT|NODE_POFF|NODE_AOFF|NODE_EXT);
-	putnodedat(node_num,thisnode);
-
-	if(sys_status&SS_SYSALERT) {
-		mswait(500);
-		if(com_port)
-			dtr(1);
-		mswait(500);
-		offhook();
-		CLS;
-		lputs("\r\n\r\nAlerting Sysop...");
-		while(!lkbrd(1)) {
-			beep(1000,200);
-			nosound();
-			mswait(200); }
-		lkbrd(0); }
-
-	sys_status&=~SS_SYSALERT;
-	if(sys_logout[0])		/* execute system logoff event */
-		external(cmdstr(sys_logout,nulstr,nulstr,NULL),EX_OUTL);	/* EX_CC */
-	}
-
-if(logout_mod[0])
-	exec_bin(logout_mod,&main_csi);
-backout();
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,useron.number);
-if(!flength(str))		/* remove any 0 byte message files */
-	remove(str);
-
-delfiles(temp_dir,"*.*");
-putmsgptrs();
-if(!REALSYSOP)
-	logofflist();
-useron.laston=now;
-
-ttoday=useron.ttoday-useron.textra; 		/* billable time used prev calls */
-if(ttoday>=level_timeperday[useron.level])
-	i=0;
-else
-	i=level_timeperday[useron.level]-ttoday;
-if(i>level_timepercall[useron.level])      /* i=amount of time without min */
-	i=level_timepercall[useron.level];
-j=(now-starttime)/60;			/* j=billable time online in min */
-if(i<0) i=0;
-if(j<0) j=0;
-
-if(useron.min && j>i) {
-    j-=i;                               /* j=time to deduct from min */
-	sprintf(str,"Minute Adjustment: %d",-j);
-	logline(">>",str);
-    if(useron.min>j)
-        useron.min-=j;
-    else
-        useron.min=0L;
-    putuserrec(useron.number,U_MIN,10,ultoa(useron.min,str,10)); }
-
-useron.tlast=(now-logontime)/60;
-useron.timeon+=useron.tlast;
-useron.ttoday+=useron.tlast;
-
-if(timeleft>0 && starttime-logontime>0) 			/* extra time */
-	useron.textra+=(starttime-logontime)/60;
-
-unixtodos(logontime,&logondate,&lt);
-if(logondate.da_day!=date.da_day) { /* date has changed while online */
-    putuserrec(useron.number,U_LTODAY,5,"0");
-	useron.ttoday=0;			/* so zero logons today and time on today */
-	useron.textra=0; }			/* and extra time */
-
-
-
-putuserrec(useron.number,U_NS_TIME,8,ultoa(last_ns_time,str,16));
-putuserrec(useron.number,U_LASTON,8,ultoa(useron.laston,str,16));
-putuserrec(useron.number,U_TIMEON,5,itoa(useron.timeon,str,10));
-putuserrec(useron.number,U_TTODAY,5,itoa(useron.ttoday,str,10));
-putuserrec(useron.number,U_TEXTRA,5,itoa(useron.textra,str,10));
-putuserrec(useron.number,U_TLAST,5,itoa(useron.tlast,str,10));
-
-getusrsubs();
-getusrdirs();
-putuserrec(useron.number,U_CURSUB,8,sub[usrsub[curgrp][cursub[curgrp]]]->code);
-putuserrec(useron.number,U_CURDIR,8,dir[usrdir[curlib][curdir[curlib]]]->code);
-
-sprintf(str,"%02d:%02d%c  ",curtime.ti_hour>12 ? curtime.ti_hour-12
-	: curtime.ti_hour==0 ? 12 : curtime.ti_hour, curtime.ti_min
-	, curtime.ti_hour>=12 ? 'p' : 'a');
-if(sys_status&SS_USERON)
-	sprintf(tmp,"T:%3u   R:%3lu   P:%3lu   E:%3lu   F:%3lu   "
-		"U:%3luk %lu   D:%3luk %lu"
-		,(uint)(now-logontime)/60,posts_read,logon_posts
-		,logon_emails,logon_fbacks,logon_ulb/1024UL,logon_uls
-		,logon_dlb/1024UL,logon_dls);
-else
-	sprintf(tmp,"T:%3u sec",(uint)(now-answertime));
-strcat(str,tmp);
-strcat(str,"\r\n");
-logline("@-",str);
-sys_status&=~SS_USERON;
-answertime=now; // Incase we're relogging on
-}
-
-/****************************************************************************/
-/* Backout of transactions and statuses for this node 						*/
-/****************************************************************************/
-void backout()
-{
-	char str[256],code[128],*buf;
-	int i,file;
-	long length,l;
-	file_t f;
-
-sprintf(str,"%sBACKOUT.DAB",node_dir);
-if(flength(str)<1L) {
-	remove(str);
-	return; }
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length);
-	return; }
-if(read(file,buf,length)!=length) {
-	close(file);
-	FREE(buf);
-	errormsg(WHERE,ERR_READ,str,length);
-	return; }
-close(file);
-for(l=0;l<length;l+=BO_LEN) {
-	switch(buf[l]) {
-		case BO_OPENFILE:	/* file left open */
-			memcpy(code,buf+l+1,8);
-			code[8]=0;
-			for(i=0;i<total_dirs;i++)			/* search by code */
-				if(!stricmp(dir[i]->code,code))
-					break;
-			if(i<total_dirs) {		/* found internal code */
-				f.dir=i;
-				memcpy(&f.datoffset,buf+l+9,4);
-				closefile(f); }
-			break;
-		default:
-			errormsg(WHERE,ERR_CHK,str,buf[l]); } }
-FREE(buf);
-remove(str);	/* always remove the backout file */
-}
-
-/****************************************************************************/
-/* Detailed usage stats for each logon                                      */
-/****************************************************************************/
-void logofflist()
-{
-    char str[256];
-    int file;
-    struct time ontime;
-
-unixtodos(logontime,&date,&ontime);
-sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOL",data_dir,date.da_mon,date.da_day
-    ,TM_YEAR(date.da_year-1900));
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-    return; }
-unixtodos(now,&date,&curtime);
-sprintf(str,"%-*.*s %-2d %-8.8s %2.2d:%2.2d %2.2d:%2.2d %3d%3ld%3ld%3ld%3ld"
-	"%3ld%3ld\r\n",LEN_ALIAS,LEN_ALIAS,useron.alias,node_num,connection
-    ,ontime.ti_hour,ontime.ti_min,curtime.ti_hour,curtime.ti_min
-    ,(int)(now-logontime)/60,posts_read,logon_posts,logon_emails
-    ,logon_fbacks,logon_uls,logon_dls);
-write(file,str,strlen(str));
-close(file);
-}
diff --git a/src/sbbs2/mail.c b/src/sbbs2/mail.c
deleted file mode 100644
index 4a3adcbe41038b3e0908cceefda74a2470487c78..0000000000000000000000000000000000000000
--- a/src/sbbs2/mail.c
+++ /dev/null
@@ -1,899 +0,0 @@
-#line 1 "MAIL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Returns the number of pieces of mail waiting for usernumber              */
-/* If sent is non-zero, it returns the number of mail sent by usernumber    */
-/* If usernumber is 0, it returns all mail on the system                    */
-/****************************************************************************/
-int getmail(int usernumber, char sent)
-{
-    char    str[128];
-    int     i=0;
-    long    l;
-    idxrec_t idx;
-
-smb_stack(&smb,SMB_STACK_PUSH);
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-sprintf(str,"%s.SID",smb.file);
-l=flength(str);
-if(l<sizeof(idxrec_t))
-	return(0);
-if(!usernumber) {
-	smb_stack(&smb,SMB_STACK_POP);
-	return(l/sizeof(idxrec_t)); }	/* Total system e-mail */
-if(smb_open(&smb)) {
-	smb_stack(&smb,SMB_STACK_POP);
-	return(0); }
-while(!feof(smb.sid_fp)) {
-	if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-	if(idx.attr&MSG_DELETE)
-		continue;
-    if((!sent && idx.to==usernumber)
-     || (sent && idx.from==usernumber))
-        i++; }
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-return(i);
-}
-
-/***************************/
-/* Delete file attachments */
-/***************************/
-void delfattach(uint to, char *title)
-{
-    char str[128],str2[128],*tp,*sp,*p;
-    uint i;
-
-strcpy(str,title);
-tp=str;
-while(1) {
-    p=strchr(tp,SP);
-    if(p) *p=0;
-    sp=strrchr(tp,'/');              /* sp is slash pointer */
-    if(!sp) sp=strrchr(tp,'\\');
-    if(sp) tp=sp+1;
-    sprintf(str2,"%sFILE\\%04u.IN\\%s"  /* str2 is path/fname */
-        ,data_dir,to,tp);
-    remove(str2);
-    if(!p)
-        break;
-    tp=p+1; }
-sprintf(str,"%sFILE\\%04u.IN",data_dir,to);
-rmdir(str);                     /* remove the dir if it's empty */
-}
-
-
-/****************************************************************************/
-/* Deletes all mail messages for usernumber that have been marked 'deleted' */
-/* smb_locksmbhdr() should be called prior to this function 				*/
-/****************************************************************************/
-int delmail(uint usernumber, int which)
-{
-	ulong	 i,l,now;
-	idxrec_t HUGE16 *idxbuf;
-	smbmsg_t msg;
-
-now=time(NULL);
-if((i=smb_getstatus(&smb))!=0) {
-	errormsg(WHERE,ERR_READ,smb.file,i);
-	return(2); }
-if(!smb.status.total_msgs)
-	return(0);
-if((idxbuf=(idxrec_t *)LMALLOC(smb.status.total_msgs*sizeof(idxrec_t)))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,smb.file,smb.status.total_msgs*sizeof(idxrec_t));
-	return(-1); }
-if((i=smb_open_da(&smb))!=0) {
-    errormsg(WHERE,ERR_OPEN,smb.file,i);
-	LFREE(idxbuf);
-    return(i); }
-if((i=smb_open_ha(&smb))!=0) {
-    smb_close_da(&smb);
-    errormsg(WHERE,ERR_OPEN,smb.file,i);
-	LFREE(idxbuf);
-    return(i); }
-rewind(smb.sid_fp);
-for(l=0;l<smb.status.total_msgs;) {
-	if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-	if(which==MAIL_ALL && !(msg.idx.attr&MSG_PERMANENT)
-		&& smb.status.max_age && now>msg.idx.time
-		&& (now-msg.idx.time)/(24L*60L*60L)>smb.status.max_age)
-		msg.idx.attr|=MSG_DELETE;
-	if(msg.idx.attr&MSG_DELETE && !(msg.idx.attr&MSG_PERMANENT)
-		&& ((which==MAIL_SENT && usernumber==msg.idx.from)
-		|| (which==MAIL_YOUR && usernumber==msg.idx.to)
-		|| (which==MAIL_ANY
-			&& (usernumber==msg.idx.to || usernumber==msg.idx.from))
-		|| which==MAIL_ALL)) {
-		/* Don't need to lock message because base is locked */
-		if(which==MAIL_ALL && !online)
-			lprintf(" #%lu",msg.idx.number);
-		if((i=smb_getmsghdr(&smb,&msg))!=0)
-			errormsg(WHERE,ERR_READ,smb.file,i);
-		else {
-			if(msg.hdr.attr!=msg.idx.attr) {
-				msg.hdr.attr=msg.idx.attr;
-				if((i=smb_putmsghdr(&smb,&msg))!=0)
-					errormsg(WHERE,ERR_WRITE,smb.file,i); }
-			if((i=smb_freemsg(&smb,&msg))!=0)
-				errormsg(WHERE,ERR_REMOVE,smb.file,i);
-			if(msg.hdr.auxattr&MSG_FILEATTACH)
-				delfattach(msg.idx.to,msg.subj);
-			smb_freemsgmem(&msg); }
-		continue; }
-	idxbuf[l]=msg.idx;
-	l++; }
-rewind(smb.sid_fp);
-chsize(fileno(smb.sid_fp),0);
-for(i=0;i<l;i++)
-	fwrite(&idxbuf[i],sizeof(idxrec_t),1,smb.sid_fp);
-LFREE(idxbuf);
-smb.status.total_msgs=l;
-smb_putstatus(&smb);
-fflush(smb.sid_fp);
-smb_close_ha(&smb);
-smb_close_da(&smb);
-return(0);
-}
-
-
-/***********************************************/
-/* Tell the user that so-and-so read your mail */
-/***********************************************/
-void telluser(smbmsg_t msg)
-{
-	char str[256],*p;
-	uint usernumber,n;
-	node_t node;
-
-if(msg.from_net.type)
-	return;
-if(msg.from_ext)
-	usernumber=atoi(msg.from_ext);
-else {
-	usernumber=matchuser(msg.from);
-	if(!usernumber)
-		return; }
-for(n=1;n<=sys_nodes;n++) { /* Tell user */
-	getnodedat(n,&node,0);
-	if(node.useron==usernumber
-	&& (node.status==NODE_INUSE
-	|| node.status==NODE_QUIET)) {
-		sprintf(str
-			,text[UserReadYourMailNodeMsg]
-			,node_num,useron.alias);
-		putnmsg(n,str);
-		break; } }
-if(n>sys_nodes) {
-	now=time(NULL);
-	sprintf(str,text[UserReadYourMail]
-		,useron.alias,timestr(&now));
-	putsmsg(usernumber,str); }
-}
-
-/****************************************************************************/
-/* Loads mail waiting for user number 'usernumber' into the mail array of   */
-/* of pointers to mail_t (message numbers and attributes)                   */
-/* smb_open(&smb) must be called prior											*/
-/****************************************************************************/
-ulong loadmail(mail_t **mail, uint usernumber, int which, int mode)
-{
-	int 		i;
-	ulong		l=0;
-    idxrec_t    idx;
-
-if((i=smb_locksmbhdr(&smb))!=0) {				/* Be sure noone deletes or */
-	errormsg(WHERE,ERR_LOCK,smb.file,i);		/* adds while we're reading */
-    return(0); }
-(*mail)=NULL;
-rewind(smb.sid_fp);
-while(!feof(smb.sid_fp)) {
-	if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-	if((which==MAIL_SENT && idx.from!=usernumber)
-		|| (which==MAIL_YOUR && idx.to!=usernumber)
-		|| (which==MAIL_ANY && idx.from!=usernumber && idx.to!=usernumber))
-        continue;
-	if(idx.attr&MSG_DELETE) {
-		if(mode&LM_QWK) 				/* Don't included deleted msgs */
-			continue;					/* in QWK packet */
-		if(!(sys_misc&SM_SYSVDELM)) 	/* Noone can view deleted msgs */
-			continue;					
-		if(!SYSOP						/* not sysop */
-			&& !(sys_misc&SM_USRVDELM)) /* users can't view deleted msgs */
-			continue; }
-	if(mode&LM_UNREAD && idx.attr&MSG_READ)
-		continue;
-	if(((*mail)=(mail_t *)REALLOC((*mail),sizeof(mail_t)*(l+1)))
-        ==NULL) {
-		smb_unlocksmbhdr(&smb);
-		errormsg(WHERE,ERR_ALLOC,smb.file,sizeof(mail_t)*(l+1));
-        return(0); }
-	(*mail)[l].offset=idx.offset;
-	(*mail)[l].number=idx.number;
-	(*mail)[l].to=idx.to;
-	(*mail)[l].from=idx.from;
-	(*mail)[l].subj=idx.subj;
-	(*mail)[l].time=idx.time;
-	(*mail)[l].attr=idx.attr;
-	l++; }
-smb_unlocksmbhdr(&smb);
-return(l);
-}
-
-/************************************************************************/
-/* Deletes all mail waiting for user number 'usernumber'                */
-/************************************************************************/
-void delallmail(uint usernumber)
-{
-	int 	i;
-	ulong	l,msgs,deleted=0;
-	mail_t	*mail;
-	smbmsg_t msg;
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	smb_stack(&smb,SMB_STACK_POP);
-	return; }
-
-msgs=loadmail(&mail,usernumber,MAIL_ANY,0);
-if(!msgs) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	return; }
-if((i=smb_locksmbhdr(&smb))!=0) {			/* Lock the base, so nobody */
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	FREE(mail);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);	/* messes with the index */
-	return; }
-for(l=0;l<msgs;l++) {
-	msg.idx.offset=0;						/* search by number */
-	if(loadmsg(&msg,mail[l].number)) {	   /* message still there */
-		msg.hdr.attr|=MSG_DELETE;
-		msg.hdr.attr&=~MSG_PERMANENT;
-		msg.idx.attr=msg.hdr.attr;
-		if((i=smb_putmsg(&smb,&msg))!=0)
-			errormsg(WHERE,ERR_WRITE,smb.file,i);
-		else
-			deleted++;
-		smb_freemsgmem(&msg);
-		smb_unlockmsghdr(&smb,&msg); } }
-
-if(msgs)
-	FREE(mail);
-if(deleted && sys_misc&SM_DELEMAIL)
-	delmail(usernumber,MAIL_ANY);
-smb_unlocksmbhdr(&smb);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-}
-
-/****************************************************************************/
-/* Reads mail waiting for usernumber.                                       */
-/****************************************************************************/
-void readmail(uint usernumber, int which)
-{
-	char	str[256],str2[256],str3[256],done=0,domsg=1
-			,*buf,*p,*tp,*sp,ch;
-	int 	file,msgs,curmsg,i,j,k,n,m,mismatches=0,act;
-    long    length,l;
-	ulong	last;
-	file_t	fd;
-	mail_t	*mail;
-	smbmsg_t msg;
-
-msg.total_hfields=0;			/* init to NULL, cause not allocated yet */
-
-fd.dir=total_dirs+1;			/* temp dir for file attachments */
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-
-msgs=loadmail(&mail,usernumber,which,0);
-if(!msgs) {
-	if(which==MAIL_SENT)
-		bputs(text[NoMailSent]);
-	else if(which==MAIL_ALL)
-		bputs(text[NoMailOnSystem]);
-	else
-		bputs(text[NoMailWaiting]);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-    return; }
-
-last=smb.status.last_msg;
-
-if(which==MAIL_SENT)
-	act=NODE_RSML;
-else if(which==MAIL_ALL)
-	act=NODE_SYSP;
-else
-	act=NODE_RMAL;
-action=act;
-if(msgs>1 && which!=MAIL_ALL) {
-	if(which==MAIL_SENT)
-		bputs(text[MailSentLstHdr]);
-	else
-		bputs(text[MailWaitingLstHdr]);
-
-	for(curmsg=0;curmsg<msgs && !msgabort();curmsg++) {
-		if(msg.total_hfields)
-			smb_freemsgmem(&msg);
-		msg.total_hfields=0;
-		msg.idx.offset=mail[curmsg].offset;
-		if(!loadmsg(&msg,mail[curmsg].number))
-			continue;
-		smb_unlockmsghdr(&smb,&msg);
-		bprintf(text[MailWaitingLstFmt],curmsg+1
-			,which==MAIL_SENT ? msg.to
-			: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous]
-			: msg.from
-			,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_READ ? ' '
-				: msg.from_net.type || msg.to_net.type ? 'N':'*'
-			,msg.subj);
-		smb_freemsgmem(&msg);
-		msg.total_hfields=0; }
-
-	ASYNC;
-	if(!(sys_status&SS_ABORT)) {
-		bprintf(text[StartWithN],1L);
-		if((curmsg=getnum(msgs))>0)
-			curmsg--;
-		else if(curmsg==-1) {
-			FREE(mail);
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-			return; } }
-	sys_status&=~SS_ABORT; }
-else {
-	curmsg=0;
-	if(which==MAIL_ALL)
-		domsg=0; }
-if(which==MAIL_SENT)
-	logline("E","Read sent mail");
-else if(which==MAIL_ALL)
-	logline("S+","Read all mail");
-else
-	logline("E","Read mail");
-if(useron.misc&RIP) {
-	strcpy(str,which==MAIL_YOUR ? "MAILREAD" : which==MAIL_ALL ?
-		"ALLMAIL" : "SENTMAIL");
-	menu(str); }
-while(online && !done) {
-	action=act;
-
-	if(msg.total_hfields)
-		smb_freemsgmem(&msg);
-	msg.total_hfields=0;
-
-	msg.idx.offset=mail[curmsg].offset;
-	msg.idx.number=mail[curmsg].number;
-	msg.idx.to=mail[curmsg].to;
-	msg.idx.from=mail[curmsg].from;
-	msg.idx.subj=mail[curmsg].subj;
-
-	if((i=smb_locksmbhdr(&smb))!=0) {
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-		break; }
-
-	if((i=smb_getstatus(&smb))!=0) {
-		smb_unlocksmbhdr(&smb);
-		errormsg(WHERE,ERR_READ,smb.file,i);
-		break; }
-	smb_unlocksmbhdr(&smb);
-
-	if(smb.status.last_msg!=last) { 	/* New messages */
-		last=smb.status.last_msg;
-		FREE(mail);
-		msgs=loadmail(&mail,usernumber,which,0);   /* So re-load */
-		if(!msgs)
-			break;
-		for(curmsg=0;curmsg<msgs;curmsg++)
-			if(mail[curmsg].number==msg.idx.number)
-				break;
-		if(curmsg>=msgs)
-			curmsg=(msgs-1);
-		continue; }
-
-	if(!loadmsg(&msg,mail[curmsg].number)) {	/* Message header gone */
-		if(mismatches>5) {	/* We can't do this too many times in a row */
-			errormsg(WHERE,ERR_CHK,"message number",mail[curmsg].number);
-			break; }
-		FREE(mail);
-		msgs=loadmail(&mail,usernumber,which,0);
-		if(!msgs)
-			break;
-		if(curmsg>(msgs-1))
-			curmsg=(msgs-1);
-		mismatches++;
-		continue; }
-	smb_unlockmsghdr(&smb,&msg);
-	msg.idx.attr=msg.hdr.attr;
-
-	mismatches=0;
-
-	if(domsg && !(sys_status&SS_ABORT)) {
-
-		show_msg(msg
-			,msg.from_ext && msg.idx.from==1 && !msg.from_net.type
-				? 0:P_NOATCODES);
-
-		if(msg.hdr.auxattr&MSG_FILEATTACH) {  /* Attached file */
-			smb_getmsgidx(&smb,&msg);
-			strcpy(str,msg.subj);					/* filenames in title */
-			strupr(str);
-			tp=str;
-			while(online) {
-				p=strchr(tp,SP);
-				if(p) *p=0;
-				sp=strrchr(tp,'/');              /* sp is slash pointer */
-				if(!sp) sp=strrchr(tp,'\\');
-                if(sp) tp=sp+1;
-				padfname(tp,fd.name);
-				sprintf(str2,"%sFILE\\%04u.IN\\%s"  /* str2 is path/fname */
-					,data_dir,msg.idx.to,tp);
-				length=flength(str2);
-				if(length<1)
-					bputs(text[FileNotFound]);
-				else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP
-					&& length/(ulong)cur_cps>timeleft)
-					bputs(text[NotEnoughTimeToDl]);
-				else {
-					sprintf(str3,text[DownloadAttachedFileQ]
-						,tp,ultoac(length,tmp));
-					if(length>0L && yesno(str3)) {
-						if(online==ON_LOCAL) {
-							bputs(text[EnterPath]);
-							if(getstr(str3,60,K_LINE|K_UPPER)) {
-								backslashcolon(str3);
-								sprintf(tmp,"%s%s",str3,tp);
-								if(!mv(str2,tmp,which!=MAIL_YOUR)) {
-									logon_dlb+=length;
-									logon_dls++;
-									useron.dls=adjustuserrec(useron.number
-										,U_DLS,5,1);
-									useron.dlb=adjustuserrec(useron.number
-										,U_DLB,10,length);
-									bprintf(text[FileNBytesSent]
-										,fd.name,ultoac(length,tmp)); } } }
-
-						else {	/* Remote User */
-							menu("DLPROT");
-							mnemonics(text[ProtocolOrQuit]);
-							strcpy(str3,"Q");
-							for(i=0;i<total_prots;i++)
-								if(prot[i]->dlcmd[0]
-									&& chk_ar(prot[i]->ar,useron)) {
-									sprintf(tmp,"%c",prot[i]->mnemonic);
-									strcat(str3,tmp); }
-							ch=getkeys(str3,0);
-							for(i=0;i<total_prots;i++)
-								if(prot[i]->dlcmd[0] && ch==prot[i]->mnemonic
-									&& chk_ar(prot[i]->ar,useron))
-									break;
-							if(i<total_prots) {
-								j=protocol(cmdstr(prot[i]->dlcmd,str2,nulstr
-									,NULL),0);
-								if((prot[i]->misc&PROT_DSZLOG
-									&& checkprotlog(fd))
-									|| (!(prot[i]->misc&PROT_DSZLOG) && !j)) {
-										if(which==MAIL_YOUR)
-											remove(str2);
-										logon_dlb+=length;	/* Update stats */
-										logon_dls++;
-										useron.dls=adjustuserrec(useron.number
-											,U_DLS,5,1);
-										useron.dlb=adjustuserrec(useron.number
-											,U_DLB,10,length);
-										bprintf(text[FileNBytesSent]
-											,fd.name,ultoac(length,tmp));
-										sprintf(str3
-											,"Downloaded attached file: %s"
-											,fd.name);
-										logline("D-",str3); }
-								autohangup(); } } } }
-					if(!p)
-						break;
-					tp=p+1;
-					while(*tp==SP) tp++; }
-			sprintf(str,"%sFILE\\%04u.IN",data_dir,usernumber);
-			rmdir(str); }
-		if(which==MAIL_YOUR && !(msg.hdr.attr&MSG_READ)) {
-			mail[curmsg].attr|=MSG_READ;
-			if(thisnode.status==NODE_INUSE)
-				telluser(msg);
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;						/* Search by number */
-			if(!smb_locksmbhdr(&smb)) { 			/* Lock the entire base */
-				if(loadmsg(&msg,msg.idx.number)) {
-					msg.hdr.attr|=MSG_READ;
-					msg.idx.attr=msg.hdr.attr;
-					if((i=smb_putmsg(&smb,&msg))!=0)
-						errormsg(WHERE,ERR_WRITE,smb.file,i);
-					smb_unlockmsghdr(&smb,&msg); }
-				smb_unlocksmbhdr(&smb); }
-			if(!msg.total_hfields) {				/* unsuccessful reload */
-				domsg=0;
-				continue; } }
-		}
-    else domsg=1;
-
-	if(useron.misc&WIP) {
-		strcpy(str,which==MAIL_YOUR ? "MAILREAD" : which==MAIL_ALL ?
-			"ALLMAIL" : "SENTMAIL");
-		menu(str); }
-
-	ASYNC;
-	if(which==MAIL_SENT)
-		bprintf(text[ReadingSentMail],curmsg+1,msgs);
-	else if(which==MAIL_ALL)
-		bprintf(text[ReadingAllMail],curmsg+1,msgs);
-	else
-		bprintf(text[ReadingMail],curmsg+1,msgs);
-	sprintf(str,"ADFLNQRT?<>[]{}-+");
-	if(SYSOP)
-		strcat(str,"CUSP");
-	if(which!=MAIL_YOUR)
-		strcat(str,"E");
-	l=getkeys(str,msgs);
-	if(l&0x80000000L) {
-		if(l==-1)	/* ctrl-c */
-            break;
-		curmsg=(l&~0x80000000L)-1;
-        continue; }
-	switch(l) {
-		case 'A':   /* Auto-reply to last piece */
-			if(which==MAIL_SENT)
-				break;
-			if((msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP) {
-				bputs(text[CantReplyToAnonMsg]);
-				break; }
-
-			quotemsg(msg,1);
-
-			if(msg.from_net.type==NET_FIDO) 		/* FidoNet type */
-				sprintf(str,"%s @%s",msg.from
-				,faddrtoa(*(faddr_t *)msg.from_net.addr));
-			else if(msg.from_net.type==NET_INTERNET)
-				strcpy(str,msg.from_net.addr);
-			else if(msg.from_net.type)
-				sprintf(str,"%s@%s",msg.from,msg.from_net.addr);
-			else									/* No net */
-				strcpy(str,msg.from);
-
-			strcpy(str2,str);
-
-			bputs(text[Email]);
-			if(!getstr(str,64,K_EDIT|K_AUTODEL))
-				break;
-			msg.hdr.number=msg.idx.number;
-			smb_getmsgidx(&smb,&msg);
-
-			if(!stricmp(str2,str))		/* Reply to sender */
-				sprintf(str2,text[Regarding],msg.subj);
-			else						/* Reply to other */
-				sprintf(str2,text[RegardingBy],msg.subj,msg.from
-					,timestr((time_t *)&msg.hdr.when_written.time));
-
-			p=strrchr(str,'@');
-			if(p) { 							/* name @addr */
-				netmail(str,msg.subj,WM_QUOTE);
-				sprintf(str2,text[DeleteMailQ],msg.from); }
-			else {
-				if(!msg.from_net.type && !stricmp(str,msg.from))
-					email(msg.idx.from,str2,msg.subj,WM_EMAIL|WM_QUOTE);
-				else if(!stricmp(str,"SYSOP"))
-					email(1,str2,msg.subj,WM_EMAIL|WM_QUOTE);
-				else if((i=finduser(str))!=0)
-					email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE);
-				sprintf(str2,text[DeleteMailQ],msg.from); }
-			if(!yesno(str2)) {
-				if(curmsg<msgs-1) curmsg++;
-				else done=1;
-				break;	}
-			/* Case 'D': must follow! */
-		case 'D':   /* Delete last piece (toggle) */
-			if(msg.hdr.attr&MSG_PERMANENT) {
-				bputs("\r\nPermanent message.\r\n");
-				domsg=0;
-				break; }
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;
-			if(loadmsg(&msg,msg.idx.number)) {
-				msg.hdr.attr^=MSG_DELETE;
-				msg.idx.attr=msg.hdr.attr;
-//				  mail[curmsg].attr=msg.hdr.attr;
-				if((i=smb_putmsg(&smb,&msg))!=0)
-					errormsg(WHERE,ERR_WRITE,smb.file,i);
-				smb_unlockmsghdr(&smb,&msg); }
-			if(curmsg<msgs-1) curmsg++;
-			else done=1;
-			break;
-		case 'F':  /* Forward last piece */
-			domsg=0;
-			bputs(text[ForwardMailTo]);
-			if(!getstr(str,LEN_ALIAS,K_UPRLWR))
-				break;
-			i=finduser(str);
-			if(!i)
-				break;
-			domsg=1;
-			if(curmsg<msgs-1) curmsg++;
-			else done=1;
-			smb_getmsgidx(&smb,&msg);
-			forwardmail(&msg,i);
-			if(msg.hdr.attr&MSG_PERMANENT)
-				break;
-			sprintf(str2,text[DeleteMailQ],msg.from);
-			if(!yesno(str2))
-				break;
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;
-			if(loadmsg(&msg,msg.idx.number)) {
-				msg.hdr.attr|=MSG_DELETE;
-				msg.idx.attr=msg.hdr.attr;
-//				  mail[curmsg].attr=msg.hdr.attr;
-				if((i=smb_putmsg(&smb,&msg))!=0)
-					errormsg(WHERE,ERR_WRITE,smb.file,i);
-				smb_unlockmsghdr(&smb,&msg); }
-
-			break;
-		case 'L':     /* List mail */
-			domsg=0;
-			bprintf(text[StartWithN],(long)curmsg+1);
-			if((i=getnum(msgs))>0)
-				i--;
-			else if(i==-1)
-				break;
-			else
-				i=curmsg;
-			if(which==MAIL_SENT)
-				bputs(text[MailSentLstHdr]);
-			else if(which==MAIL_ALL)
-				bputs(text[MailOnSystemLstHdr]);
-			else
-				bputs(text[MailWaitingLstHdr]);
-			for(;i<msgs && !msgabort();i++) {
-				if(msg.total_hfields)
-					smb_freemsgmem(&msg);
-				msg.total_hfields=0;
-				msg.idx.offset=mail[i].offset;
-				if(!loadmsg(&msg,mail[i].number))
-					continue;
-				smb_unlockmsghdr(&smb,&msg);
-				if(which==MAIL_ALL)
-					bprintf(text[MailOnSystemLstFmt]
-						,i+1,msg.from,msg.to
-						,msg.hdr.attr&MSG_DELETE ? '-'
-							: msg.hdr.attr&MSG_READ ? SP
-							: msg.from_net.type || msg.to_net.type ? 'N':'*'
-						,msg.subj);
-				else
-					bprintf(text[MailWaitingLstFmt],i+1
-						,which==MAIL_SENT ? msg.to
-						: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
-						? text[Anonymous] : msg.from
-						,msg.hdr.attr&MSG_DELETE ? '-'
-							: msg.hdr.attr&MSG_READ ? SP
-							: msg.from_net.type || msg.to_net.type ? 'N':'*'
-						,msg.subj);
-				smb_freemsgmem(&msg);
-				msg.total_hfields=0; }
-			break;
-		case 'Q':
-			done=1;
-			break;
-		case 'C':   /* Change attributes of last piece */
-			i=chmsgattr(msg.hdr.attr);
-			if(msg.hdr.attr==i)
-				break;
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;
-			if(loadmsg(&msg,msg.idx.number)) {
-				msg.hdr.attr=msg.idx.attr=i;
-				if((i=smb_putmsg(&smb,&msg))!=0)
-					errormsg(WHERE,ERR_WRITE,smb.file,i);
-				smb_unlockmsghdr(&smb,&msg); }
-			break;
-		case '>':
-			for(i=curmsg+1;i<msgs;i++)
-				if(mail[i].subj==msg.idx.subj)
-					break;
-			if(i<msgs)
-				curmsg=i;
-			else
-				domsg=0;
-			break;
-		case '<':   /* Search Title backward */
-			for(i=curmsg-1;i>-1;i--)
-				if(mail[i].subj==msg.idx.subj)
-					break;
-            if(i>-1)
-				curmsg=i;
-			else
-				domsg=0;
-			break;
-		case '}':   /* Search Author forward */
-			strcpy(str,msg.from);
-			for(i=curmsg+1;i<msgs;i++)
-				if(mail[i].from==msg.idx.from)
-					break;
-			if(i<msgs)
-				curmsg=i;
-			else
-				domsg=0;
-			break;
-		case 'N':   /* Got to next un-read message */
-			for(i=curmsg+1;i<msgs;i++)
-				if(!(mail[i].attr&MSG_READ))
-					break;
-			if(i<msgs)
-				curmsg=i;
-			else
-				domsg=0;
-            break;
-		case '{':   /* Search Author backward */
-			strcpy(str,msg.from);
-			for(i=curmsg-1;i>-1;i--)
-				if(mail[i].from==msg.idx.from)
-					break;
-			if(i>-1)
-				curmsg=i;
-			else
-				domsg=0;
-			break;
-		case ']':   /* Search To User forward */
-			strcpy(str,msg.to);
-			for(i=curmsg+1;i<msgs;i++)
-				if(mail[i].to==msg.idx.to)
-					break;
-			if(i<msgs)
-				curmsg=i;
-			else
-				domsg=0;
-			break;
-		case '[':   /* Search To User backward */
-			strcpy(str,msg.to);
-			for(i=curmsg-1;i>-1;i--)
-				if(mail[i].to==msg.idx.to)
-					break;
-			if(i>-1)
-				curmsg=i;
-			else
-				domsg=0;
-            break;
-		case 0:
-		case '+':
-			if(curmsg<msgs-1) curmsg++;
-			else done=1;
-			break;
-		case '-':
-			if(curmsg>0) curmsg--;
-			break;
-		case 'S':
-			domsg=0;
-/*
-			if(!yesno(text[SaveMsgToFile]))
-				break;
-*/
-			bputs(text[FileToWriteTo]);
-			if(getstr(str,40,K_LINE|K_UPPER))
-				msgtotxt(msg,str,1,1);
-			break;
-		case 'E':
-			editmsg(&msg,INVALID_SUB);
-			break;
-		case 'T':
-			domsg=0;
-			i=curmsg;
-			if(i) i++;
-			j=i+10;
-			if(j>msgs)
-				j=msgs;
-
-			if(which==MAIL_SENT)
-				bputs(text[MailSentLstHdr]);
-			else if(which==MAIL_ALL)
-				bputs(text[MailOnSystemLstHdr]);
-			else
-                bputs(text[MailWaitingLstHdr]);
-			for(;i<j;i++) {
-				if(msg.total_hfields)
-					smb_freemsgmem(&msg);
-				msg.total_hfields=0;
-				msg.idx.offset=mail[i].offset;
-				if(!loadmsg(&msg,mail[i].number))
-					continue;
-				smb_unlockmsghdr(&smb,&msg);
-				if(which==MAIL_ALL)
-					bprintf(text[MailOnSystemLstFmt]
-						,i+1,msg.from,msg.to
-						,msg.hdr.attr&MSG_DELETE ? '-'
-							: msg.hdr.attr&MSG_READ ? SP
-							: msg.from_net.type || msg.to_net.type ? 'N':'*'
-						,msg.subj);
-				else
-					bprintf(text[MailWaitingLstFmt],i+1
-						,which==MAIL_SENT ? msg.to
-						: (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
-						? text[Anonymous] : msg.from
-						,msg.hdr.attr&MSG_DELETE ? '-'
-							: msg.hdr.attr&MSG_READ ? SP
-							: msg.from_net.type || msg.to_net.type ? 'N':'*'
-						,msg.subj);
-				smb_freemsgmem(&msg);
-				msg.total_hfields=0; }
-			curmsg=(i-1);
-			break;
-		case 'U':   /* user edit */
-			msg.hdr.number=msg.idx.number;
-			smb_getmsgidx(&smb,&msg);
-			useredit(which==MAIL_SENT ? msg.idx.to : msg.idx.from,0);
-			break;
-		case 'P':   /* Purge author and all mail to/from */
-			if(noyes(text[AreYouSureQ]))
-				break;
-            msg.hdr.number=msg.idx.number;
-            smb_getmsgidx(&smb,&msg);
-            purgeuser(msg.idx.from);
-			if(curmsg<msgs-1) curmsg++;
-            break;
-		case '?':
-			strcpy(str,which==MAIL_YOUR ? "MAILREAD" : which==MAIL_ALL
-					? "ALLMAIL" : "SENTMAIL");
-			menu(str);
-			if(SYSOP && which==MAIL_SENT)
-				menu("SYSSMAIL");
-			else if(SYSOP && which==MAIL_YOUR)
-				menu("SYSMAILR");   /* Sysop Mail Read */
-			domsg=0;
-			break;
-			} }
-
-if(msg.total_hfields)
-	smb_freemsgmem(&msg);
-
-if(msgs)
-    FREE(mail);
-
-/***************************************/
-/* Delete messages marked for deletion */
-/***************************************/
-
-if(sys_misc&SM_DELEMAIL) {
-	if((i=smb_locksmbhdr(&smb))!=0) 			/* Lock the base, so nobody */
-		errormsg(WHERE,ERR_LOCK,smb.file,i);	/* messes with the index */
-	else
-		delmail(usernumber,which); }
-
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-}
-
diff --git a/src/sbbs2/main.c b/src/sbbs2/main.c
deleted file mode 100644
index ce05b9bf905c89562e383d490f757fe0d4dba252..0000000000000000000000000000000000000000
--- a/src/sbbs2/main.c
+++ /dev/null
@@ -1,307 +0,0 @@
-#line 1 "MAIN.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*********************************************************/
-/* Entry point to the BBS and the waitforcall() function */
-/*********************************************************/
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-csi_t	main_csi;
-uint	curshell=0;
-
-char onquiet=0,qwklogon;
-char term_ret=0;
-ulong connect_rate=0;	/* already connected at xbps */
-
-#if __OS2__
-void cbreakh(int sig)		 /* Ctrl-C */
-{
-sys_status|=SS_ABORT;
-signal(sig,cbreakh);
-}
-
-#else
-
-int cbreakh()	/* ctrl-break handler */
-{
-sys_status|=SS_ABORT;
-return(1);		/* 1 to continue, 0 to abort */
-}
-#endif
-
-/****************************************************************************/
-/* This is the entry point to the BBS from dos                              */
-/* No arguments are defined as of yet.                                      */
-/****************************************************************************/
-main(int argc, char *argv[])
-{
-	char	str[256];
-	int 	i,j,file,twenty;
-	node_t	node;
-
-startup(argc,argv);    /* startup code overlaid */
-
-while(1) {
-	
-	while(1) {
-		qwklogon=0;
-		twenty=0;
-
-		/* Reset TEXT.DAT */
-
-		for(i=0;i<TOTAL_TEXT;i++)
-			if(text[i]!=text_sav[i]) {
-				if(text[i]!=nulstr)
-					FREE(text[i]);
-				text[i]=text_sav[i]; }
-
-		/* Reset COMMAND SHELL */
-
-		if(main_csi.cs)
-			FREE(main_csi.cs);
-		if(main_csi.str)
-			FREE(main_csi.str);
-		freevars(&main_csi);
-		memset(&main_csi,0,sizeof(csi_t));
-		main_csi.str=MALLOC(1024);
-		if(!main_csi.str) {
-			errormsg(WHERE,ERR_ALLOC,"command shell",1024);
-			bail(1); }
-		memset(main_csi.str,0,1024);
-		menu_dir[0]=0;
-		twenty+=10;
-
-		/* Reset Global Variables */
-
-		if(global_str_var)
-			for(i=0;i<global_str_vars;i++)
-				if(global_str_var[i]) {
-					FREE(global_str_var[i]);
-					global_str_var[i]=0; }
-		if(global_str_var) {
-			FREE(global_str_var);
-			global_str_var=0; }
-		if(global_str_var_name) {
-			FREE(global_str_var_name);
-			global_str_var_name=0; }
-		global_str_vars=0;
-		if(global_int_var) {
-			FREE(global_int_var);
-			global_int_var=0; }
-		if(global_int_var_name) {
-			FREE(global_int_var_name);
-			global_int_var_name=0; }
-		global_int_vars=0;
-		twenty*=2;
-
-		if(waitforcall())		/* Got caller/logon */
-			break; }
-
-	if(qwklogon) {
-		getsmsg(useron.number);
-        qwk_sec();
-        hangup();
-		logout();
-        continue; }
-
-	while(useron.number && (main_csi.misc&CS_OFFLINE_EXEC || online)) {
-
-		if(!main_csi.cs || curshell!=useron.shell) {
-			if(useron.shell>=total_shells)
-				useron.shell=0;
-			sprintf(str,"%s%s.BIN",exec_dir,shell[useron.shell]->code);
-			if((file=nopen(str,O_RDONLY|O_BINARY))==-1) {
-				errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
-				hangup();
-				break; }
-			if(main_csi.cs)
-				FREE(main_csi.cs);
-			freevars(&main_csi);
-			clearvars(&main_csi);
-
-			main_csi.length=filelength(file);
-			if((main_csi.cs=(uchar *)MALLOC(main_csi.length))==NULL) {
-				close(file);
-				errormsg(WHERE,ERR_ALLOC,str,main_csi.length);
-				hangup();
-				break; }
-
-			if(lread(file,main_csi.cs,main_csi.length)!=main_csi.length) {
-				errormsg(WHERE,ERR_READ,str,main_csi.length);
-				close(file);
-				FREE(main_csi.cs);
-                main_csi.cs=NULL;
-				hangup();
-				break; }
-			close(file);
-
-			main_csi.ip=main_csi.cs;
-			curshell=useron.shell;
-			menu_dir[0]=0;
-			menu_file[0]=0;
-		#ifdef __MSDOS__
-			freedosmem=farcoreleft();
-		#endif
-			}
-		if(exec(&main_csi))
-			break;
-
-		if(!(main_csi.misc&CS_OFFLINE_EXEC))
-			checkline();
-
-#if 0
-		if(freedosmem!=farcoreleft()) {
-			if(freedosmem>farcoreleft())
-				errormsg(WHERE,ERR_CHK,"memory",freedosmem-farcoreleft());
-			freedosmem=farcoreleft(); }
-#endif
-		}
-	logout();
-	catsyslog(0);
-	if(!REALSYSOP || sys_misc&SM_SYSSTAT)
-		logoffstats();	/* Updates both system and node dsts.dab files */
-	if(qoc) {
-		while(!wfc_events(time(NULL)))
-			;
-		catsyslog(0);
-		if(qoc==1)
-			offhook();
-		lclini(node_scrnlen);
-		lputc(FF);
-		bail(0); }
-	}
-}
-
-/************************************/
-/* encrypted string output function */
-/************************************/
-char *decrypt(ulong l[], char *instr)
-{
-	static char str[128];
-    uchar ch,bits,len;
-	ushort i,j,lc=0;
-
-len=(uchar)(l[0]&0x7f)^0x49;
-bits=7;
-for(i=0,j=0;i<len;i++) {
-    ch=(char)((l[j]>>bits)&0x7fL);
-    ch^=(i^0x2c);
-	str[lc++]=ch;
-    bits+=7;
-    if(bits>=26 && i+1<len) {
-		if(bits==32)
-			ch=0;
-		else
-			ch=(char)((l[j]>>bits)&0x7fL);
-        bits=(32-bits);
-        j++;
-        ch|=((l[j]&0x7f)<<(bits))&0x7f;
-        i++;
-        ch^=(i^0x2c);
-        bits=7-bits;
-		str[lc++]=ch; } }
-str[lc]=0;
-if(instr) {
-	strcpy(instr,str);
-	return(instr); }
-else
-	return(str);
-}
-
-/****************************************************************************/
-/* Writes NODE.LOG at end of SYSTEM.LOG										*/
-/****************************************************************************/
-void catsyslog(int crash)
-{
-	char str[256];
-	char HUGE16 *buf;
-	int  i,file;
-	ulong length;
-
-if(sys_status&SS_LOGOPEN) {
-	if(close(logfile)) {
-		errormsg(WHERE,ERR_CLOSE,"logfile",0);
-		return; }
-	sys_status&=~SS_LOGOPEN; }
-sprintf(str,"%sNODE.LOG",node_dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-length=filelength(file);
-if(length) {
-	if((buf=(char HUGE16 *)LMALLOC(length))==NULL) {
-		close(file);
-		errormsg(WHERE,ERR_ALLOC,str,length);
-		return; }
-	if(lread(file,buf,length)!=length) {
-		close(file);
-		errormsg(WHERE,ERR_READ,str,length);
-		FREE((char *)buf);
-		return; }
-	close(file);
-	now=time(NULL);
-	unixtodos(now,&date,&curtime);
-	sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG",data_dir,date.da_mon,date.da_day
-		,TM_YEAR(date.da_year-1900));
-	if((file=nopen(str,O_WRONLY|O_APPEND|O_CREAT))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_APPEND|O_CREAT);
-		FREE((char *)buf);
-		return; }
-	if(lwrite(file,buf,length)!=length) {
-		close(file);
-		errormsg(WHERE,ERR_WRITE,str,length);
-		FREE((char *)buf);
-		return; }
-	close(file);
-	if(crash) {
-		for(i=0;i<2;i++) {
-			sprintf(str,"%sCRASH.LOG",i ? data_dir : node_dir);
-			if((file=nopen(str,O_WRONLY|O_APPEND|O_CREAT))==-1) {
-				errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_APPEND|O_CREAT);
-				FREE((char *)buf);
-				return; }
-			if(lwrite(file,buf,length)!=length) {
-				close(file);
-				errormsg(WHERE,ERR_WRITE,str,length);
-				FREE((char *)buf);
-				return; }
-			close(file); } }
-	FREE((char *)buf); }
-else
-	close(file);
-sprintf(str,"%sNODE.LOG",node_dir);
-if((logfile=nopen(str,O_WRONLY|O_TRUNC))==-1) /* Truncate NODE.LOG */
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
-else sys_status|=SS_LOGOPEN;
-}
-
-void quicklogonstuff()
-{
-	int i;
-	node_t node;
-
-reset_logon_vars();
-
-lclini(node_scrnlen-1);
-if(com_port && !DCDHIGH)				/* don't take phone offhook if */
-	offhook();							/* connected */
-useron.number=1;
-getuserdat(&useron);
-autoterm=ANSI;
-if(!useron.number)
-	useron.level=99;
-console=CON_L_ECHO|CON_L_INPUT;
-online=ON_LOCAL;
-statline=sys_def_stat;
-statusline();
-answertime=logontime=time(NULL);
-sprintf(connection,"%.*s",LEN_MODEM,text[Locally]);
-cur_rate=14400;
-cur_cps=1750;
-sys_status|=SS_USERON;
-}
-
-
diff --git a/src/sbbs2/main_ovl.c b/src/sbbs2/main_ovl.c
deleted file mode 100644
index df989db688acd8ff85ba3cca968a07f136298c5b..0000000000000000000000000000000000000000
--- a/src/sbbs2/main_ovl.c
+++ /dev/null
@@ -1,839 +0,0 @@
-#line 1 "MAIN_OVL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "etext.h"
-#include <signal.h>
-
-#ifndef __FLAT__
-#include "spawno.h"
-#endif
-
-uint asmrev;		// RCIOL.OBJ revision
-char llo=0			// Local logon only
-	,nmi=0; 		// No modem init
-char cidarg[65];	// Caller ID arguments
-uint addrio;		// Additional RIOCTL call on init
-
-FILE *nodefile_fp,*node_ext_fp,*logfile_fp;
-
-char prompt[128];
-
-extern char *compile_time,*compile_date;
-
-#ifdef __FLAT__
-int mswtyp=0;
-#else
-extern mswtyp;
-extern uint riobp;
-#endif
-
-extern char onquiet;
-extern char term_ret;
-extern ulong connect_rate;	 /* already connected at xbps */
-extern char *wday[],*mon[];
-
-#ifdef __OS2__
-extern long _timezone=0L;
-extern int _daylight=0L;
-#else
-extern long timezone=0L;
-extern int	daylight=0L;
-#endif
-
-#ifdef __OS2__
-	extern HEV con_out_sem;
-	void con_out_thread(void *);
-#endif
-
-
-#ifdef __OS2__
-void cbreakh(int sig);
-#else
-int cbreakh();
-#endif
-
-void reset_logon_vars(void);
-
-time_t checktime(void)
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-void console_test(void)
-{
-	int i;
-	time_t start=time(NULL);;
-
-lclxy(1,1);
-online=ON_LOCAL;
-console=CON_L_ECHO;
-useron.misc=ANSI|COLOR;
-for(i=0;i<500;i++)
-	bprintf("\1n%05d\t\1hWhite\1rRed\1bBlue\1gGreen\001\x82"
-		"\1mMagenta\t\b\b\1cCyan\1nNormal\1gGreen"
-		"\1yBrown\1hYellow\1rR\1gG\1bB\1cC\1mM\1yY\1kK"
-		"\1>\r\n"
-		,i);
-bprintf("\r\n%lu secs\r\n",time(NULL)-start);
-getch();
-lputc(FF);
-}
-
-
-
-
-void  startup(int argc, char *argv[])
-{
-	char str[256],HUGE16 *buf,c;
-    void *v;
-	int i,j,events_only=0;
-    int file;
-    ulong l;
-	node_t node;
-    struct ffblk ff;
-    struct tm *gm;
-#ifdef __FLAT__
-	uchar *cptab;	/* unused */
-#else
-	uchar cptab[1024];
-    union REGS reg;
-#endif
-
-#ifdef __MSDOS__
-setcbrk(0);
-#endif
-
-#ifndef __FLAT__
-if((asmrev=*(&riobp-1))!=23) {
-    printf("Wrong rciol.obj\n");
-    exit(1); }
-#endif
-
-#ifdef __OS2__
-signal(SIGINT,cbreakh);
-signal(SIGBREAK,cbreakh);
-fixkbdmode();
-#elif defined(__MSDOS__)
-ctrlbrk(cbreakh);
-#endif
-
-#ifndef __FLAT__				/* no DESQview under OS/2 */
-inDV = 0;
-_CX = 0x4445; /* 'DE' */        /* set CX to 4445H; DX to 5351H     */
-_DX = 0x5351; /* 'SQ' */        /* (an invalid date)                */
-_AX = 0x2B01;					/* DOS' set data function           */
-geninterrupt( 0x21 );			/* call DOS 						*/
-if ( _AL != 0xFF )				/* if DOS didn't see as invalid     */
-	_AX = _BX;					/* AH=major ver; AL=minor ver		*/
-else							/* DOS saw as invalid				*/
-	_AX = 0;					/* no desqview						*/
-inDV = _AX; 					/* Save version in inDV flag		*/
-#endif
-
-#ifdef __FLAT__
-if(putenv("TZ=UCT0"))
-	printf("putenv() failed!\n");
-tzset();
-#endif
-
-if((l=checktime())!=0) {   /* Check binary time */
-	printf("Time problem (%08lx)\n",l);
-	exit(1); }
-
-directvideo=1;  /* default to direct video */
-
-_fmode=O_BINARY;
-nulstr="";
-crlf="\r\n";
-strcpy(cap_fname,"CAPTURE.TXT");
-sys_status=lncntr=tos=criterrs=keybufbot=keybuftop=lbuflen=slcnt=0L;
-debug=1;
-curatr=LIGHTGRAY;
-errorlevel=0;
-logcol=1;
-next_event=0;
-lastuseron[0]=0;
-emsver=0;
-emshandle=0xffff;
-randomize();
-srand(clock());
-
-for(i=0;i<127 && environ[i];i++)  /* save original environment for execl() */
-	envp[i]=environ[i];
-envp[i]=0;
-
-strcpy(str,getenv("PROMPT"));
-if(!strstr(str,"[SBBS]")) {
-	sprintf(prompt,"PROMPT=[SBBS] %s",str);
-	putenv(prompt); }
-
-comspec=getenv("COMSPEC");
-
-lputc(FF);
-
-#ifndef __FLAT__
-node_scrnlen=lclini(0xd<<8);      /* Tab expansion, no CRLF expansion */
-#else
-node_scrnlen=25;
-#endif
-lclini(node_scrnlen);
-lclatr(LIGHTGRAY);
-
-#ifdef __OS2__	// Test console speed
-
-if(DosCreateEventSem(NULL,&con_out_sem,0,0)) {
-	printf("Can't create console output semaphore.\n");
-	exit(2); }
-
-if(_beginthread(con_out_thread,1024,NULL)==-1) {
-	printf("Can't start console output thread.\n");
-	exit(3); }
-//console_test();
-#endif
-
-#if defined(__OS2__)
-lputs(decrypt(VersionNoticeOS2,0));
-#elif defined(__WIN32__)
-lputs(decrypt(VersionNoticeW32,0));
-#else
-lputs(decrypt(VersionNoticeDOS,0));
-#endif
-lputs(decrypt(CopyrightNotice,0));	 /* display copyright notice */
-lputc(CR);
-lputc(LF);
-cidarg[0]=0;
-addrio=0;
-strcpy(orgcmd,argv[0]);     /* build up original command line */
-strcat(orgcmd," ");
-for(i=1;i<argc;i++) {
-    for(c=0;c<strlen(argv[i]);c++)
-        switch(toupper(argv[i][c])) {
-            case '/':   /* ignore these characters */
-            case '-':
-                break;
-            case 'B':   /* desqview or other that needs bios video only */
-                directvideo=0;
-                strcat(orgcmd,"B");
-                break;
-            case 'C':   /* connected at xbps */
-				connect_rate=atol(argv[i]+c+1);
-                c=strlen(argv[i]);
-                break;
-			case 'D':   /* assume DCD is always high */
-				sys_status|=SS_DCDHIGH;
-				strcat(orgcmd,"D");
-				break;
-			case 'E':
-				next_event=time(NULL)+(atol(argv[i]+c+1)*60L);
-				c=strlen(argv[i]);
-				break;
-			case 'F':
-				sys_status|=SS_DAILY;
-				break;
-#ifdef __OS2__
-			case 'H':
-				rio_handle=atoi(argv[i]+c+1);
-				c=strlen(argv[i]);
-				break;
-#endif
-			case 'I':   /* no modem init */
-				strcat(orgcmd,"I");
-				nmi=1;
-				break;
-			case 'L':   /* local logon only */
-				strcat(orgcmd,"L");
-				llo=1;
-				break;
-			case 'M':   /* modem debug info */
-				strcat(orgcmd,"M");
-				sys_status|=SS_MDMDEBUG;
-				break;
-			case 'O':   /* execute events only */
-				events_only=1;
-				break;
-            case 'Q':   /* quit after one caller - phone off hook */
-                strcat(orgcmd,"Q");
-                qoc=1;
-                break;
-			case 'R':   /* additional rioctl call */
-				addrio=ahtoul(argv[i]+c+1);
-				c=strlen(argv[i]);
-				break;
-            case 'X':   /* quit after one caller - phone on hook */
-                strcat(orgcmd,"X");
-                qoc=2;
-                break;
-			case 'Z':
-				sprintf(cidarg,"%-.64s",argv[i]+c+1);
-                c=strlen(argv[i]);
-				break;
-			case 'V':
-				lputs(crlf);
-				lprintf("Revision %c%s %s %.5s  "
-				#ifdef __FLAT__
-					"RIOLIB %u.%02u"
-				#else
-					"RCIOL %u"
-				#endif
-					"  SMBLIB %s  BCC %X.%02X"
-					,REVISION,BETA,compile_date,compile_time
-				#ifdef __FLAT__
-					,rioctl(GVERS)/100,rioctl(GVERS)%100
-				#else
-					,rioctl(GVERS)
-				#endif
-					,smb_lib_ver()
-					,__BORLANDC__>>8
-					,__BORLANDC__&0xff);
-				lputs(crlf);
-				bail(0);
-            default:
-				lputs("\r\nusage: sbbs [bdmoqxfliv] [c#] [e#] [zs] [r#] [h#]"
-					"\r\n\r\n"
-                    "b  = use bios for video\r\n"
-					"d  = assume DCD is always high\r\n"
-					"m  = modem debug output\r\n"
-                    "q  = quit after one call (phone off hook)\r\n"
-                    "x  = quit after one call\r\n"
-					"o  = execute events only and then quit\r\n"
-					"c# = connected at # bps (ex: c2400)\r\n"
-					"e# = external event in # minutes (ex: e30)\r\n"
-					"f  = force daily event\r\n"
-					"l  = local logon only\r\n"
-					"i  = no modem initialization\r\n"
-					"zs = use s for caller-id information\r\n"
-					"r# = additional rioctl call during port init\r\n"
-					"h# = open port handle (SBBS4OS2 only)\r\n"
-					"v  = version information\r\n"
-					);
-                bail(0); } }
-
-
-node_disk=getdisk();
-getcwd(node_dir,MAXDIR);        /* Get current Directory    */
-if(strlen(node_dir)>40) {
-    lputs("\r\n\7Current Directory is too long for bbs to run reliably.\r\n");
-    bail(1); }
-strcat(node_dir,"\\");
-initdata();                     /* auto-sense scrnlen can be overridden */
-
-mswtyp=0;
-if(node_misc&NM_INT28)
-	mswtyp|=TS_INT28;
-if(node_misc&NM_WINOS2)
-	mswtyp|=TS_WINOS2;
-if(node_misc&NM_NODV)
-	mswtyp|=TS_NODV;
-
-#ifndef __FLAT__
-
-__spawn_ext = (node_swap & SWAP_EXT) != 0 ;
-__spawn_ems = (node_swap & SWAP_EMS) != 0 ;
-__spawn_xms = (node_swap & SWAP_XMS) != 0 ;
-
-#endif
-
-#ifndef __FLAT__				 /* no EMS under OS/2 */
-if(node_misc&NM_EMSOVL) {
-	lputs("\r\nEMS: ");
-	if((i=open("EMMXXXX0",O_RDONLY))==-1)
-		lputs("not installed.");
-	else {
-		close(i);
-		reg.h.ah=0x46;			/* Get EMS version */
-		int86(0x67,&reg,&reg);
-		if(reg.h.ah)
-			lputs("\7error getting version.");
-		else {
-			lprintf("Version %u.%u ",(reg.h.al&0xf0)>>4,reg.h.al&0xf);
-			emsver=reg.h.al;
-			reg.h.ah=0x4b;		/* get handle count */
-			int86(0x67,&reg,&reg);
-			if(reg.h.ah)
-				lputs("\7error getting handle count.");
-			else {
-				if(_OvrInitEms(0,0,23))    /* use up to 360K */
-					lprintf("allocation failed.");
-				else
-					emshandle=reg.x.bx; } } } }
-#endif
-
-sprintf(str,"%s%s",ctrl_dir,"NODE.DAB");
-if((nodefile_fp=fnopen(&nodefile,str
-	,O_DENYNONE|O_RDWR|O_CREAT))==NULL) {
-    lprintf("\r\n\7Error opening/creating %s\r\n",str);
-    exit(1); }
-sprintf(str,"%s%s",ctrl_dir,"NODE.EXB");
-if((node_ext_fp=fnopen(&node_ext,str,O_DENYNONE|O_RDWR|O_CREAT))==NULL) {
-    lprintf("\r\n\7Error opening/creating %s\r\n",str);
-    exit(1); }
-memset(&node,0,sizeof(node_t));  /* write NULL to node struct */
-node.status=NODE_OFFLINE;
-while(filelength(nodefile)<sys_nodes*sizeof(node_t)) {
-    lseek(nodefile,0L,SEEK_END);
-    write(nodefile,&node,sizeof(node_t)); }
-if(lock(nodefile,(node_num-1)*sizeof(node_t),sizeof(node_t))
-	|| unlock(nodefile,(node_num-1)*sizeof(node_t),sizeof(node_t))) {
-    lprintf("\r\n\7File locking failed.\r\n");
-
-#ifndef __FLAT__			 /* no SHARE under Win32 and OS/2 */
-    reg.x.ax=0x1000;
-    int86(0x2f,&reg,&reg);
-	if(!reg.h.al) {
-        lputs("SHARE is not installed. Must run SHARE before SBBS.\r\n");
-		lputs("SHARE.EXE is included with DOS v3.0 and higher.\r\n"); }
-    else if(reg.h.al==1)
-        lputs("SHARE is not installed and NOT OKAY to install.\r\n");
-    else if(reg.h.al==0xff)
-        lputs("SHARE is installed.\r\n");
-    else
-        lprintf("INT 2F returned %xh in AL.\r\n",reg.h.al);
-#endif
-
-    bail(1); }
-sys_status|=SS_NODEDAB; /* says that node.dab is okay to use */
-getnodedat(node_num,&thisnode,1);
-
-/* if not returning, clear node.dab record */
-if(!connect_rate) {
-	thisnode.status=thisnode.action=thisnode.useron=0;
-    thisnode.aux=0; /* use to always clear */
-    thisnode.misc&=NODE_EVENT; }    /* turn off all misc bits but event */
-criterrs=thisnode.errors;
-putnodedat(node_num,thisnode);
-
-if(com_base==0xb)
-	rioctl(I14PC);
-else if(com_base==0xd)
-	rioctl(I14DB);
-else if(com_base==0xe)
-	rioctl(I14PS);
-else if(com_base==0xf)
-	rioctl(I14FO);
-if(com_port) {
-    comini();
-	setrate(); }
-
-for(i=0;i<total_qhubs;i++) {
-	if(qhub[i]->node!=node_num)
-		continue;
-	for(j=0;j<10;j++) {
-		sprintf(str,"%s%s.QW%c",data_dir,qhub[i]->id,j ? (j-1)+'0' : 'K');
-		if(fexist(str)) {
-			lclini(node_scrnlen-1);
-			delfiles(temp_dir,"*.*");
-			unpack_qwk(str,i); } } }
-
-sprintf(str,"%sTIME.DAB",ctrl_dir);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-    lprintf("Error opening/creating %s\r\n",str);
-    bail(1); }
-for(i=0;i<total_events;i++) {
-	event[i]->last=0;
-	if(filelength(file)<sizeof(time_t)*(i+1))
-		write(file,&event[i]->last,sizeof(time_t));
-	else
-		read(file,&event[i]->last,sizeof(time_t)); }
-
-close(file);
-
-sprintf(str,"%sQNET.DAB",ctrl_dir);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-    lprintf("Error opening/creating %s\r\n",str);
-    bail(1); }
-
-for(i=0;i<total_qhubs;i++) {
-	qhub[i]->last=0;
-	if(filelength(file)<sizeof(time_t)*(i+1))
-		write(file,&qhub[i]->last,sizeof(time_t));
-    else
-		read(file,&qhub[i]->last,sizeof(time_t)); }
-
-close(file);
-
-sprintf(str,"%sPNET.DAB",ctrl_dir);
-if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-    lprintf("Error opening/creating %s\r\n",str);
-    bail(1); }
-
-for(i=0;i<total_phubs;i++) {
-	phub[i]->last=0;
-	if(filelength(file)<sizeof(time_t)*(i+1))
-        write(file,&phub[i]->last,sizeof(time_t));
-    else
-        read(file,&phub[i]->last,sizeof(time_t)); }
-
-close(file);
-
-sprintf(str,"%sNODE.LOG",node_dir);
-lprintf("\r\nOpening %s...",str);
-if((logfile_fp=fnopen(&logfile,str,O_WRONLY|O_CREAT|O_APPEND|O_DENYALL))==NULL) {
-	lprintf("\r\n\7Error opening %s\r\n\r\n"
-		"Perhaps this node is already running.\r\n",str);
-    bail(1); }
-lprintf("\r%s opened.",str);
-sys_status|=SS_LOGOPEN;
-if(filelength(logfile)) {
-	log(crlf);
-	now=time(NULL);
-    gm=localtime(&now);
-	sprintf(str,"%02d:%02d%c  %s %s %02d %u  "
-		"End of preexisting log entry (possible crash)"
-		,gm->tm_hour>12 ? gm->tm_hour-12 : gm->tm_hour==0 ? 12 : gm->tm_hour
-		,gm->tm_min,gm->tm_hour>=12 ? 'p' : 'a',wday[gm->tm_wday]
-		,mon[gm->tm_mon],gm->tm_mday,gm->tm_year+1900);
-	logline("L!",str);
-	log(crlf);
-	catsyslog(1); }
-lputc(CLREOL);
-sprintf(dszlog,"DSZLOG=%sPROTOCOL.LOG",node_dir);
-putenv(dszlog); 		/* Makes the DSZ LOG active */
-sprintf(sbbsnode,"SBBSNODE=%s",node_dir);
-putenv(sbbsnode);		/* create enviornment var to contain node num */
-sprintf(sbbsnnum,"SBBSNNUM=%d",node_num);
-putenv(sbbsnnum);	   /* create enviornment var to contain node num */
-backout();
-if(events_only) {
-	reset_logon_vars();
-	while(!wfc_events(time(NULL)))
-		;
-	bail(0); }
-}
-
-/****************************************************************************/
-/* Reads data from DSTS.DAB into stats structure                            */
-/* If node is zero, reads from ctrl\dsts.dab, otherwise from each node		*/
-/****************************************************************************/
-void getstats(char node,stats_t *stats)
-{
-    char str[256];
-    int file;
-
-sprintf(str,"%sDSTS.DAB",node ? node_path[node-1] : ctrl_dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    return; }
-lseek(file,4L,SEEK_SET);    /* Skip update time/date */
-read(file,stats,sizeof(stats_t));
-close(file);
-}
-
-
-/****************************************************************************/
-/* Updates dstst.dab file upon user logoff. 								*/
-/* First node, then system stats.                                           */
-/****************************************************************************/
-void logoffstats()
-{
-    char str[256];
-    int i,file;
-    stats_t stats;
-
-for(i=0;i<2;i++) {
-    sprintf(str,"%sDSTS.DAB",i ? ctrl_dir : node_dir);
-    if((file=nopen(str,O_RDWR))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-        return; }
-    lseek(file,12L,SEEK_SET);   /* Skip timestamp, logons and logons today */
-    read(file,&stats.timeon,4);   /* Total time on system  */
-	stats.timeon+=(now-logontime)/60;
-    read(file,&stats.ttoday,4); /* Time today on system  */
-	stats.ttoday+=(now-logontime)/60;
-    read(file,&stats.uls,4);        /* Uploads today         */
-    stats.uls+=logon_uls;
-    read(file,&stats.ulb,4);        /* Upload bytes today    */
-    stats.ulb+=logon_ulb;
-    read(file,&stats.dls,4);        /* Downloads today       */
-    stats.dls+=logon_dls;
-    read(file,&stats.dlb,4);        /* Download bytes today  */
-    stats.dlb+=logon_dlb;
-	read(file,&stats.ptoday,4); 	/* Posts today			 */
-	if(!(useron.rest&FLAG('Q')))
-		stats.ptoday+=logon_posts;
-    read(file,&stats.etoday,4); /* Emails today          */
-    stats.etoday+=logon_emails;
-    read(file,&stats.ftoday,4); /* Feedback sent today  */
-    stats.ftoday+=logon_fbacks;
-	read(file,&stats.nusers,2); /* New users today		*/
-	if(sys_status&SS_NEWUSER)
-		stats.nusers++;
-    lseek(file,12L,SEEK_SET);
-	write(file,&stats.timeon,4);	/* Total time on system  */
-    write(file,&stats.ttoday,4);    /* Time today on system  */
-    write(file,&stats.uls,4);       /* Uploads today         */
-    write(file,&stats.ulb,4);       /* Upload bytes today    */
-    write(file,&stats.dls,4);       /* Downloads today       */
-    write(file,&stats.dlb,4);       /* Download bytes today  */
-    write(file,&stats.ptoday,4);    /* Posts today           */
-    write(file,&stats.etoday,4);    /* Emails today          */
-	write(file,&stats.ftoday,4);	/* Feedback sent today	 */
-	write(file,&stats.nusers,2);	/* New users today		 */
-    close(file); }
-
-}
-
-/****************************************************************************/
-/* Lists system statistics for everyday the bbs has been running.           */
-/* Either for the current node (node=1) or the system (node=0)              */
-/****************************************************************************/
-void printstatslog(uint node)
-{
-    char str[256];
-    uchar *buf;
-    int file;
-    time_t timestamp;
-    long l;
-    ulong   length,
-            logons,
-            timeon,
-            posts,
-            emails,
-            fbacks,
-            ulb,
-            uls,
-            dlb,
-            dls;
-
-if(node)
-    bprintf(text[NodeStatsLogHdr],node);
-else
-    bputs(text[SysStatsLogHdr]);
-sprintf(str,"%sCSTS.DAB",node ? node_path[node-1] : ctrl_dir);
-if((file=nopen(str,O_RDONLY))==-1)
-    return;
-length=filelength(file);
-if(length<40) {
-    close(file);
-    return; }
-if((buf=(char *)MALLOC(length))==0) {
-    close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length);
-    return; }
-read(file,buf,length);
-close(file);
-l=length-4;
-while(l>-1L && !msgabort()) {
-    fbacks=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    emails=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    posts=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    dlb=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    dls=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    ulb=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    uls=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    timeon=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    logons=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    timestamp=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    unixtodos(timestamp-(24*60*60),&date,&curtime); /* 1 day less than stamp */
-    bprintf(text[SlogFmt]
-        ,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900),timeon,logons,posts,emails
-        ,fbacks,ulb/1024,uls,dlb/1024,dls); }
-FREE(buf);
-}
-
-#ifdef __OS2__
-#define INPUT_LOOP 1000
-#else
-#define INPUT_LOOP 1000
-#endif
-
-/****************************************************************************/
-/* Terminal mode                                                            */
-/* Returns 1 if it is to logon locally, 0 if it is done.                    */
-/****************************************************************************/
-char terminal()
-{
-    char str[256],c,x,y,*p;
-	int file;
-	uint i,l;
-
-lclini(node_scrnlen-1);
-statline=-1;
-statusline();
-if(!term_ret) {
-#ifdef __FLAT__
-	setbaud(com_rate);
-#else
-	setbaud((uint)(com_rate&0xffffL));
-#endif
-	mdmcmd(mdm_term); }
-else
-    lputs("\r\nReturned.\r\n");
-
-l=0;    /* l is the ansi response code counter */
-
-while(1) {
-    if(lkbrd(1)) {
-        i=lkbrd(0);
-        if((i&0xff)==0) {
-            i>>=8;
-			if(i==45) { 			/* Alt-X */
-                rioctl(0x11);
-				if(DCDHIGH) {
-                    lputs("\r\nHang up (Yes/No/Abort) ? ");
-					c=toupper(getch());
-					if(c!='Y' && c!='N') {  /* Hang-up Y/N/Abort */
-                        lputs("Abort\r\n");
-                        continue; }
-					if(c=='Y') {    /* Yes, hang-up */
-						if(mdm_misc&MDM_NODTR)
-							mdmcmd(mdm_hang);
-						else
-							if(dtr(15))
-								lputs("Dropping DTR Failed"); } }
-                break; }
-			else if(i==35) {		/* Alt-H */
-				if(mdm_misc&MDM_NODTR)
-					mdmcmd(mdm_hang);
-				else
-					if(dtr(15))
-						lputs("Dropping DTR Failed\r\n");
-                dtr(1); }
-			else if((i>=0x3b &&i<=0x44) || (i>=0x54 &&i<=0x71)
-				|| (i>=0x85 &&i<=0x8c)) {
-                sprintf(str,"%s%sF%d.MAC",text_dir
-                    ,i<0x45 || (i>=0x85 && i<=0x86) ? nulstr
-                    :i<0x5e || (i>=0x87 && i<=0x88) ? "SHFT-"
-                    :i<0x68 || (i>=0x89 && i<=0x8a) ? "CTRL-" : "ALT-"
-                    ,i<0x45 ? i-0x3a : i<0x5e ? i-0x53 : i<0x68 ? i-0x5d
-                    :i<0x72 ? i-0x67 : i<0x87 ? i-0x7a : i<0x89 ? i-0x7c
-                    :i<0x8b ? i-0x7e : i-0x80);
-                if((file=nopen(str,O_RDONLY))==-1)
-                    continue;
-                i=filelength(file);
-                while(i--) {
-                    read(file,&c,1);
-                    if(c!=LF)
-                        putcomch(c); }
-                close(file); }
-			else if(i==0x48)	/* up arrow */
-				putcom("\x1b[A");
-			else if(i==0x50)	/* dn arrow */
-				putcom("\x1b[B");
-			else if(i==0x4b)	/* left */
-				putcom("\x1b[D");
-			else if(i==0x4d)	/* right */
-				putcom("\x1b[C");
-            else if(i==0x16) {  /* Alt-U User Edit */
-				if((p=MALLOC((node_scrnlen*80)*2))==NULL) {
-                    lputs("Allocation error.\r\n");
-                    continue; }
-                gettext(1,1,80,node_scrnlen,p);
-                x=lclwx();
-                y=lclwy();
-                quicklogonstuff();
-				useredit(0,1);
-                puttext(1,1,80,node_scrnlen,p);
-				FREE(p);
-                lclxy(x,y); }
-            else if(i==0x26) { /* Alt-L logon locally */
-                lputc(FF);
-                quicklogonstuff();
-                if(!useron.number) {
-                    lputc(7);
-                    lputs("A Sysop account hasn't been created");
-                    continue; }
-                term_ret=1;
-                return(1); }
-            else if(i==0x20) {  /* Alt-D Shell to DOS */
-				if((p=MALLOC((node_scrnlen*80)*2))==NULL) {
-                    lputs("Allocation error.\r\n");
-                    continue; }
-                gettext(1,1,80,node_scrnlen,p);
-                x=lclwx();
-                y=lclwy();
-                lclini(node_scrnlen);
-                lputc(FF);
-				external(comspec,0);
-                puttext(1,1,80,node_scrnlen,p);
-				FREE(p);
-                lclxy(x,y); } }
-		else {
-			putcomch(i);
-			continue; } }
-	for(i=0;i<INPUT_LOOP;i++) {
-        if((c=incom())!=0) {
-			if(c==ESC)
-                l=!l;
-            else if(l) {
-                if(c=='[') {
-                    if(l!=1) l=0; else l++; }
-                else if(c=='6') {
-                    if(l!=2) l=0; else l++; }
-                else if(c=='n') {
-                    if(l==3) {
-						sprintf(str,"\x1b[%u;%uR"
-                            ,lclwy(),lclwx());
-                        putcom(str); }
-                    l=0; }
-                else l=0; }
-			outcon(c); }
-		else
-			break; }
-	if(!c)
-		mswait(0); }
-term_ret=0;
-return(0);
-}
-
-
-/****************************************************************************/
-/* Exits bbs to DOS with appropriate error code after setting COM port isr  */
-/* back to normal.                                                          */
-/****************************************************************************/
-void bail(int code)
-{
-
-if(sys_status&SS_COMISR)
-    rioini(0,0);
-
-lclatr(LIGHTGRAY);
-if(code) {
-	getnodedat(node_num,&thisnode,1);
-	criterrs=++thisnode.errors;
-	putnodedat(node_num,thisnode);
-    now=time(NULL);
-    lprintf("\r\nExiting with errorlevel (%d) on %s\r\n",code,timestr(&now));
-    if(sys_misc&SM_ERRALARM) {
-		beep(500,220); beep(250,220);
-		beep(500,220); beep(250,220);
-		beep(500,220); beep(250,220);
-        nosound(); } }
-
-if(sys_status&SS_INITIAL) {
-    getnodedat(node_num,&thisnode,1);
-    thisnode.status=NODE_OFFLINE;
-    putnodedat(node_num,thisnode);
-    close(nodefile);
-    close(node_ext); }
-
-exit(code);
-}
-
-
diff --git a/src/sbbs2/main_sec.c b/src/sbbs2/main_sec.c
deleted file mode 100644
index deb0e7e510916292a9b49ab3ae5d33c0be3f9f75..0000000000000000000000000000000000000000
--- a/src/sbbs2/main_sec.c
+++ /dev/null
@@ -1,330 +0,0 @@
-#line 1 "MAIN_SEC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/******************************************************/
-/* This file contains the single function, main_sec() */
-/******************************************************/
-
-#include "sbbs.h"
-
-extern void logoff();
-
-void main_cfg_cmd();
-void main_ext_cmd(char ch);
-void main_str_cmd(char *str);
-void sysop_page(void);
-ulong getposts(uint subnum);
-
-char no_rip_menu=0;
-
-void new_scan_ptr_cfg()
-{
-	char	str[128];
-	long	i,j,s;
-	ulong	l;
-	time_t	t,lt;
-
-while(online) {
-	bputs(text[CfgGrpLstHdr]);
-	for(i=0;i<usrgrps && online;i++) {
-		checkline();
-		if(i<9) outchar(SP);
-		if(i<99) outchar(SP);
-		bprintf(text[CfgGrpLstFmt],i+1,grp[usrgrp[i]]->lname); }
-	SYNC;
-	mnemonics(text[WhichOrAll]);
-	s=getkeys("AQ",i);
-	if(!s || s==-1 || s=='Q')
-		break;
-	if(s=='A') {
-		mnemonics("\r\nEnter number of messages from end, ~Date, ~Quit, or"
-			" [Last Message]: ");
-		s=getkeys("DLQ",9999);
-		if(s==-1 || s=='Q')
-			continue;
-		if(s=='D') {
-			t=time(NULL);
-			if(inputnstime(&t) && !(sys_status&SS_ABORT)) {
-				bputs(text[LoadingMsgPtrs]);
-				for(i=0;i<usrgrps && online;i++)
-					for(j=0;j<usrsubs[i] && online;j++) {
-						checkline();
-						sub[usrsub[i][j]]->ptr=getmsgnum(usrsub[i][j],t); } }
-			continue; }
-		if(s=='L')
-			s=0;
-		if(s)
-			s&=~0x80000000L;
-		bputs(text[LoadingMsgPtrs]);
-		for(i=0;i<usrgrps;i++)
-			for(j=0;j<usrsubs[i] && online;j++) {
-				checkline();
-				getlastmsg(usrsub[i][j],&l,0);
-				if(s>l)
-					sub[usrsub[i][j]]->ptr=0;
-				else
-					sub[usrsub[i][j]]->ptr=l-s; }
-		continue; }
-	i=(s&~0x80000000L)-1;
-	while(online) {
-		l=0;
-		bprintf(text[CfgSubLstHdr],grp[usrgrp[i]]->lname);
-		for(j=0;j<usrsubs[i] && online;j++) {
-			checkline();
-			if(j<9) outchar(SP);
-			if(j<99) outchar(SP);
-			t=getmsgtime(usrsub[i][j],sub[usrsub[i][j]]->ptr);
-			if(t>l)
-				l=t;
-			bprintf(text[SubPtrLstFmt],j+1,sub[usrsub[i][j]]->lname
-				,timestr(&t),nulstr); }
-		SYNC;
-		mnemonics(text[WhichOrAll]);
-		s=getkeys("AQ",j);
-		if(sys_status&SS_ABORT) {
-			lncntr=0;
-			return; }
-		if(s==-1 || !s || s=='Q')
-			break;
-		if(s=='A') {    /* The entire group */
-			mnemonics("\r\nEnter number of messages from end, ~Date, ~Quit, or"
-				" [Last Message]: ");
-			s=getkeys("DLQ",9999);
-			if(s==-1 || s=='Q')
-				continue;
-			if(s=='D') {
-				t=l;
-				if(inputnstime(&t) && !(sys_status&SS_ABORT)) {
-					bputs(text[LoadingMsgPtrs]);
-					for(j=0;j<usrsubs[i] && online;j++) {
-						checkline();
-						sub[usrsub[i][j]]->ptr=getmsgnum(usrsub[i][j],t); } }
-				continue; }
-			if(s=='L')
-				s=0;
-			if(s)
-				s&=~0x80000000L;
-			bputs(text[LoadingMsgPtrs]);
-			for(j=0;j<usrsubs[i] && online;j++) {
-				checkline();
-				getlastmsg(usrsub[i][j],&l,0);
-				if(s>l)
-					sub[usrsub[i][j]]->ptr=0;
-				else
-					sub[usrsub[i][j]]->ptr=l-s; }
-			continue; }
-		else {
-			j=(s&~0x80000000L)-1;
-			mnemonics("\r\nEnter number of messages from end, ~Date, ~Quit, or"
-				" [Last Message]: ");
-			s=getkeys("DLQ",9999);
-			if(s==-1 || s=='Q')
-				continue;
-			if(s=='D') {
-				t=getmsgtime(usrsub[i][j],sub[usrsub[i][j]]->ptr);
-				if(inputnstime(&t) && !(sys_status&SS_ABORT)) {
-					bputs(text[LoadingMsgPtrs]);
-					sub[usrsub[i][j]]->ptr=getmsgnum(usrsub[i][j],t); }
-				continue; }
-			if(s=='L')
-				s=0;
-			if(s)
-				s&=~0x80000000L;
-			getlastmsg(usrsub[i][j],&l,0);
-			if(s>l)
-				sub[usrsub[i][j]]->ptr=0;
-			else
-				sub[usrsub[i][j]]->ptr=l-s; }
-			} }
-}
-
-void new_scan_cfg(ulong misc)
-{
-	long	s;
-	ulong	i,j;
-	ulong	t;
-
-while(online) {
-	bputs(text[CfgGrpLstHdr]);
-	for(i=0;i<usrgrps && online;i++) {
-		checkline();
-		if(i<9) outchar(SP);
-		if(i<99) outchar(SP);
-		bprintf(text[CfgGrpLstFmt],i+1,grp[usrgrp[i]]->lname); }
-	SYNC;
-	if(misc&SUB_NSCAN)
-		mnemonics(text[NScanCfgWhichGrp]);
-	else
-		mnemonics(text[SScanCfgWhichGrp]);
-	s=getnum(i);
-	if(s<1)
-		break;
-	i=s-1;
-	while(online) {
-		if(misc&SUB_NSCAN)
-			misc&=~SUB_YSCAN;
-		bprintf(text[CfgSubLstHdr],grp[usrgrp[i]]->lname);
-		for(j=0;j<usrsubs[i] && online;j++) {
-			checkline();
-			if(j<9) outchar(SP);
-			if(j<99) outchar(SP);
-			bprintf(text[CfgSubLstFmt],j+1
-				,sub[usrsub[i][j]]->lname
-				,sub[usrsub[i][j]]->misc&misc ?
-					(misc&SUB_NSCAN && sub[usrsub[i][j]]->misc&SUB_YSCAN) ?
-					"To You Only" : text[On] : text[Off]);
-				}
-		SYNC;
-		if(misc&SUB_NSCAN)
-			mnemonics(text[NScanCfgWhichSub]);
-		else
-			mnemonics(text[SScanCfgWhichSub]);
-		s=getkeys("AQ",j);
-		if(sys_status&SS_ABORT) {
-			lncntr=0;
-			return; }
-		if(!s || s==-1 || s=='Q')
-			break;
-		if(s=='A') {
-			t=sub[usrsub[i][0]]->misc&misc;
-			if(misc&SUB_NSCAN && !t)
-				if(!noyes("Messages to you only"))
-					misc|=SUB_YSCAN;
-			for(j=0;j<usrsubs[i] && online;j++) {
-				checkline();
-				if(t) sub[usrsub[i][j]]->misc&=~misc;
-				else  {
-					if(misc&SUB_NSCAN)
-						sub[usrsub[i][j]]->misc&=~SUB_YSCAN;
-					sub[usrsub[i][j]]->misc|=misc; } }
-			continue; }
-		j=(s&~0x80000000L)-1;
-		if(misc&SUB_NSCAN && !(sub[usrsub[i][j]]->misc&misc)) {
-			if(!noyes("Messages to you only"))
-				sub[usrsub[i][j]]->misc|=SUB_YSCAN;
-			else
-				sub[usrsub[i][j]]->misc&=~SUB_YSCAN; }
-		sub[usrsub[i][j]]->misc^=misc; } }
-}
-
-/****************************************************************************/
-/* Performs a new message scan all all sub-boards							*/
-/****************************************************************************/
-void scanallsubs(char mode)
-{
-	char str[256];
-	int i,j,found=0;
-
-if(/* action==NODE_MAIN && */ mode&(SCAN_FIND|SCAN_TOYOU)) {
-	i=yesno(text[DisplayTitlesOnlyQ]);
-	if(mode&SCAN_FIND) {
-		bputs(text[SearchStringPrompt]);
-		if(!getstr(str,40,K_LINE|K_UPPER))
-			return;
-		if(i) { 			/* if titles only */
-			for(i=0;i<usrgrps;i++) {
-				for(j=0;j<usrsubs[i] && !msgabort();j++)
-					found=searchsub(usrsub[i][j],str);
-				if(j<usrsubs[i])
-					break; }
-			if(!found)
-				CRLF;
-			sprintf(tmp,"Searched messages for '%s'",str);
-			logline(nulstr,tmp);
-			return; } }
-	else if(mode&SCAN_TOYOU && i) {
-		for(i=0;i<usrgrps;i++) {
-			for(j=0;j<usrsubs[i] && !msgabort();j++)
-				found=searchsub_toyou(usrsub[i][j]);
-			if(j<usrsubs[i])
-				break; }
-		if(!found)
-			CRLF;
-		return; } }
-
-if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT)) {
-	menu("MSGSCAN"); }
-for(i=0;i<usrgrps;i++) {
-	for(j=0;j<usrsubs[i] && !msgabort();j++)
-		if(((mode&SCAN_NEW && sub[usrsub[i][j]]->misc&(SUB_NSCAN|SUB_FORCED))
-			|| mode&SCAN_FIND
-			|| (mode&SCAN_TOYOU && sub[usrsub[i][j]]->misc&SUB_SSCAN))
-			&& scanposts(usrsub[i][j],mode,str)) break;
-	if(j<usrsubs[i])
-		break; }
-bputs(text[MessageScan]);
-if(i<usrgrps) {
-	bputs(text[MessageScanAborted]);
-	return; }
-bputs(text[MessageScanComplete]);
-if(mode&SCAN_NEW && !(mode&(SCAN_BACK|SCAN_TOYOU))
-	&& useron.misc&ANFSCAN && !(useron.rest&FLAG('T'))) {
-	xfer_cmds++;
-	scanalldirs(FL_ULTIME); }
-}
-
-/****************************************************************************/
-/* Used to scan single or multiple sub-boards. 'mode' is the scan type.     */
-/****************************************************************************/
-void scansubs(char mode)
-{
-	char ch,str[256];
-	int i=0,j,found=0;
-
-mnemonics(text[SubGroupOrAll]);
-ch=getkeys("SGA\r",0);
-if(sys_status&SS_ABORT || ch==CR)
-	return;
-
-if(ch!='A' && mode&(SCAN_FIND|SCAN_TOYOU)) {
-	if(yesno(text[DisplayTitlesOnlyQ])) i=1;
-	if(mode&SCAN_FIND) {
-		bputs(text[SearchStringPrompt]);
-		if(!getstr(str,40,K_LINE|K_UPPER))
-			return;
-		if(i) { 			/* if titles only */
-			if(ch=='S')
-				found=searchsub(usrsub[curgrp][cursub[curgrp]],str);
-			else if(ch=='G')
-				for(i=0;i<usrsubs[curgrp] && !msgabort();i++)
-					found=searchsub(usrsub[curgrp][i],str);
-			sprintf(tmp,"Searched messages for '%s'",str);
-			logline(nulstr,tmp);
-			if(!found)
-				CRLF;
-			return; } }
-	else if(mode&SCAN_TOYOU && i) {
-		if(ch=='S')
-			found=searchsub_toyou(usrsub[curgrp][cursub[curgrp]]);
-		else if(ch=='G')
-			for(i=0;i<usrsubs[curgrp] && !msgabort();i++)
-				found=searchsub_toyou(usrsub[curgrp][i]);
-		if(!found)
-			CRLF;
-		return; } }
-
-if(ch=='S') {
-	if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT)) {
-		menu("MSGSCAN"); }
-	i=scanposts(usrsub[curgrp][cursub[curgrp]],mode,str);
-	bputs(text[MessageScan]);
-	if(i) bputs(text[MessageScanAborted]);
-	else bputs(text[MessageScanComplete]);
-	return; }
-if(ch=='G') {
-	if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT)) {
-		menu("MSGSCAN"); }
-	for(i=0;i<usrsubs[curgrp] && !msgabort();i++)
-		if(((mode&SCAN_NEW &&
-			sub[usrsub[curgrp][i]]->misc&(SUB_NSCAN|SUB_FORCED))
-			|| (mode&SCAN_TOYOU && sub[usrsub[curgrp][i]]->misc&SUB_SSCAN)
-			|| mode&SCAN_FIND)
-			&& scanposts(usrsub[curgrp][i],mode,str)) break;
-	bputs(text[MessageScan]);
-	if(i==usrsubs[curgrp]) bputs(text[MessageScanComplete]);
-		else bputs(text[MessageScanAborted]);
-	return; }
-
-scanallsubs(mode);
-}
diff --git a/src/sbbs2/main_wfc.c b/src/sbbs2/main_wfc.c
deleted file mode 100644
index 9d459961b41b3a996ba0181b352e1da3428ccbba..0000000000000000000000000000000000000000
--- a/src/sbbs2/main_wfc.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-#line 1 "MAIN_WFC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "etext.h"
-#include "cmdshell.h"
-#include "qwk.h"
-
-extern char onquiet,nmi,llo,qwklogon;
-extern char term_ret;
-extern ulong connect_rate;	 /* already connected at xbps */
-extern char *wday[],*mon[];
-extern char *hungupstr;
-extern char cidarg[];
-
-void reset_logon_vars(void)
-{
-	int i;
-
-sys_status&=~(SS_USERON|SS_TMPSYSOP|SS_LCHAT|SS_ABORT
-    |SS_PAUSEON|SS_PAUSEOFF|SS_EVENT|SS_NEWUSER|SS_NEWDAY);
-keybufbot=keybuftop=lbuflen=slcnt=altul=timeleft_warn=0;
-logon_uls=logon_ulb=logon_dls=logon_dlb=0;
-logon_posts=logon_emails=logon_fbacks=0;
-posts_read=0;
-batdn_total=batup_total=0;
-usrgrps=usrlibs=0;
-curgrp=curlib=0;
-for(i=0;i<total_libs;i++)
-	curdir[i]=0;
-for(i=0;i<total_grps;i++)
-	cursub[i]=0;
-}
-
-void mail_maint(void)
-{
-	int i;
-
-lprintf("\r\n\r\nPurging deleted/expired e-mail...");
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0)
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-else {
-	if((i=smb_locksmbhdr(&smb))!=0)
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-	else
-		delmail(0,MAIL_ALL);
-	smb_close(&smb); }
-}
-
-/*************************************************************/
-/* Returns 0 to reinitialize modem and start WFC cycle again */
-/* Returns 1 to continue checking things peacefully 		 */
-/*************************************************************/
-char wfc_events(time_t lastnodechk)
-{
-	char	str[256],str2[256],*buf;
-	int 	i,j,k,file,ret=1,chunk;
-	ulong	l,m;
-	user_t	user;
-	node_t	node;
-	struct	ffblk ff;
-	struct	tm *gm;
-	struct	date lastdate;
-
-for(i=0;i<total_qhubs;i++) {
-	gm=localtime(&now); 	  /* Qnet call out based on time */
-	unixtodos(qhub[i]->last,&date,&curtime);
-	if(node_num==qhub[i]->node				/* or frequency */
-		&& (qhub[i]->last==-1L
-		|| ((qhub[i]->freq
-			&& (now-qhub[i]->last)/60>qhub[i]->freq)
-		|| (qhub[i]->time
-			&& (gm->tm_hour*60)+gm->tm_min>=qhub[i]->time
-		&& (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)))
-		&& qhub[i]->days&(1<<gm->tm_wday))) {
-		offhook();
-		lputc(FF);
-		sprintf(str,"%sQNET\\%s.NOW"
-			,data_dir,qhub[i]->id);
-		remove(str);					/* Remove semaphore file */
-		sprintf(str,"%sQNET\\%s.PTR"
-			,data_dir,qhub[i]->id);
-		file=nopen(str,O_RDONLY);
-		for(j=0;j<qhub[i]->subs;j++) {
-			sub[qhub[i]->sub[j]]->ptr=0;
-			lseek(file,sub[qhub[i]->sub[j]]->ptridx*4L,SEEK_SET);
-			read(file,&sub[qhub[i]->sub[j]]->ptr,4); }
-		if(file!=-1)
-			close(file);
-		if(pack_rep(i)) {
-			if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
-				errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-			else {
-				for(j=l=0;j<qhub[i]->subs;j++) {
-					while(filelength(file)<sub[qhub[i]->sub[j]]->ptridx*4L)
-						write(file,&l,4);		/* initialize ptrs to null */
-					lseek(file,sub[qhub[i]->sub[j]]->ptridx*4L,SEEK_SET);
-					write(file,&sub[qhub[i]->sub[j]]->ptr,4); }
-				close(file); } }
-		delfiles(temp_dir,"*.*");
-
-		qhub[i]->last=time(NULL);
-		sprintf(str,"%sQNET.DAB",ctrl_dir);
-		if((file=nopen(str,O_WRONLY))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-			bail(1); }
-		lseek(file,sizeof(time_t)*i,SEEK_SET);
-		write(file,&qhub[i]->last,sizeof(time_t));
-		close(file);
-
-		if(qhub[i]->call[0]) {
-			getnodedat(node_num,&thisnode,1);
-			thisnode.status=NODE_NETTING;
-			putnodedat(node_num,thisnode);
-			lputc(FF);
-			external(cmdstr(qhub[i]->call,nulstr,nulstr,NULL),EX_SWAP);
-			ret=0; }
-		for(j=0;j<10;j++) {
-			sprintf(str,"%s%s.QW%c",data_dir,qhub[i]->id,j ? (j-1)+'0' : 'K');
-			if(fexist(str)) {
-				lclini(node_scrnlen-1);
-				delfiles(temp_dir,"*.*");
-				unpack_qwk(str,i); } }
-		lputc(FF); } }
-
-for(i=0;i<total_phubs;i++) {
-	gm=localtime(&now); 	  /* PostLink call out based on time */
-	unixtodos(phub[i]->last,&date,&curtime);
-	if(node_num==phub[i]->node				/* or frequency */
-		&& ((phub[i]->freq
-			&& (now-phub[i]->last)/60>phub[i]->freq)
-		|| (phub[i]->time
-			&& (gm->tm_hour*60)+gm->tm_min>=phub[i]->time
-		&& (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)))
-		&& phub[i]->days&(1<<gm->tm_wday)) {
-		offhook();
-		lputc(FF);
-
-		phub[i]->last=time(NULL);
-		sprintf(str,"%sPNET.DAB",ctrl_dir);
-		if((file=nopen(str,O_WRONLY))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-			bail(1); }
-		lseek(file,sizeof(time_t)*i,SEEK_SET);
-		write(file,&phub[i]->last,sizeof(time_t));
-		close(file);
-
-		if(phub[i]->call[0]) {
-			getnodedat(node_num,&thisnode,1);
-			thisnode.status=NODE_NETTING;
-			putnodedat(node_num,thisnode);
-			lputc(FF);
-			external(cmdstr(phub[i]->call,nulstr,nulstr,NULL),EX_SWAP);
-			ret=0; } } }
-
-for(i=0;i<total_events;i++) {
-	if(!event[i]->node || event[i]->node>sys_nodes)
-        continue;
-	gm=localtime(&now);
-	unixtodos(event[i]->last,&date,&curtime);
-	if(event[i]->last==-1
-		|| ((gm->tm_hour*60)+gm->tm_min>=event[i]->time
-		&& (gm->tm_mday!=date.da_day || gm->tm_mon!=date.da_mon-1)
-		&& event[i]->days&(1<<gm->tm_wday))) {
-
-		if(event[i]->misc&EVENT_EXCL) { /* exclusive event */
-			offhook();
-			lputc(FF);
-			if(event[i]->node!=node_num) {
-				lprintf("Waiting for node %d to run timed event.\r\n\r\n"
-					,event[i]->node);
-				lputs("Hit any key to abort wait...");
-				getnodedat(node_num,&thisnode,1);
-				thisnode.status=NODE_EVENT_LIMBO;
-				thisnode.aux=event[i]->node;
-				putnodedat(node_num,thisnode);
-				lastnodechk=0;	 /* really last event time check */
-				while(!lkbrd(0)) {
-					mswait(1);
-					now=time(NULL);
-					if(now-lastnodechk<10)
-						continue;
-					getnodedat(node_num,&thisnode,0);
-					if(thisnode.misc&NODE_DOWN)
-						return(0);
-					lastnodechk=now;
-					sprintf(str,"%sTIME.DAB",ctrl_dir);
-					if((file=nopen(str,O_RDONLY))==-1) {
-						errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-						event[i]->last=now;
-						return(0); }
-					lseek(file,(long)i*4L,SEEK_SET);
-					read(file,&event[i]->last,sizeof(time_t));
-					close(file);
-					if(now-event[i]->last<(60*60))	/* event is done */
-						break; }
-				sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
-				remove(str);
-				event[i]->last=now;
-				ret=0; }
-			else {
-				lputs("Waiting for all nodes to become inactive before "
-					"running timed event.\r\n\r\n");
-				lputs("Hit any key to abort wait and run event now...\r\n\r\n");
-				getnodedat(node_num,&thisnode,1);
-				thisnode.status=NODE_EVENT_WAITING;
-				putnodedat(node_num,thisnode);
-				lastnodechk=0;
-				while(!lkbrd(0)) {
-					mswait(1);
-					now=time(NULL);
-					if(now-lastnodechk<10)
-						continue;
-					lastnodechk=now;
-					getnodedat(node_num,&thisnode,0);
-					if(thisnode.misc&NODE_DOWN)
-                        return(0);
-					for(j=1;j<=sys_nodes;j++) {
-						if(j==node_num)
-							continue;
-						getnodedat(j,&node,0);
-						if(node.status!=NODE_OFFLINE
-							&& node.status!=NODE_EVENT_LIMBO)
-							break; }
-					if(j>sys_nodes) /* all nodes either offline or in limbo */
-						break;
-					lprintf("\rWaiting for node %d (status=%d)"
-						,j,node.status);
-					lputc(CLREOL); } } }
-		if(event[i]->node!=node_num)
-			event[i]->last=now;
-		else {
-			sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
-			remove(str);
-			offhook();
-			lputc(FF);
-			getnodedat(node_num,&thisnode,1);
-			thisnode.status=NODE_EVENT_RUNNING;
-			putnodedat(node_num,thisnode);
-			if(event[i]->dir[0]) {
-				if(event[i]->dir[1]==':')           /* drive letter specified */
-					setdisk(toupper(event[i]->dir[0])-'A');
-				if(chdir(event[i]->dir))
-					errormsg(WHERE,ERR_CHDIR,event[i]->dir,0); }
-
-			external(cmdstr(event[i]->cmd,nulstr,nulstr,NULL),0);  /* EX_CC */
-			event[i]->last=time(NULL);
-			sprintf(str,"%sTIME.DAB",ctrl_dir);
-			if((file=nopen(str,O_WRONLY))==-1) {
-				errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-				return(ret); }
-			lseek(file,(long)i*4L,SEEK_SET);
-			write(file,&event[i]->last,sizeof(time_t));
-			close(file);
-			ret=0; } } }
-
-
-if(sys_status&SS_DAILY || thisnode.misc&NODE_EVENT) {  /* daily events */
-
-	offhook();
-    lputc(FF);
-
-	if(sys_status&SS_DAILY) {
-
-		getnodedat(node_num,&thisnode,1);
-		now=time(NULL);
-		j=lastuser();
-		thisnode.status=NODE_EVENT_RUNNING;
-		putnodedat(node_num,thisnode);
-
-		lprintf("Running system daily maintenance...\r\n\r\n");
-		logentry("!:","Ran system daily maintenance");
-		for(i=1;i<=j;i++) {
-
-			lprintf("\rChecking user %5u of %-5u",i,j);
-			user.number=i;
-			getuserdat(&user);
-
-			/***********************************************/
-			/* Fix name (NAME.DAT and USER.DAT) mismatches */
-			/***********************************************/
-			if(user.misc&DELETED) {
-				if(strcmp(username(i,str2),"DELETED USER"))
-					putusername(i,nulstr);
-				continue; }
-
-			if(strcmp(user.alias,username(i,str2)))
-				putusername(i,user.alias);
-
-			if(!(user.misc&(DELETED|INACTIVE))
-				&& user.expire && (ulong)user.expire<=(ulong)now) {
-				putsmsg(i,text[AccountHasExpired]);
-				sprintf(str,"%s #%u Expired",user.alias,user.number);
-				logentry("!%",str);
-				if(level_misc[user.level]&LEVEL_EXPTOVAL
-					&& level_expireto[user.level]<10) {
-					user.flags1=val_flags1[level_expireto[user.level]];
-					user.flags2=val_flags2[level_expireto[user.level]];
-					user.flags3=val_flags3[level_expireto[user.level]];
-					user.flags4=val_flags4[level_expireto[user.level]];
-					user.exempt=val_exempt[level_expireto[user.level]];
-					user.rest=val_rest[level_expireto[user.level]];
-					if(val_expire[level_expireto[user.level]])
-						user.expire=now
-							+(val_expire[level_expireto[user.level]]*24*60*60);
-					else
-						user.expire=0;
-					user.level=val_level[level_expireto[user.level]]; }
-				else {
-					if(level_misc[user.level]&LEVEL_EXPTOLVL)
-						user.level=level_expireto[user.level];
-					else
-						user.level=expired_level;
-					user.flags1&=~expired_flags1; /* expired status */
-					user.flags2&=~expired_flags2; /* expired status */
-					user.flags3&=~expired_flags3; /* expired status */
-					user.flags4&=~expired_flags4; /* expired status */
-					user.exempt&=~expired_exempt;
-					user.rest|=expired_rest;
-					user.expire=0; }
-				putuserrec(i,U_LEVEL,2,itoa(user.level,str,10));
-				putuserrec(i,U_FLAGS1,8,ultoa(user.flags1,str,16));
-				putuserrec(i,U_FLAGS2,8,ultoa(user.flags2,str,16));
-				putuserrec(i,U_FLAGS3,8,ultoa(user.flags3,str,16));
-				putuserrec(i,U_FLAGS4,8,ultoa(user.flags4,str,16));
-				putuserrec(i,U_EXPIRE,8,ultoa(user.expire,str,16));
-				putuserrec(i,U_EXEMPT,8,ultoa(user.exempt,str,16));
-				putuserrec(i,U_REST,8,ultoa(user.rest,str,16));
-				if(expire_mod[0]) {
-					useron=user;
-					online=ON_LOCAL;
-					exec_bin(expire_mod,&main_csi);
-					online=0; }
-				}
-
-			/***********************************************************/
-			/* Auto deletion based on expiration date or days inactive */
-			/***********************************************************/
-			if(!(user.exempt&FLAG('P'))     /* Not a permanent account */
-				&& !(user.misc&(DELETED|INACTIVE))	 /* alive */
-				&& (sys_autodel && (now-user.laston)/(long)(24L*60L*60L)
-				> sys_autodel)) {			/* Inactive too long */
-				sprintf(str,"Auto-Deleted %s #%u",user.alias,user.number);
-				logentry("!*",str);
-				delallmail(i);
-				putusername(i,nulstr);
-				putuserrec(i,U_MISC,8,ultoa(user.misc|DELETED,str,16)); }
-
-			if(!(user.misc&(DELETED|INACTIVE))
-				&& preqwk_ar[0] && chk_ar(preqwk_ar,user)) {  /* Pre-QWK */
-				for(k=1;k<=sys_nodes;k++) {
-					getnodedat(k,&node,0);
-					if((node.status==NODE_INUSE || node.status==NODE_QUIET
-						|| node.status==NODE_LOGON) && node.useron==i)
-						break; }
-				if(k<=sys_nodes)	/* Don't pre-pack with user online */
-					continue;
-				lclini(node_scrnlen-1);
-				lclatr(LIGHTGRAY);
-                lputc(FF);
-				console|=CON_L_ECHO;
-				lprintf("Pre-packing QWK for %s...\r\n"
-					,user.alias);
-				useron=user;
-				online=ON_LOCAL;
-				statline=sys_def_stat;
-				statusline();
-				useron.qwk&=~QWK_FILES; /* turn off for pre-packing */
-				useron.misc|=(ANSI|COLOR);
-				delfiles(temp_dir,"*.*");
-				getmsgptrs();
-				getusrsubs();
-				batdn_total=0;
-				sprintf(str,"%sFILE\\%04u.QWK"
-					,data_dir,useron.number);
-				if(pack_qwk(str,&l,1)) {
-					qwk_success(l,0,1);
-					putmsgptrs(); }
-				delfiles(temp_dir,"*.*");
-				lclatr(LIGHTGRAY);
-				lclini(node_scrnlen);
-				online=0;
-				lputc(FF); } }
-
-		mail_maint();
-
-		lprintf("\r\n\r\nRunning system daily event...\r\n");
-		logentry("!:","Ran system daily event");
-		sys_status&=~SS_DAILY;
-		if(sys_daily[0])
-			external(cmdstr(sys_daily,nulstr,nulstr,NULL),0); }    /* EX_CC */
-
-	if(thisnode.misc&NODE_EVENT) {
-		getnodedat(node_num,&thisnode,1);
-        thisnode.status=NODE_EVENT_RUNNING;
-        putnodedat(node_num,thisnode);
-		if(node_daily[0])
-			external(cmdstr(node_daily,nulstr,nulstr,NULL),0); /* EX_CC */
-		getnodedat(node_num,&thisnode,1);
-		thisnode.misc&=~NODE_EVENT;
-		putnodedat(node_num,thisnode); }
-	ret=0; }
-return(ret);
-}
-
-/****************************************************************************/
-/* This function waits for either a caller or a local logon. It returns 0   */
-/* if the user failed the logon procedure, a 1 if the user succeeded        */
-/* Called from function main                                                */
-/****************************************************************************/
-char waitforcall()
-{
-	static uint calls;
-	uchar str[256],str2[256],cname[LEN_CID+1],c,gotcaller=0,x,y,dcd,*p
-		,ans=0,hbeat=0,menuon=0,blank=0
-		,*ok=mdm_misc&MDM_VERBAL ? "OK":"0"
-
-	/* IP logging vars added by enigma */
-		, ipstr[256], *ips;
-
-	uint i,j,k,nodes,lastnodes=0;
-	long l,m;
-	int file,result_code=0;
-	time_t start,lastnodechk=0,laststatchk=0,laststatfdate=0;
-    node_t node;
-    struct tm *gm;
-	struct dfree d;
-	stats_t stats,node_stats;
-
-reset_logon_vars();
-ipstr[0]=cid[0]=cname[0]=0;
-online=console=0;
-start=time(NULL);
-
-getnodedat(node_num,&thisnode,1);
-thisnode.status=NODE_WFC;
-thisnode.misc&=~(NODE_INTR|NODE_MSGW|NODE_NMSG|NODE_UDAT|NODE_POFF|NODE_AOFF);
-putnodedat(node_num,thisnode);
-catsyslog(0);
-if(term_ret)
-    return(terminal());
-/***
-if(com_port)
-    rioctl(0x10f);  /* for blanking debug line */
-***/
-
-if(qoc && calls) {
-    if(qoc==1)
-        offhook();
-    lclini(node_scrnlen);
-    lputc(FF);
-    bail(0); }
-useron.misc=0;
-rows=24;
-lputc(FF);
-if(node_misc&NM_RESETVID) {
-	textmode(C40);
-	textmode(C80);
-	_setcursortype(_NORMALCURSOR); }
-
-lclatr(curatr=LIGHTGRAY);
-lclini(node_scrnlen);
-
-
-lputc(FF);
-if(com_port && !connect_rate) {  /* Initialize the modem */
-	lprintf("\rSetting DTE rate: %lu baud",com_rate);
-	lputc(CLREOL);
-#ifdef __OS2__
-	if((i=setbaud(com_rate))!=0) {
-#else
-	if((i=setbaud((uint)(com_rate&0xffffL)))!=0) {
-#endif
-		lprintf(" - Failed! (%d)\r\n",i);
-		bail(1); }
-    c=0;
-	if(!nmi && !(mdm_misc&MDM_DUMB))	/* if not dumb */
-    while(c<4) {
-        rioctl(IOFB);
-        rioctl(IOCM|PAUSE|ABORT);
-        rioctl(IOCS|PAUSE|ABORT);
-
-		if(mdm_misc&MDM_CTS)
-            if(!(rioctl(IOSTATE)&CTS)) {
-				lputs("\rWaiting up to 30 seconds for CTS to raise (  )\b\b\b");
-				for(i=0;i<30 && !lkbrd(0);i++) {   /* wait upto 15 seconds */
-					lprintf("%2d\b\b",i+1);
-					mswait(1000);
-					if(rioctl(IOSTATE)&CTS)
-						break; }
-				if(i==30) {
-					lputs("\r\n\r\nModem configured for hardware flow "
-						"control and CTS is stuck low.\r\n");
-					logline("@!","CTS stuck low. Can't initialize.");
-					bail(1); } }
-
-		lputs("\rInitializing modem...");
-		lputc(CLREOL);
-
-		dtr(5); 		/* in case we're still connected to somebody */
-        dtr(1);
-		mswait(750);	/* DTR is sometimes slow */
-        rioctl(IOFB);   /* crap comes in when dtr is raised ? */
-		if(rioctl(IOSTATE)&DCD && mdm_hang[0]) {
-			mdmcmd(mdm_hang);
-			if(strcmp(str,"0") && strcmp(str,"OK"))
-				getmdmstr(str,SEC_OK); }
-
-		/******************************************/
-		/* Take phone off-hook while initializing */
-		/******************************************/
-		offhook();		
-		getmdmstr(str,SEC_OK);
-        if(strcmp(str,"0") && strcmp(str,"OK"))
-			getmdmstr(str,SEC_OK);
-
-		/*********************************************************/
-		/* Send User Configured (broken?) initialization strings */
-		/*********************************************************/
-        mdmcmd(mdm_init);
-        if(mdm_spec[0]) {
-			getmdmstr(str,SEC_OK);
-			if(strcmp(str,"0") && strcmp(str,"OK"))
-				getmdmstr(str,SEC_OK);
-            mdmcmd(mdm_spec); }
-		getmdmstr(str,SEC_OK);
-		if(strcmp(str,"0") && strcmp(str,"OK"))
-			getmdmstr(str,SEC_OK);
-
-		/*****************************/
-		/* Send AT&C1 if DCD is high */
-		/*****************************/
-        if(rioctl(IOSTATE)&DCD) {
-			lputs("\r\nDCD is high. Sending AT&C1 to modem...");
-			mdmcmd("AT&C1");
-			getmdmstr(str,SEC_OK);
-			if(strcmp(str,ok))
-				getmdmstr(str,SEC_OK); }
-
-		/**********************************************/
-		/* DCD still high? Pause and try dropping DTR */
-		/**********************************************/
-        if(rioctl(IOSTATE)&DCD) {
-			lputs("\r\nDCD is high. Pausing...");
-			dtr(0);
-			mswait(2000);
-			rioctl(MSR);
-			if(rioctl(IOSTATE)&DCD) {
-				lputs("\rDCD was high after modem init.\r\n");
-				logentry("@!","DCD was high after modem init");
-				if(mdm_misc&MDM_NODTR)
-					mdmcmd(mdm_hang);
-				else
-					dtr(15);
-				if(rioctl(IOSTATE)&DCD) {
-					lputs("Hanging up failed to lower DCD.\r\n");
-					logentry("@!","Hanging up failed to lower DCD");
-					if(++c==4)
-						break;
-					continue; } }
-			dtr(1); }
-
-		/************************************************************/
-		/* Let's repair any damage the user configured init strings */
-		/* may have caused											*/
-		/************************************************************/
-		for(i=0;i<4;i++) {
-			rioctl(IOFB);
-			mdmcmd("AT");
-			if(!getmdmstr(str,SEC_OK) || !strcmp(str,ok))
-				break;
-			if(!strcmp(str,"AT")) {     /* Echoing commands? */
-				getmdmstr(str,SEC_OK);	/* Get OK */
-				lputs("\r\nCommand echoed. Sending ATE0 to modem...");
-				mdmcmd("ATE0"); }
-			else if(mdm_misc&MDM_VERBAL && !strcmp(str,"0")) { /* numeric? */
-				lputs("\r\nNumeric response. Sending ATV1 to modem...");
-				mdmcmd("ATV1"); }
-			else if(!(mdm_misc&MDM_VERBAL) && !strcmp(str,"OK")) {
-				lputs("\r\nVerbal response. Sending ATV0 to modem...");
-				mdmcmd("ATV0"); }
-			else {
-				lprintf("\r\nUnrecognized response '%s'. Sending AT to modem..."
-					,str);
-				mdmcmd("AT"); }
-			if(getmdmstr(str,SEC_OK) && !strcmp(str,ok))
-				break; }
-
-		/************************************************/
-		/* Put phone back on-hook and check result code */
-		/************************************************/
-		if(!mdm_hang[0])
-			mdmcmd("ATH");
-		else
-			mdmcmd(mdm_hang); 
-		if(!getmdmstr(str,SEC_OK)) {
-			lputs("\r\nNo response.\r\n");
-			logentry("@!","No response"); }
-        else {
-			if(!strcmp(str,ok))
-                break;
-			lprintf("\r\nInvalid result code: '%s' "
-				"instead of '%s'.\r\n",str,ok);
-			sprintf(tmp,"Invalid result code: '%s' instead of '%s'.",str,ok);
-            logentry("@!",tmp); }
-        if(++c==4)
-            break;
-        rioini(0,0);                /* remove com routines */
-        sys_status&=~SS_COMISR;
-		comini();
-		setrate(); }
-    if(c==4) {
-		lputs("\r\nModem failed initialization.\r\n");
-		errorlog("Modem failed initialization.");
-		offhook();
-        bail(1); }
-	lputc(FF); }
-
-else if(com_port && connect_rate) {
-    gotcaller=1;
-	console=CON_R_ECHO|CON_L_ECHO|CON_R_INPUT|CON_L_INPUT;
-	online=ON_REMOTE;
-	sprintf(connection,"%lu",connect_rate);
-	cur_rate=connect_rate;
-	cur_cps=connect_rate/10;
-	connect_rate=0;
-	if(cidarg[0]) { 					/* Caller-id passed as argument */
-		mdm_misc|=MDM_CALLERID;
-		p=strstr(cidarg,"NUMBER:");
-		if(p) p+=8;
-		else {
-			p=strstr(cidarg,"NMBR");
-			if(p) p+=7; }
-		if(p) { 						   /* 3 message format */
-			sprintf(cid,"%.*s",LEN_CID,p);
-			for(i=strlen(cid);!isdigit(cid[i]) && i;i--)
-				;
-			cid[i+1]=0; 					/* chop off non-numbers */
-			p=strstr(cidarg,"NAME:");
-			if(p) p+=6;
-			else {
-				p=strstr(cidarg,"NAME");
-				if(p) p+=7; }
-			if(p)
-				sprintf(cname,"%.*s",LEN_CID,p); }
-		else if(strlen(cidarg)>12)		   /* Single message format */
-			sprintf(cid,"%.*s",LEN_CID,cidarg+12);
-		else
-			sprintf(cid,"ERROR: '%s'",cidarg); } }
-
-
-if(!online) {
-	/*******************************************************/
-    /* To make sure that BBS print routines work correctly */
-    /*******************************************************/
-    useron.number=1;
-    getuserdat(&useron);
-    if(!useron.number)
-        useron.misc=ANSI|COLOR; }
-
-useron.misc&=~UPAUSE;	/* make sure pause is off */
-
-if(llo) {
-	quicklogonstuff();
-	sys_status&=~SS_USERON;
-	gotcaller=1; }
-
-if(!(useron.misc&EXPERT) && !gotcaller) {	/* Novice sysop */
-	console=CON_L_ECHO;
-	online=ON_LOCAL;
-	lputc(FF);
-	tos=1;
-	lncntr=0;
-	menu("WFC");
-	menuon=1;
-	online=0; }
-
-while(!gotcaller) {
-	mswait(0);		   /* give up rest of time slice */
-
-	console=CON_L_ECHO;
-    now=time(NULL);
-
-	if(node_scrnblank && (now-start)/60>node_scrnblank
-		&& !blank) { /* blank screen */
-		lputc(FF);
-		menuon=0;
-		blank=1; }
-	if(mdm_reinit && (now-start)/60>mdm_reinit) /* reinitialize modem */
-		return(0);
-	if(now-lastnodechk>node_sem_check) {  /* check node.dab every x seconds */
-
-#if 1
-		if((i=heapcheck())!=_HEAPOK) {
-			lputc(FF);
-			offhook();
-			errormsg(WHERE,ERR_CHK,"heap",i);
-			bail(1); }
-#endif
-
-		for(i=0;i<total_qhubs;i++)
-			if(node_num==qhub[i]->node) {
-				sprintf(str,"%sQNET\\%s.NOW",data_dir,qhub[i]->id);
-				if(fexist(str))
-					qhub[i]->last=-1; }
-
-		for(i=0;i<total_events;i++)
-			if(node_num==event[i]->node || event[i]->misc&EVENT_EXCL) {
-				sprintf(str,"%s%s.NOW",data_dir,event[i]->code);
-				if(fexist(str))
-					event[i]->last=-1; }
-
-        lastnodechk=now;
-        getnodedat(node_num,&thisnode,0);
-        if(thisnode.misc&NODE_DOWN) {
-            lputc(FF);
-            offhook();
-            bail(0); }
-        if(thisnode.status!=NODE_WFC) {
-            getnodedat(node_num,&thisnode,1);
-            thisnode.status=NODE_WFC;
-            putnodedat(node_num,thisnode); }
-        if(thisnode.misc&NODE_RRUN) {   /* Re-run the node */
-            offhook();
-            lputc(FF);
-            getnodedat(node_num,&thisnode,1);
-            thisnode.status=NODE_OFFLINE;
-            thisnode.misc=0;
-            putnodedat(node_num,thisnode);
-            close(nodefile);
-			close(node_ext);
-			sys_status&=~SS_NODEDAB;
-            if(sys_status&SS_LOGOPEN)
-                close(logfile);
-            if(sys_status&SS_COMISR)
-                rioini(0,0);
-            sys_status&=~(SS_COMISR|SS_INITIAL|SS_LOGOPEN);
-            p=strchr(orgcmd,' ');
-            if(p)
-                p++;
-			close(5);
-			if(execle(orgcmd,orgcmd,p,NULL,envp)) {
-				lprintf("\r\nCouldn't execute %s!\r\n",orgcmd);
-                bail(1); } } }
-
-	if(!wfc_events(lastnodechk))
-		return(0);
-
-	if(!menuon) {
-		/******************/
-		/* Roaming cursor */
-		/******************/
-		x=lclwx();
-		y=lclwy();
-		switch(random(5)) {
-			case 0:
-				if(x>1)
-					x--;
-				break;
-			case 1:
-				if(x<79)
-					x++;
-				break;
-			case 2:
-				if(y>1)
-					y--;
-				break;
-			case 4:
-				if(y<node_scrnlen-2)
-					y++;
-				break; } }
-	else {						/* across the bottom */
-		y=25;
-		x=lclwx();
-		if(x%2) x+=2;
-		else x-=2;
-		if(x<1)
-			x=1;
-		else if(x>80)
-			x=80;
-/*
-		lclxy(x,y);
-		gettext(x,y,x,y,&i);
-		lclatr(random(0xf)+1);
-		lputc(i);
-		lclatr(LIGHTGRAY);
-*/
-/**
-		mswait(100);
-		puttext(x,y,x,y,&i);
-**/ 	   }
-
-#ifndef __FLAT__		// Heart beat always for 32-bit OSs
-	if(inDV) {
-#endif
-		lclxy(80,1);
-		if(hbeat) {
-			lclatr(RED|HIGH);
-			lputc(3); }
-		else
-			lputc(0);
-		hbeat=!hbeat;
-		lclatr(LIGHTGRAY);
-#ifndef __FLAT__
-		}
-#endif
-
-	lclxy(x,y);
-	mswait(100);
-
-								/* Wait for call screen */
-								/* check every 10 seconds */
-
-	if(node_misc&NM_WFCSCRN && now-laststatchk>node_stat_check
-		&& !menuon && !blank) {
-		laststatchk=now;
-		sprintf(str,"%sDSTS.DAB",ctrl_dir);
-		if(fdate(str)!=laststatfdate) {   /* system statistics */
-			lclxy(1,1);
-			lclatr(LIGHTGRAY);
-			lputs("Retrieving Statistics.");
-			lputc(CLREOL);
-			if(!laststatfdate)	/* First time this WFC */
-				getstats(node_num,&node_stats);
-			lputc('.');
-			laststatfdate=fdate(str);
-			getstats(0,&stats);
-			lputc('.');
-			l=m=0;
-			if(node_misc&NM_WFCMSGS) {
-				for(i=0;i<total_subs;i++)
-					l+=getposts(i); 			/* l=total posts */
-				lputc('.');
-				for(i=0;i<total_dirs;i++)
-					m+=getfiles(i); 			/* m=total files */
-				lputc('.'); }
-			i=getmail(0,0); 				/* i=total email */
-			lputc('.');
-			j=getmail(1,0); 				/* j=total fback */
-			lclxy(1,1);
-			lclatr(GREEN);
-			lprintf("Node #: ");
-			lclatr(GREEN|HIGH);
-			gm=localtime(&now);
-			lprintf("%-3u ",node_num);
-			lclatr(GREEN);
-			lprintf("%-3.3s %-2u  Space: ",mon[gm->tm_mon],gm->tm_mday);
-			if(temp_dir[1]==':')
-				k=temp_dir[0]-'A'+1;
-			else k=0;
-			getdfree(k,&d);
-			if((ulong)d.df_bsec*(ulong)d.df_sclus
-				*(ulong)d.df_avail<((ulong)min_dspace*1024L)*2L)
-				lclatr(RED|HIGH|BLINK);
-			else
-				lclatr(GREEN|HIGH);
-			sprintf(str,"%sk",ultoac(((ulong)d.df_bsec
-				*(ulong)d.df_sclus*(ulong)d.df_avail)/1024UL,tmp));
-			lprintf("%-12.12s",str);
-			if(lastuseron[0]) {
-				lclatr(GREEN);
-				lprintf("Laston: ");
-				lclatr(GREEN|HIGH);
-				lprintf(lastuseron);
-				lclatr(GREEN);
-				if(thisnode.connection)
-					lprintf(" %u",thisnode.connection);
-				else
-					lprintf(" Local"); }
-			lprintf("\r\n");
-			lclatr(GREEN);
-			lprintf("Logons: ");
-			lclatr(GREEN|HIGH);
-			sprintf(tmp,"%lu/%lu",node_stats.ltoday,stats.ltoday);
-			lprintf("%-12.12s",tmp);
-			lclatr(GREEN);
-			lprintf("Total: ");
-			lclatr(GREEN|HIGH);
-			lprintf("%-12.12s",ultoac(stats.logons,tmp));
-			lclatr(GREEN);
-			lprintf("Timeon: ");
-			lclatr(GREEN|HIGH);
-			sprintf(tmp,"%lu/%lu",node_stats.ttoday,stats.ttoday);
-			lprintf("%-12.12s",tmp);
-			lclatr(GREEN);
-			lprintf("Total: ");
-			lclatr(GREEN|HIGH);
-			lprintf("%-12.12s\r\n",ultoac(stats.timeon,tmp));
-			lclatr(GREEN);
-			lprintf("Emails: ");
-			lclatr(GREEN|HIGH);
-			sprintf(str,"%u/%u",(uint)stats.etoday,i);
-			lprintf("%-12.12s",str);
-			lclatr(GREEN);
-			lprintf("Posts: ");
-			lclatr(GREEN|HIGH);
-			sprintf(str,"%u",(uint)stats.ptoday);
-			if(node_misc&NM_WFCMSGS) {
-				strcat(str,"/");
-				strcat(str,ultoa(l,tmp,10)); }
-			lprintf("%-12.12s",str);
-			lclatr(GREEN);
-			lprintf("Fbacks: ");
-			lclatr(GREEN|HIGH);
-			sprintf(str,"%u/%u",(uint)stats.ftoday,j);
-			lprintf("%-12.12s",str);
-			lclatr(GREEN);
-			lprintf("Users: ");
-			lclatr(GREEN|HIGH);
-			sprintf(str,"%u/%u",stats.nusers,lastuser());
-			lprintf("%-12.12s\r\n",str);
-			lclatr(GREEN);
-			lprintf("Uloads: ");
-			lclatr(GREEN|HIGH);
-			ultoac(stats.ulb/1024UL,tmp);
-			strcat(tmp,"k");
-			lprintf("%-12.12s",tmp);
-			lclatr(GREEN);
-			lprintf("Files: ");
-			lclatr(GREEN|HIGH);
-			sprintf(str,"%u",(uint)stats.uls);
-			if(node_misc&NM_WFCMSGS) {
-				strcat(str,"/");
-				strcat(str,ultoa(m,tmp,10)); }
-			lprintf("%-12.12s",str);
-			lclatr(GREEN);
-			lprintf("Dloads: ");
-			lclatr(GREEN|HIGH);
-			ultoac(stats.dlb/1024UL,tmp);
-			strcat(tmp,"k");
-			lprintf("%-12.12s",tmp);
-			lclatr(GREEN);
-			lprintf("Files: ");
-			lclatr(GREEN|HIGH);
-			lprintf("%-12.12s\r\n",ultoac(stats.dls,tmp)); }
-		lclatr(curatr=LIGHTGRAY);
-		lclxy(1,6);
-		nodes=0;
-		for(i=1;i<=sys_nodes;i++) {
-			getnodedat(i,&node,0);
-			if((node.status!=NODE_WFC && node.status!=NODE_OFFLINE)
-				|| node.errors) {
-				lputc(CLREOL);
-				printnodedat(i,node);
-				nodes++; } }
-		if(nodes<lastnodes) {
-			i=j=lclwy();
-			j+=(lastnodes-nodes)+1;
-			for(;i<=node_scrnlen && i<j;i++) {
-				lclxy(1,i);
-				lputc(CLREOL); } }
-		lastnodes=nodes;
-		lclatr(curatr=LIGHTGRAY); }
-
-
-	if(!(node_misc&NM_NO_LKBRD) && lkbrd(1)) {
-		start=time(NULL);
-		/* menuon=0; */
-        lputc(FF);
-        tos=1;
-		lncntr=0;
-		i=lkbrd(0);
-		if(!(i&0xff) && (i>=0x3b00 && i<=0x4400)
-			|| i==0x8500 || i==0x8600) {		/* F1-F12 */
-			if(i>=0x3b00 && i<=0x4400)
-				i=((i-0x3b00)>>8);
-			else if(i==0x8500)
-				i=10;
-			else
-				i=11;
-			offhook();
-			external(cmdstr(wfc_scmd[i],nulstr,nulstr,NULL),EX_SWAP);
-            return(0); }
-
-		if(isdigit(i&0xff)) {
-			offhook();
-			external(cmdstr(wfc_cmd[i&0xf],nulstr,nulstr,NULL),0);
-			return(0); }
-
-		switch(toupper(i)) {
-            case 'A':   /* forced answer */
-                ans=1;
-                break;
-			case 'C':   /* configure */
-				if(node_misc&NM_SYSPW) {
-					quicklogonstuff();
-					if(!chksyspass(1))
-                        return(0); }
-                offhook();
-                 if(sys_status&SS_LOGOPEN) {
-                    close(logfile);
-                    sys_status&=~SS_LOGOPEN; }
-                if(sys_status&SS_COMISR) {
-                    rioini(0,0);    /* replace COM i/o vectors */
-                    sys_status&=~SS_COMISR; }
-                close(nodefile);
-				close(node_ext);
-				sys_status&=~SS_NODEDAB;
-				sprintf(str,"%sEXECSBBS.%s",exec_dir,
-#ifdef __OS2__
-					"EXE"
-#else
-					"COM"
-#endif
-					);
-				sprintf(tmp,"\"%s \"",cmdstr(scfg_cmd,nulstr,nulstr,NULL));
-				if(execl(str,str,".",tmp,orgcmd,NULL,envp)) {
-					errormsg(WHERE,ERR_EXEC,str,0);
-                    bail(1); }
-			case 'D':   /* Dos shell */
-                offhook();
-				external(comspec,0);
-				return(0);
-			case 'F':   /* Force Network Call-out */
-                quicklogonstuff();
-				lclatr(YELLOW);
-				lputs("QWK Hub ID: ");
-				lclatr(WHITE);
-				if(!getstr(str,8,K_UPPER))
-					return(0);
-				for(i=0;i<total_qhubs;i++)
-					if(!stricmp(str,qhub[i]->id)) {
-						if(qhub[i]->node==node_num)
-							qhub[i]->last=-1;
-						else {
-							sprintf(tmp,"%sQNET\\%s.NOW",data_dir,str);
-							if((file=nopen(tmp,O_CREAT|O_TRUNC|O_WRONLY))
-								!=-1)
-								close(file); }
-						break; }
-                return(0);
-            case 'L':   /* Log */
-				if(node_misc&NM_SYSPW) {
-					quicklogonstuff();
-					if(!chksyspass(1))
-                        return(0); }
-                offhook();
-                now=time(NULL);
-                unixtodos(now,&date,&curtime);
-                sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG"
-                    ,data_dir,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900));
-				external(cmdstr(node_viewer,str,nulstr,NULL),0);
-                return(0);
-            case 'M':   /* Read all mail */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-                    return(0);
-				readmail(1,MAIL_ALL);
-                online=console=0;
-                return(0);
-            case 'N':   /* Node statistics */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-                    return(0);
-				useron.misc|=UPAUSE;
-                printstatslog(node_num);
-                pause();
-                return(0);
-            case 'Q':   /* Quit */
-                offhook();
-                bail(0);
-			case 'R':   /* Read feedback */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-                    return(0);
-				readmail(1,MAIL_YOUR);
-                return(0);
-			case 'K':   /* Sent mail */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-                    return(0);
-				readmail(1,MAIL_SENT);
-				return(0);
-            case 'S':   /* System Statistics */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-                    return(0);
-				useron.misc|=UPAUSE;
-                printstatslog(0);
-                pause();
-                return(0);
-			case 'T':   /* Terminal mode */
-				if(!com_port) {
-					lprintf("No COM port configured.");
-					getch();
-                    lputc(FF);
-					return(0); }
-				if(node_misc&NM_SYSPW) {
-                    quicklogonstuff();
-					if(!chksyspass(1))
-                        return(0); }
-                return(terminal());
-			case 'U':   /* User edit */
-                quicklogonstuff();
-				useredit(0,1);
-                return(0);
-			case 'E':
-			case 'W':   /* Write e-mail */
-                quicklogonstuff();
-				if(node_misc&NM_SYSPW && !chksyspass(1))
-					return(0);
-                bputs(text[Email]);
-				if(!getstr(str,50,0))
-                    return(0);
-				if(!strchr(str,'@') && (i=finduser(str))!=0)
-					email(i,nulstr,nulstr,WM_EMAIL);
-				else
-					netmail(str,nulstr,0);
-                return(0);
-			case 'X':   /* Exit with phone on-hook */
-                bail(0);
-			case 'Y':   /* Yesterday's log */
-				if(node_misc&NM_SYSPW) {
-					quicklogonstuff();
-					if(!chksyspass(1))
-						return(0); }
-                offhook();
-                now=time(NULL);
-                now-=(ulong)60L*24L*60L;
-                unixtodos(now,&date,&curtime);
-                sprintf(str,"%sLOGS\\%2.2d%2.2d%2.2d.LOG"
-                    ,data_dir,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900));
-				external(cmdstr(node_viewer,str,nulstr,NULL),0);
-                return(0);
-			case 'Z':
-				mail_maint();
-				return(0);
-			case '?':   /* Menu */
-				if(menuon) {
-					menuon=0;
-					lputc(FF);
-					laststatchk=0;
-					laststatfdate=0; }
-				else {
-					online=ON_LOCAL;
-					menu("WFC");
-					menuon=1;
-					blank=0;
-					online=0; }
-                continue;
-			case SP:   /* Log on */
-				lclatr(WHITE|HIGH); lputc('Y'); lclatr(GREEN);
-				lputs(" Yes\r\n");
-				lclatr(WHITE|HIGH); lputc('Z'); lclatr(GREEN);
-				lputs(" Yes, Quiet\r\n");
-				lclatr(WHITE|HIGH); lputc('F'); lclatr(GREEN);
-				lputs(" Fast User #1\r\n");
-				lclatr(WHITE|HIGH); lputc('Q'); lclatr(GREEN);
-				lputs(" Fast User #1, Quiet\r\n");
-				lclatr(BROWN|HIGH);
-				lputs("\r\nLog on? [No]: ");
-				lclatr(LIGHTGRAY);
-				i=getch();
-				switch(toupper(i)) {
-                    case 'Z':
-                        onquiet=1;
-					case 'Y':       /* Yes, logon */
-                        lputc(FF);
-                        quicklogonstuff();
-						sys_status&=~SS_USERON;
-						useron.misc=(UPAUSE|ANSI|COLOR);
-                        gotcaller=1;
-                        continue;
-                    case 'Q':
-                        onquiet=1;
-                    case 'F':
-                        lputc(FF);
-                        quicklogonstuff();
-						if(sys_misc&SM_REQ_PW || node_misc&NM_SYSPW) {
-							useron.misc=(UPAUSE|ANSI|COLOR);
-							gotcaller=1;
-							continue; }
-                        if(!useron.number) {
-                            lputc(7);
-                            lputs("A Sysop account hasn't been created");
-							getch();
-                            return(0); }
-						return(logon());
-                    default:
-						return(0); }
-            default:
-                lputs("Hit '?' for a menu.");
-                continue; } }
-	if(com_port) {
-		if(mdm_misc&MDM_VERBAL) {
-			if(rioctl(RXBC)) {
-				lputc(FF);
-				getmdmstr(str,SEC_RING);
-				if(!strcmp(str,"RING"))
-					ans=1; } }
-		else {	/* numeric */
-			if(incom()=='2')
-				ans=1; }
-		if(mdm_misc&MDM_DUMB && DCDHIGH)
-			ans=1; }
-	if(ans && com_port) {
-        lputc(FF);
-		if(mdm_misc&MDM_CALLERID) {
-			lputs("Obtaining Caller-ID...");
-			getmdmstr(str,SEC_CID);
-			lprintf("\r\nCID: %s",str);
-			if(!strncmpi(str,"TIME:",5)) {  /* 3 message format */
-				getmdmstr(str,SEC_CID);
-				lprintf("\r\nCID: %s",str);
-				p=strchr(str,':');
-				if(p)
-					strcpy(cid,p+2);		/* Phone Number */
-				getmdmstr(str,SEC_CID);
-				lprintf("\r\nCID: %s",str);
-				p=strchr(str,':');
-				if(p)
-					sprintf(cname,"%.*s",LEN_CID,p+2); }    /* Caller Name */
-			else if(!strncmpi(str,"DATE =",6)) { /* Supra format */
-				getmdmstr(str,SEC_CID);
-				lprintf("\r\nCID: %s",str);     /* TIME = line */
-				getmdmstr(str,SEC_CID);
-				lprintf("\r\nCID: %s",str);     /* NMBR = line */
-				p=strchr(str,'=');
-				if(p)
-					sprintf(strstr(str,"NAME") ? cname:cid,"%.*s",LEN_CID,p+2);
-				getmdmstr(str,SEC_CID); 		/* NAME = line */
-				lprintf("\r\nCID: %s",str);
-				p=strchr(str,'=');
-				if(p)
-					sprintf(strstr(str,"NAME") ? cname:cid,"%.*s",LEN_CID,p+2);
-				}
-			else if(strlen(str)>12) 		/* Single message format */
-				sprintf(cid,"%.*s",LEN_CID,str+12);
-			else
-				sprintf(cid,"ERROR: '%s'",str);
-			lputs(crlf); }
-		cur_rate=cur_cps=0;
-		connection[0]=0;
-		result_code=0;
-		if(!(mdm_misc&MDM_DUMB)) {
-			if(mdm_rings>1) {
-				lputs("Ring\r\n");
-				for(i=1;i<mdm_rings;i++)
-					if(!getmdmstr(str,10))
-						break;
-					else
-						lputs("Ring\r\n");
-				if(i<mdm_rings)
-					return(0);
-				lputs(crlf); }
-			lputs("Answering...");
-			mdmcmd(mdm_answ);
-			rioctl(IOFI);						// flush extra ring results
-			while(!cur_rate || rioctl(RXBC)) {	// no connect or more rsults
-				if(!getmdmstr(str,SEC_ANSWER)) {
-					if(cur_rate)
-						break;
-					lprintf("\r\nNO CARRIER\r\n");
-					if(!(mdm_misc&MDM_NODTR)) {
-						dtr(15);
-						dtr(1);
-						mswait(500); }
-					mdmcmd(nulstr);
-					hangup();
-					return(0); }
-				i=0;
-				while(i<2
-					&& (!strcmp(str,"2")
-					|| !strcmp(str,"RING"))) { /* Ring? Get next result */
-					lputs("Ring\r\n");
-					if(i) {
-						mdmcmd(mdm_answ);	  /* Give a second ATA */
-						rioctl(IOFI); }
-					if(!getmdmstr(str,SEC_ANSWER)) {
-						if(!(mdm_misc&MDM_NODTR)) {
-							dtr(15);
-							dtr(1);
-							mswait(500); }
-						mdmcmd(nulstr);
-						hangup();		  /* Get next result code from modem */
-						return(0); }
-					i++; }
-				if(!strcmp(str,"3") || !strcmp(str,"NO CARRIER")) {
-					lprintf("\r\nNO CARRIER\r\n");
-					hangup();
-					return(0); }
-
-				lprintf("\r\nResult Code: %s\r\n",str);
-
-				/* IP (vmodem) logging additions by enigma */
-				ips = strstr(str, "TEL FROM ");
-				if(ips) {
-				  strcpy(ipstr, ips+9);
-				}
-
-				if(strstr(str,"FAX") || strstr(str,"+FCO")) {
-                                    /* Just for the ZyXEL's */
-                    mswait(1500);   /* 1 and a half second wait for ZyXEL */
-                    sys_misc&=~SM_ERRALARM;
-                    bail(100); }
-
-				if(mdm_misc&MDM_VERBAL) {
-					if(!cur_rate
-						&& (!strnicmp(str,"CONNECT ",8)
-						|| !strnicmp(str,"CARRIER ",8))) {
-						cur_rate=atol(str+8);
-						// build description
-						for(i=8,j=0;str[i] && j<LEN_MODEM;i++) {
-							if(j==2 && isdigit(str[i])
-								&& str[i+1]=='0' && str[i+2]=='0'
-								&& !isdigit(str[i+3]) && j+1<LEN_MODEM) {
-								connection[j++]='.';
-								connection[j++]=str[i];
-								i+=2; }
-							else
-								connection[j++]=str[i]; }
-						connection[j]=0; }
-					if(!cur_rate && !strcmp(str,"CONNECT"))
-						cur_rate=com_rate;
-					if(cur_rate
-						&& (strstr(str,"ARQ") || strstr(str,"MNP")
-						|| strstr(str,"V42") || strstr(str,"LAPM")
-						|| strstr(str,"REL")))
-						cur_cps=cur_rate/9; }
-				else {	/* numeric */
-					j=atoi(str);
-					for(i=0;i<mdm_results;i++)
-						if(mdm_result[i].code==j) break;
-					if(!cur_rate) {
-						if(i==mdm_results) {
-							lprintf("Unknown result code: '%s'\r\n",str);
-							sprintf(tmp,"Unknown modem result code: '%s'",str);
-							errorlog(tmp);
-							if(mdm_misc&MDM_KNOWNRES || !mdm_results) {
-								hangup();
-								return(0); }	/* Don't allow invalid codes */
-							i--; }	/* Use last configured result code */
-						else
-							result_code=mdm_result[i].code; }
-					if(!strncmpi(mdm_result[i].str,"EXIT ",5))
-						bail(atoi(mdm_result[i].str+5));
-					if(!strcmpi(mdm_result[i].str,"FAX")) {
-						lputs("FAX Connection\r\n");
-						bail(100); }
-					if(!strcmpi(mdm_result[i].str,"IGNORE") || cur_rate)
-                        lputs("Ignored\r\n");
-					else {
-						cur_rate=mdm_result[i].rate;
-						cur_cps=mdm_result[i].cps;
-						strcpy(connection,mdm_result[i].str); } } } }
-		else   /* dumb modem */
-			cur_rate=com_rate;
-
-		if(!connection[0])
-			sprintf(connection,"%lu",cur_rate);
-		lprintf("Logging Caller in at %s\r\n",connection);
-		if(!cur_cps)
-			cur_cps=cur_rate/10L;
-
-        rioctl(IOCE|((RXLOST|FERR|PERR|OVRR)<<8));  /* clear error flags */
-        console=CON_R_ECHO|CON_L_ECHO|CON_R_INPUT|CON_L_INPUT;
-        online=ON_REMOTE;
-        gotcaller=1;
-		putcom(crlf);
-#if defined(__OS2__)
-		putcom(decrypt(VersionNoticeOS2,0));
-#elif defined(__WIN32__)
-		putcom(decrypt(VersionNoticeW32,0));
-#else
-		putcom(decrypt(VersionNoticeDOS,0));
-#endif
-		putcom(crlf);
-		lprintf("Pausing %u Seconds...",mdm_ansdelay);
-		if(node_misc&NM_ANSALARM) {
-			now=time(NULL);
-			while(time(NULL)-now<mdm_ansdelay)
-                for(x=0;x<10;x++)
-					for(y=0;y<10;y++)
-						beep((x*100)+(y*5),10); }
-		else
-			secwait(mdm_ansdelay);
-        nosound();
-		rioctl(IOFI); } }	/* flush input buffer */
-
-reset_logon_vars();
-calls++;
-useron.misc=0;
-answertime=logontime=starttime=time(NULL);
-if(online==ON_REMOTE) {
-	setrate();
-
-    now=time(NULL);
-    gm=localtime(&now);
-	sprintf(str,"%02d:%02d%c  %s %s %02d %u            Node %3u  %5lubps (%s)"
-        ,gm->tm_hour>12 ? gm->tm_hour-12 : gm->tm_hour==0 ? 12 : gm->tm_hour
-		,gm->tm_min,gm->tm_hour>=12 ? 'p' : 'a',wday[gm->tm_wday]
-        ,mon[gm->tm_mon],gm->tm_mday,gm->tm_year+1900,node_num,cur_rate
-        ,connection);
-	if(result_code) {
-		sprintf(tmp," [%d]",result_code);
-		strcat(str,tmp); }
-	logline("@",str);
-
-	/* IP trashcan modification by enigma */
-	if(trashcan(ipstr,"IP")) {
-		sprintf(tmp, "IP Trashcan: %s, hanging up!\r\n", ipstr);
-		logline("@!",tmp);
-		hangup();
-		return(0); }
-
-	if(mdm_misc&MDM_CALLERID) {
-		outcom(0xC);
-#if defined(__OS2__)
-		putcom(decrypt(VersionNoticeOS2,0));
-#elif defined(__WIN32__)
-		putcom(decrypt(VersionNoticeW32,0));
-#else
-		putcom(decrypt(VersionNoticeDOS,0));
-#endif
-		putcom(crlf);
-		sprintf(str,"CID: %-*s %s",LEN_CID,cid,cname);
-		logline("@*",str);
-		if(trashcan(cid,"CID")) {
-			hangup();
-			return(0); } } }
-lclini(node_scrnlen-1);
-if(online==ON_REMOTE) {
-    if(node_dollars_per_call) { /* Billing node stuff */
-        now=time(NULL);
-        bprintf(text[BillingNodeMsg],sys_name,node_dollars_per_call);
-		while(online && now-answertime<30) {
-			if(incom()!=NOINP) {
-				if(!(mdm_misc&MDM_NODTR))
-					dtr(15);
-				else
-					mdmcmd(mdm_hang); }
-            checkline();
-            now=time(NULL); }
-        if(!online)
-            return(0); }
-	rioctl(IOFI);
-	putcom("\x1b[99B\x1b[6n\x1b[!_\x1b[0t_\x1b[0m_\xC");
-    lputc(FF);
-	i=l=lncntr=autoterm=0;
-	tos=1;
-#if defined(__OS2__)
-	strcpy(str,decrypt(VersionNoticeOS2,0));
-#elif defined(__WIN32__)
-	strcpy(str,decrypt(VersionNoticeW32,0));
-#else
-	strcpy(str,decrypt(VersionNoticeDOS,0));
-#endif
-	strcat(str,decrypt(CopyrightNotice,0));
-	center(str);
-	mswait(500);
-	while(i++<30 && l<40) { 		/* wait up to 3 seconds for response */
-		if((c=(incom()&0x7f))=='R') {   /* break immediately if response */
-			str[l++]=c;
-			mswait(110);
-			break; }
-        if(c) {
-			str[l++]=c;
-			if(l==1 && c!=ESC)
-				break; }
-        else
-			mswait(100); }
-
-	if(rioctl(RXBC))	/* wait a bit for extra RIP reply chars */
-		mswait(550);
-
-	while((i=(incom()&0x7f))!=NOINP && l<40)
-		str[l++]=i;
-	str[l]=0;
-
-#if 0
-	for(i=0;str[i];i++)
-		lprintf("%02X ",str[i]);
-	lputs(crlf);
-#endif
-
-    if(l) {
-        if(str[0]==ESC && str[1]=='[') {
-			useron.misc|=(ANSI|COLOR);
-			autoterm|=ANSI;
-            rows=((str[2]&0xf)*10)+(str[3]&0xf);
-			if(rows<10 || rows>99) rows=24; }
-		truncsp(str);
-		if(strstr(str,"RIPSCRIP")) {
-			logline("@R",strstr(str,"RIPSCRIP"));
-			useron.misc|=(RIP|COLOR|ANSI);
-			autoterm|=(RIP|COLOR|ANSI); }
-		else if(strstr(str,"DC-TERM")
-			&& toupper(*(strstr(str,"DC-TERM")+12))=='W') {
-			logline("@W",strstr(str,"DC-TERM"));
-			useron.misc|=(WIP|COLOR|ANSI);
-			autoterm|=(WIP|COLOR|ANSI); } }
-    rioctl(IOFI); /* flush left-over or late response chars */
-    sprintf(str,"%sANSWER",text_dir);
-	sprintf(tmp,"%s.%s",str,autoterm&WIP ? "WIP":"RIP");
-	sprintf(str2,"%s.ANS",str);
-	if(autoterm&(RIP|WIP) && fexist(tmp))
-		strcat(str,autoterm&WIP ? ".WIP":".RIP");
-	else if(autoterm&ANSI && fexist(str2))
-        strcat(str,".ANS");
-    else
-		strcat(str,".ASC");
-    rioctl(IOSM|PAUSE);
-	sys_status|=SS_PAUSEON;
-	tos=1;
-    printfile(str,P_NOABORT);
-	sys_status&=~SS_PAUSEON;
-    CRLF; }
-else
-	useron.misc=(UPAUSE|ANSI|COLOR);
-
-useron.number=0;
-
-exec_bin(login_mod,&main_csi);
-
-if(!useron.number)
-    hangup();
-if(!online) {
-	logout();
-	return(0); }
-
-if(online==ON_REMOTE && mdm_misc&MDM_CALLERID) {
-	strcpy(useron.note,cid);
-	putuserrec(useron.number,U_NOTE,LEN_NOTE,useron.note); }
-
-/* log the IP by enigma */
-
-if(online==ON_REMOTE && ipstr[0]!='\0') {
-	sprintf(useron.note, "Telnet: %s", ipstr);
-	putuserrec(useron.number,U_NOTE,LEN_NOTE,useron.note);
-	logline("@*", useron.note); }
-
-if(!(sys_status&SS_USERON)) {
-    errormsg(WHERE,ERR_CHK,"User not logged on",0);
-	hangup();
-	logout();
-	return(0); }
-
-return(1);
-}
-
diff --git a/src/sbbs2/makefile b/src/sbbs2/makefile
deleted file mode 100644
index 1a2595638bb309d869cf52d69cd616b099cde1e9..0000000000000000000000000000000000000000
--- a/src/sbbs2/makefile
+++ /dev/null
@@ -1,225 +0,0 @@
-#########################################################################
-# Makefile for Synchronet BBS 						#
-# For use with Borland c++ for DOS/Win32 or Borland C++ for OS/2 	#
-# Tabstop=8		      						#
-# usage: make           (under DOS/Windows to build DOS\SBBS.EXE)	#
-#        make           (under OS/2 to build OS2\SBBS4OS2.EXE)		#
-#        make -DW32	(under Windows 95/NT to build W32\SBBS4W32.EXE) #
-#########################################################################
-
-# Macros
-BCDIR	= e:\bc31
-CC	= $(BCDIR)\bin\bcc
-LD	= $(BCDIR)\bin\tlink
-INCLUDE = $(BCDIR)\include;smb;rio;..\spawno
-LIB     = $(BCDIR)\lib
-DEFINES = -DSBBS 
-
-!if $d(__OS2__)
-CC	= c:\bcos2\bin\bcc
-LD	= c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;smb;rio
-LIB	= c:\bcos2\lib
-OS	= OS2
-CFLAGS	= -N -d -C -sm -I$(INCLUDE) $(DEFINES) -n$(OS) -w-pro
-LFLAGS	= -m -s -c -Toe -ap -S:18000
-#16k still caused stack overflows?
-#-w-srf?
-MAIN	= $(OS)\sbbs4os2.exe
-
-!elif $d(W32)
-
-OS	= W32 
-CC      = \bc45\bin\bcc32
-LD      = \bc45\bin\tlink32
-INCLUDE = \bc45\include;smb;rio
-LIB	= \bc45\lib
-CFLAGS	= -N -d -C -H -tWC -tWM -I$(INCLUDE) $(DEFINES) -n$(OS) -w-pro
-LFLAGS  = -m -n -c -Tpe -ax -S:18000
-MAIN	= $(OS)\sbbs4w32.exe
-
-!else
-OS      = DOS
-MODEL	= l
-CFLAGS	= -N -d -C -Y -O1 -m$(MODEL) -I$(INCLUDE) $(DEFINES) -n$(OS) -w-pro
-LFLAGS	= -l -m -n -c 
-MAIN	= $(OS)\sbbs.exe
-!endif
-
-
-!if $d(__OS2__)
-OBJS	= OS2\riolib.obj
-!elif $d(W32)
-OBJS	= W32\riolib.obj
-!else
-OBJS	= DOS\rciol.obj ..\mswait\DOS\mswait$(MODEL).obj
-!endif
-OBJS	= $(OBJS) $(OS)\etext.obj $(OS)\scfgvars.obj $(OS)\vars.obj \
-	  $(OS)\xtrn.obj 
-
-OVLOBJS = $(OS)\ars.obj\
-	  $(OS)\chk_ar.obj\
-	  $(OS)\comio.obj \
-	  $(OS)\con_in.obj \
-	  $(OS)\con_out.obj \
-          $(OS)\con_mid.obj \
-          $(OS)\con_hi.obj \
-	  $(OS)\atcodes.obj \
-	  $(OS)\data.obj \
-	  $(OS)\data_ovl.obj\
-	  $(OS)\getuser.obj\
-	  $(OS)\userrec.obj\
-	  $(OS)\getnode.obj\
-	  $(OS)\putnode.obj\
-	  $(OS)\exec.obj \
-	  $(OS)\execmisc.obj \
-	  $(OS)\execfunc.obj \
-	  $(OS)\execmsg.obj \
-	  $(OS)\execfile.obj \
-	  $(OS)\file.obj $(OS)\file_ovl.obj \ 
-	  $(OS)\chat.obj $(OS)\fido.obj \
-	  $(OS)\initdata.obj \ 
-	  $(OS)\listfile.obj \
-	  $(OS)\viewfile.obj \
-	  $(OS)\logio.obj \
-	  $(OS)\login.obj \
-	  $(OS)\logon.obj \
-	  $(OS)\logout.obj \
-	  $(OS)\newuser.obj \
-	  $(OS)\mail.obj \  
- 	  $(OS)\main.obj $(OS)\main_ovl.obj $(OS)\main_sec.obj \
-	  $(OS)\main_wfc.obj \
-          $(OS)\msg1.obj \
-	  $(OS)\msg2.obj\
-	  $(OS)\putmsg.obj\
-	  $(OS)\postmsg.obj\
-	  $(OS)\email.obj\
-	  $(OS)\netmail.obj\
-	  $(OS)\bulkmail.obj\
-          $(OS)\misc.obj\
-	  $(OS)\qwk.obj\
-	  $(OS)\qwktomsg.obj\
-	  $(OS)\msgtoqwk.obj\
-	  $(OS)\pack_qwk.obj\
-	  $(OS)\pack_rep.obj\
-	  $(OS)\un_qwk.obj\
-	  $(OS)\un_rep.obj\
-	  $(OS)\readmsgs.obj\
-	  $(OS)\scfglib1.obj\
-	  $(OS)\scfglib2.obj\
-	  $(OS)\str.obj $(OS)\text_sec.obj $(OS)\useredit.obj\
-	  $(OS)\xfer_lo.obj $(OS)\xfer_mid.obj $(OS)\xfer_hi.obj\
-	  $(OS)\xtrn_ovl.obj $(OS)\xfer_sec.obj $(OS)\lzh.obj\
-	  $(OS)\smblib.obj
-
-HEADERS = sbbs.h sbbsdefs.h gen_defs.h nodedefs.h text.h vars.c scfgvars.c \
-	  smb\smblib.h smb\smbdefs.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) $(OVLOBJS) $(OS)\ver.obj
-    	@echo Linking $< ...
-!if $d(__OS2__)
-	$(LD) $(LFLAGS) @&&+
-$(OBJS) $(LIB)\c02.obj $(OS)\ver.obj $(OVLOBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2mt.lib
-!elif $d(W32)
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0X32.OBJ $(OBJS) $(OS)\ver.obj $(OVLOBJS)
-+, $*, $*, $(LIB)\import32.lib $(LIB)\cw32mt.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) $(OS)\ver.obj /o $(OVLOBJS), \
-$*, $*, ..\spawno\spawnl $(LIB)\overlay $(LIB)\c$(MODEL) \
-	$(LIB)\math$(MODEL) $(LIB)\emu
-+
-!endif
-
-$(OS)\smblib.obj: smb\smblib.c smb\smblib.h smb\smbdefs.h
-	@echo Compiling SMBLIB ...
-	$(CC) $(CFLAGS) -c -DSMB_GETMSGTXT smb\smblib.c
-
-$(OS)\lzh.obj: smb\lzh.c smb\lzh.h 
-	@echo Compiling LZH ...
-	$(CC) $(CFLAGS) -c -DLZH_DYNAMIC_BUF smb\lzh.c
-
-$(OS)\riolib.obj: rio\riolib.c rio\riolib.h rio\riodefs.h
-	@echo Compiling RIOLIB ...
-	$(CC) $(CFLAGS) -c rio\riolib.c
-
-etext.h: etext.dat
-	@echo Creating new encrypted text (ETEXT) Code and Header files...
-	genetext
-			
-# All .obj modules
-$(OS)\ars.obj:		$(HEADERS) ars_defs.h
-$(OS)\chk_ar.obj:	$(HEADERS) ars_defs.h
-$(OS)\atcodes.obj:	$(HEADERS) cmdshell.h
-$(OS)\chat.obj:        	$(HEADERS)
-$(OS)\comio.obj:       	$(HEADERS)
-$(OS)\con_in.obj:      	$(HEADERS)
-$(OS)\con_out.obj:     	$(HEADERS)
-$(OS)\con_mid.obj:     	$(HEADERS)
-$(OS)\con_hi.obj:      	$(HEADERS)
-$(OS)\data.obj:        	$(HEADERS)
-$(OS)\data_ovl.obj:    	$(HEADERS)
-$(OS)\exec.obj:		$(HEADERS) cmdshell.h
-$(OS)\execmisc.obj:	$(HEADERS) cmdshell.h
-$(OS)\execfunc.obj:	$(HEADERS) cmdshell.h
-$(OS)\execmsg.obj:	$(HEADERS) cmdshell.h
-$(OS)\execfile.obj:	$(HEADERS) cmdshell.h
-$(OS)\etext.obj:       	etext.h
-$(OS)\fido.obj:        	$(HEADERS)
-$(OS)\file.obj:        	$(HEADERS)
-$(OS)\file_ovl.obj:    	$(HEADERS)
-$(OS)\initdata.obj:    	$(HEADERS)
-$(OS)\listfile.obj:	$(HEADERS)
-$(OS)\viewfile.obj:	$(HEADERS)
-$(OS)\logio.obj:       	$(HEADERS)
-$(OS)\login.obj:	$(HEADERS)
-$(OS)\logon.obj:    	$(HEADERS) cmdshell.h
-$(OS)\logout.obj:	$(HEADERS)
-$(OS)\main.obj:        	$(HEADERS) cmdshell.h
-$(OS)\mail.obj:	       	$(HEADERS)
-$(OS)\main_ovl.obj:    	$(HEADERS) etext.h
-$(OS)\main_sec.obj:    	$(HEADERS)
-$(OS)\main_wfc.obj:	$(HEADERS) qwk.h etext.h
-$(OS)\misc.obj:        	$(HEADERS) ars_defs.h smb\crc32.h
-$(OS)\msg1.obj:	       	$(HEADERS)
-$(OS)\msg2.obj:     	$(HEADERS)
-$(OS)\newuser.obj:	$(HEADERS)
-$(OS)\putmsg.obj:	$(HEADERS)
-$(OS)\email.obj:	$(HEADERS) cmdshell.h
-$(OS)\postmsg.obj:     	$(HEADERS)
-$(OS)\netmail.obj:     	$(HEADERS) qwk.h
-$(OS)\bulkmail.obj:    	$(HEADERS)
-$(OS)\qwk.obj:		$(HEADERS) qwk.h post.h etext.h
-$(OS)\qwktomsg.obj:	$(HEADERS) qwk.h
-$(OS)\msgtoqwk.obj:	$(HEADERS) qwk.h
-$(OS)\pack_qwk.obj:	$(HEADERS) qwk.h post.h
-$(OS)\pack_rep.obj:	$(HEADERS) qwk.h post.h
-$(OS)\un_qwk.obj:	$(HEADERS) qwk.h
-$(OS)\un_rep.obj:	$(HEADERS) qwk.h
-$(OS)\readmsgs.obj:	$(HEADERS) post.h
-$(OS)\scfglib1.obj:    	$(HEADERS) scfglib.h
-$(OS)\scfglib2.obj:    	$(HEADERS) scfglib.h
-$(OS)\scfgvars.obj:    	$(HEADERS)
-$(OS)\str.obj:         	$(HEADERS)
-$(OS)\getnode.obj:	$(HEADERS)
-$(OS)\putnode.obj:	$(HEADERS)
-$(OS)\text_sec.obj:	$(HEADERS)
-$(OS)\getuser.obj:	$(HEADERS)
-$(OS)\userrec.obj:	$(HEADERS)
-$(OS)\useredit.obj:    	$(HEADERS)
-$(OS)\vars.obj:        	$(HEADERS)
-$(OS)\ver.obj:		$(OBJS) $(OVLOBJS) $(HEADERS)
-$(OS)\xfer_lo.obj:     	$(HEADERS)
-$(OS)\xfer_mid.obj:    	$(HEADERS)
-$(OS)\xfer_hi.obj:     	$(HEADERS)
-$(OS)\xfer_sec.obj:	$(HEADERS)
-$(OS)\xtrn.obj:        	$(HEADERS) cmdshell.h
-$(OS)\xtrn_ovl.obj:    	$(HEADERS)
diff --git a/src/sbbs2/misc.c b/src/sbbs2/misc.c
deleted file mode 100644
index 8bb6116ca613ca94e53bfdc0ef121ef05c53a0f5..0000000000000000000000000000000000000000
--- a/src/sbbs2/misc.c
+++ /dev/null
@@ -1,815 +0,0 @@
-#line 1 "MISC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/***************************************************************************/
-/* Miscellaneous functions that are useful many places throughout the code */
-/***************************************************************************/
-
-#include "sbbs.h"
-#include "crc32.h"
-
-#ifdef __WIN32__
-#include <windows.h>	// Required for kbd_state(), beep(), and mswait()
-#endif
-
-/****************************************************************************/
-/* Returns the number of characters in 'str' not counting ctrl-ax codes		*/
-/* or the null terminator													*/
-/****************************************************************************/
-int bstrlen(char *str)
-{
-	int i=0;
-
-while(*str) {
-	if(*str==1) /* ctrl-a */
-		str++;
-	else
-		i++;
-	if(!(*str)) break;
-	str++; }
-return(i);
-}
-
-void strip_ctrl(char *str)
-{
-	char tmp[1024];
-	int i,j,k;
-
-k=strlen(str);
-for(i=j=0;i<k;i++)
-	if(str[i]==1)  /* Ctrl-a */
-        i++;
-	else if(j && str[i]<=SP && tmp[j-1]==SP)
-		continue;
-	else if(i && !isalnum(str[i]) && str[i]==str[i-1])
-		continue;
-	else if((uchar)str[i]>=SP)
-		tmp[j++]=str[i];
-	else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
-		tmp[j++]=SP;
-tmp[j]=0;
-strcpy(str,tmp);
-}
-
-void strip_exascii(char *str)
-{
-	char tmp[1024];
-	int i,j,k;
-
-k=strlen(str);
-for(i=j=0;i<k;i++)
-	if(!(str[i]&0x80))
-		tmp[j++]=str[i];
-tmp[j]=0;
-strcpy(str,tmp);
-}
-
-/****************************************************************************/
-/* Returns in 'string' a character representation of the number in l with   */
-/* commas.																	*/
-/****************************************************************************/
-char *ultoac(ulong l, char *string)
-{
-	char str[256];
-	char i,j,k;
-
-ultoa(l,str,10);
-i=strlen(str)-1;
-j=i/3+1+i;
-string[j--]=0;
-for(k=1;i>-1;k++) {
-	string[j--]=str[i--];
-	if(j>0 && !(k%3))
-		string[j--]=','; }
-return(string);
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access&O_DENYNONE) {
-	share=SH_DENYNO;
-	access&=~O_DENYNONE; }
-else if(access==O_RDONLY) share=SH_DENYWR;
-else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN)
-	if(count>10)
-		mswait(55);
-if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN) {
-	sprintf(logstr,"NOPEN COLLISION - File: %s Count: %d"
-		,str,count);
-	logline("!!",logstr); }
-if(file==-1 && errno==EACCES)
-	bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	errormsg(WHERE,ERR_FDOPEN,str,access);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,2*1024);
-return(stream);
-}
-
-#ifndef __FLAT__
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char huge *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-
-long lfread(char huge *buf, long bytes, FILE *fp)
-{
-	long count;
-
-for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
-	if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
-		return(0);
-if(fread((char *)buf,1,(int)count,fp)!=count)
-	return(0);
-return(bytes);
-}
-
-/****************************************************************************/
-/* This function writes files that are potentially larger than 32767 bytes  */
-/* Up to one megabytes of data can be written with each call.				*/
-/****************************************************************************/
-long lwrite(int file, char huge *buf, long bytes)
-{
-
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(write(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(write(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-#endif
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	uint c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings if not just a drive letter and colon	*/
-/****************************************************************************/
-void backslashcolon(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\' && str[i-1]!=':') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns CRC-16 of string (not including terminating NULL)				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns CRC-32 of string (not including terminating NULL)				*/
-/****************************************************************************/
-ulong crc32(char *buf, ulong len)
-{
-	ulong l,crc=0xffffffff;
-
-for(l=0;l<len;l++)
-	crc=ucrc32(buf[l],crc);
-return(~crc);
-}
-
-/****************************************************************************/
-/* Compares pointers to pointers to char. Used in conjuction with qsort()   */
-/****************************************************************************/
-int pstrcmp(char **str1, char **str2)
-{
-return(strcmp(*str1,*str2));
-}
-
-/****************************************************************************/
-/* Returns the number of characters that are the same between str1 and str2 */
-/****************************************************************************/
-int strsame(char *str1, char *str2)
-{
-	int i,j=0;
-
-for(i=0;i<strlen(str1);i++)
-	if(str1[i]==str2[i]) j++;
-return(j);
-}
-
-#define MV_BUFLEN	4096
-
-/****************************************************************************/
-/* Moves or copies a file from one dir to another                           */
-/* both 'src' and 'dest' must contain full path and filename                */
-/* returns 0 if successful, -1 if error                                     */
-/****************************************************************************/
-int mv(char *src, char *dest, char copy)
-{
-	char str[256],*buf,atr=curatr;
-	int  ind,outd;
-	long length,chunk=MV_BUFLEN,l;
-	struct ftime ftime;
-	FILE *inp,*outp;
-
-if(!stricmp(src,dest))	 /* source and destination are the same! */
-	return(0);
-if(!fexist(src)) {
-	bprintf("\r\n\7MV ERROR: Source doesn't exist\r\n'%s'\r\n"
-		,src);
-	return(-1); }
-if(!copy && fexist(dest)) {
-	bprintf("\r\n\7MV ERROR: Destination already exists\r\n'%s'\r\n"
-		,dest);
-	return(-1); }
-if(!copy && ((src[1]!=':' && dest[1]!=':')
-	|| (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
-	if(rename(src,dest)) {						/* same drive, so move */
-		bprintf("\r\nMV ERROR: Error renaming '%s'"
-				"\r\n                      to '%s'\r\n\7",src,dest);
-		return(-1); }
-	return(0); }
-attr(WHITE);
-if((ind=nopen(src,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,src,O_RDONLY);
-	return(-1); }
-if((inp=fdopen(ind,"rb"))==NULL) {
-	close(ind);
-	errormsg(WHERE,ERR_FDOPEN,str,O_RDONLY);
-	return(-1); }
-setvbuf(inp,NULL,_IOFBF,32*1024);
-if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-	fclose(inp);
-	errormsg(WHERE,ERR_OPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
-	return(-1); }
-if((outp=fdopen(outd,"wb"))==NULL) {
-	close(outd);
-	fclose(inp);
-	errormsg(WHERE,ERR_FDOPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
-	return(-1); }
-setvbuf(outp,NULL,_IOFBF,8*1024);
-length=filelength(ind);
-if(!length) {
-	fclose(inp);
-	fclose(outp);
-	errormsg(WHERE,ERR_LEN,src,0);
-	return(-1); }
-if((buf=(char *)MALLOC(MV_BUFLEN))==NULL) {
-	fclose(inp);
-	fclose(outp);
-	errormsg(WHERE,ERR_ALLOC,nulstr,MV_BUFLEN);
-	return(-1); }
-l=0L;
-while(l<length) {
-	bprintf("%2lu%%",l ? (long)(100.0/((float)length/l)) : 0L);
-	if(l+chunk>length)
-		chunk=length-l;
-	if(fread(buf,1,chunk,inp)!=chunk) {
-		FREE(buf);
-		fclose(inp);
-		fclose(outp);
-		errormsg(WHERE,ERR_READ,src,chunk);
-		return(-1); }
-	if(fwrite(buf,1,chunk,outp)!=chunk) {
-		FREE(buf);
-		fclose(inp);
-		fclose(outp);
-		errormsg(WHERE,ERR_WRITE,dest,chunk);
-		return(-1); }
-	l+=chunk;
-	bputs("\b\b\b"); }
-bputs("   \b\b\b");  /* erase it */
-attr(atr);
-getftime(ind,&ftime);
-setftime(outd,&ftime);
-FREE(buf);
-fclose(inp);
-fclose(outp);
-if(!copy && remove(src)) {
-	errormsg(WHERE,ERR_REMOVE,src,0);
-	return(-1); }
-return(0);
-}
-
-/****************************************************************************/
-/* Prompts user for System Password. Returns 1 if user entered correct PW	*/
-/****************************************************************************/
-char chksyspass(int local)
-{
-	static	int inside;
-	char	str[256],str2[256],x,y,atr;
-	int 	orgcon=console;
-
-if(inside) return(0);
-if(online==ON_REMOTE && !(sys_misc&SM_R_SYSOP))
-	return(0);
-if(online==ON_LOCAL) {
-	if(!(sys_misc&SM_L_SYSOP))
-		return(0);
-	if(!(node_misc&NM_SYSPW) && !(sys_misc&SM_REQ_PW))
-		return(1); }
-if(local) {
-	x=lclwx();
-	y=lclwy();
-	atr=lclatr(LIGHTGRAY<<4);
-	STATUSLINE;
-	lclxy(1,node_scrnlen);
-	lputc(CLREOL);
-	lputs("  System Password: "); }
-else
-	bputs("SY: ");
-console&=~(CON_R_ECHO|CON_L_ECHO);
-inside=1;
-getstr(str,40,K_UPPER);
-if(local) {
-	TEXTWINDOW;
-	lclatr(atr);
-	lclxy(x,y);
-	statusline(); }
-inside=0;
-console=orgcon;
-if(!local)
-	CRLF;
-if(strcmp(sys_pass,str)) {
-	sprintf(str2,"%s #%u System password attempt: '%s'"
-		,useron.alias,useron.number,str);
-	logline("S!",str2);
-	return(0); }
-return(1);
-}
-
-/****************************************************************************/
-/* Converts when_t.zone into ASCII format                                   */
-/****************************************************************************/
-char *zonestr(short zone)
-{
-    static char str[32];
-
-switch((ushort)zone) {
-    case 0:     return("UT");
-    case AST:   return("AST");
-    case EST:   return("EST");
-    case CST:   return("CST");
-    case MST:   return("MST");
-    case PST:   return("PST");
-    case YST:   return("YST");
-    case HST:   return("HST");
-    case BST:   return("BST");
-    case ADT:   return("ADT");
-    case EDT:   return("EDT");
-    case CDT:   return("CDT");
-    case MDT:   return("MDT");
-    case PDT:   return("PDT");
-    case YDT:   return("YDT");
-    case HDT:   return("HDT");
-    case BDT:   return("BDT");
-    case MID:   return("MID");
-    case VAN:   return("VAN");
-    case EDM:   return("EDM");
-    case WIN:   return("WIN");
-    case BOG:   return("BOG");
-    case CAR:   return("CAR");
-    case RIO:   return("RIO");
-    case FER:   return("FER");
-    case AZO:   return("AZO");
-    case LON:   return("LON");
-    case BER:   return("BER");
-    case ATH:   return("ATH");
-    case MOS:   return("MOS");
-    case DUB:   return("DUB");
-    case KAB:   return("KAB");
-    case KAR:   return("KAR");
-    case BOM:   return("BOM");
-    case KAT:   return("KAT");
-    case DHA:   return("DHA");
-    case BAN:   return("BAN");
-    case HON:   return("HON");
-    case TOK:   return("TOK");
-    case SYD:   return("SYD");
-    case NOU:   return("NOU");
-    case WEL:   return("WEL");
-    }
-
-sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
-return(str);
-}
-
-/****************************************************************************/
-/* Waits so many seconds. Call with 2 or greater.							*/
-/****************************************************************************/
-void secwait(int sec)
-{
-	time_t start;
-
-start=time(NULL);
-while(time(NULL)-start<sec)
-	mswait(1);
-}
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-
-if(!strncmp(str,"00/00/00",8))
-	return(0);
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-if(str[6]<'7')
-	date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
-else
-	date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
-if(sys_misc&SM_EURODATE) {
-	date.da_mon=((str[3]&0xf)*10)+(str[4]&0xf);
-	date.da_day=((str[0]&0xf)*10)+(str[1]&0xf); }
-else {
-	date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-	date.da_day=((str[3]&0xf)*10)+(str[4]&0xf); }
-return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	if(sys_misc&SM_EURODATE)
-		sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
-			,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
-	else
-		sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-			,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0 /*FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-	return(f.ff_fsize);
-return(-1L);
-}
-
-time_t ftimetounix(struct ftime ft)
-{
-	struct date da;
-	struct time ti;
-
-ti.ti_min=ft.ft_min;
-ti.ti_hour=ft.ft_hour;
-ti.ti_hund=0;
-ti.ti_sec=ft.ft_tsec*2;
-da.da_year=1980+ft.ft_year;
-da.da_day=ft.ft_day;
-da.da_mon=ft.ft_month;
-return(dostounix(&da,&ti));
-}
-
-struct ftime unixtoftime(time_t unix)
-{
-	struct date da;
-	struct time ti;
-	struct ftime ft;
-
-unixtodos(unix,&da,&ti);
-ft.ft_min=ti.ti_min;
-ft.ft_hour=ti.ti_hour;
-ft.ft_tsec=ti.ti_sec/2;
-ft.ft_year=da.da_year-1980;
-ft.ft_day=da.da_day;
-ft.ft_month=da.da_mon;
-return(ft);
-}
-
-/****************************************************************************/
-/* Returns the time/date of the file in 'filespec' in time_t (unix) format  */
-/****************************************************************************/
-long fdate(char *filespec)
-{
-    int file;
-    struct ftime f;
-	time_t t;
-
-if((file=nopen(filespec,O_RDONLY))==-1)
-	return(0);
-getftime(file,&f);
-t=ftimetounix(f);
-close(file);
-return(t);
-}
-
-long fdate_dir(char *filespec)
-{
-    struct ffblk f;
-    struct date fd;
-    struct time ft;
-
-if(findfirst(filespec,&f,0/* FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0) {
-	fd.da_day=f.ff_fdate&0x1f;
-	fd.da_mon=(f.ff_fdate>>5)&0xf;
-	fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
-	ft.ti_hour=(f.ff_ftime>>11)&0x1f;
-	ft.ti_min=(f.ff_ftime>>5)&0x3f;
-	ft.ti_sec=(f.ff_ftime&0xf)*2;
-    return(dostounix(&fd,&ft)); }
-else return(0);
-}
-
-
-
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-faddr_t atofaddr(char *str)
-{
-    char *p;
-    faddr_t addr;
-
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-    addr.zone=atoi(str);
-    addr.net=atoi(p+1); }
-else {
-    if(total_faddrs)
-		addr.zone=faddr[0].zone;
-    else
-        addr.zone=1;
-    addr.net=atoi(str); }
-if(!addr.zone)              /* no such thing as zone 0 */
-    addr.zone=1;
-if((p=strchr(str,'/'))!=NULL)
-    addr.node=atoi(p+1);
-else {
-    if(total_faddrs)
-		addr.net=faddr[0].net;
-    else
-        addr.net=1;
-    addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL)
-    addr.point=atoi(p+1);
-return(addr);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(faddr_t addr)
-{
-    static char str[25];
-    char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-    sprintf(point,".%u",addr.point);
-    strcat(str,point); }
-return(str);
-}
-
-/****************************************************************************/
-/* Returns string for 2 digit hex+ numbers up to 575						*/
-/****************************************************************************/
-char *hexplus(uint num, char *str)
-{
-sprintf(str,"%03x",num);
-str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
-str[1]=str[2];
-str[2]=0;
-return(str);
-}
-
-uint hptoi(char *str)
-{
-	char tmp[128];
-	uint i;
-
-if(!str[1] || toupper(str[0])<='F')
-	return(ahtoul(str));
-strcpy(tmp,str);
-tmp[0]='F';
-i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
-return(i);
-}
-
-#ifndef __FLAT__
-
-void beep(int freq, int dur)
-{
-sound(freq);
-mswait(dur);
-nosound();
-}
-
-int kbd_state(void)
-{
-return(peekb(0,0x417)); 	 /* Check scroll lock */
-}
-
-#elif defined(__WIN32__)
-
-void beep(int freq, int dur)
-{
-Beep(freq,dur); 				// Requires WINDOWS.H
-}
-
-void mswait(int ms)
-{
-Sleep(ms);						// Requires WINDOWS.H
-}
-
-#endif
-
-#ifdef __OS2__
-
-int kbd_state(void)
-{
-	KBDINFO info;
-
-KbdGetStatus(&info,0);
-return(info.fsState);
-}
-
-void mswait(int msec)
-{
-DosSleep(msec ? msec : 1);
-}
-
-#elif defined(__WIN32__)
-
-#define KBDSTF_RIGHTSHIFT				0x0001
-#define KBDSTF_LEFTSHIFT				0x0002
-#define KBDSTF_CONTROL					0x0004
-#define KBDSTF_ALT						0x0008
-#define KBDSTF_SCROLLLOCK_ON			0x0010
-#define KBDSTF_NUMLOCK_ON				0x0020
-#define KBDSTF_CAPSLOCK_ON				0x0040
-#define KBDSTF_INSERT_ON				0x0080
-#define KBDSTF_LEFTCONTROL				0x0100
-#define KBDSTF_LEFTALT					0x0200
-#define KBDSTF_RIGHTCONTROL 			0x0400
-#define KBDSTF_RIGHTALT 				0x0800
-#define KBDSTF_SCROLLLOCK				0x1000
-#define KBDSTF_NUMLOCK					0x2000
-#define KBDSTF_CAPSLOCK 				0x4000
-#define KBDSTF_SYSREQ					0x8000
-
-int kbd_state(void)
-{
-	int i=0;
-	ulong l;
-	INPUT_RECORD rec;
-
-PeekConsoleInput(stdin,&rec,1,&l);
-if(rec.EventType==KEY_EVENT)
-	l=rec.Event.KeyEvent.dwControlKeyState;
-else if(rec.EventType==MOUSE_EVENT)
-	l=rec.Event.MouseEvent.dwControlKeyState;
-else
-	return(0);
-
-/* Translate Win32 key state to IBM key state */
-
-if(l&RIGHT_ALT_PRESSED)
-	i|=KBDSTF_RIGHTALT;
-if(l&LEFT_ALT_PRESSED)
-	i|=KBDSTF_LEFTALT;
-if(l&RIGHT_CTRL_PRESSED)
-	i|=KBDSTF_RIGHTCONTROL;
-if(l&LEFT_CTRL_PRESSED)
-	i|=KBDSTF_LEFTCONTROL;
-if(l&CAPSLOCK_ON)
-	i|=KBDSTF_CAPSLOCK;
-if(l&NUMLOCK_ON)
-	i|=KBDSTF_NUMLOCK;
-if(l&SCROLLLOCK_ON)
-	i|=KBDSTF_SCROLLLOCK;
-if(l&SHIFT_PRESSED)
-	i|=KBDSTF_LEFTSHIFT;
-
-return(i);
-}
-
-
-
-#endif
-
diff --git a/src/sbbs2/mlabels/make.bat b/src/sbbs2/mlabels/make.bat
deleted file mode 100755
index e2aa293fc7244f197065ab99dbbe1f66801dc1af..0000000000000000000000000000000000000000
--- a/src/sbbs2/mlabels/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -I.. mlabels.c
diff --git a/src/sbbs2/mlabels/mlabels.c b/src/sbbs2/mlabels/mlabels.c
deleted file mode 100644
index 080f6a653c0faf8f9f4d1278388129103c528471..0000000000000000000000000000000000000000
--- a/src/sbbs2/mlabels/mlabels.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* MLABELS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Make mailing labels from Synchronet BBS user database					*/
-/* Digital Dynamics - 03/16/93 v1.00										*/
-/* Digital Dynamics - 03/03/94 v2.00										*/
-/* Digital Dynamics - 04/13/95 v2.10										*/
-/* Digital Dynamics - 07/17/95 v2.20										*/
-
-/* For compilation under Borland/Turbo C(++)								*/
-
-/* Set tabstops to 4 for viewing/printing									*/
-
-/* This program and source code are public domain. Modified versions may	*/
-/* note be distributed without consent from Digital Dynamics.				*/
-
-#include <io.h>
-#include <share.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys\stat.h>
-#include "sbbsdefs.h"           /* Synchronet typedefs and macros header */
-
-#define DOUBLE_COLUMN	(1<<0)		/* Print double column labels */
-#define ATTN_ALIAS		(1<<1)		/* Print ATTN: Alias/Real Name */
-
-char *nulstr="";
-int  min=0,max=99;
-long reqflags[4]={0},reqrest=0,reqexempt=0;
-
-char *usage=
-"\nusage: mlabels <data\\user path> [[-require] [...]] [/options] <outfile>\n"
-"\nwhere require is one of:\n"
-"       L#                  set minimum level to # (default=0)\n"
-"       M#                  set maximum level to # (default=99)\n"
-"       F#<flags>           set required flags from flag set #\n"
-"       E<flags>            set required exemptions\n"
-"       R<flags>            set required restrictions\n"
-"\nwhere options is one or more of:\n"
-"       D                   double column labels\n"
-"       A                   include ATTN: alias/name on label\n"
-"\nexample:\n"
-"\nMLABELS \\SBBS\\DATA\\USER -L50 /D PRN\n";
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Returns bytes offset into user record for flag set # 'set'               */
-/****************************************************************************/
-long getflagoff(int set)
-{
-switch(set) {
-	default:
-		return(U_FLAGS1);
-	case 2:
-		return(U_FLAGS2);
-	case 3:
-		return(U_FLAGS3);
-	case 4:
-		return(U_FLAGS4); }
-}
-
-/****************************************************************************/
-/* Checks a user record against the requirements set on the command line	*/
-/* Returns 1 if the user meets the requirements (or no requirements were	*/
-/* specified) or 0 if the user does not meet any of the requirements.		*/
-/****************************************************************************/
-int chkuser(FILE *stream, long offset)
-{
-	char str[128];
-	int i;
-
-if(min || max!=99) {			/* Check security level */
-	fseek(stream,offset+U_LEVEL,SEEK_SET);
-	fread(str,2,1,stream);
-	str[2]=0;
-	i=atoi(str);
-	if(i<min || i>max)			/* not within range */
-		return(0); }			/* so skip this user */
-
-for(i=0;i<4;i++)
-	if(reqflags[i]) {
-		fseek(stream,offset+getflagoff(i+1),SEEK_SET);
-		fread(str,8,1,stream);
-		str[8]=0;
-		truncsp(str);
-		if((ahtoul(str)&reqflags[i])!=reqflags[i])
-			return(0); }	/* doesn't have 'em all */
-
-if(reqrest) {
-	fseek(stream,offset+U_REST,SEEK_SET);
-	fread(str,8,1,stream);
-	str[8]=0;
-	truncsp(str);
-	if((ahtoul(str)&reqrest)!=reqrest)
-		return(0); }
-
-if(reqexempt) {
-	fseek(stream,offset+U_REST,SEEK_SET);
-	fread(str,8,1,stream);
-	str[8]=0;
-	truncsp(str);
-	if((ahtoul(str)&reqexempt)!=reqexempt)
-        return(0); }
-
-return(1);
-}
-
-/****************************************************************************/
-/* Attempts to lock a user record, retries for up to 10 seconds 			*/
-/* Returns 0 on success, -1 on failure										*/
-/****************************************************************************/
-int lockuser(FILE *stream, ulong offset)
-{
-	time_t start;
-
-if(lock(fileno(stream),offset,U_LEN)==0)
-	return(0);
-start=time(NULL);
-while(1) {
-	if(lock(fileno(stream),offset,U_LEN)==0)
-		return(0);
-	if(time(NULL)-start>=10L)
-		break; }
-return(-1);
-}
-
-/***************/
-/* Entry point *
-/***************/
-int main(int argc, char **argv)
-{
-	char	str[256],buf1[U_LEN],buf2[U_LEN],infile[128]="",outfile[128]=""
-			,mode=0;	/* optional modes bits */
-	int 	i,j,k,file,printed=0;
-	long	l,length,offset;
-	FILE	*in,*out;
-
-printf("\nSynchronet Mailing Labels v2.10\n");
-for(i=1;i<argc;i++) {
-	if(argv[i][0]=='-')
-		switch(toupper(argv[i][1])) {
-			case 'L':                       /* Set minimum sec level */
-				min=atoi(argv[i]+2);
-				break;
-			case 'M':                       /* Set maximum sec level */
-				max=atoi(argv[i]+2);
-				break;
-			case 'F':                       /* Set required flags */
-				j=3;
-				k=1;
-				if(isdigit(argv[i][2]))
-					k=argv[i][2]&0xf;
-				else
-					j=2;
-				for(;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqflags[k-1]|=FLAG(toupper(argv[i][j]));
-				break;
-			case 'R':                       /* Set required restrictions */
-				for(j=2;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqrest|=FLAG(toupper(argv[i][j]));
-				break;
-			case 'E':                       /* Set required exemptions */
-				for(j=2;argv[i][j];j++)
-                    if(isalpha(argv[i][j]))
-						reqexempt|=FLAG(toupper(argv[i][j]));
-                break;
-			default:						/* Unrecognized include */
-				printf(usage);
-                exit(1); }
-
-	else if(argv[i][0]=='/') {
-		k=strlen(argv[i]);
-		for(j=1;j<k;j++)
-			switch(toupper(argv[i][j])) {
-				case 'D':   /* Double column labels */
-					mode|=DOUBLE_COLUMN;
-					break;
-				case 'A':   /* Attention Alias/Real Name */
-					mode|=ATTN_ALIAS;
-					break;
-				default:
-					printf("\nUnknown option\n");
-				case '?':
-					printf(usage);
-					exit(1); } }
-	else if(infile[0])				/* in filename already given */
-		strcpy(outfile,argv[i]);
-	else
-		strcpy(infile,argv[i]); }
-
-if(!infile[0] || !outfile[0]) {
-	printf("\nFilename not specified\n");
-	printf(usage);
-	exit(1); }
-
-if(infile[strlen(infile)-1]!='\\' && infile[strlen(infile)-1]!=':')
-	strcat(infile,"\\");
-strcat(infile,"USER.DAT");
-if((file=sopen(infile,O_RDONLY|O_BINARY,SH_DENYNO))==-1) {
-	printf("\nError opening %s\n",infile);
-	exit(1); }
-if((in=fdopen(file,"rb"))==NULL) {
-	printf("\nError opening %s\n",infile);
-	exit(1); }
-setvbuf(in,NULL,_IOFBF,2048);
-length=filelength(file);
-
-if((file=open(outfile,O_WRONLY|O_TRUNC|O_CREAT|O_BINARY
-	,S_IWRITE|S_IREAD))==-1) {
-	printf("\nError opening/creating %s\n",outfile);
-	exit(1); }
-if((out=fdopen(file,"wb"))==NULL) {
-	printf("\nError opening %s\n",outfile);
-	exit(1); }
-setvbuf(out,NULL,_IOFBF,2048);
-
-printf("\n");
-for(offset=0;offset<length;offset+=U_LEN) {
-	printf("%lu of %lu (%u labels)\r"
-		,(offset/U_LEN)+1,length/U_LEN,printed);
-	if(lockuser(in,offset)) {
-		printf("Error locking offset %lu\n",offset);
-		continue; }
-
-	if(!chkuser(in,offset)) {
-		unlock(fileno(in),offset,U_LEN);
-		continue; }
-
-	fseek(in,offset,SEEK_SET);
-	if(!fread(buf1,U_LEN,1,in)) {
-		printf("Couldn't read %lu bytes at %lu\n",U_LEN,offset);
-		break; }
-	unlock(fileno(in),offset,U_LEN);
-	for(i=0;i<U_LEN;i++) {				/* Convert ETX (3) to NULL (0) */
-		if(buf1[i]==ETX)
-			buf1[i]=NULL; }
-
-	buf1[U_MISC+8]=0;
-	l=ahtoul(buf1+U_MISC);
-	if(l&(DELETED|INACTIVE))			 /* skip if deleted or inactive */
-		continue;
-
-	while(mode&DOUBLE_COLUMN) { 		 /* double wide - right column */
-		offset+=U_LEN;
-		printf("%lu of %lu (%u labels)\r"
-			,(offset/U_LEN)+1,length/U_LEN,printed);
-		if(lockuser(in,offset)) {
-			printf("Error locking offset %lu\n",offset);
-			continue; }
-		fseek(in,offset,SEEK_SET);
-		if(!fread(buf2,U_LEN,1,in)) {
-			mode&=~DOUBLE_COLUMN;
-			unlock(fileno(in),offset,U_LEN); }
-		else {
-			if(!chkuser(in,offset)) {
-				unlock(fileno(in),offset,U_LEN);
-				continue; }
-			unlock(fileno(in),offset,U_LEN);
-			for(i=0;i<U_LEN;i++) {		/* Convert ETX (3) to NULL (0) */
-				if(buf2[i]==ETX)
-					buf2[i]=NULL; }
-			buf2[U_MISC+8]=0;
-			l=ahtoul(buf2+U_MISC);
-			if(l&(DELETED|INACTIVE))	/* skip if deleted or inactive */
-				continue;
-			else
-				break; } }
-
-	if(mode&DOUBLE_COLUMN) {			/* print two columns */
-		fprintf(out,"    %-*.*s%*s%.*s\r\n"
-			,LEN_NAME,LEN_NAME
-			,buf1+U_NAME
-			,41-LEN_NAME,nulstr
-			,LEN_NAME
-			,buf2+U_NAME);
-
-		fprintf(out,"    %-*.*s%*s%.*s\r\n"
-			,LEN_ADDRESS,LEN_ADDRESS
-			,buf1+U_ADDRESS
-			,41-LEN_ADDRESS,nulstr
-			,LEN_ADDRESS
-			,buf2+U_ADDRESS);
-
-		sprintf(str,"%.*s %.*s"
-			,LEN_LOCATION,buf1+U_LOCATION
-			,LEN_ZIPCODE,buf1+U_ZIPCODE);
-
-		fprintf(out,"    %-41s%.*s %.*s\r\n"
-			,str
-			,LEN_LOCATION,buf2+U_LOCATION
-			,LEN_ZIPCODE,buf2+U_ZIPCODE);
-
-		sprintf(str,"ATTN: %.*s",LEN_ALIAS,buf1+U_ALIAS);
-
-        if(mode&ATTN_ALIAS)
-			fprintf(out,"    %-41sATTN: %.*s\r\n\r\n\r\n"
-                ,str,LEN_ALIAS,buf2+U_ALIAS);
-        else
-			fprintf(out,"\r\n\r\n\r\n");
-
-		printed+=2; }
-
-	else {								/* single column labels */
-		fprintf(out,"    %.*s\r\n"
-			,LEN_NAME
-			,buf1+U_NAME);
-
-		fprintf(out,"    %.*s\r\n"
-			,LEN_ADDRESS
-			,buf1+U_ADDRESS);
-
-		fprintf(out,"    %.*s %.*s\r\n"
-			,LEN_LOCATION
-			,buf1+U_LOCATION
-			,LEN_ZIPCODE
-			,buf1+U_ZIPCODE);
-
-		if(mode&ATTN_ALIAS)
-			fprintf(out,"    ATTN: %.*s\r\n\r\n\r\n"
-				,LEN_ALIAS,buf1+U_ALIAS);
-        else
-			fprintf(out,"\r\n\r\n\r\n");
-
-		printed++; } }
-printf("\nDone.\n");
-fclose(in);
-fclose(out);
-return(0);
-}
-
-/* end of mlabels.c */
diff --git a/src/sbbs2/msg1.c b/src/sbbs2/msg1.c
deleted file mode 100644
index e13d7a5065a4a84237dde8263a9007a8ea5d8350..0000000000000000000000000000000000000000
--- a/src/sbbs2/msg1.c
+++ /dev/null
@@ -1,493 +0,0 @@
-#line 1 "MSG1.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/***********************************************************************/
-/* Functions that do i/o with messages (posts/mail/auto) or their data */
-/***********************************************************************/
-
-#include "sbbs.h"
-
-#define LZH 1
-
-void lfputs(char HUGE16 *buf, FILE *fp)
-{
-while(*buf) {
-    fputc(*buf,fp);
-    buf++; }
-}
-
-/****************************************************************************/
-/* Loads an SMB message from the open msg base the fastest way possible 	*/
-/* first by offset, and if that's the wrong message, then by number.        */
-/* Returns 1 if the message was loaded and left locked, otherwise			*/
-/****************************************************************************/
-int loadmsg(smbmsg_t *msg, ulong number)
-{
-	char str[128];
-	int i;
-
-if(msg->idx.offset) {				/* Load by offset if specified */
-
-	if((i=smb_lockmsghdr(&smb,msg))!=0) {
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-		return(0); }
-
-	i=smb_getmsghdr(&smb,msg);
-	if(!i && msg->hdr.number==number)
-		return(1);
-
-	/* Wrong offset  */
-
-	if(!i) {
-		smb_freemsgmem(msg);
-		msg->total_hfields=0; }
-
-	smb_unlockmsghdr(&smb,msg); }
-
-msg->hdr.number=number;
-if((i=smb_getmsgidx(&smb,msg))!=0)				 /* Message is deleted */
-	return(0);
-if((i=smb_lockmsghdr(&smb,msg))!=0) {
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return(0); }
-if((i=smb_getmsghdr(&smb,msg))!=0) {
-	sprintf(str,"(%06lX) #%lu/%lu %s",msg->idx.offset,msg->idx.number
-		,number,smb.file);
-	smb_unlockmsghdr(&smb,msg);
-	errormsg(WHERE,ERR_READ,str,i);
-	return(0); }
-return(msg->total_hfields);
-}
-
-/****************************************************************************/
-/* Displays a text file to the screen, reading/display a block at time		*/
-/****************************************************************************/
-void putmsg_fp(FILE *fp, long length, int mode)
-{
-	uchar *buf,tmpatr;
-	int i,j,b=8192,orgcon=console;
-	long l;
-
-tmpatr=curatr;	/* was lclatr(-1) */
-if((buf=MALLOC(b+1))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,b+1L);
-    return; }
-for(l=0;l<length;l+=b) {
-	if(l+b>length)
-		b=length-l;
-	i=j=fread(buf,1,b,fp);
-	if(!j) break;						/* No bytes read */
-	if(l+i<length)						/* Not last block */
-		while(i && buf[i-1]!=LF) i--;	/* Search for last LF */
-	if(!i) i=j; 						/* None found */
-	buf[i]=0;
-	if(i<j)
-		fseek(fp,(long)-(j-i),SEEK_CUR);
-	b=i;
-	if(putmsg(buf,mode|P_SAVEATR))
-		break; }
-if(!(mode&P_SAVEATR)) {
-	console=orgcon;
-	attr(tmpatr); }
-FREE(buf);
-}
-
-void show_msgattr(ushort attr)
-{
-
-bprintf(text[MsgAttr]
-	,attr&MSG_PRIVATE	? "Private  "   :nulstr
-	,attr&MSG_READ		? "Read  "      :nulstr
-	,attr&MSG_DELETE	? "Deleted  "   :nulstr
-	,attr&MSG_KILLREAD	? "Kill  "      :nulstr
-	,attr&MSG_ANONYMOUS ? "Anonymous  " :nulstr
-	,attr&MSG_LOCKED	? "Locked  "    :nulstr
-	,attr&MSG_PERMANENT ? "Permanent  " :nulstr
-	,attr&MSG_MODERATED ? "Moderated  " :nulstr
-	,attr&MSG_VALIDATED ? "Validated  " :nulstr
-	,attr&MSG_REPLIED	? "Replied  "	:nulstr
-	,nulstr
-	,nulstr
-	,nulstr
-	,nulstr
-	,nulstr
-	,nulstr
-	);
-}
-
-/****************************************************************************/
-/* Displays a message header to the screen                                  */
-/****************************************************************************/
-void show_msghdr(smbmsg_t msg)
-{
-	char	*sender=NULL;
-	int 	i;
-
-attr(LIGHTGRAY);
-if(useron.misc&CLRSCRN)
-    outchar(FF);
-else
-    CRLF;
-bprintf(text[MsgSubj],msg.subj);
-if(msg.hdr.attr)
-	show_msgattr(msg.hdr.attr);
-
-bprintf(text[MsgTo],msg.to);
-if(msg.to_ext)
-	bprintf(text[MsgToExt],msg.to_ext);
-if(msg.to_net.addr)
-	bprintf(text[MsgToNet],msg.to_net.type==NET_FIDO
-        ? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
-if(!(msg.hdr.attr&MSG_ANONYMOUS) || SYSOP) {
-	bprintf(text[MsgFrom],msg.from);
-	if(msg.from_ext)
-		bprintf(text[MsgFromExt],msg.from_ext);
-	if(msg.from_net.addr)
-		bprintf(text[MsgFromNet],msg.from_net.type==NET_FIDO
-			? faddrtoa(*(faddr_t *)msg.from_net.addr)
-				: msg.from_net.addr); }
-bprintf(text[MsgDate]
-	,timestr((time_t *)&msg.hdr.when_written.time)
-    ,zonestr(msg.hdr.when_written.zone));
-
-CRLF;
-
-for(i=0;i<msg.total_hfields;i++) {
-	if(msg.hfield[i].type==SENDER)
-		sender=msg.hfield_dat[i];
-	if(msg.hfield[i].type==FORWARDED && sender)
-		bprintf(text[ForwardedFrom],sender
-			,timestr((time_t *)msg.hfield_dat[i])); }
-
-/* Debug stuff
-if(SYSOP) {
-	bprintf("\1n\1c\r\nAux  : \1h%08lX",msg.hdr.auxattr);
-	bprintf("\1n\1c\r\nNum  : \1h%lu",msg.hdr.number); }
-*/
-
-CRLF;
-}
-
-#if !LZH
-
-/****************************************************************************/
-/* Displays message header and text (if not deleted)                        */
-/****************************************************************************/
-void show_msg(smbmsg_t msg, int mode)
-{
-	ushort xlat;
-    int i;
-
-show_msghdr(msg);
-for(i=0;i<msg.hdr.total_dfields;i++)
-	switch(msg.dfield[i].type) {
-        case TEXT_BODY:
-        case TEXT_TAIL:
-			fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-                ,SEEK_SET);
-			fread(&xlat,2,1,smb.sdt_fp);
-			if(xlat!=XLAT_NONE) 		/* no translations supported */
-				continue;
-			putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
-            CRLF;
-            break; }
-}
-
-#else
-
-/****************************************************************************/
-/* Displays message header and text (if not deleted)                        */
-/****************************************************************************/
-void show_msg(smbmsg_t msg, int mode)
-{
-	char *inbuf,*lzhbuf;
-	ushort xlat;
-	int i,lzh;
-	long lzhlen,length;
-
-show_msghdr(msg);
-for(i=0;i<msg.hdr.total_dfields;i++)
-	switch(msg.dfield[i].type) {
-        case TEXT_BODY:
-        case TEXT_TAIL:
-			fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-                ,SEEK_SET);
-			fread(&xlat,2,1,smb.sdt_fp);
-			lzh=0;
-			if(xlat==XLAT_LZH) {
-				lzh=1;
-				fread(&xlat,2,1,smb.sdt_fp); }
-			if(xlat!=XLAT_NONE) 		/* no translations supported */
-				continue;
-			if(lzh) {
-				length=msg.dfield[i].length-4;
-				if((inbuf=MALLOC(length))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,nulstr,length);
-					continue; }
-				fread(inbuf,length,1,smb.sdt_fp);
-				lzhlen=*(long *)inbuf;
-/**
-				if(SYSOP)
-				bprintf("Decoding %lu bytes of LZH into %lu bytes of text "
-					"(%d%% compression)"
-					,length,lzhlen
-					,(int)(((float)(lzhlen-length)/lzhlen)*100.0));
-**/
-				if((lzhbuf=MALLOC(lzhlen+2L))==NULL) {
-					FREE(inbuf);
-					errormsg(WHERE,ERR_ALLOC,nulstr,lzhlen+2L);
-					continue; }
-				lzh_decode(inbuf,length,lzhbuf);
-				lzhbuf[lzhlen]=0;
-//				  CRLF;
-				putmsg(lzhbuf,P_NOATCODES);
-				FREE(lzhbuf);
-				FREE(inbuf); }
-			else
-				putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
-            CRLF;
-            break; }
-}
-
-#endif
-
-void quotemsg(smbmsg_t msg, int tails)
-{
-	char	str[256];
-
-sprintf(str,"%sQUOTES.TXT",node_dir);
-remove(str);
-msgtotxt(msg,str,0,tails);
-}
-
-
-/****************************************************************************/
-/* Writes message header and text data to a text file						*/
-/****************************************************************************/
-void msgtotxt(smbmsg_t msg, char *str, int header, int tails)
-{
-	uchar	HUGE16 *buf;
-	ushort	xlat;
-	int 	i,j,x;
-	ulong	l;
-	FILE	*out;
-
-if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,0);
-	return; }
-if(header) {
-	fprintf(out,"\r\n");
-	fprintf(out,"Subj : %s\r\n",msg.subj);
-	fprintf(out,"To   : %s",msg.to);
-	if(msg.to_ext)
-		fprintf(out," #%s",msg.to_ext);
-	if(msg.to_net.addr)
-		fprintf(out," (%s)",msg.to_net.type==NET_FIDO
-			? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
-	fprintf(out,"\r\nFrom : %s",msg.from);
-	if(msg.from_ext && !(msg.hdr.attr&MSG_ANONYMOUS))
-		fprintf(out," #%s",msg.from_ext);
-	if(msg.from_net.addr)
-		fprintf(out," (%s)",msg.from_net.type==NET_FIDO
-			? faddrtoa(*(faddr_t *)msg.from_net.addr)
-				: msg.from_net.addr);
-	fprintf(out,"\r\nDate : %.24s %s"
-		,timestr((time_t *)&msg.hdr.when_written.time)
-		,zonestr(msg.hdr.when_written.zone));
-	fprintf(out,"\r\n\r\n"); }
-
-buf=smb_getmsgtxt(&smb,&msg,tails);
-if(buf) {
-	lfputs(buf,out);
-	LFREE(buf); }
-else if(smb_getmsgdatlen(&msg)>2)
-	errormsg(WHERE,ERR_ALLOC,smb.file,smb_getmsgdatlen(&msg));
-fclose(out);
-}
-
-
-/****************************************************************************/
-/* Returns total number of posts in a sub-board 							*/
-/****************************************************************************/
-ulong getposts(uint subnum)
-{
-	char str[128];
-	ulong l;
-
-sprintf(str,"%s%s.SID",sub[subnum]->data_dir,sub[subnum]->code);
-l=flength(str);
-if((long)l==-1)
-	return(0);
-return(l/sizeof(idxrec_t));
-}
-
-/****************************************************************************/
-/* Returns message number posted at or after time							*/
-/****************************************************************************/
-ulong getmsgnum(uint subnum, time_t t)
-{
-    int     i;
-	ulong	l,total,bot,top;
-	smbmsg_t msg;
-
-if(!t)
-	return(0);
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
-
-if(!total) {		   /* Empty base */
-	smb_close(&smb);
-	return(0); }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-    return(0); }
-
-if((i=smb_getlastidx(&smb,&msg.idx))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-    return(0); }
-
-if(msg.idx.time<=t) {
-	smb_close(&smb);
-	return(msg.idx.number); }
-
-bot=0;
-top=total;
-l=total/2; /* Start at middle index */
-clearerr(smb.sid_fp);
-while(1) {
-	fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
-		break;
-	if(bot==top-1)
-		break;
-	if(msg.idx.time>t) {
-		top=l;
-		l=bot+((top-bot)/2);
-		continue; }
-	if(msg.idx.time<t) {
-		bot=l;
-		l=top-((top-bot)/2);
-		continue; }
-	break; }
-smb_close(&smb);
-return(msg.idx.number);
-}
-
-/****************************************************************************/
-/* Returns the time of the message number pointed to by 'ptr'               */
-/****************************************************************************/
-time_t getmsgtime(uint subnum, ulong ptr)
-{
-	char	str[128];
-	int 	i;
-	long	l;
-	smbmsg_t msg;
-	idxrec_t lastidx;
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-if(!filelength(fileno(smb.sid_fp))) {			/* Empty base */
-	smb_close(&smb);
-	return(0); }
-msg.offset=0;
-msg.hdr.number=0;
-if(smb_getmsgidx(&smb,&msg)) {				/* Get first message index */
-	smb_close(&smb);
-	return(0); }
-if(!ptr || msg.idx.number>=ptr) {			/* ptr is before first message */
-	smb_close(&smb);
-	return(msg.idx.time); } 				/* so return time of first msg */
-
-if(smb_getlastidx(&smb,&lastidx)) { 			 /* Get last message index */
-	smb_close(&smb);
-	return(0); }
-if(lastidx.number<ptr) {					/* ptr is after last message */
-	smb_close(&smb);
-	return(lastidx.time); } 				/* so return time of last msg */
-
-msg.idx.time=0;
-msg.hdr.number=ptr;
-if(!smb_getmsgidx(&smb,&msg)) {
-	smb_close(&smb);
-	return(msg.idx.time); }
-
-if(ptr-msg.idx.number < lastidx.number-ptr) {
-	msg.offset=0;
-	msg.idx.number=0;
-	while(msg.idx.number<ptr) {
-		msg.hdr.number=0;
-		if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr)
-			break;
-		msg.offset++; }
-	smb_close(&smb);
-	return(msg.idx.time); }
-
-ptr--;
-while(ptr) {
-	msg.hdr.number=ptr;
-	if(!smb_getmsgidx(&smb,&msg))
-		break;
-	ptr--; }
-smb_close(&smb);
-return(msg.idx.time);
-}
-
-
-/****************************************************************************/
-/* Returns the total number of msgs in the sub-board and sets 'ptr' to the  */
-/* number of the last message in the sub (0) if no messages.				*/
-/****************************************************************************/
-ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
-{
-	char		str[256];
-	int 		i;
-	ulong		total;
-	idxrec_t	idx;
-
-if(ptr)
-	(*ptr)=0;
-if(t)
-	(*t)=0;
-if(subnum>=total_subs)
-	return(0);
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-if(!filelength(fileno(smb.sid_fp))) {			/* Empty base */
-	smb_close(&smb);
-	return(0); }
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return(0); }
-if((i=smb_getlastidx(&smb,&idx))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-	return(0); }
-total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
-smb_unlocksmbhdr(&smb);
-smb_close(&smb);
-if(ptr)
-	(*ptr)=idx.number;
-if(t)
-	(*t)=idx.time;
-return(total);
-}
-
diff --git a/src/sbbs2/msg2.c b/src/sbbs2/msg2.c
deleted file mode 100644
index b8468f8693ec5caefd87e8177d73e389951512e8..0000000000000000000000000000000000000000
--- a/src/sbbs2/msg2.c
+++ /dev/null
@@ -1,1202 +0,0 @@
-#line 1 "MSG2.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-#define MAX_LINE_LEN 82L
-
-char *qstr=" > %.76s\r\n";
-
-int qwk_route(char *inaddr, char *fulladdr);
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Modify 'str' to for quoted format. Remove ^A codes, etc.                 */
-/****************************************************************************/
-void quotestr(char *str)
-{
-	char tmp[512];
-	int i,j;
-
-j=strlen(str);
-while(j && (str[j-1]==SP || str[j-1]==LF || str[j-1]==CR)) j--;
-str[j]=0;
-remove_ctrl_a(str);
-}
-
-void editor_inf(int xeditnum,char *dest, char *title,int mode
-	,uint subnum)
-{
-	char str[512];
-	int file;
-
-xeditnum--;
-
-if(xedit[xeditnum]->misc&QUICKBBS) {
-	sprintf(str,"%sMSGINF",node_dir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-	sprintf(str,"%s\r\n%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n"
-		,(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_NAME) ? useron.name
-			: useron.alias
-			,dest,title,1
-			,mode&WM_NETMAIL ? "NetMail"
-			:mode&WM_EMAIL ? "Electronic Mail"
-			:subnum==INVALID_SUB ? nulstr
-			:sub[subnum]->sname
-		,mode&WM_PRIVATE ? "YES":"NO");
-	write(file,str,strlen(str));
-	close(file); }
-else {
-	sprintf(str,"%sEDITOR.INF",node_dir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-	sprintf(str,"%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n%u\r\n"
-		,title,dest,useron.number
-		,(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_NAME) ? useron.name
-		: useron.alias
-		,useron.name,useron.level);
-	write(file,str,strlen(str));
-	close(file); }
-}
-
-/****************************************************************************/
-/* Creates a message (post or mail) using standard line editor. 'fname' is  */
-/* is name of file to create, 'top' is a buffer to place at beginning of    */
-/* message and 'title' is the title (70chars max) for the message.          */
-/* 'dest' contains a text description of where the message is going.        */
-/* Returns positive if successful or 0 if aborted.                          */
-/****************************************************************************/
-char writemsg(char *fname, char *top, char *title, int mode, int subnum
-	,char *dest)
-{
-	uchar str[256],quote[128],msgtmp[32],c,HUGE16 *buf,ex_mode=0,*p,*tp
-		,useron_level;
-	int i,j,file,linesquoted=0;
-	long length,qlen,qtime;
-	ulong l;
-	FILE *stream;
-
-useron_level=useron.level;
-
-if((buf=(char HUGE16*)LMALLOC(level_linespermsg[useron_level]*MAX_LINE_LEN))
-	==NULL) {
-	errormsg(WHERE,ERR_ALLOC,fname
-		,level_linespermsg[useron_level]*MAX_LINE_LEN);
-    return(0); }
-
-if(mode&WM_NETMAIL ||
-	(!(mode&(WM_EMAIL|WM_NETMAIL)) && sub[subnum]->misc&SUB_PNET))
-	mode|=WM_NOTOP;
-
-if(useron.xedit && xedit[useron.xedit-1]->misc&QUICKBBS)
-	strcpy(msgtmp,"MSGTMP");
-else
-	strcpy(msgtmp,"INPUT.MSG");
-
-if(mode&WM_QUOTE && !(useron.rest&FLAG('J'))
-	&& ((mode&(WM_EMAIL|WM_NETMAIL) && sys_misc&SM_QUOTE_EM)
-	|| (!(mode&(WM_EMAIL|WM_NETMAIL)) && (uint)subnum!=INVALID_SUB
-		&& sub[subnum]->misc&SUB_QUOTE))) {
-
-	/* Quote entire message to MSGTMP or INPUT.MSG */
-
-	if(useron.xedit && xedit[useron.xedit-1]->misc&QUOTEALL) {
-		sprintf(str,"%sQUOTES.TXT",node_dir);
-		if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-			errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-			LFREE(buf);
-			return(0); }
-
-		sprintf(str,"%s%s",node_dir,msgtmp);    /* file for quoted msg */
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-			LFREE(buf);
-			fclose(stream);
-			return(0); }
-
-		while(!feof(stream) && !ferror(stream)) {
-			if(!fgets(str,255,stream))
-				break;
-			quotestr(str);
-			sprintf(tmp,qstr,str);
-			write(file,tmp,strlen(tmp));
-			linesquoted++; }
-		fclose(stream);
-		close(file); }
-
-	/* Quote nothing to MSGTMP or INPUT.MSG automatically */
-
-	else if(useron.xedit && xedit[useron.xedit-1]->misc&QUOTENONE)
-		;
-
-	else if(yesno(text[QuoteMessageQ])) {
-		sprintf(str,"%sQUOTES.TXT",node_dir);
-		if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-			errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-			LFREE(buf);
-			return(0); }
-
-		sprintf(str,"%s%s",node_dir,msgtmp);    /* file for quoted msg */
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-			LFREE(buf);
-			fclose(stream);
-			return(0); }
-
-		l=ftell(stream);			/* l now points to start of message */
-
-		while(online) {
-			sprintf(str,text[QuoteLinesPrompt],linesquoted ? "Done":"All");
-			mnemonics(str);
-			i=getstr(quote,10,K_UPPER);
-			if(sys_status&SS_ABORT) {
-				fclose(stream);
-				close(file);
-				LFREE(buf);
-				return(0); }
-			if(!i && linesquoted)
-				break;
-			if(!i || quote[0]=='A') {                   /* Quote all */
-				fseek(stream,l,SEEK_SET);
-				while(!feof(stream) && !ferror(stream)) {
-					if(!fgets(str,255,stream))
-						break;
-					quotestr(str);
-					sprintf(tmp,qstr,str);
-					write(file,tmp,strlen(tmp));
-					linesquoted++; }
-				break; }
-			if(quote[0]=='L') {
-				fseek(stream,l,SEEK_SET);
-				i=1;
-				CRLF;
-				attr(LIGHTGRAY);
-				while(!feof(stream) && !ferror(stream) && !msgabort()) {
-					if(!fgets(str,255,stream))
-						break;
-					quotestr(str);
-					bprintf("%3d: %.74s\r\n",i,str);
-					i++; }
-				continue; }
-
-			if(!isdigit(quote[0]))
-				break;
-			p=quote;
-			while(p) {
-				if(*p==',' || *p==SP)
-					p++;
-				i=atoi(p);
-				if(!i)
-					break;
-				fseek(stream,l,SEEK_SET);
-				j=1;
-				while(!feof(stream) && !ferror(stream) && j<i) {
-					if(!fgets(tmp,255,stream))
-						break;
-					j++; }		/* skip beginning */
-				tp=strchr(p,'-');   /* tp for temp pointer */
-				if(tp) {		 /* range */
-					i=atoi(tp+1);
-					while(!feof(stream) && !ferror(stream) && j<=i) {
-						if(!fgets(str,255,stream))
-							break;
-						quotestr(str);
-						sprintf(tmp,qstr,str);
-						write(file,tmp,strlen(tmp));
-						linesquoted++;
-						j++; } }
-				else {			/* one line */
-					if(fgets(str,255,stream)) {
-						quotestr(str);
-						sprintf(tmp,qstr,str);
-						write(file,tmp,strlen(tmp));
-						linesquoted++; } }
-				p=strchr(p,',');
-				// if(!p) p=strchr(p,SP);  02/05/96 huh?
-				} }
-
-		fclose(stream);
-		close(file); } }
-else {
-	sprintf(str,"%sQUOTES.TXT",node_dir);
-	remove(str); }
-
-if(!online || sys_status&SS_ABORT) {
-	LFREE(buf);
-	return(0); }
-
-if(!(mode&WM_EXTDESC)) {
-	if(mode&WM_FILE) {
-		c=12;
-		CRLF;
-		bputs(text[Filename]); }
-	else {
-		c=LEN_TITLE;
-		bputs(text[TitlePrompt]); }
-	if(!(mode&(WM_EMAIL|WM_NETMAIL)) && !(mode&WM_FILE)
-		&& sub[subnum]->misc&(SUB_QNET /* |SUB_PNET */ ))
-        c=25;
-	if(mode&WM_QWKNET)
-		c=25;
-	if(!getstr(title,c,mode&WM_FILE ? K_LINE|K_UPPER : K_LINE|K_EDIT|K_AUTODEL)
-		&& useron_level && useron.logons) {
-		LFREE(buf);
-        return(0); }
-    if(!(mode&(WM_EMAIL|WM_NETMAIL)) && sub[subnum]->misc&SUB_QNET
-		&& !SYSOP
-		&& (!stricmp(title,"DROP") || !stricmp(title,"ADD")
-		|| !strnicmp(dest,"SBBS",4))) {
-		LFREE(buf);   /* Users can't post DROP or ADD in QWK netted subs */
-		return(0); } }	/* or messages to "SBBS" */
-
-if(!online || sys_status&SS_ABORT) {
-	LFREE(buf);
-	return(0); }
-
-/* Create WWIV compatible EDITOR.INF file */
-
-if(useron.xedit) {
-	editor_inf(useron.xedit,dest,title,mode,subnum);
-	if(xedit[useron.xedit-1]->type) {
-		gettimeleft();
-		xtrndat(useron.alias,node_dir,xedit[useron.xedit-1]->type,timeleft); }
-	}
-
-if(console&CON_RAW_IN) {
-    bprintf(text[EnterMsgNowRaw]
-		,(ulong)level_linespermsg[useron_level]*MAX_LINE_LEN);
-	if(top[0] && !(mode&WM_NOTOP)) {
-		strcpy((char *)buf,top);
-		strcat((char *)buf,crlf);
-		l=strlen((char *)buf); }
-	else
-        l=0;
-	while(l<level_linespermsg[useron_level]*MAX_LINE_LEN) {
-        c=getkey(0);
-        if(sys_status&SS_ABORT) {  /* Ctrl-C */
-			LFREE(buf);
-            return(0); }
-        if((c==ESC || c==1) && useron.rest&FLAG('A')) /* ANSI restriction */
-            continue;
-#ifndef __OS2__
-		if(lclaes() && c=='"') c=7; /* convert keyboard reassignmnet to beep */
-#endif
-        if(c==7 && useron.rest&FLAG('B'))   /* Beep restriction */
-            continue;
-		if(!(console&CON_RAW_IN))	/* Ctrl-Z was hit */
-            break;
-        outchar(c);
-        buf[l++]=c; }
-    buf[l]=0;
-	if(l==level_linespermsg[useron_level]*MAX_LINE_LEN)
-		bputs(text[OutOfBytes]); }
-
-
-else if((online==ON_LOCAL && node_misc&NM_LCL_EDIT && node_editor[0])
-    || useron.xedit) {
-
-	if(useron.xedit && xedit[useron.xedit-1]->misc&IO_INTS) {
-		ex_mode|=EX_OUTL;
-		if(online==ON_REMOTE)
-			ex_mode|=(EX_OUTR|EX_INR);
-		if(xedit[useron.xedit-1]->misc&WWIVCOLOR)
-			ex_mode|=EX_WWIV; }
-
-	sprintf(str,"%s%s",node_dir,msgtmp);    /* temporary file for input */
-	if(!linesquoted && fexist(str))
-		remove(str);
-	if(linesquoted) {
-		qlen=flength(str);
-		qtime=fdate(str); }
-    if(online==ON_LOCAL) {
-        if(node_misc&NM_LCL_EDIT && node_editor[0])
-			external(cmdstr(node_editor,str,nulstr,NULL)
-				,0);  /* EX_CC removed and EX_OUTL removed */
-        else
-			external(cmdstr(xedit[useron.xedit-1]->lcmd,str,nulstr,NULL)
-				,ex_mode); }
-
-    else {
-        rioctl(IOCM|PAUSE|ABORT);
-		external(cmdstr(xedit[useron.xedit-1]->rcmd,str,nulstr,NULL),ex_mode);
-        rioctl(IOSM|PAUSE|ABORT); }
-	checkline();
-	if(!fexist(str) || !online
-		|| (linesquoted && qlen==flength(str) && qtime==fdate(str))) {
-		LFREE(buf);
-        return(0); }
-	buf[0]=0;
-	if(!(mode&WM_NOTOP))
-		strcpy((char *)buf,top);
-	if((file=nopen(str,O_RDONLY))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-		LFREE(buf);
-        return(0); }
-    length=filelength(file);
-	l=strlen((char *)buf);	  /* reserve space for top and terminating null */
-	/* truncate if too big */
-	if(length>(level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1)) {
-		length=(level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1);
-		bputs(text[OutOfBytes]); }
-	lread(file,buf+l,length);
-    close(file);
-	// remove(str); 	   /* no need to save the temp input file */
-	buf[l+length]=0; }
-else {
-    buf[0]=0;
-	if(linesquoted) {
-		sprintf(str,"%s%s",node_dir,msgtmp);
-		if((file=nopen(str,O_RDONLY))!=-1) {
-			length=filelength(file);
-			l=length>level_linespermsg[useron_level]*MAX_LINE_LEN
-				? level_linespermsg[useron_level]*MAX_LINE_LEN : length;
-			lread(file,buf,l);
-			buf[l]=0;
-			close(file);
-			// remove(str);
-			} }
-	if(!(msgeditor((char *)buf,mode&WM_NOTOP ? nulstr : top,title))) {
-		LFREE(buf);
-		return(0); } }
-
-now=time(NULL);
-bputs(text[Saving]);
-if((stream=fnopen(&file,fname,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
-	errormsg(WHERE,ERR_OPEN,fname,O_WRONLY|O_CREAT|O_TRUNC);
-	LFREE(buf);
-    return(0); }
-for(l=i=0;buf[l] && i<level_linespermsg[useron_level];l++) {
-	if(buf[l]==141 && useron.xedit && xedit[useron.xedit-1]->misc&QUICKBBS) {
-		fwrite(crlf,2,1,stream);
-		i++;
-		continue; }
-	if(buf[l]==LF && (!l || buf[l-1]!=CR) && useron.xedit
-		&& xedit[useron.xedit-1]->misc&EXPANDLF) {
-		fwrite(crlf,2,1,stream);
-		i++;
-		continue; }
-	if(!(mode&(WM_EMAIL|WM_NETMAIL))
-		&& (!l || buf[l-1]==LF)
-		&& buf[l]=='-' && buf[l+1]=='-' && buf[l+2]=='-'
-		&& (buf[l+3]==SP || buf[l+3]==TAB || buf[l+3]==CR))
-		buf[l+1]='+';
-	if(buf[l]==LF)
-		i++;
-	fputc(buf[l],stream); }
-
-if(buf[l])
-	bputs(text[NoMoreLines]);
-fclose(stream);
-LFREE((char *)buf);
-bprintf(text[SavedNBytes],l,i);
-return(1);
-}
-
-
-/****************************************************************************/
-/* Removes from file 'str' every LF terminated line that starts with 'str2' */
-/* That is divisable by num. Function skips first 'skip' number of lines    */
-/****************************************************************************/
-void removeline(char *str, char *str2, char num, char skip)
-{
-	char	HUGE16 *buf;
-    char    slen,c;
-    int     i,file;
-	ulong	l=0,m,flen;
-    FILE    *stream;
-
-if((file=nopen(str,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-    return; }
-flen=filelength(file);
-slen=strlen(str2);
-if((buf=(char *)MALLOC(flen))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,flen);
-    return; }
-if(lread(file,buf,flen)!=flen) {
-    close(file);
-    errormsg(WHERE,ERR_READ,str,flen);
-	FREE(buf);
-    return; }
-close(file);
-if((stream=fnopen(&file,str,O_WRONLY|O_TRUNC))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
-	FREE(buf);
-    return; }
-for(i=0;l<flen && i<skip;l++) {
-    fputc(buf[l],stream);
-    if(buf[l]==LF)
-        i++; }
-while(l<flen) {
-	if(!strncmp((char *)buf+l,str2,slen)) {
-		for(i=0;i<num && l<flen;i++) {
-			while(l<flen && buf[l]!=LF) l++;
-			l++; } }
-    else {
-		for(i=0;i<num && l<flen;i++) {
-			while(l<flen && buf[l]!=LF) fputc(buf[l++],stream);
-			fputc(buf[l++],stream); } } }
-fclose(stream);
-FREE((char *)buf);
-}
-
-/*****************************************************************************/
-/* The Synchronet editor.                                                    */
-/* Returns the number of lines edited.                                       */
-/*****************************************************************************/
-ulong msgeditor(char *buf, char *top, char *title)
-{
-	int i,j,line,lines=0,maxlines;
-	char strin[256],**str,done=0;
-    ulong l,m;
-
-if(online==ON_REMOTE) {
-    rioctl(IOCM|ABORT);
-    rioctl(IOCS|ABORT); }
-
-maxlines=level_linespermsg[useron.level];
-
-if((str=(char **)MALLOC(sizeof(char *)*(maxlines+1)))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,"msgeditor",sizeof(char *)*(maxlines+1));
-	return(0); }
-m=strlen(buf);
-l=0;
-while(l<m && lines<maxlines) {
-    msgabort(); /* to allow pausing */
-	if((str[lines]=MALLOC(MAX_LINE_LEN))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
-        for(i=0;i<lines;i++)
-			FREE(str[lines]);
-		FREE(str);
-        if(online==ON_REMOTE)
-            rioctl(IOSM|ABORT);
-        return(0); }
-    for(i=0;i<79 && l<m;i++,l++) {
-        if(buf[l]==CR) {
-            l+=2;
-            break; }
-        if(buf[l]==TAB) {
-            if(!(i%8))                  /* hard-coded tabstop of 8 */
-                str[lines][i++]=SP;     /* for expansion */
-            while(i%8 && i<79)
-                str[lines][i++]=SP;
-            i--;
-            /***
-            bprintf("\r\nMessage editor: Expanded tab on line #%d",lines+1);
-            ***/ }
-        else str[lines][i]=buf[l]; }
-    if(i==79) {
-        if(buf[l]==CR)
-            l+=2;
-		else
-			bprintf("\r\nMessage editor: Split line #%d",lines+1); }
-    str[lines][i]=0;
-    lines++; }
-if(lines)
-    bprintf("\r\nMessage editor: Read in %d lines\r\n",lines);
-bprintf(text[EnterMsgNow],maxlines);
-for(i=0;i<79;i++)
-    if(i%TABSIZE || !i)
-        outchar('-');
-    else outchar('+');
-CRLF;
-putmsg(top,P_SAVEATR|P_NOATCODES);
-for(line=0;line<lines && !msgabort();line++) { /* display lines in buf */
-	putmsg(str[line],P_SAVEATR|P_NOATCODES);
-    if(useron.misc&ANSI)
-        bputs("\x1b[K");  /* delete to end of line */
-    CRLF; }
-SYNC;
-if(online==ON_REMOTE)
-    rioctl(IOSM|ABORT);
-while(online && !done) {
-    checkline();
-    if(line==lines) {
-		if((str[line]=MALLOC(MAX_LINE_LEN))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
-            for(i=0;i<lines;i++)
-				FREE(str[i]);
-			FREE(str);
-            return(0); }
-        str[line][0]=0; }
-    if(line>(maxlines-10)) {
-        if(line==maxlines)
-            bputs(text[NoMoreLines]);
-        else
-            bprintf(text[OnlyNLinesLeft],maxlines-line); }
-    strcpy(strin,str[line]);
-	do {
-		if(!line)
-			outchar(CR);
-		getstr(strin,79,K_WRAP|K_MSG|K_EDIT);
-		} while(console&CON_UPARROW && !line);
-
-    if(sys_status&SS_ABORT) {
-        if(line==lines)
-			FREE(str[line]);
-        continue; }
-    if(strin[0]=='/' && strlen(strin)<8) {
-		if(!stricmp(strin,"/DEBUG") && SYSOP) {
-            if(line==lines)
-                FREE(str[line]);
-            bprintf("\r\nline=%d lines=%d rows=%d\r\n",line,lines,rows);
-            continue; }
-		else if(!stricmp(strin,"/ABT")) {
-			if(line==lines) 		/* delete a line */
-                FREE(str[line]);
-			for(i=0;i<lines;i++)
-				FREE(str[i]);
-			FREE(str);
-            return(0); }
-        else if(toupper(strin[1])=='D') {
-            if(line==lines)         /* delete a line */
-				FREE(str[line]);
-            if(!lines)
-                continue;
-            i=atoi(strin+2)-1;
-            if(i==-1)   /* /D means delete last line */
-                i=lines-1;
-            if(i>=lines || i<0)
-                bputs(text[InvalidLineNumber]);
-            else {
-				FREE(str[i]);
-                lines--;
-                while(i<lines) {
-                    str[i]=str[i+1];
-                    i++; }
-                if(line>lines)
-                    line=lines; }
-            continue; }
-        else if(toupper(strin[1])=='I') {
-            if(line==lines)         /* insert a line before number x */
-				FREE(str[line]);
-            if(line==maxlines || !lines)
-                continue;
-            i=atoi(strin+2)-1;
-            if(i==-1)
-                i=lines-1;
-            if(i>=lines || i<0)
-                bputs(text[InvalidLineNumber]);
-            else {
-                for(line=lines;line>i;line--)   /* move the pointers */
-                    str[line]=str[line-1];
-				if((str[i]=MALLOC(MAX_LINE_LEN))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
-                    for(i=0;i<lines;i++)
-						FREE(str[i]);
-					FREE(str);
-                    return(0); }
-                str[i][0]=0;
-                line=++lines; }
-            continue; }
-        else if(toupper(strin[1])=='E') {
-            if(line==lines)         /* edit a line */
-				FREE(str[line]);
-            if(!lines)
-                continue;
-            i=atoi(strin+2)-1;
-            j=K_MSG|K_EDIT; /* use j for the getstr mode */
-            if(i==-1) { /* /E means edit last line */
-                i=lines-1;
-                j|=K_WRAP; }    /* wrap when editing last line */
-            if(i>=lines || i<0)
-                bputs(text[InvalidLineNumber]);
-			else
-                getstr(str[i],79,j);
-            continue; }
-        else if(!stricmp(strin,"/CLR")) {
-            bputs(text[MsgCleared]);
-			if(line!=lines)
-				lines--;
-            for(i=0;i<=lines;i++)
-				FREE(str[i]);
-            line=0;
-            lines=0;
-			putmsg(top,P_SAVEATR|P_NOATCODES);
-            continue; }
-        else if(toupper(strin[1])=='L') {   /* list message */
-            if(line==lines)
-				FREE(str[line]);
-            if(lines)
-                i=!noyes(text[WithLineNumbers]);
-            CRLF;
-            attr(LIGHTGRAY);
-			putmsg(top,P_SAVEATR|P_NOATCODES);
-            if(!lines) {
-                continue; }
-            j=atoi(strin+2);
-            if(j) j--;  /* start from line j */
-            while(j<lines && !msgabort()) {
-                if(i) { /* line numbers */
-					sprintf(tmp,"%3d: %-.74s",j+1,str[j]);
-					putmsg(tmp,P_SAVEATR|P_NOATCODES); }
-                else
-					putmsg(str[j],P_SAVEATR|P_NOATCODES);
-                if(useron.misc&ANSI)
-                    bputs("\x1b[K");  /* delete to end of line */
-                CRLF;
-                j++; }
-            SYNC;
-            continue; }
-        else if(!stricmp(strin,"/S")) { /* Save */
-            if(line==lines)
-				FREE(str[line]);
-            done=1;
-            continue;}
-        else if(!stricmp(strin,"/T")) { /* Edit title */
-            if(line==lines)
-				FREE(str[line]);
-            if(title[0]) {
-                bputs(text[TitlePrompt]);
-				getstr(title,LEN_TITLE,K_LINE|K_EDIT|K_AUTODEL);
-                SYNC;
-                CRLF; }
-            continue; }
-        else if(!stricmp(strin,"/?")) {
-            if(line==lines)
-				FREE(str[line]);
-            menu("EDITOR"); /* User Editor Commands */
-            SYNC;
-            continue; }
-		else if(!stricmp(strin,"/ATTR"))    {
-            if(line==lines)
-				FREE(str[line]);
-            menu("ATTR");   /* User ANSI Commands */
-            SYNC;
-            continue; } }
-    strcpy(str[line],strin);
-    if(line<maxlines)
-        line++;
-    else
-		FREE(str[line]);
-	if(line>lines)
-		lines++;
-    if(console&CON_UPARROW) {
-        outchar(CR);
-		bprintf("\x1b[A\x1b[K");    /* up one line, clear to eol */
-		line-=2; }
-	}
-if(!online) {
-    for(i=0;i<lines;i++)
-		FREE(str[i]);
-	FREE(str);
-    return(0); }
-strcpy(buf,top);
-for(i=0;i<lines;i++) {
-    strcat(buf,str[i]);
-    strcat(buf,crlf);
-	FREE(str[i]); }
-FREE(str);
-return(lines);
-}
-
-
-/****************************************************************************/
-/* Edits an existing file or creates a new one in MSG format                */
-/****************************************************************************/
-void editfile(char *str)
-{
-	char *buf,str2[128],mode=0;   /* EX_CC */
-    int file;
-	long length,maxlines,lines,l;
-
-maxlines=level_linespermsg[useron.level];
-sprintf(str2,"%sQUOTES.TXT",node_dir);
-remove(str2);
-if(node_editor[0] && online==ON_LOCAL) {
-	external(cmdstr(node_editor,str,nulstr,NULL),0); /* EX_CC */
-    return; }
-if(useron.xedit) {
-	editor_inf(useron.xedit,nulstr,nulstr,0,INVALID_SUB);
-	if(xedit[useron.xedit-1]->misc&IO_INTS) {
-		mode|=EX_OUTL;
-		if(online==ON_REMOTE)
-			mode|=(EX_OUTR|EX_INR);
-		if(xedit[useron.xedit-1]->misc&WWIVCOLOR)
-			mode|=EX_WWIV; }
-    if(online==ON_LOCAL)
-		external(cmdstr(xedit[useron.xedit-1]->lcmd,str,nulstr,NULL),mode);
-    else {
-        rioctl(IOCM|PAUSE|ABORT);
-		external(cmdstr(xedit[useron.xedit-1]->rcmd,str,nulstr,NULL),mode);
-        rioctl(IOSM|PAUSE|ABORT); }
-    return; }
-if((buf=(char *)MALLOC(maxlines*MAX_LINE_LEN))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,maxlines*MAX_LINE_LEN);
-    return; }
-if((file=nopen(str,O_RDONLY))!=-1) {
-    length=filelength(file);
-	if(length>(ulong)maxlines*MAX_LINE_LEN) {
-        attr(color[clr_err]);
-		bprintf("\7\r\nFile size (%lu bytes) is larger than (%lu).\r\n"
-			,length,(ulong)maxlines*MAX_LINE_LEN);
-        close(file);
-		FREE(buf); }
-    if(read(file,buf,length)!=length) {
-        close(file);
-		FREE(buf);
-        errormsg(WHERE,ERR_READ,str,length);
-        return; }
-    buf[length]=0;
-    close(file); }
-else {
-    buf[0]=0;
-    bputs(text[NewFile]); }
-if(!msgeditor(buf,nulstr,nulstr)) {
-	FREE(buf);
-    return; }
-bputs(text[Saving]);
-if((file=nopen(str,O_CREAT|O_WRONLY|O_TRUNC))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_TRUNC);
-	FREE(buf);
-    return; }
-if(write(file,buf,strlen(buf))!=strlen(buf)) {
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,strlen(buf));
-	FREE(buf);
-    return; }
-for(l=lines=0;buf[l];l++)
-	if(buf[l]==LF)
-		lines++;
-bprintf(text[SavedNBytes],l,lines);
-close(file);
-FREE(buf);
-return;
-}
-
-/*************************/
-/* Copy file attachments */
-/*************************/
-void copyfattach(uint to, uint from, char *title)
-{
-	char str[128],str2[128],str3[128],*tp,*sp,*p;
-    uint i;
-
-strcpy(str,title);
-tp=str;
-while(1) {
-    p=strchr(tp,SP);
-    if(p) *p=0;
-    sp=strrchr(tp,'/');              /* sp is slash pointer */
-    if(!sp) sp=strrchr(tp,'\\');
-    if(sp) tp=sp+1;
-    sprintf(str2,"%sFILE\\%04u.IN\\%s"  /* str2 is path/fname */
-        ,data_dir,to,tp);
-	sprintf(str3,"%sFILE\\%04u.IN\\%s"  /* str2 is path/fname */
-		,data_dir,from,tp);
-	if(strcmp(str2,str3))
-		mv(str3,str2,1);
-    if(!p)
-        break;
-    tp=p+1; }
-}
-
-
-/****************************************************************************/
-/* Forwards mail (fname) to usernumber                                      */
-/* Called from function readmail											*/
-/****************************************************************************/
-void forwardmail(smbmsg_t *msg, ushort usernumber)
-{
-	char str[256],touser[128];
-	int i;
-	node_t		node;
-	msghdr_t	hdr=msg->hdr;
-	idxrec_t	idx=msg->idx;
-
-if(useron.etoday>=level_emailperday[useron.level] && !SYSOP) {
-	bputs(text[TooManyEmailsToday]);
-    return; }
-if(useron.rest&FLAG('F')) {
-    bputs(text[R_Forward]);
-    return; }
-if(usernumber==1 && useron.rest&FLAG('S')) {
-    bprintf(text[R_Feedback],sys_op);
-    return; }
-if(usernumber!=1 && useron.rest&FLAG('E')) {
-    bputs(text[R_Email]);
-    return; }
-
-msg->idx.attr&=~(MSG_READ|MSG_DELETE);
-msg->hdr.attr=msg->idx.attr;
-
-
-smb_hfield(msg,SENDER,strlen(useron.alias),useron.alias);
-sprintf(str,"%u",useron.number);
-smb_hfield(msg,SENDEREXT,strlen(str),str);
-
-username(usernumber,touser);
-smb_hfield(msg,RECIPIENT,strlen(touser),touser);
-sprintf(str,"%u",usernumber);
-smb_hfield(msg,RECIPIENTEXT,sizeof(str),str);
-msg->idx.to=usernumber;
-
-now=time(NULL);
-smb_hfield(msg,FORWARDED,sizeof(time_t),&now);
-
-
-if((i=smb_open_da(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if((i=smb_incdat(&smb,msg->hdr.offset,smb_getmsgdatlen(msg),1))!=0) {
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return; }
-smb_close_da(&smb);
-
-
-if((i=smb_addmsghdr(&smb,msg,SMB_SELFPACK))!=0) {
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-    return; }
-
-if(msg->hdr.auxattr&MSG_FILEATTACH)
-	copyfattach(usernumber,useron.number,msg->subj);
-
-bprintf(text[Forwarded],username(usernumber,str),usernumber);
-sprintf(str,"Forwarded mail to %s #%d",username(usernumber,tmp)
-    ,usernumber);
-logline("E",str);
-msg->idx=idx;
-msg->hdr=hdr;
-
-
-if(usernumber==1) {
-    useron.fbacks++;
-    logon_fbacks++;
-    putuserrec(useron.number,U_FBACKS,5,itoa(useron.fbacks,tmp,10)); }
-else {
-    useron.emails++;
-    logon_emails++;
-    putuserrec(useron.number,U_EMAILS,5,itoa(useron.emails,tmp,10)); }
-useron.etoday++;
-putuserrec(useron.number,U_ETODAY,5,itoa(useron.etoday,tmp,10));
-
-for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
-    getnodedat(i,&node,0);
-    if(node.useron==usernumber && !(node.misc&NODE_POFF)
-        && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
-        sprintf(str,text[EmailNodeMsg],node_num,useron.alias);
-		putnmsg(i,str);
-        break; } }
-if(i>sys_nodes) {	/* User wasn't online, so leave short msg */
-	sprintf(str,text[UserSentYouMail],useron.alias);
-    putsmsg(usernumber,str); }
-}
-
-/****************************************************************************/
-/* Auto-Message Routine ('A' from the main menu)                            */
-/****************************************************************************/
-void automsg()
-{
-    char str[256],buf[300],anon=0;
-    int file;
-    struct ffblk ff;
-
-while(online) {
-    SYNC;
-    mnemonics(text[AutoMsg]);
-    switch(getkeys("RWQ",0)) {
-        case 'R':
-            sprintf(str,"%sMSGS\\AUTO.MSG",data_dir);
-			printfile(str,P_NOABORT|P_NOATCODES);
-            break;
-        case 'W':
-            if(useron.rest&FLAG('W')) {
-                bputs(text[R_AutoMsg]);
-                break; }
-            action=NODE_AMSG;
-            SYNC;
-            bputs("\r\n3 lines:\r\n");
-			if(!getstr(str,68,K_WRAP|K_MSG))
-				break;
-            strcpy(buf,str);
-            strcat(buf,"\r\n          ");
-            getstr(str,68,K_WRAP|K_MSG);
-            strcat(buf,str);
-            strcat(buf,"\r\n          ");
-            getstr(str,68,K_MSG);
-            strcat(str,crlf);
-            strcat(buf,str);
-            if(yesno(text[OK])) {
-                if(useron.exempt&FLAG('A')) {
-                    if(!noyes(text[AnonymousQ]))
-                        anon=1; }
-                sprintf(str,"%sMSGS\\AUTO.MSG",data_dir);
-                if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-                    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-                    return; }
-                if(anon)
-                    sprintf(tmp,"%.80s",text[Anonymous]);
-                else
-                    sprintf(tmp,"%s #%d",useron.alias,useron.number);
-                sprintf(str,text[AutoMsgBy],tmp);
-                strcat(str,"          ");
-                write(file,str,strlen(str));
-                write(file,buf,strlen(buf));
-                close(file); }
-            break;
-        case 'Q':
-            return; } }
-}
-
-/****************************************************************************/
-/* Edits messages															*/
-/****************************************************************************/
-void editmsg(smbmsg_t *msg, uint subnum)
-{
-	char	str[256],buf[SDT_BLOCK_LEN];
-	ushort	xlat;
-	int 	file,i,j,x;
-	ulong	length,offset;
-	FILE	*instream;
-
-if(!msg->hdr.total_dfields)
-	return;
-sprintf(str,"%sINPUT.MSG",node_dir);
-remove(str);
-msgtotxt(*msg,str,0,1);
-editfile(str);
-length=flength(str)+2;	 /* +2 for translation string */
-if(length<1L)
-	return;
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-    return; }
-
-if((i=smb_getstatus(&smb))!=0) {
-	errormsg(WHERE,ERR_READ,smb.file,i);
-	return; }
-
-if(!(smb.status.attr&SMB_HYPERALLOC)) {
-	if((i=smb_open_da(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-        return; }
-	for(x=0;x<msg->hdr.total_dfields;x++)
-		if((i=smb_freemsgdat(&smb,msg->hdr.offset+msg->dfield[x].offset
-			,msg->dfield[x].length,1))!=0)
-			errormsg(WHERE,ERR_WRITE,smb.file,i); }
-
-msg->dfield[0].type=TEXT_BODY;				/* Make one single data field */
-msg->dfield[0].length=length;
-msg->dfield[0].offset=0;
-for(x=1;x<msg->hdr.total_dfields;x++) { 	/* Clear the other data fields */
-	msg->dfield[x].type=UNUSED; 			/* so we leave the header length */
-	msg->dfield[x].length=0;				/* unchanged */
-	msg->dfield[x].offset=0; }
-
-
-if(smb.status.attr&SMB_HYPERALLOC) {
-	offset=smb_hallocdat(&smb); }
-else {
-	if((subnum!=INVALID_SUB && sub[subnum]->misc&SUB_FAST)
-		|| (subnum==INVALID_SUB && sys_misc&SM_FASTMAIL))
-		offset=smb_fallocdat(&smb,length,1);
-	else
-		offset=smb_allocdat(&smb,length,1);
-	smb_close_da(&smb); }
-
-msg->hdr.offset=offset;
-if((file=open(str,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_unlocksmbhdr(&smb);
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
-	return; }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;	/* Convert to NULL */
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-
-smb_unlocksmbhdr(&smb);
-msg->hdr.length=smb_getmsghdrlen(msg);
-if((i=smb_putmsghdr(&smb,msg))!=0)
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-}
-
-/****************************************************************************/
-/* Moves a message from one message base to another 						*/
-/****************************************************************************/
-char movemsg(smbmsg_t msg, uint subnum)
-{
-	char str[256],*buf;
-	int i,j,x,file,newgrp,newsub,storage;
-	long l;
-	ulong offset,length;
-
-for(i=0;i<usrgrps;i++)		 /* Select New Group */
-	uselect(1,i,"Message Group",grp[usrgrp[i]]->lname,0);
-if((newgrp=uselect(0,0,0,0,0))<0)
-	return(0);
-
-for(i=0;i<usrsubs[newgrp];i++)		 /* Select New Sub-Board */
-	uselect(1,i,"Sub-Board",sub[usrsub[newgrp][i]]->lname,0);
-if((newsub=uselect(0,0,0,0,0))<0)
-	return(0);
-newsub=usrsub[newgrp][newsub];
-
-length=smb_getmsgdatlen(&msg);
-if((buf=(char *)MALLOC(length))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,smb.file,length);
-	return(0); }
-
-fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
-fread(buf,length,1,smb.sdt_fp);
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	FREE(buf);
-	errormsg(WHERE,ERR_OPEN,sub[newsub]->code,i);
-	return(0); }
-
-sprintf(smb.file,"%s%s",sub[newsub]->data_dir,sub[newsub]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	FREE(buf);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=sub[newsub]->maxcrcs;
-	smb.status.max_msgs=sub[newsub]->maxmsgs;
-	smb.status.max_age=sub[newsub]->maxage;
-	smb.status.attr=sub[newsub]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
-	if((i=smb_create(&smb))!=0) {
-		FREE(buf);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return(0); } }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	FREE(buf);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return(0); }
-
-if((i=smb_getstatus(&smb))!=0) {
-	FREE(buf);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-	return(0); }
-
-if(smb.status.attr&SMB_HYPERALLOC) {
-	offset=smb_hallocdat(&smb);
-    storage=SMB_HYPERALLOC; }
-else {
-	if((i=smb_open_da(&smb))!=0) {
-		FREE(buf);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		return(0); }
-	if(sub[newsub]->misc&SUB_FAST) {
-		offset=smb_fallocdat(&smb,length,1);
-		storage=SMB_FASTALLOC; }
-	else {
-		offset=smb_allocdat(&smb,length,1);
-		storage=SMB_SELFPACK; }
-	smb_close_da(&smb); }
-
-msg.hdr.offset=offset;
-
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-
-smb_unlocksmbhdr(&smb);
-
-fseek(smb.sdt_fp,offset,SEEK_SET);
-fwrite(buf,length,1,smb.sdt_fp);
-fflush(smb.sdt_fp);
-FREE(buf);
-
-i=smb_addmsghdr(&smb,&msg,storage);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-if(i) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return(0); }
-
-bprintf("\r\nMoved to %s %s\r\n\r\n"
-	,grp[usrgrp[newgrp]]->sname,sub[newsub]->lname);
-sprintf(str,"Moved message from %s %s to %s %s"
-	,grp[newgrp]->sname,sub[newsub]->sname
-	,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
-logline("M+",str);
-if(sub[newsub]->misc&SUB_FIDO && sub[newsub]->echomail_sem[0])
-	if((file=nopen(sub[newsub]->echomail_sem
-		,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-		close(file);
-return(1);
-}
-
-ushort chmsgattr(ushort attr)
-{
-	int ch;
-
-while(online && !(sys_status&SS_ABORT)) {
-	CRLF;
-	show_msgattr(attr);
-	menu("MSGATTR");
-	ch=getkey(K_UPPER);
-	if(ch)
-		bprintf("%c\r\n",ch);
-	switch(ch) {
-		case 'P':
-			attr^=MSG_PRIVATE;
-			break;
-		case 'R':
-			attr^=MSG_READ;
-			break;
-		case 'K':
-			attr^=MSG_KILLREAD;
-			break;
-		case 'A':
-			attr^=MSG_ANONYMOUS;
-			break;
-		case 'N':   /* Non-purgeable */
-			attr^=MSG_PERMANENT;
-			break;
-		case 'M':
-			attr^=MSG_MODERATED;
-			break;
-		case 'V':
-			attr^=MSG_VALIDATED;
-			break;
-		case 'D':
-			attr^=MSG_DELETE;
-			break;
-		case 'L':
-			attr^=MSG_LOCKED;
-			break;
-		default:
-			return(attr); } }
-return(attr);
-}
diff --git a/src/sbbs2/msg2ans/msg2ans.c b/src/sbbs2/msg2ans/msg2ans.c
deleted file mode 100644
index 586744d1dd0b593a10bdd311e7823e5fb16d5dc2..0000000000000000000000000000000000000000
--- a/src/sbbs2/msg2ans/msg2ans.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* msg2ans.c */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Converts Synchronet Ctrl-A codes into ANSI escape sequences */
-
-#include <stdio.h>
-#include <conio.h>
-
-#define ANSI fprintf(out,"\x1b[")
-
-int main(int argc, char **argv)
-{
-	int i,ch;
-	FILE *in,*out;
-
-if(argc<3) {
-	printf("\nMSG2ANS v1.03\n");
-	printf("\nusage: msg2ans infile.msg outfile.ans\n");
-	exit(0); }
-
-if((in=fopen(argv[1],"rb"))==NULL) {
-	printf("\nerror opening %s\n",argv[1]);
-	exit(1); }
-
-if((out=fopen(argv[2],"wb"))==NULL) {
-	printf("\nerror opening %s\n",argv[2]);
-	exit(1); }
-
-while((ch=fgetc(in))!=EOF) {
-	if(ch==1) { /* ctrl-a */
-		ch=fgetc(in);
-		if(ch==EOF)
-			break;
-		if(ch>=0x7f) {					/* move cursor right x columns */
-			ANSI;
-			fprintf(out,"%uC",ch-0x7f);
-			continue; }
-		switch(toupper(ch)) {
-			case 'A':
-				fputc('\1',out);
-				break;
-			case '<':
-				fputc('\b',out);
-				break;
-			case '>':
-				ANSI;
-				fputc('K',out);
-				break;
-			case '[':
-				fputc('\r',out);
-				break;
-			case ']':
-				fputc('\n',out);
-				break;
-			case 'L':
-				ANSI;
-				fprintf(out,"2J");
-				break;
-			case '-':
-			case '_':
-			case 'N':
-				ANSI;
-				fprintf(out,"0m");
-				break;
-			case 'H':
-				ANSI;
-				fprintf(out,"1m");
-                break;
-			case 'I':
-				ANSI;
-				fprintf(out,"5m");
-				break;
-			case 'K':
-				ANSI;
-				fprintf(out,"30m");
-				break;
-			case 'R':
-				ANSI;
-				fprintf(out,"31m");
-                break;
-			case 'G':
-				ANSI;
-				fprintf(out,"32m");
-                break;
-			case 'Y':
-				ANSI;
-				fprintf(out,"33m");
-                break;
-			case 'B':
-				ANSI;
-				fprintf(out,"34m");
-                break;
-			case 'M':
-				ANSI;
-				fprintf(out,"35m");
-                break;
-			case 'C':
-				ANSI;
-				fprintf(out,"36m");
-                break;
-			case 'W':
-				ANSI;
-				fprintf(out,"37m");
-                break;
-			case '0':
-				ANSI;
-				fprintf(out,"40m");
-                break;
-			case '1':
-				ANSI;
-				fprintf(out,"41m");
-                break;
-			case '2':
-				ANSI;
-				fprintf(out,"42m");
-                break;
-			case '3':
-				ANSI;
-				fprintf(out,"43m");
-                break;
-			case '4':
-				ANSI;
-				fprintf(out,"44m");
-                break;
-			case '5':
-				ANSI;
-				fprintf(out,"45m");
-                break;
-			case '6':
-				ANSI;
-				fprintf(out,"46m");
-                break;
-			case '7':
-				ANSI;
-				fprintf(out,"47m");
-				break;
-			default:
-				fprintf(out,"\1%c",ch);
-				break; } }
-	else
-		fputc(ch,out); }
-}
-
-
-
-
diff --git a/src/sbbs2/msgtoqwk.c b/src/sbbs2/msgtoqwk.c
deleted file mode 100644
index 68ad8a92cbaca79c6f7a9d95a9a94765071d032d..0000000000000000000000000000000000000000
--- a/src/sbbs2/msgtoqwk.c
+++ /dev/null
@@ -1,298 +0,0 @@
-#line 1 "MSGTOQWK.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-#include "etext.h"
-
-#define MAX_MSGNUM	0x7FFFFFUL	// only 7 (decimal) digits allowed for msg num 
-
-/****************************************************************************/
-/* Converts message 'msg' to QWK format, writing to file 'qwk_fp'.          */
-/* mode determines how to handle Ctrl-A codes								*/
-/****************************************************************************/
-ulong msgtoqwk(smbmsg_t msg, FILE *qwk_fp, int mode, int subnum
-	, int conf)
-{
-	uchar	str[512],from[512],to[512],ch,tear=0,tearwatch=0,HUGE16 *buf,*p;
-	ushort	xlat;
-	long	l,size=0,offset;
-	int 	i;
-
-offset=ftell(qwk_fp);
-memset(str,SP,128);
-fwrite(str,128,1,qwk_fp);		/* Init header to space */
-
-if(msg.from_net.addr && (uint)subnum==INVALID_SUB) {
-	if(mode&TO_QNET)
-		sprintf(from,"%.128s",msg.from);
-	else if(msg.from_net.type==NET_FIDO)
-		sprintf(from,"%.128s@%.128s"
-			,msg.from,faddrtoa(*(faddr_t *)msg.from_net.addr));
-	else if(msg.from_net.type==NET_INTERNET)
-		sprintf(from,"%.128s",msg.from_net.addr);
-	else
-		sprintf(from,"%.128s@%.128s",msg.from,msg.from_net.addr);
-	if(strlen(from)>25) {
-		sprintf(str,"From: %.128s\xe3\xe3",from);
-		fwrite(str,strlen(str),1,qwk_fp);
-		size+=strlen(str);
-		sprintf(from,"%.128s",msg.from); } }
-else {
-	sprintf(from,"%.128s",msg.from);
-	if(msg.hdr.attr&MSG_ANONYMOUS && !SYSOP)	   /* from user */
-		strcpy(from,text[Anonymous]); }
-
-if(msg.to_net.addr && (uint)subnum==INVALID_SUB) {
-	if(msg.to_net.type==NET_FIDO)
-		sprintf(to,"%.128s@%s",msg.to,faddrtoa(*(faddr_t *)msg.to_net.addr));
-	else if(msg.to_net.type==NET_INTERNET)
-		sprintf(to,"%.128s",msg.to_net.addr);
-	else if(msg.to_net.type==NET_QWK) {
-		if(mode&TO_QNET) {
-			p=strchr(msg.to_net.addr,'/');
-			if(p) { 	/* Another hop */
-				p++;
-				strcpy(to,"NETMAIL");
-				sprintf(str,"%.128s@%.128s\xe3",msg.to,p);
-				fwrite(str,strlen(str),1,qwk_fp);
-				size+=strlen(str); }
-			else
-				sprintf(to,"%.128s",msg.to); }
-		else
-			sprintf(to,"%.128s@%.128s",msg.to,msg.to_net.addr); }
-	else
-		sprintf(to,"%.128s@%.128s",msg.to,msg.to_net.addr);
-	if(strlen(to)>25) {
-		sprintf(str,"To: %.128s\xe3\xe3",to);
-		fwrite(str,strlen(str),1,qwk_fp);
-		size+=strlen(str);
-		if(msg.to_net.type==NET_QWK)
-			strcpy(to,"NETMAIL");
-		else
-			sprintf(to,"%.128s",msg.to); } }
-else
-	sprintf(to,"%.128s",msg.to);
-
-if(msg.from_net.type==NET_QWK && mode&VIA && !msg.forwarded) {
-	sprintf(str,"@VIA:%.128s\xe3",msg.from_net.addr);
-	fwrite(str,strlen(str),1,qwk_fp);
-	size+=strlen(str); }
-
-if(msg.hdr.when_written.zone && mode&TZ) {
-	sprintf(str,"@TZ:%04x\xe3",msg.hdr.when_written.zone);
-	fwrite(str,strlen(str),1,qwk_fp);
-	size+=strlen(str); }
-
-p=0;
-for(i=0;i<msg.total_hfields;i++) {
-	if(msg.hfield[i].type==SENDER)
-		p=msg.hfield_dat[i];
-	if(msg.hfield[i].type==FORWARDED && p) {
-		sprintf(str,"Forwarded from %s on %s\xe3",p
-			,timestr((time_t *)msg.hfield_dat[i]));
-		fwrite(str,strlen(str),1,qwk_fp);
-		size+=strlen(str); } }
-
-buf=smb_getmsgtxt(&smb,&msg,1);
-if(!buf)
-	return(0);
-
-for(l=0;buf[l];l++) {
-	ch=buf[l];
-
-	if(ch==LF) {
-		if(tear)
-			tear++; 				/* Count LFs after tearline */
-		if(tear>3)					/* more than two LFs after the tear */
-			tear=0;
-		if(tearwatch==4) {			/* watch for LF---LF */
-			tear=1;
-			tearwatch=0; }
-		else if(!tearwatch)
-			tearwatch=1;
-		else
-			tearwatch=0;
-		ch=0xe3;
-		fputc(ch,qwk_fp);		  /* Replace LF with funky char */
-		size++;
-		continue; }
-
-	if(ch==CR) {					/* Ignore CRs */
-		if(tearwatch<4) 			/* LF---CRLF is okay */
-			tearwatch=0;			/* LF-CR- is not okay */
-		continue; }
-
-	if(ch==SP && tearwatch==4) {	/* watch for "LF--- " */
-		tear=1;
-		tearwatch=0; }
-
-	if(ch=='-') {                   /* watch for "LF---" */
-		if(l==0 || (tearwatch && tearwatch<4))
-			tearwatch++;
-		else
-			tearwatch=0; }
-	else
-		tearwatch=0;
-
-	if((uint)subnum!=INVALID_SUB && sub[subnum]->misc&SUB_ASCII) {
-		if(ch<SP && ch!=1)
-			ch='.';
-		else if(ch>0x7f)
-			ch='*'; }
-
-	if(ch==0xE3)					/* funky char */
-		ch='*';
-
-	if(ch==1) {  /* ctrl-a */
-		ch=buf[++l];
-		if(!ch)
-			break;
-		if(mode&A_EXPAND) {
-			str[0]=0;
-			switch(toupper(ch)) {		/* non-color codes */
-				case 'L':
-					strcpy(str,"\x1b[2J");
-					break;
-				case 'W':
-					strcpy(str,ansi(LIGHTGRAY));
-					break;
-				case 'K':
-					strcpy(str,ansi(BLACK));
-					break;
-				case 'H':
-					strcpy(str,ansi(HIGH));
-					break;
-				case 'I':
-					strcpy(str,ansi(BLINK));
-					break;
-				case 'N':   /* Normal */
-					strcpy(str,"\x1b[0m");
-					break;
-				case '0':
-					strcpy(str,"\x1b[40m");
-					break;
-				case '7':
-					strcpy(str,ansi(LIGHTGRAY<<4));
-					break;
-				case 'R':                               /* Color codes */
-					strcpy(str,ansi(RED));
-					break;
-				case 'G':
-					strcpy(str,ansi(GREEN));
-					break;
-				case 'B':
-					strcpy(str,ansi(BLUE));
-					break;
-				case 'C':
-					strcpy(str,ansi(CYAN));
-					break;
-				case 'M':
-					strcpy(str,ansi(MAGENTA));
-					break;
-				case 'Y':   /* Yellow */
-					strcpy(str,ansi(BROWN));
-					break;
-				case '1':
-					strcpy(str,ansi(RED<<4));
-					break;
-				case '2':
-					strcpy(str,ansi(GREEN<<4));
-					break;
-				case '3':
-					strcpy(str,ansi(BROWN<<4));
-					break;
-				case '4':
-					strcpy(str,ansi(BLUE<<4));
-					break;
-				case '5':
-					strcpy(str,ansi(MAGENTA<<4));
-					break;
-				case '6':
-					strcpy(str,ansi(CYAN<<4));
-					break; }
-			if(str[0]) {
-				fwrite(str,strlen(str),1,qwk_fp);
-				size+=strlen(str); }
-			continue; } 						/* End Expand */
-
-		if(mode&A_LEAVE) {
-			fputc(1,qwk_fp);
-			fputc(ch,qwk_fp);
-			size+=2L; }
-		else									/* Strip */
-			if(toupper(ch)=='L') {
-				fputc(FF,qwk_fp);
-				size++; }
-		continue; } 							/* End of Ctrl-A shit */
-	fputc(ch,qwk_fp);
-	size++; }
-
-LFREE(buf);
-if(ch!=0xE3) {
-	fputc(0xE3,qwk_fp); 		/* make sure it ends in CRLF */
-	size++; }
-
-if(mode&TAGLINE && !(sub[subnum]->misc&SUB_NOTAG)) {
-	if(!tear)										/* no tear line */
-		strcpy(str,"\1n---\xe3");                   /* so add one */
-    else
-		strcpy(str,"\1n");
-	if(sub[subnum]->misc&SUB_ASCII) ch='*';
-	else ch='�';
-	sprintf(tmp," %c \1g%s\1n %c %.127s\xe3"
-		,ch,decrypt(Synchronet,0),ch,sub[subnum]->tagline);
-	strcat(str,tmp);
-	if(!(mode&A_LEAVE))
-		remove_ctrl_a(str);
-	fwrite(str,strlen(str),1,qwk_fp);
-	size+=strlen(str); }
-
-while(size%128L) {				 /* Pad with spaces */
-	size++;
-	fputc(SP,qwk_fp); }
-
-unixtodos(msg.hdr.when_written.time,&date,&curtime);
-
-sprintf(tmp,"%02u-%02u-%02u%02u:%02u"
-    ,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900)
-    ,curtime.ti_hour,curtime.ti_min);
-
-if(msg.hdr.attr&MSG_PRIVATE) {
-    if(msg.hdr.attr&MSG_READ)
-        ch='*'; /* private, read */
-    else
-        ch='+'; /* private, unread */ }
-else {
-    if(msg.hdr.attr&MSG_READ)
-        ch='-'; /* public, read */
-    else
-        ch=' '; /* public, unread */ }
-
-
-sprintf(str,"%c%-7lu%-13.13s%-25.25s"
-	"%-25.25s%-25.25s%12s%-8lu%-6lu\xe1%c%c%c%c%c"
-    ,ch                     /* message status flag */
-	,mode&REP ? (ulong)conf /* conference or */
-		: msg.hdr.number&MAX_MSGNUM	/* message number */
-	,tmp					/* date and time */
-	,to 					/* To: */
-	,from					/* From: */
-    ,msg.subj               /* Subject */
-    ,nulstr                 /* Password */
-    ,msg.hdr.thread_orig&MAX_MSGNUM    /* Message Re: Number */
-	,(size/128L)+1			/* Number of 128byte blocks */
-    ,(char)conf&0xff        /* Conference number lo byte */
-	,(ushort)conf>>8		/*					 hi byte */
-    ,SP                     /* not used */
-    ,SP                     /* not used */
-    ,useron.rest&FLAG('Q') ? '*' : SP     /* Net tag line */
-    );
-
-fseek(qwk_fp,offset,SEEK_SET);
-fwrite(str,128,1,qwk_fp);
-fseek(qwk_fp,size,SEEK_CUR);
-
-return(size);
-}
diff --git a/src/sbbs2/netmail.c b/src/sbbs2/netmail.c
deleted file mode 100644
index d5d4670f3819e4a87e3f9f4d6d77baf15c3fcea5..0000000000000000000000000000000000000000
--- a/src/sbbs2/netmail.c
+++ /dev/null
@@ -1,389 +0,0 @@
-#line 1 "NETMAIL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-
-/****************************************************************************/
-/****************************************************************************/
-void inetmail(char *into, char *subj, char mode)
-{
-	char	str[256],str2[256],msgpath[256],title[256],name[256],ch
-			,buf[SDT_BLOCK_LEN],*p,addr[256];
-	ushort	xlat=XLAT_NONE,net=NET_INTERNET;
-	int 	i,j,x,file;
-	long	l;
-	ulong	length,offset;
-	FILE	*instream;
-	node_t	node;
-	smbmsg_t msg;
-
-strcpy(name,into);
-strcpy(addr,into);
-strcpy(title,subj);
-
-if((!SYSOP && !(inetmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M')) {
-    bputs(text[NoNetMailAllowed]);
-    return; }
-
-if(inetmail_cost && !(useron.exempt&FLAG('S'))) {
-	if(useron.cdt+useron.freecdt<inetmail_cost) {
-		bputs(text[NotEnoughCredits]);
-		return; }
-	sprintf(str,text[NetMailCostContinueQ],inetmail_cost);
-	if(noyes(str))
-		return; }
-
-p=strrchr(name,'@');
-if(!p)
-	p=strrchr(name,'!');
-if(p) {
-	*p=0;
-	truncsp(name); }
-bprintf(text[NetMailing],name,addr
-	,inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name
-	,sys_inetaddr);
-action=NODE_SMAL;
-nodesync();
-
-sprintf(msgpath,"%sNETMAIL.MSG",node_dir);
-if(!writemsg(msgpath,nulstr,title,mode,0,into)) {
-    bputs(text[Aborted]);
-    return; }
-
-if(mode&WM_FILE) {
-	sprintf(str2,"%sFILE\\%04u.OUT",data_dir,useron.number);
-	mkdir(str2);
-	sprintf(str2,"%sFILE\\%04u.OUT\\%s",data_dir,useron.number,title);
-	if(fexist(str2)) {
-		bputs(text[FileAlreadyThere]);
-		remove(msgpath);
-		return; }
-	if(online==ON_LOCAL) {		/* Local upload */
-		bputs(text[EnterPath]);
-		if(!getstr(str,60,K_LINE|K_UPPER)) {
-			bputs(text[Aborted]);
-			remove(msgpath);
-			return; }
-		backslash(str);
-		strcat(str,title);
-		mv(str,str2,1); }
-	else { /* Remote */
-		menu("ULPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(str,"Q");
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && chk_ar(prot[x]->ar,useron)) {
-				sprintf(tmp,"%c",prot[x]->mnemonic);
-				strcat(str,tmp); }
-		ch=getkeys(str,0);
-		if(ch=='Q' || sys_status&SS_ABORT) {
-			bputs(text[Aborted]);
-			remove(msgpath);
-			return; }
-		for(x=0;x<total_prots;x++)
-			if(prot[x]->ulcmd[0] && prot[x]->mnemonic==ch
-				&& chk_ar(prot[x]->ar,useron))
-				break;
-		if(x<total_prots)	/* This should be always */
-			protocol(cmdstr(prot[x]->ulcmd,str2,nulstr,NULL),0); }
-	l=flength(str2);
-	if(l>0)
-		bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
-	else {
-		bprintf(text[FileNotReceived],title);
-		remove(msgpath);
-		return; } }
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=mail_maxcrcs;
-	smb.status.max_age=mail_maxage;
-	smb.status.max_msgs=MAX_SYSMAIL;
-	smb.status.attr=SMB_EMAIL;
-	if((i=smb_create(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return; } }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return; }
-
-length=flength(msgpath)+2;	 /* +2 for translation string */
-
-if(length&0xfff00000UL) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LEN,msgpath,length);
-    return; }
-
-if((i=smb_open_da(&smb))!=0) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if(sys_misc&SM_FASTMAIL)
-	offset=smb_fallocdat(&smb,length,1);
-else
-	offset=smb_allocdat(&smb,length,1);
-smb_close_da(&smb);
-
-if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_freemsgdat(&smb,offset,length,1);
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
-	return; }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-if(mode&WM_FILE)
-	msg.hdr.auxattr|=MSG_FILEATTACH;
-msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone;
-
-msg.hdr.offset=offset;
-
-net=NET_INTERNET;
-smb_hfield(&msg,RECIPIENT,strlen(name),name);
-msg.idx.to=0;	/* Out-bound NetMail set to 0 */
-smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
-smb_hfield(&msg,RECIPIENTNETADDR,strlen(addr),addr);
-
-strcpy(str,inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
-smb_hfield(&msg,SENDER,strlen(str),str);
-
-sprintf(str,"%u",useron.number);
-smb_hfield(&msg,SENDEREXT,strlen(str),str);
-msg.idx.from=useron.number;
-
-/*
-smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
-smb_hfield(&msg,SENDERNETADDR,strlen(sys_inetaddr),sys_inetaddr);
-*/
-
-smb_hfield(&msg,SUBJECT,strlen(title),title);
-strcpy(str,title);
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-smb_dfield(&msg,TEXT_BODY,length);
-
-smb_unlocksmbhdr(&smb);
-i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-smb_freemsgmem(&msg);
-if(i) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return; }
-
-if(mode&WM_FILE && online==ON_REMOTE)
-	autohangup();
-
-if(inetmail_sem[0]) 	 /* update semaphore file */
-	if((file=nopen(inetmail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-		close(file);
-if(!(useron.exempt&FLAG('S')))
-	subtract_cdt(inetmail_cost);
-sprintf(str,"Sent Internet Mail to %s (%s)",name,addr);
-logline("EN",str);
-}
-
-void qnetmail(char *into, char *subj, char mode)
-{
-	char	str[256],str2[128],msgpath[128],title[128],to[128],fulladdr[128],ch
-			,buf[SDT_BLOCK_LEN],*addr,*p;
-	ushort	xlat=XLAT_NONE,net=NET_QWK,touser;
-	int 	i,j,x,file;
-	long	l;
-	ulong	length,offset;
-	FILE	*instream;
-	node_t	node;
-	smbmsg_t msg;
-
-strcpy(to,into);
-strcpy(title,subj);
-
-if(useron.rest&FLAG('M')) {
-    bputs(text[NoNetMailAllowed]);
-    return; }
-
-addr=strrchr(to,'@');
-if(!addr) {
-	bputs("Invalid netmail address\r\n");
-	return; }
-*addr=0;
-addr++;
-strupr(addr);
-truncsp(addr);
-touser=qwk_route(addr,fulladdr);
-if(!fulladdr[0]) {
-	bputs("Invalid netmail address\r\n");
-	return; }
-
-truncsp(to);
-if(!stricmp(to,"SBBS") && !SYSOP) {
-	bputs("Invalid netmail address\r\n");
-    return; }
-bprintf(text[NetMailing],to,fulladdr
-	,useron.alias,sys_id);
-action=NODE_SMAL;
-nodesync();
-
-sprintf(msgpath,"%sNETMAIL.MSG",node_dir);
-if(!writemsg(msgpath,nulstr,title,mode|WM_QWKNET,0,to)) {
-    bputs(text[Aborted]);
-    return; }
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,"MAIL",i);
-	return; }
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=mail_maxcrcs;
-	smb.status.max_msgs=MAX_SYSMAIL;
-	smb.status.max_age=mail_maxage;
-	smb.status.attr=SMB_EMAIL;
-	if((i=smb_create(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return; } }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return; }
-
-length=flength(msgpath)+2;	 /* +2 for translation string */
-
-if(length&0xfff00000UL) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LEN,msgpath,length);
-    return; }
-
-if((i=smb_open_da(&smb))!=0) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return; }
-if(sys_misc&SM_FASTMAIL)
-	offset=smb_fallocdat(&smb,length,1);
-else
-	offset=smb_allocdat(&smb,length,1);
-smb_close_da(&smb);
-
-if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_freemsgdat(&smb,offset,length,1);
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
-	return; }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-if(mode&WM_FILE)
-	msg.hdr.auxattr|=MSG_FILEATTACH;
-msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone;
-
-msg.hdr.offset=offset;
-
-net=NET_QWK;
-smb_hfield(&msg,RECIPIENT,strlen(to),to);
-msg.idx.to=touser;
-smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
-smb_hfield(&msg,RECIPIENTNETADDR,strlen(fulladdr),fulladdr);
-
-smb_hfield(&msg,SENDER,strlen(useron.alias),useron.alias);
-
-sprintf(str,"%u",useron.number);
-smb_hfield(&msg,SENDEREXT,strlen(str),str);
-msg.idx.from=useron.number;
-
-smb_hfield(&msg,SUBJECT,strlen(title),title);
-strcpy(str,title);
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-smb_dfield(&msg,TEXT_BODY,length);
-
-smb_unlocksmbhdr(&smb);
-i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-smb_freemsgmem(&msg);
-if(i) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return; }
-
-sprintf(str,"Sent QWK NetMail to %s (%s)",to,fulladdr);
-logline("EN",str);
-}
diff --git a/src/sbbs2/newuser.c b/src/sbbs2/newuser.c
deleted file mode 100644
index 40802c077e30a3b3304f98bd5656e0c5246c9b40..0000000000000000000000000000000000000000
--- a/src/sbbs2/newuser.c
+++ /dev/null
@@ -1,404 +0,0 @@
-#line 1 "NEWUSER.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-extern char qwklogon;
-
-/****************************************************************************/
-/* This function is invoked when a user enters "NEW" at the NN: prompt		*/
-/* Prompts user for personal information and then sends feedback to sysop.  */
-/* Called from function waitforcall											*/
-/****************************************************************************/
-void newuser()
-{
-	char	c,str[512],usa;
-	int 	file;
-	uint	i,j;
-	long	misc;
-	FILE	*stream;
-
-if(cur_rate<node_minbps) {
-	bprintf(text[MinimumModemSpeed],node_minbps);
-	sprintf(str,"%sTOOSLOW.MSG",text_dir);
-	if(fexist(str))
-		printfile(str,0);
-	sprintf(str,"New user modem speed: %lu<%u"
-		,cur_rate,node_minbps);
-	logline("N!",str);
-	hangup();
-	return; }
-
-getnodedat(node_num,&thisnode,0);
-if(thisnode.misc&NODE_LOCK) {
-	bputs(text[NodeLocked]);
-	logline("N!","New user locked node logon attempt");
-	hangup();
-	return; }
-
-if(sys_misc&SM_CLOSED) {
-	bputs(text[NoNewUsers]);
-	hangup();
-	return; }
-getnodedat(node_num,&thisnode,1);
-thisnode.status=NODE_NEWUSER;
-if(online==ON_LOCAL)
-	thisnode.connection=0;
-else
-	thisnode.connection=cur_rate;
-putnodedat(node_num,thisnode);
-memset(&useron,0,sizeof(user_t));	  /* Initialize user info to null */
-if(new_pass[0] && online==ON_REMOTE) {
-	c=0;
-	while(++c<4) {
-		bputs(text[NewUserPasswordPrompt]);
-		getstr(str,40,K_UPPER);
-		if(!strcmp(str,new_pass))
-			break;
-		sprintf(tmp,"NUP Attempted: '%s'",str);
-		logline("N!",tmp); }
-	if(c==4) {
-		sprintf(str,"%sNUPGUESS.MSG",text_dir);
-		if(fexist(str))
-			printfile(str,P_NOABORT);
-		hangup();
-		return; } }
-
-if(autoterm || yesno(text[AutoTerminalQ])) {
-	useron.misc|=AUTOTERM;
-	useron.misc|=autoterm; }
-
-if(!(useron.misc&AUTOTERM)) {
-	if(yesno(text[AnsiTerminalQ]))
-		useron.misc|=ANSI; }
-
-if(useron.misc&ANSI) {
-	useron.rows=0;	/* Auto-rows */
-	if(useron.misc&(RIP|WIP) || yesno(text[ColorTerminalQ]))
-		useron.misc|=COLOR; }
-else
-	useron.rows=24;
-if(!yesno(text[ExAsciiTerminalQ]))
-	useron.misc|=NO_EXASCII;
-
-/* Sets defaults per sysop config */
-useron.misc|=(new_misc&~(DELETED|INACTIVE|QUIET|NETMAIL));
-useron.qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL);
-strcpy(useron.modem,connection);
-useron.firston=useron.laston=useron.pwmod=time(NULL);
-if(new_expire) {
-	now=time(NULL);
-	useron.expire=now+((long)new_expire*24L*60L*60L); }
-else
-	useron.expire=0;
-useron.sex=SP;
-useron.prot=new_prot;
-strcpy(useron.note,cid);		/* Caller ID if supported, NULL otherwise */
-strcpy(useron.alias,"New");     /* just for status line */
-strcpy(useron.modem,connection);
-if(!lastuser()) {	/* Automatic sysop access for first user */
-	useron.level=99;
-	useron.exempt=useron.flags1=useron.flags2=0xffffffffUL;
-	useron.flags3=useron.flags4=0xffffffffUL;
-	useron.rest=0L; }
-else {
-	useron.level=new_level;
-	useron.flags1=new_flags1;
-	useron.flags2=new_flags2;
-	useron.flags3=new_flags3;
-	useron.flags4=new_flags4;
-	useron.rest=new_rest;
-	useron.exempt=new_exempt; }
-
-useron.cdt=new_cdt;
-useron.min=new_min;
-useron.freecdt=level_freecdtperday[useron.level];
-
-if(total_fcomps)
-	strcpy(useron.tmpext,fcomp[0]->ext);
-else
-	strcpy(useron.tmpext,"ZIP");
-for(i=0;i<total_xedits;i++)
-	if(!stricmp(xedit[i]->code,new_xedit) && chk_ar(xedit[i]->ar,useron))
-		break;
-if(i<total_xedits)
-	useron.xedit=i+1;
-
-
-useron.shell=new_shell;
-
-statline=sys_def_stat;
-statusline();
-useron.alias[0]=0;
-while(online) {
-	while(online) {
-		if(uq&UQ_ALIASES)
-			bputs(text[EnterYourAlias]);
-		else
-			bputs(text[EnterYourRealName]);
-		getstr(useron.alias,LEN_ALIAS
-			,K_UPRLWR|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL);
-		truncsp(useron.alias);
-		if(useron.alias[0]<=SP || !isalpha(useron.alias[0])
-			|| strchr(useron.alias,0xff)
-			|| matchuser(useron.alias) || trashcan(useron.alias,"NAME")
-			|| (!(uq&UQ_ALIASES) && !strchr(useron.alias,SP))) {
-			bputs(text[YouCantUseThatName]);
-			continue; }
-		break; }
-	statusline();
-	if(!online) return;
-	if(uq&UQ_ALIASES && uq&UQ_REALNAME) {
-		while(online) {
-			bputs(text[EnterYourRealName]);
-			if(!getstr(useron.name,LEN_NAME
-				,K_UPRLWR|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)
-				|| trashcan(useron.name,"NAME")
-				|| strchr(useron.name,0xff)
-				|| !strchr(useron.name,SP)
-				|| (uq&UQ_DUPREAL
-					&& userdatdupe(useron.number,U_NAME,LEN_NAME
-						,useron.name,0)))
-				bputs(text[YouCantUseThatName]);
-			else
-				break; } }
-	else if(uq&UQ_COMPANY) {
-			bputs(text[EnterYourCompany]);
-			getstr(useron.name,LEN_NAME,(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL); }
-	if(!useron.name[0])
-        strcpy(useron.name,useron.alias);
-    if(!online) return;
-	if(!useron.handle[0])
-		sprintf(useron.handle,"%.*s",LEN_HANDLE,useron.alias);
-	while(uq&UQ_HANDLE && online) {
-		bputs(text[EnterYourHandle]);
-		if(!getstr(useron.handle,LEN_HANDLE
-			,K_LINE|K_EDIT|K_AUTODEL|(uq&UQ_NOEXASC))
-			|| strchr(useron.handle,0xff)
-			|| (uq&UQ_DUPHAND
-				&& userdatdupe(0,U_HANDLE,LEN_HANDLE,useron.handle,0))
-			|| trashcan(useron.handle,"NAME"))
-			bputs(text[YouCantUseThatName]);
-		else
-			break; }
-	if(!online) return;
-	if(uq&UQ_ADDRESS)
-		while(online) { 	   /* Get address and zip code */
-			bputs(text[EnterYourAddress]);
-			if(getstr(useron.address,LEN_ADDRESS
-				,K_UPRLWR|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL))
-				break; }
-	if(!online) return;
-	while(uq&UQ_LOCATION && online) {
-		bputs(text[EnterYourCityState]);
-		if(getstr(useron.location,LEN_LOCATION
-			,K_UPRLWR|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)
-			&& (uq&UQ_NOCOMMAS || strchr(useron.location,',')))
-			break;
-		bputs("\r\nYou must include a comma between the city and state.\r\n");
-		useron.location[0]=0; }
-	if(uq&UQ_ADDRESS)
-		while(online) {
-			bputs(text[EnterYourZipCode]);
-			if(getstr(useron.zipcode,LEN_ZIPCODE
-				,K_UPPER|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL))
-				break; }
-	if(!online) return;
-	if(uq&UQ_PHONE) {
-		usa=yesno(text[CallingFromNorthAmericaQ]);
-		while(online) {
-			bputs(text[EnterYourPhoneNumber]);
-			if(!usa) {
-				if(getstr(useron.phone,LEN_PHONE
-					,K_UPPER|K_LINE|(uq&UQ_NOEXASC)|K_EDIT|K_AUTODEL)<5)
-					continue; }
-			else {
-				if(gettmplt(useron.phone,sys_phonefmt
-					,K_LINE|(uq&UQ_NOEXASC)|K_EDIT)<strlen(sys_phonefmt))
-					continue; }
-			if(!trashcan(useron.phone,"PHONE"))
-				break; } }
-	if(!online) return;
-	if(uq&UQ_SEX) {
-		bputs(text[EnterYourSex]);
-		useron.sex=getkeys("MF",0); }
-	while(uq&UQ_BIRTH && online) {
-		bputs(text[EnterYourBirthday]);
-		if(gettmplt(useron.birth,"nn/nn/nn",K_EDIT)==8 && getage(useron.birth))
-			break; }
-	if(yesno(text[UserInfoCorrectQ]))
-		break; }
-sprintf(str,"New user: %s",useron.alias);
-logline("N",str);
-if(!online) return;
-if(uq&UQ_COMP)
-	getcomputer(useron.comp);
-CLS;
-sprintf(str,"%sSBBS.MSG",text_dir);
-printfile(str,P_NOABORT);
-if(lncntr)
-	pause();
-CLS;
-sprintf(str,"%sSYSTEM.MSG",text_dir);
-printfile(str,P_NOABORT);
-if(lncntr)
-	pause();
-CLS;
-sprintf(str,"%sNEWUSER.MSG",text_dir);
-printfile(str,P_NOABORT);
-if(lncntr)
-	pause();
-CLS;
-answertime=time(NULL);		/* could take 10 minutes to get this far */
-
-if(total_xedits && uq&UQ_XEDIT && !noyes("Use an external editor")) {
-	if(useron.xedit) useron.xedit--;
-    for(i=0;i<total_xedits;i++)
-		uselect(1,i,"External Editor",xedit[i]->name,xedit[i]->ar);
-	if((int)(i=uselect(0,useron.xedit,0,0,0))>=0)
-		useron.xedit=i+1; }
-
-if(total_shells>1 && uq&UQ_CMDSHELL) {
-    for(i=0;i<total_shells;i++)
-		uselect(1,i,"Command Shell",shell[i]->name,shell[i]->ar);
-	if((int)(i=uselect(0,useron.shell,0,0,0))>=0)
-		useron.shell=i; }
-
-c=0;
-while(c<LEN_PASS) { 				/* Create random password */
-	useron.pass[c]=random(43)+48;
-	if(isalnum(useron.pass[c]))
-		c++; }
-useron.pass[c]=0;
-bprintf(text[YourPasswordIs],useron.pass);
-
-if(sys_misc&SM_PWEDIT && yesno(text[NewPasswordQ]))
-	while(online) {
-		bputs(text[NewPassword]);
-		getstr(str,LEN_PASS,K_UPPER|K_LINE);
-		truncsp(str);
-		if(chkpass(str,useron)) {
-			strcpy(useron.pass,str);
-			CRLF;
-			bprintf(text[YourPasswordIs],useron.pass);
-			break; }
-		CRLF; }
-
-c=0;
-while(online) {
-	bprintf(text[NewUserPasswordVerify]);
-	console|=CON_R_ECHOX;
-	if(!(sys_misc&SM_ECHO_PW))
-		console|=CON_L_ECHOX;
-	str[0]=0;
-	getstr(str,LEN_PASS,K_UPPER);
-	console&=~(CON_R_ECHOX|CON_L_ECHOX);
-	if(!strcmp(str,useron.pass)) break;
-	sprintf(tmp,"Failed PW verification: '%s' instead of '%s'",str
-		,useron.pass);
-	logline(nulstr,tmp);
-	if(++c==4) {
-		logline("N!","Couldn't figure out password.");
-		hangup(); }
-	bputs(text[IncorrectPassword]);
-	bprintf(text[YourPasswordIs],useron.pass); }
-if(!online) return;
-if(new_magic[0]) {
-	bputs(text[MagicWordPrompt]);
-	str[0]=0;
-	getstr(str,50,K_UPPER);
-	if(strcmp(str,new_magic)) {
-		bputs(text[FailedMagicWord]);
-		sprintf(tmp,"Failed magic word: '%s'",str);
-		logline("N!",tmp);
-		hangup(); }
-	if(!online) return; }
-
-i=1;
-bputs(text[CheckingSlots]);
-sprintf(str,"%s\\USER\\NAME.DAT",data_dir);
-if(fexist(str)) {
-	if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-		errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-		hangup();
-		return; }
-	j=filelength(file)/(LEN_ALIAS+2);	   /* total users */
-	while(i<=j) {
-		fread(str,LEN_ALIAS+2,1,stream);
-		for(c=0;c<LEN_ALIAS;c++)
-			if(str[c]==ETX) break;
-		str[c]=0;
-		if(!c) {	 /* should be a deleted user */
-			getuserrec(i,U_MISC,8,str);
-			misc=ahtoul(str);
-			if(misc&DELETED) {	 /* deleted bit set too */
-				getuserrec(i,U_LASTON,8,str);
-				now=ahtoul(str);				/* delete long enough ? */
-				if((time(NULL)-now)/86400>=sys_deldays) break; } }
-		i++; }
-	fclose(stream); }
-
-j=lastuser();		/* Check against data file */
-if(i<=j) {			/* Overwriting existing user */
-	getuserrec(i,U_MISC,8,str);
-	misc=ahtoul(str);
-	if(!(misc&DELETED)) /* Not deleted? Set usernumber to end+1 */
-		i=j+1; }
-
-useron.number=i;
-putuserdat(useron);
-putusername(useron.number,useron.alias);
-logline(nulstr,"Wrote user data");
-if(new_sif[0]) {
-	sprintf(str,"%sUSER\\%4.4u.DAT",data_dir,useron.number);
-	create_sif_dat(new_sif,str); }
-if(!(uq&UQ_NODEF))
-	maindflts(useron);
-
-delallmail(useron.number);
-
-if(useron.number!=1 && node_valuser) {
-	sprintf(str,"%sFEEDBACK.MSG",text_dir);
-	CLS;
-	printfile(str,P_NOABORT);
-	sprintf(str,text[NewUserFeedbackHdr]
-		,nulstr,getage(useron.birth),useron.sex,useron.birth
-		,useron.name,useron.phone,useron.comp,useron.modem);
-	email(node_valuser,str,"New User Validation",WM_EMAIL);
-	if(!useron.fbacks && !useron.emails) {
-		if(online) {						/* didn't hang up */
-			bprintf(text[NoFeedbackWarning],username(node_valuser,tmp));
-			email(node_valuser,str,"New User Validation",WM_EMAIL);
-			} /* give 'em a 2nd try */
-		if(!useron.fbacks && !useron.emails) {
-        	bprintf(text[NoFeedbackWarning],username(node_valuser,tmp));
-			logline("N!","Aborted feedback");
-			hangup();
-			putuserrec(useron.number,U_COMMENT,60,"Didn't leave feedback");
-			putuserrec(useron.number,U_MISC,8
-				,ultoa(useron.misc|DELETED,tmp,16));
-			putusername(useron.number,nulstr);
-			return; } } }
-
-sprintf(str,"%sFILE\\%04u.IN",data_dir,useron.number);  /* delete any files */
-delfiles(str,"*.*");                                    /* waiting for user */
-rmdir(str);
-sprintf(tmp,"%04u.*",useron.number);
-sprintf(str,"%sFILE",data_dir);
-delfiles(str,tmp);
-
-answertime=starttime=time(NULL);	  /* set answertime to now */
-sprintf(str,"%sUSER\\PTRS\\%04u.IXB",data_dir,useron.number); /* msg ptrs */
-remove(str);
-sprintf(str,"%sMSGS\\%04u.MSG",data_dir,useron.number); /* delete short msg */
-remove(str);
-sprintf(str,"%sUSER\\%04u.MSG",data_dir,useron.number); /* delete ex-comment */
-remove(str);
-if(newuser_mod[0])
-	exec_bin(newuser_mod,&main_csi);
-user_event(EVENT_NEWUSER);
-logline("N+","Successful new user logon");
-sys_status|=SS_NEWUSER;
-}
diff --git a/src/sbbs2/node/make.bat b/src/sbbs2/node/make.bat
deleted file mode 100755
index b20b2c0d196d53a05305fad1e3653c283ba59df1..0000000000000000000000000000000000000000
--- a/src/sbbs2/node/make.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-bcc -w-pro -I.. -C -mt -nDOS node.c
-if errorlevel 1 goto end
-exe2bin dos\node.exe dos\node.com
-:end
\ No newline at end of file
diff --git a/src/sbbs2/node/make.cmd b/src/sbbs2/node/make.cmd
deleted file mode 100755
index 4094c5e6d77d01ca6f534258c60289f007ea5743..0000000000000000000000000000000000000000
--- a/src/sbbs2/node/make.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -I.. -w-pro -nOS2 node.c
diff --git a/src/sbbs2/node/node.c b/src/sbbs2/node/node.c
deleted file mode 100644
index 9532dc12d540d74190aefb6d69a05973d9fa33ec..0000000000000000000000000000000000000000
--- a/src/sbbs2/node/node.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/* NODE.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet BBS Node control program */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <io.h>
-#include <dos.h>
-#include <fcntl.h>
-#include <string.h>
-#include "sbbsdefs.h"
-
-enum {
-	 MODE_LIST
-	,MODE_ANON
-	,MODE_LOCK
-	,MODE_INTR
-	,MODE_RRUN
-	,MODE_DOWN
-	,MODE_EVENT
-	,MODE_NOPAGE
-	,MODE_NOALERTS
-	,MODE_STATUS
-	,MODE_USERON
-	,MODE_ACTION
-	,MODE_ERRORS
-	,MODE_MISC
-	,MODE_CONN
-	,MODE_AUX
-	,MODE_EXTAUX
-	};
-
-char tmp[256];
-int nodefile;
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(uchar number, node_t *node, char lockit)
-{
-	char str[256];
-	int count=0;
-
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count)
-	printf("NODE.DAB COLLISION (READ) - Count:%d\n",count);
-if(count==LOOP_NODEDAB) {
-	printf("Error reading nodefile for node %d\n",number+1);
-	return; }
-}
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(uchar number, node_t node)
-{
-	char str[256];
-	int count;
-
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	printf("Error writing to nodefile for node %d\n",number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-
-/****************************************************************************/
-/* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
-/* node.extaux, and the other 8bits in the upper byte of node.aux			*/
-/****************************************************************************/
-char *unpackchatpass(char *pass, node_t node)
-{
-	char 	bits;
-	int 	i;
-
-pass[0]=(node.aux&0x1f00)>>8;
-pass[1]=((node.aux&0xe000)>>13)|((node.extaux&0x3)<<3);
-bits=2;
-for(i=2;i<8;i++) {
-	pass[i]=(node.extaux>>bits)&0x1f;
-	bits+=5; }
-pass[8]=0;
-for(i=0;i<8;i++)
-	if(pass[i])
-		pass[i]+=64;
-return(pass);
-}
-
-/****************************************************************************/
-/* Displays the information for node number 'number' contained in 'node'    */
-/****************************************************************************/
-void printnodedat(uchar number, node_t node)
-{
-	uint i;
-    char hour,mer[3];
-
-printf("Node %2d: ",number);
-switch(node.status) {
-    case NODE_WFC:
-		printf("Waiting for call");
-        break;
-    case NODE_OFFLINE:
-		printf("Offline");
-        break;
-    case NODE_NETTING:
-		printf("Networking");
-        break;
-    case NODE_LOGON:
-		printf("At logon prompt");
-        break;
-    case NODE_EVENT_WAITING:
-		printf("Waiting for all nodes to become inactive");
-        break;
-    case NODE_EVENT_LIMBO:
-		printf("Waiting for node %d to finish external event",node.aux);
-        break;
-    case NODE_EVENT_RUNNING:
-		printf("Running external event");
-        break;
-    case NODE_NEWUSER:
-		printf("New user");
-		printf(" applying for access ");
-        if(!node.connection)
-			printf("Locally");
-        else
-			printf("at %ubps",node.connection);
-        break;
-	case NODE_QUIET:
-    case NODE_INUSE:
-		printf("User #%d",node.useron);
-		printf(" ");
-        switch(node.action) {
-            case NODE_MAIN:
-				printf("at main menu");
-                break;
-            case NODE_RMSG:
-				printf("reading messages");
-                break;
-            case NODE_RMAL:
-				printf("reading mail");
-                break;
-            case NODE_RSML:
-				printf("reading sent mail");
-                break;
-            case NODE_RTXT:
-				printf("reading text files");
-                break;
-            case NODE_PMSG:
-				printf("posting message");
-                break;
-            case NODE_SMAL:
-				printf("sending mail");
-                break;
-            case NODE_AMSG:
-				printf("posting auto-message");
-                break;
-            case NODE_XTRN:
-                if(!node.aux)
-					printf("at external program menu");
-				else
-					printf("running external program #%d",node.aux);
-                break;
-            case NODE_DFLT:
-				printf("changing defaults");
-                break;
-            case NODE_XFER:
-				printf("at transfer menu");
-                break;
-			case NODE_RFSD:
-				printf("retrieving from device #%d",node.aux);
-                break;
-            case NODE_DLNG:
-				printf("downloading");
-                break;
-            case NODE_ULNG:
-				printf("uploading");
-                break;
-            case NODE_BXFR:
-				printf("transferring bidirectional");
-                break;
-            case NODE_LFIL:
-				printf("listing files");
-                break;
-            case NODE_LOGN:
-				printf("logging on");
-                break;
-            case NODE_LCHT:
-				printf("in local chat with sysop");
-                break;
-            case NODE_MCHT:
-                if(node.aux) {
-					printf("in multinode chat channel %d",node.aux&0xff);
-                    if(node.aux&0x1f00) { /* password */
-						putchar('*');
-						printf(" %s",unpackchatpass(tmp,node)); } }
-                else
-					printf("in multinode global chat channel");
-                break;
-			case NODE_PAGE:
-				printf("paging node %u for private chat",node.aux);
-                break;
-			case NODE_PCHT:
-				printf("in private chat with node %u",node.aux);
-				break;
-            case NODE_GCHT:
-				printf("chatting with The Guru");
-                break;
-            case NODE_CHAT:
-				printf("in chat section");
-                break;
-            case NODE_TQWK:
-				printf("transferring QWK packet");
-                break;
-            case NODE_SYSP:
-				printf("performing sysop activities");
-                break;
-            default:
-				printf(itoa(node.action,tmp,10));
-                break;  }
-        if(!node.connection)
-			printf(" locally");
-        else
-			printf(" at %ubps",node.connection);
-        if(node.action==NODE_DLNG) {
-			if((node.aux/60)>=12) {
-				if(node.aux/60==12)
-					hour=12;
-				else
-					hour=(node.aux/60)-12;
-                strcpy(mer,"pm"); }
-            else {
-                if((node.aux/60)==0)    /* 12 midnite */
-                    hour=12;
-                else hour=node.aux/60;
-                strcpy(mer,"am"); }
-			printf(" ETA %02d:%02d %s"
-                ,hour,node.aux-((node.aux/60)*60),mer); }
-        break; }
-if(node.misc&(NODE_LOCK|NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG)) {
-	printf(" (");
-    if(node.misc&NODE_AOFF)
-		putchar('A');
-    if(node.misc&NODE_LOCK)
-		putchar('L');
-	if(node.misc&(NODE_MSGW|NODE_NMSG))
-		putchar('M');
-    if(node.misc&NODE_POFF)
-		putchar('P');
-	putchar(')'); }
-if(((node.misc
-    &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
-    || node.status==NODE_QUIET)) {
-	printf(" [");
-    if(node.misc&NODE_ANON)
-		putchar('A');
-    if(node.misc&NODE_INTR)
-		putchar('I');
-    if(node.misc&NODE_RRUN)
-		putchar('R');
-    if(node.misc&NODE_UDAT)
-		putchar('U');
-    if(node.status==NODE_QUIET)
-		putchar('Q');
-    if(node.misc&NODE_EVENT)
-		putchar('E');
-    if(node.misc&NODE_DOWN)
-		putchar('D');
-	putchar(']'); }
-if(node.errors)
-	printf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' );
-printf("\n");
-}
-
-
-/****************************/
-/* Main program entry point */
-/****************************/
-int main(int argc, char **argv)
-{
-	char str[256],ctrl_dir[41],*p,debug=0;
-	uchar sys_nodes,node_num=0,onoff=0;
-	uint i,j,mode=0,misc;
-	long value;
-	node_t node;
-
-printf("\nSynchronet Node Display/Control Utility v1.03\n\n");
-
-if(argc<2) {
-	printf("usage: node [/debug] [action [on|off]] [node numbers] [...]"
-		"\n\n");
-	printf("actions (default is list):\n\n");
-	printf("list        = list status\n");
-	printf("anon        = anonymous user\n");
-	printf("lock        = locked\n");
-	printf("intr        = interrupt\n");
-	printf("down        = shut-down\n");
-	printf("rerun       = rerun\n");
-	printf("event       = run event\n");
-	printf("nopage      = page disable\n");
-	printf("noalerts    = activity alerts disable\n");
-	printf("status=#    = set status value\n");
-	printf("useron=#    = set useron number\n");
-	printf("action=#    = set action value\n");
-	printf("errors=#    = set error counter\n");
-	printf("conn=#      = set connection value\n");
-	printf("misc=#      = set misc value\n");
-	printf("aux=#       = set aux value\n");
-	printf("extaux=#    = set extended aux value\n");
-	exit(0); }
-
-p=getenv("SBBSCTRL");
-if(p==NULL) {
-	printf("\7\nSBBSCTRL environment variable is not set.\n");
-	printf("This environment variable must be set to your CTRL directory.");
-	printf("\nExample: SET SBBSCTRL=C:\\SBBS\\CTRL\n");
-	exit(1); }
-sprintf(ctrl_dir,"%.40s",p);
-strupr(ctrl_dir);
-if(ctrl_dir[strlen(ctrl_dir)-1]!='\\')
-	strcat(ctrl_dir,"\\");
-
-sprintf(str,"%sNODE.DAB",ctrl_dir);
-if((nodefile=open(str,O_RDWR|O_DENYNONE|O_BINARY))==-1) {
-	printf("\7\nError opening %s.\n",str);
-	exit(1); }
-
-sys_nodes=filelength(nodefile)/sizeof(node_t);
-if(!sys_nodes) {
-	printf("%s reflects 0 nodes!\n",str);
-	exit(1); }
-
-for(i=1;i<argc;i++) {
-	if(isdigit(argv[i][0]))
-		node_num=atoi(argv[i]);
-	else {
-		node_num=onoff=value=0;
-		if(!stricmp(argv[i],"/DEBUG"))
-			debug=1;
-		else if(!stricmp(argv[i],"LOCK"))
-			mode=MODE_LOCK;
-		else if(!stricmp(argv[i],"ANON"))
-			mode=MODE_ANON;
-		else if(!stricmp(argv[i],"INTR"))
-			mode=MODE_INTR;
-		else if(!stricmp(argv[i],"DOWN"))
-			mode=MODE_DOWN;
-		else if(!stricmp(argv[i],"RERUN"))
-			mode=MODE_RRUN;
-		else if(!stricmp(argv[i],"EVENT"))
-			mode=MODE_EVENT;
-		else if(!stricmp(argv[i],"NOPAGE"))
-			mode=MODE_NOPAGE;
-		else if(!stricmp(argv[i],"NOALERTS"))
-			mode=MODE_NOALERTS;
-		else if(!stricmp(argv[i],"ON"))
-			onoff=1;
-		else if(!stricmp(argv[i],"OFF"))
-			onoff=2;
-		else if(!strnicmp(argv[i],"STATUS=",7)) {
-			mode=MODE_STATUS;
-			value=atoi(argv[i]+7); }
-		else if(!strnicmp(argv[i],"ERRORS=",7)) {
-			mode=MODE_ERRORS;
-			value=atoi(argv[i]+7); }
-		else if(!strnicmp(argv[i],"USERON=",7)) {
-			mode=MODE_USERON;
-			value=atoi(argv[i]+7); }
-		else if(!strnicmp(argv[i],"ACTION=",7)) {
-			mode=MODE_ACTION;
-            value=atoi(argv[i]+7); }
-		else if(!strnicmp(argv[i],"CONN=",5)) {
-			mode=MODE_CONN;
-			value=atoi(argv[i]+5); }
-		else if(!strnicmp(argv[i],"MISC=",5)) {
-			mode=MODE_MISC;
-			value=atoi(argv[i]+5); }
-		else if(!strnicmp(argv[i],"AUX=",4)) {
-			mode=MODE_AUX;
-			value=atoi(argv[i]+4); }
-		else if(!strnicmp(argv[i],"EXTAUX=",7)) {
-			mode=MODE_EXTAUX;
-			value=atoi(argv[i]+7); }
-		}
-	if((mode && node_num) || i+1==argc)
-		for(j=1;j<=sys_nodes;j++)
-			if(!node_num || j==node_num) {
-				getnodedat(j,&node,1);
-				misc=0;
-				switch(mode) {
-					case MODE_ANON:
-						misc=NODE_ANON;
-						break;
-					case MODE_LOCK:
-						misc=NODE_LOCK;
-						break;
-					case MODE_INTR:
-						misc=NODE_INTR;
-                        break;
-					case MODE_DOWN:
-						misc=NODE_DOWN;
-                        break;
-					case MODE_RRUN:
-						misc=NODE_RRUN;
-						break;
-					case MODE_EVENT:
-						misc=NODE_EVENT;
-						break;
-					case MODE_NOPAGE:
-						misc=NODE_POFF;
-						break;
-					case MODE_NOALERTS:
-						misc=NODE_AOFF;
-						break;
-					case MODE_STATUS:
-						node.status=value;
-						break;
-					case MODE_ERRORS:
-						node.errors=value;
-						break;
-					case MODE_ACTION:
-						node.action=value;
-						break;
-					case MODE_USERON:
-						node.useron=value;
-						break;
-					case MODE_MISC:
-						node.misc=value;
-						break;
-					case MODE_CONN:
-						node.connection=value;
-						break;
-					case MODE_AUX:
-						node.aux=value;
-						break;
-					case MODE_EXTAUX:
-						node.extaux=value;
-						break; }
-				if(misc) {
-					if(onoff==0)
-						node.misc^=misc;
-					else if(onoff==1)
-						node.misc|=misc;
-					else if(onoff==2)
-						node.misc&=~misc; }
-				putnodedat(j,node);
-				printnodedat(j,node);
-				if(debug) {
-					printf("status=%u\n",node.status);
-					printf("errors=%u\n",node.errors);
-					printf("action=%d\n",node.action);
-					printf("useron=%u\n",node.useron);
-					printf("conn=%u\n",node.connection);
-					printf("misc=%u\n",node.misc);
-					printf("aux=%u\n",node.aux);
-					printf("extaux=%lu\n",node.extaux); } } }
-
-close(nodefile);
-return(0);
-}
diff --git a/src/sbbs2/nodedefs.h b/src/sbbs2/nodedefs.h
deleted file mode 100644
index c661445e3e4a652a6164a0ab397b3b9f71187626..0000000000000000000000000000000000000000
--- a/src/sbbs2/nodedefs.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* NODEDEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/************************************************************/
-/* Constants, macros, and typedefs for use ONLY with SBBS	*/
-/************************************************************/
-
-#ifndef _NODEDEFS_H
-#define _NODEDEFS_H
-
-#include "gen_defs.h"
-
-enum {                              /* Node Status */
-     NODE_WFC                       /* Waiting for Call */
-    ,NODE_LOGON                     /* at logon prompt */
-    ,NODE_NEWUSER                   /* New user applying */
-    ,NODE_INUSE                     /* In Use */
-    ,NODE_QUIET                     /* In Use - quiet mode */
-    ,NODE_OFFLINE                   /* Offline */
-    ,NODE_NETTING                   /* Networking */
-    ,NODE_EVENT_WAITING             /* Waiting for all nodes to be inactive */
-    ,NODE_EVENT_RUNNING             /* Running an external event */
-    ,NODE_EVENT_LIMBO               /* Allowing another node to run an event */
-    };
-
-                                    /* Bit values for node.misc */
-#define NODE_ANON   (1<<0)          /* Anonymous User */
-#define NODE_LOCK   (1<<1)          /* Locked for sysops only */
-#define NODE_INTR   (1<<2)          /* Interrupted - hang up */
-#define NODE_MSGW   (1<<3)          /* Message is waiting (old way) */
-#define NODE_POFF   (1<<4)          /* Page disabled */
-#define NODE_AOFF   (1<<5)          /* Activity Alert disabled */
-#define NODE_UDAT   (1<<6)          /* User data has been updated */
-#define NODE_RRUN   (1<<7)          /* Re-run this node when log off */
-#define NODE_EVENT  (1<<8)          /* Must run node event after log off */
-#define NODE_DOWN   (1<<9)          /* Down this node after logoff */
-#define NODE_RPCHT  (1<<10)         /* Reset private chat */
-#define NODE_NMSG   (1<<11)         /* Node message waiting (new way) */
-#define NODE_EXT    (1<<12)         /* Extended info on node action */
-
-enum {                              /* Node Action */
-     NODE_MAIN                      /* Main Prompt */
-    ,NODE_RMSG                      /* Reading Messages */
-    ,NODE_RMAL                      /* Reading Mail */
-    ,NODE_SMAL                      /* Sending Mail */
-    ,NODE_RTXT                      /* Reading G-Files */
-    ,NODE_RSML                      /* Reading Sent Mail */
-    ,NODE_PMSG                      /* Posting Message */
-    ,NODE_AMSG                      /* Auto-message */
-    ,NODE_XTRN                      /* Running External Program */
-    ,NODE_DFLT                      /* Main Defaults Section */
-    ,NODE_XFER                      /* Transfer Prompt */
-    ,NODE_DLNG                      /* Downloading File */
-    ,NODE_ULNG                      /* Uploading File */
-    ,NODE_BXFR                      /* Bidirectional Transfer */
-    ,NODE_LFIL                      /* Listing Files */
-    ,NODE_LOGN                      /* Logging on */
-    ,NODE_LCHT                      /* In Local Chat with Sysop */
-    ,NODE_MCHT                      /* In Multi-Chat with Other Nodes */
-    ,NODE_GCHT                      /* In Local Chat with Guru */
-    ,NODE_CHAT                      /* In Chat Section */
-    ,NODE_SYSP                      /* Sysop Activity */
-    ,NODE_TQWK                      /* Transferring QWK packet */
-    ,NODE_PCHT                      /* In Private Chat */
-    ,NODE_PAGE                      /* Paging another node for Private Chat */
-    ,NODE_RFSD                      /* Retrieving file from seq dev (aux=dev)*/
-    };
-
-typedef struct {						/* Node information kept in NODE.DAB */
-    uchar   status,                     /* Current Status of Node */
-            errors,                     /* Number of Critical Errors */
-            action;                     /* Action User is doing on Node */
-    ushort  useron,                     /* User on Node */
-            connection,                 /* Connection rate of Node */
-            misc,                       /* Miscellaneous bits for node */
-            aux;                        /* Auxillary word for node */
-    ulong   extaux;                     /* Extended aux dword for node */
-            } node_t;
-
-#endif /* Don't add anything after this line */
diff --git a/src/sbbs2/pack_qwk.c b/src/sbbs2/pack_qwk.c
deleted file mode 100644
index c5ebb17c918140db37e2ee7d689346fc31e1ffcb..0000000000000000000000000000000000000000
--- a/src/sbbs2/pack_qwk.c
+++ /dev/null
@@ -1,527 +0,0 @@
-#line 1 "PACK_QWK.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-#include "post.h"
-#include "etext.h"
-
-/****************************************************************************/
-/* Creates QWK packet, returning 1 if successful, 0 if not. 				*/
-/****************************************************************************/
-char pack_qwk(char *packet, ulong *msgcnt, int prepack)
-{
-	uchar	str[256],tmp2[256],ch,*p;
-	uchar	HUGE16 *qwkbuf;
-	int 	file,mode;
-	uint	i,j,k,n,conf;
-	long	l,size,msgndx;
-	ulong	totalcdt,totalsize,totaltime,lastmsg
-			,mailmsgs=0,files,submsgs,msgs,posts,netfiles=0,preqwk=0;
-	float	f;	/* Sparky is responsible */
-	time_t	start;
-	node_t	node;
-	mail_t	*mail;
-	post_t	HUGE16 *post;
-	FILE	*stream,*qwk,*personal,*ndx;
-    struct  ffblk ff;
-	smbmsg_t msg;
-
-delfiles(temp_dir,"*.*");
-sprintf(str,"%sFILE\\%04u.QWK",data_dir,useron.number);
-if(fexist(str)) {
-	for(k=0;k<total_fextrs;k++)
-		if(!stricmp(fextr[k]->ext,useron.tmpext)
-			&& chk_ar(fextr[k]->ar,useron))
-			break;
-	if(k>=total_fextrs)
-		k=0;
-	i=external(cmdstr(fextr[k]->cmd,str,"*.*",NULL),EX_OUTL|EX_OUTR);
-	if(!i)
-        preqwk=1; }
-
-if(useron.rest&FLAG('Q') && useron.qwk&QWK_RETCTLA)
-	useron.qwk|=(QWK_NOINDEX|QWK_NOCTRL|QWK_VIA|QWK_TZ);
-
-if(useron.qwk&QWK_EXPCTLA)
-	mode=A_EXPAND;
-else if(useron.qwk&QWK_RETCTLA)
-	mode=A_LEAVE;
-else mode=0;
-if(useron.qwk&QWK_TZ)
-	mode|=TZ;
-if(useron.qwk&QWK_VIA)
-	mode|=VIA;
-(*msgcnt)=0L;
-if(!prepack && !(useron.qwk&QWK_NOCTRL)) {
-	/***************************/
-	/* Create CONTROL.DAT file */
-	/***************************/
-	sprintf(str,"%sCONTROL.DAT",temp_dir);
-	if((stream=fnopen(&file,str,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return(0); }
-
-	now=time(NULL);
-	unixtodos(now,&date,&curtime);
-
-	fprintf(stream,"%s\r\n%s\r\n%s\r\n%s, Sysop\r\n0000,%s\r\n"
-		"%02u-%02u-%u,%02u:%02u:%02u\r\n"
-		,sys_name
-		,sys_location
-		,node_phone
-		,sys_op
-		,sys_id
-		,date.da_mon,date.da_day,date.da_year
-		,curtime.ti_hour,curtime.ti_min,curtime.ti_sec);
-	k=0;
-	for(i=0;i<usrgrps;i++)
-		for(j=0;j<usrsubs[i];j++)
-			k++;	/* k is how many subs */
-	fprintf(stream,"%s\r\n\r\n0\r\n0\r\n%u\r\n",useron.alias,k);
-	fprintf(stream,"0\r\nE-mail\r\n");   /* first conference is e-mail */
-	for(i=0;i<usrgrps;i++)
-		for(j=0;j<usrsubs[i];j++)
-			fprintf(stream,"%u\r\n%s\r\n"
-				,sub[usrsub[i][j]]->qwkconf ? sub[usrsub[i][j]]->qwkconf
-				: ((i+1)*1000)+j+1,sub[usrsub[i][j]]->qwkname);
-	fprintf(stream,"HELLO\r\nBBSNEWS\r\nGOODBYE\r\n");
-	fclose(stream);
-	/***********************/
-	/* Create DOOR.ID File */
-	/***********************/
-	sprintf(str,"%sDOOR.ID",temp_dir);
-	if((stream=fnopen(&file,str,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return(0); }
-	p="CONTROLTYPE = ";
-	fprintf(stream,"DOOR = %s\r\nVERSION = %s\r\n"
-		"SYSTEM = %s v%s\r\n"
-		"CONTROLNAME = SBBS\r\n"
-		"%sADD\r\n"
-		"%sDROP\r\n"
-		"%sYOURS\r\n"
-		"%sRESET\r\n"
-		"%sRESETALL\r\n"
-		"%sFILES\r\n"
-		"%sATTACH\r\n"
-		"%sOWN\r\n"
-		"%sMAIL\r\n"
-		"%sDELMAIL\r\n"
-		"%sCTRL-A\r\n"
-		"%sFREQ\r\n"
-		"%sNDX\r\n"
-		"%sTZ\r\n"
-		"%sVIA\r\n"
-		"%sCONTROL\r\n"
-		"MIXEDCASE = YES\r\n"
-		,decrypt(Synchronet,0)
-		,VERSION
-		,decrypt(Synchronet,0)
-		,VERSION
-		,p,p,p,p
-		,p,p,p,p
-		,p,p,p,p
-		,p,p,p,p
-		);
-	fclose(stream);
-	if(useron.rest&FLAG('Q')) {
-		/***********************/
-		/* Create NETFLAGS.DAT */
-		/***********************/
-		sprintf(str,"%sNETFLAGS.DAT",temp_dir);
-		if((stream=fnopen(&file,str,O_WRONLY|O_CREAT))==NULL) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-			return(0); }
-		ch=1;						/* Net enabled */
-		if(usrgrps)
-			for(i=0;i<(usrgrps*1000)+usrsubs[usrgrps-1];i++)
-				fputc(ch,stream);
-		fclose(stream); }
-	} /* !prepack */
-
-/****************************************************/
-/* Create MESSAGES.DAT, write header and leave open */
-/****************************************************/
-sprintf(str,"%sMESSAGES.DAT",temp_dir);
-if((qwk=fnopen(&file,str,O_CREAT|O_WRONLY|O_TRUNC))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_TRUNC);
-	return(0); }
-l=filelength(file);
-if(!l) {
-	fprintf(qwk,"%-128s",decrypt(QWKheader,0));
-	msgndx=1; }
-else
-	msgndx=l/128L;
-fseek(qwk,0,SEEK_END);
-sprintf(str,"%sNEWFILES.DAT",temp_dir);
-remove(str);
-if(!(useron.rest&FLAG('T')) && useron.qwk&QWK_FILES)
-	files=create_filelist("NEWFILES.DAT",FL_ULTIME);
-else
-	files=0;
-
-start=time(NULL);
-
-if(useron.rest&FLAG('Q'))
-	useron.qwk|=(QWK_EMAIL|QWK_ALLMAIL|QWK_DELMAIL);
-
-if(!(useron.qwk&QWK_NOINDEX)) {
-    sprintf(str,"%sPERSONAL.NDX",temp_dir);
-    if((personal=fnopen(&file,str,O_CREAT|O_WRONLY|O_APPEND))==NULL) {
-        fclose(qwk);
-        errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-        return(0); }
-    fseek(personal,0L,SEEK_END); }
-else
-    personal=NULL;
-
-if(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL) && !prepack) {
-	sprintf(smb.file,"%sMAIL",data_dir);
-	smb.retry_time=smb_retry_time;
-	if((i=smb_open(&smb))!=0) {
-        fclose(qwk);
-		if(personal)
-			fclose(personal);
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		return(0); }
-
-	/***********************/
-	/* Pack E-mail, if any */
-	/***********************/
-	qwkmail_time=time(NULL);
-	mailmsgs=loadmail(&mail,useron.number,0,useron.qwk&QWK_ALLMAIL ? LM_QWK
-		: LM_UNREAD|LM_QWK);
-	if(mailmsgs && !(sys_status&SS_ABORT)) {
-		bputs(text[QWKPackingEmail]);
-		if(!(useron.qwk&QWK_NOINDEX)) {
-			sprintf(str,"%s000.NDX",temp_dir);
-			if((ndx=fnopen(&file,str,O_CREAT|O_WRONLY|O_APPEND))==NULL) {
-				fclose(qwk);
-				if(personal)
-					fclose(personal);
-				smb_close(&smb);
-				errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-				FREE(mail);
-				return(0); }
-			fseek(ndx,0L,SEEK_END); }
-		else
-			ndx=NULL;
-
-		if(useron.rest&FLAG('Q'))
-			mode|=TO_QNET;
-		else
-			mode&=~TO_QNET;
-
-		for(l=0;l<mailmsgs;l++) {
-			bprintf("\b\b\b\b\b\b\b\b\b\b\b\b%4lu of %-4lu"
-				,l+1,mailmsgs);
-
-			msg.idx.offset=mail[l].offset;
-			if(!loadmsg(&msg,mail[l].number))
-				continue;
-
-			if(msg.hdr.auxattr&MSG_FILEATTACH && useron.qwk&QWK_ATTACH) {
-				sprintf(str,"%sFILE\\%04u.IN\\%s"
-					,data_dir,useron.number,msg.subj);
-				sprintf(tmp,"%s%s",temp_dir,msg.subj);
-				if(fexist(str) && !fexist(tmp))
-					mv(str,tmp,1); }
-
-			size=msgtoqwk(msg,qwk,mode,INVALID_SUB,0);
-			smb_unlockmsghdr(&smb,&msg);
-			smb_freemsgmem(&msg);
-			if(ndx) {
-				msgndx++;
-				f=ltomsbin(msgndx); 	/* Record number */
-				ch=0;					/* Sub number, not used */
-				if(personal) {
-					fwrite(&f,4,1,personal);
-					fwrite(&ch,1,1,personal); }
-				fwrite(&f,4,1,ndx);
-				fwrite(&ch,1,1,ndx);
-				msgndx+=size/128L; } }
-		bprintf(text[QWKPackedEmail],mailmsgs);
-		if(ndx)
-			fclose(ndx); }
-	smb_close(&smb);					/* Close the e-mail */
-	if(mailmsgs)
-		FREE(mail);
-	}
-
-/*********************/
-/* Pack new messages */
-/*********************/
-for(i=0;i<usrgrps;i++) {
-	for(j=0;j<usrsubs[i] && !msgabort();j++)
-		if(sub[usrsub[i][j]]->misc&SUB_NSCAN
-			|| (!(useron.rest&FLAG('Q'))
-			&& sub[usrsub[i][j]]->misc&SUB_FORCED)) {
-			if(!chk_ar(sub[usrsub[i][j]]->read_ar,useron))
-				continue;
-			lncntr=0;						/* defeat pause */
-			if(useron.rest&FLAG('Q') && !(sub[usrsub[i][j]]->misc&SUB_QNET))
-				continue;	/* QWK Net Node and not QWK networked, so skip */
-
-			msgs=getlastmsg(usrsub[i][j],&lastmsg,0);
-			if(!msgs || lastmsg<=sub[usrsub[i][j]]->ptr) { /* no msgs */
-				if(sub[usrsub[i][j]]->ptr>lastmsg)	{ /* corrupted ptr */
-					sub[usrsub[i][j]]->ptr=lastmsg; /* so fix automatically */
-					sub[usrsub[i][j]]->last=lastmsg; }
-				bprintf(text[NScanStatusFmt]
-					,grp[sub[usrsub[i][j]]->grp]->sname
-					,sub[usrsub[i][j]]->lname,0L,msgs);
-				continue; }
-
-			sprintf(smb.file,"%s%s"
-				,sub[usrsub[i][j]]->data_dir,sub[usrsub[i][j]]->code);
-			smb.retry_time=smb_retry_time;
-			if((k=smb_open(&smb))!=0) {
-				errormsg(WHERE,ERR_OPEN,smb.file,k);
-				continue; }
-
-			k=0;
-			if(useron.qwk&QWK_BYSELF)
-				k|=LP_BYSELF;
-			if(!(sub[usrsub[i][j]]->misc&SUB_YSCAN))
-				k|=LP_OTHERS;
-			post=loadposts(&posts,usrsub[i][j],sub[usrsub[i][j]]->ptr,k);
-
-			bprintf(text[NScanStatusFmt]
-				,grp[sub[usrsub[i][j]]->grp]->sname
-				,sub[usrsub[i][j]]->lname,posts,msgs);
-			if(!posts)	{ /* no new messages */
-				smb_close(&smb);
-				continue; }
-			bputs(text[QWKPackingSubboard]);	
-			submsgs=0;
-			conf=sub[usrsub[i][j]]->qwkconf;
-			if(!conf)
-				conf=((i+1)*1000)+j+1;
-
-			if(!(useron.qwk&QWK_NOINDEX)) {
-				sprintf(str,"%s%u.NDX",temp_dir,conf);
-                if((ndx=fnopen(&file,str,O_CREAT|O_WRONLY|O_APPEND))==NULL) {
-					fclose(qwk);
-					if(personal)
-						fclose(personal);
-					smb_close(&smb);
-					errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-					LFREE(post);
-					return(0); }
-				fseek(ndx,0L,SEEK_END); }
-			else
-				ndx=NULL;
-
-			for(l=0;l<posts && !msgabort();l++) {
-				bprintf("\b\b\b\b\b%-5lu",l+1);
-
-				sub[usrsub[i][j]]->ptr=post[l].number;	/* set ptr */
-				sub[usrsub[i][j]]->last=post[l].number; /* set last read */
-
-				msg.idx.offset=post[l].offset;
-				if(!loadmsg(&msg,post[l].number))
-					continue;
-
-				if(useron.rest&FLAG('Q')) {
-					if(msg.from_net.type && msg.from_net.type!=NET_QWK &&
-						!(sub[usrsub[i][j]]->misc&SUB_GATE)) { /* From other */
-						smb_freemsgmem(&msg);			 /* net, don't gate */
-						smb_unlockmsghdr(&smb,&msg);
-						continue; }
-					mode|=(TO_QNET|TAGLINE);
-					if(msg.from_net.type==NET_QWK) {
-						mode&=~TAGLINE;
-						if(route_circ(msg.from_net.addr,useron.alias)
-							|| !strnicmp(msg.subj,"NE:",3)) {
-							smb_freemsgmem(&msg);
-							smb_unlockmsghdr(&smb,&msg);
-							continue; } } }
-				else
-					mode&=~(TAGLINE|TO_QNET);
-
-				size=msgtoqwk(msg,qwk,mode,usrsub[i][j],conf);
-				smb_unlockmsghdr(&smb,&msg);
-
-				if(ndx) {
-					msgndx++;
-					f=ltomsbin(msgndx); 	/* Record number */
-					ch=0;					/* Sub number, not used */
-					if(personal
-						&& (!stricmp(msg.to,useron.alias)
-							|| !stricmp(msg.to,useron.name))) {
-						fwrite(&f,4,1,personal);
-						fwrite(&ch,1,1,personal); }
-					fwrite(&f,4,1,ndx);
-					fwrite(&ch,1,1,ndx);
-					msgndx+=size/128L; }
-
-				smb_freemsgmem(&msg);
-				(*msgcnt)++;
-				submsgs++;
-				if(max_qwkmsgs
-					&& !(useron.rest&FLAG('Q')) && (*msgcnt)>=max_qwkmsgs) {
-					bputs(text[QWKmsgLimitReached]);
-					break; } }
-			if(!(sys_status&SS_ABORT))
-				bprintf(text[QWKPackedSubboard],submsgs,(*msgcnt));
-			if(ndx) {
-				fclose(ndx);
-				sprintf(str,"%s%u.NDX",temp_dir,conf);
-				if(!flength(str))
-					remove(str); }
-			smb_close(&smb);
-			LFREE(post);
-			if(l<posts)
-				break; }
-	if(j<usrsubs[i]) /* if sub aborted, abort all */
-		break; }
-
-if((*msgcnt)+mailmsgs && time(NULL)-start)
-	bprintf("\r\n\r\n\1n\1hPacked %lu messages in %lu seconds "
-		"(%lu messages/second)."
-		,(*msgcnt)+mailmsgs,time(NULL)-start
-		,((*msgcnt)+mailmsgs)/(time(NULL)-start));
-
-fclose(qwk);			/* close MESSAGE.DAT */
-if(personal) {
-	fclose(personal);		 /* close PERSONAL.NDX */
-	sprintf(str,"%sPERSONAL.NDX",temp_dir);
-	if(!flength(str))
-		remove(str); }
-CRLF;
-
-if(!prepack && (sys_status&SS_ABORT || !online))
-    return(0);
-
-if(!prepack && useron.rest&FLAG('Q')) { /* If QWK Net node, check for files */
-    sprintf(str,"%sQNET\\%s.OUT\\*.*",data_dir,useron.alias);
-    i=findfirst(str,&ff,0);
-    while(!i) {                 /* Move files into temp dir */
-        sprintf(str,"%sQNET\\%s.OUT\\%s",data_dir,useron.alias,ff.ff_name);
-		strupr(str);
-        sprintf(tmp2,"%s%s",temp_dir,ff.ff_name);
-		lncntr=0;	/* Default pause */
-		bprintf(text[RetrievingFile],str);
-		if(!mv(str,tmp2,1))
-			netfiles++;
-		i=findnext(&ff); }
-	if(netfiles)
-		CRLF; }
-
-if(batdn_total) {
-	for(i=0,totalcdt=0;i<batdn_total;i++)
-			totalcdt+=batdn_cdt[i];
-	if(!(useron.exempt&FLAG('D'))
-		&& totalcdt>useron.cdt+useron.freecdt) {
-		bprintf(text[YouOnlyHaveNCredits]
-			,ultoac(useron.cdt+useron.freecdt,tmp)); }
-	else {
-		for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
-			totalsize+=batdn_size[i];
-			if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
-				totaltime+=batdn_size[i]/(ulong)cur_cps; }
-		if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft)
-			bputs(text[NotEnoughTimeToDl]);
-		else {
-			for(i=0;i<batdn_total;i++) {
-				lncntr=0;
-				unpadfname(batdn_name[i],tmp);
-				sprintf(tmp2,"%s%s",temp_dir,tmp);
-				if(!fexist(tmp2)) {
-					seqwait(dir[batdn_dir[i]]->seqdev);
-					bprintf(text[RetrievingFile],tmp);
-					sprintf(str,"%s%s"
-						,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-						? altpath[batdn_alt[i]-1]
-						: dir[batdn_dir[i]]->path
-						,tmp);
-					mv(str,tmp2,1); /* copy the file to temp dir */
-					getnodedat(node_num,&thisnode,1);
-					thisnode.aux=0xfe;
-					putnodedat(node_num,thisnode);
-					CRLF; } } } } }
-
-if(!(*msgcnt) && !mailmsgs && !files && !netfiles && !batdn_total
-	&& (prepack || !preqwk)) {
-	bputs(text[QWKNoNewMessages]);
-	return(0); }
-
-if(!prepack && !(useron.rest&FLAG('Q'))) {      /* Don't include in network */
-	/***********************/					/* packets */
-	/* Copy QWK Text files */
-	/***********************/
-	sprintf(str,"%sQWK\\HELLO",text_dir);
-	if(fexist(str)) {
-		sprintf(tmp2,"%sHELLO",temp_dir);
-		mv(str,tmp2,1); }
-	sprintf(str,"%sQWK\\BBSNEWS",text_dir);
-	if(fexist(str)) {
-		sprintf(tmp2,"%sBBSNEWS",temp_dir);
-		mv(str,tmp2,1); }
-	sprintf(str,"%sQWK\\GOODBYE",text_dir);
-	if(fexist(str)) {
-		sprintf(tmp2,"%sGOODBYE",temp_dir);
-		mv(str,tmp2,1); }
-	sprintf(str,"%sQWK\\BLT-*.*",text_dir);
-	i=findfirst(str,&ff,0);
-	while(!i) { 				/* Copy BLT-*.* files */
-		padfname(ff.ff_name,str);
-		if(isdigit(str[4]) && isdigit(str[9])) {
-			sprintf(str,"%sQWK\\%s",text_dir,ff.ff_name);
-			sprintf(tmp2,"%s%s",temp_dir,ff.ff_name);
-			mv(str,tmp2,1); }
-		i=findnext(&ff); } }
-
-if(prepack) {
-	for(i=1;i<=sys_nodes;i++) {
-		getnodedat(i,&node,0);
-		if((node.status==NODE_INUSE || node.status==NODE_QUIET
-			|| node.status==NODE_LOGON) && node.useron==useron.number)
-			break; }
-	if(i<=sys_nodes)	/* Don't pre-pack with user online */
-		return(0); }
-
-/*******************/
-/* Compress Packet */
-/*******************/
-sprintf(tmp2,"%s*.*",temp_dir);
-i=external(cmdstr(temp_cmd(),packet,tmp2,NULL),EX_OUTL|EX_OUTR);
-if(!fexist(packet)) {
-	bputs(text[QWKCompressionFailed]);
-	if(i)
-		errormsg(WHERE,ERR_EXEC,cmdstr(temp_cmd(),packet,tmp2,NULL),i);
-	else
-		errorlog("Couldn't compress QWK packet");
-	return(0); }
-
-if(prepack) 		/* Early return if pre-packing */
-	return(1);
-
-l=flength(packet);
-sprintf(str,"%s.QWK",sys_id);
-bprintf(text[FiFilename],str);
-bprintf(text[FiFileSize],ultoac(l,tmp));
-if(l>0L && cur_cps)
-	i=l/(ulong)cur_cps;
-else
-	i=0;
-bprintf(text[FiTransferTime],sectostr(i,tmp));
-CRLF;
-if(!(useron.exempt&FLAG('T')) && i>timeleft) {
-	bputs(text[NotEnoughTimeToDl]);
-	return(0); }
-
-if(useron.rest&FLAG('Q')) {
-	sprintf(str,"%s.QWK",sys_id);
-	sprintf(tmp,"%s*.*",temp_dir);
-	i=findfirst(tmp,&ff,0);
-	while(!i) {
-		if(stricmp(str,ff.ff_name)) {
-			sprintf(tmp,"%s%s",temp_dir,ff.ff_name);
-			remove(tmp); }
-		i=findnext(&ff); } }
-
-return(1);
-}
diff --git a/src/sbbs2/pack_rep.c b/src/sbbs2/pack_rep.c
deleted file mode 100644
index 6a9cdaaf976fa5602f02aff69495c6a9264ef45d..0000000000000000000000000000000000000000
--- a/src/sbbs2/pack_rep.c
+++ /dev/null
@@ -1,245 +0,0 @@
-#line 1 "PACK_REP.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "post.h"
-#include "qwk.h"
-
-/****************************************************************************/
-/* Creates an REP packet for upload to QWK hub 'hubnum'.                    */
-/* Returns 1 if successful, 0 if not.										*/
-/****************************************************************************/
-char pack_rep(uint hubnum)
-{
-	uchar	str[256],tmp2[256],ch,*p;
-	uchar	HUGE16 *qwkbuf;
-	int 	file,mode;
-	uint	i,j,k,n;
-	long	l,size,msgcnt,submsgs,mailmsgs,packedmail,netfiles=0,deleted;
-	ulong	last,ptr,posts,msgs;
-	post_t	HUGE16 *post;
-	mail_t	*mail;
-	struct	ffblk ff;
-	FILE	*rep;
-	smbmsg_t msg;
-
-msgcnt=0L;
-delfiles(temp_dir,"*.*");
-sprintf(str,"%s%s.REP",data_dir,qhub[hubnum]->id);
-if(fexist(str))
-	external(cmdstr(qhub[hubnum]->unpack,str,"*.*",NULL),EX_OUTL);
-/*************************************************/
-/* Create SYSID.MSG, write header and leave open */
-/*************************************************/
-sprintf(str,"%s%s.MSG",temp_dir,qhub[hubnum]->id);
-if((rep=fnopen(&file,str,O_CREAT|O_WRONLY))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY);
-	return(0); }
-if(!filelength(file)) { 						/* New REP packet */
-	sprintf(str,"%-128s",qhub[hubnum]->id);     /* So write header */
-	fwrite(str,128,1,rep); }
-fseek(rep,0L,SEEK_END);
-/*********************/
-/* Pack new messages */
-/*********************/
-console|=CON_L_ECHO;
-
-sprintf(smb.file,"%sMAIL",data_dir);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	fclose(rep);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-/***********************/
-/* Pack E-mail, if any */
-/***********************/
-qwkmail_time=time(NULL);
-mailmsgs=loadmail(&mail,0,MAIL_YOUR,LM_QWK);
-packedmail=0;
-if(mailmsgs) {
-	bputs(text[QWKPackingEmail]);
-	for(l=0;l<mailmsgs;l++) {
-		bprintf("\b\b\b\b\b%-5lu",l+1);
-
-		msg.idx.offset=mail[l].offset;
-		if(!loadmsg(&msg,mail[l].number))
-			continue;
-
-		sprintf(str,"%s/",qhub[hubnum]->id);
-		if(msg.to_net.type!=NET_QWK
-			|| (strcmp(msg.to_net.addr,qhub[hubnum]->id)
-			&& strncmp(msg.to_net.addr,str,strlen(str)))) {
-			smb_unlockmsghdr(&smb,&msg);
-			smb_freemsgmem(&msg);
-			continue; }
-
-		msgtoqwk(msg,rep,TO_QNET|REP|A_LEAVE,INVALID_SUB,0);
-		packedmail++;
-		smb_unlockmsghdr(&smb,&msg);
-		smb_freemsgmem(&msg); }
-	bprintf(text[QWKPackedEmail],packedmail); }
-smb_close(&smb);					/* Close the e-mail */
-if(mailmsgs)
-	FREE(mail);
-
-useron.number=1;
-getuserdat(&useron);
-for(i=0;i<qhub[hubnum]->subs;i++) {
-	j=qhub[hubnum]->sub[i]; 			/* j now equals the real sub num */
-	msgs=getlastmsg(j,&last,0);
-	lncntr=0;						/* defeat pause */
-	if(!msgs || last<=sub[j]->ptr) {
-		if(sub[j]->ptr>last) {
-			sub[j]->ptr=last;
-			sub[j]->last=last; }
-		bprintf(text[NScanStatusFmt]
-			,grp[sub[j]->grp]->sname
-			,sub[j]->lname,0L,msgs);
-		continue; }
-
-	sprintf(smb.file,"%s%s"
-		,sub[j]->data_dir,sub[j]->code);
-	smb.retry_time=smb_retry_time;
-	if((k=smb_open(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,k);
-		continue; }
-
-	post=loadposts(&posts,j,sub[j]->ptr,LP_BYSELF|LP_OTHERS|LP_PRIVATE|LP_REP);
-	bprintf(text[NScanStatusFmt]
-		,grp[sub[j]->grp]->sname
-		,sub[j]->lname,posts,msgs);
-	if(!posts)	{ /* no new messages */
-		smb_close(&smb);
-		continue; }
-
-    sub[j]->ptr=last;                   /* set pointer */
-	bputs(text[QWKPackingSubboard]);	/* ptr to last msg	*/
-	submsgs=0;
-	for(l=0;l<posts;l++) {
-		bprintf("\b\b\b\b\b%-5lu",l+1);
-
-		msg.idx.offset=post[l].offset;
-		if(!loadmsg(&msg,post[l].number))
-			continue;
-
-		if(msg.from_net.type && msg.from_net.type!=NET_QWK &&
-			!(sub[j]->misc&SUB_GATE)) {
-			smb_freemsgmem(&msg);
-			smb_unlockmsghdr(&smb,&msg);
-			continue; }
-
-		if(!strncmpi(msg.subj,"NE:",3) || (msg.from_net.type==NET_QWK &&
-			route_circ(msg.from_net.addr,qhub[hubnum]->id))) {
-			smb_freemsgmem(&msg);
-			smb_unlockmsghdr(&smb,&msg);
-			continue; }
-
-		mode=qhub[hubnum]->mode[i]|TO_QNET|REP;
-		if(mode&A_LEAVE) mode|=(VIA|TZ);
-		if(msg.from_net.type!=NET_QWK)
-			mode|=TAGLINE;
-
-		msgtoqwk(msg,rep,mode,j,qhub[hubnum]->conf[i]);
-
-		smb_freemsgmem(&msg);
-		smb_unlockmsghdr(&smb,&msg);
-		msgcnt++;
-		submsgs++; }
-	bprintf(text[QWKPackedSubboard],submsgs,msgcnt);
-	LFREE(post);
-	smb_close(&smb); }
-
-fclose(rep);			/* close MESSAGE.DAT */
-CRLF;
-						/* Look for extra files to send out */
-sprintf(str,"%sQNET\\%s.OUT\\*.*",data_dir,qhub[hubnum]->id);
-i=findfirst(str,&ff,0);
-while(!i) {
-    sprintf(str,"%sQNET\\%s.OUT\\%s",data_dir,qhub[hubnum]->id,ff.ff_name);
-    sprintf(tmp2,"%s%s",temp_dir,ff.ff_name);
-	bprintf(text[RetrievingFile],str);
-	if(!mv(str,tmp2,1))
-        netfiles++;
-    i=findnext(&ff); }
-if(netfiles)
-	CRLF;
-
-if(!msgcnt && !netfiles && !packedmail) {
-	bputs(text[QWKNoNewMessages]);
-	return(0); }
-
-/*******************/
-/* Compress Packet */
-/*******************/
-sprintf(str,"%s%s.REP",data_dir,qhub[hubnum]->id);
-sprintf(tmp2,"%s*.*",temp_dir);
-i=external(cmdstr(qhub[hubnum]->pack,str,tmp2,NULL),EX_OUTL);
-if(!fexist(str)) {
-	bputs(text[QWKCompressionFailed]);
-	if(i)
-		errormsg(WHERE,ERR_EXEC,cmdstr(qhub[hubnum]->pack,str,tmp2,NULL),i);
-	else
-		errorlog("Couldn't compress REP packet");
-	return(0); }
-sprintf(str,"%sQNET\\%s.OUT\\",data_dir,qhub[hubnum]->id);
-delfiles(str,"*.*");
-
-if(packedmail) {						/* Delete NetMail */
-	sprintf(smb.file,"%sMAIL",data_dir);
-	smb.retry_time=smb_retry_time;
-	if((i=smb_open(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		return(1); }
-
-	mailmsgs=loadmail(&mail,0,MAIL_YOUR,LM_QWK);
-
-	if((i=smb_locksmbhdr(&smb))!=0) {			  /* Lock the base, so nobody */
-		if(mailmsgs)
-			FREE(mail);
-		smb_close(&smb);
-		errormsg(WHERE,ERR_LOCK,smb.file,i);	/* messes with the index */
-		return(1); }
-
-	if((i=smb_getstatus(&smb))!=0) {
-		if(mailmsgs)
-			FREE(mail);
-		smb_close(&smb);
-		errormsg(WHERE,ERR_READ,smb.file,i);
-		return(1); }
-
-	deleted=0;
-	/* Mark as READ and DELETE */
-	for(l=0;l<mailmsgs;l++) {
-		if(mail[l].time>qwkmail_time)
-			continue;
-		msg.idx.offset=0;
-		if(!loadmsg(&msg,mail[l].number))
-			continue;
-
-		sprintf(str,"%s/",qhub[hubnum]->id);
-		if(msg.to_net.type!=NET_QWK
-			|| (strcmp(msg.to_net.addr,qhub[hubnum]->id)
-			&& strncmp(msg.to_net.addr,str,strlen(str)))) {
-			smb_unlockmsghdr(&smb,&msg);
-			smb_freemsgmem(&msg);
-            continue; }
-
-		msg.hdr.attr|=MSG_DELETE;
-		msg.idx.attr=msg.hdr.attr;
-		if((i=smb_putmsg(&smb,&msg))!=0)
-			errormsg(WHERE,ERR_WRITE,smb.file,i);
-		else
-			deleted++;
-		smb_unlockmsghdr(&smb,&msg);
-		smb_freemsgmem(&msg); }
-
-	if(deleted && sys_misc&SM_DELEMAIL)
-		delmail(0,MAIL_YOUR);
-	smb_close(&smb);
-	if(mailmsgs)
-		FREE(mail); }
-
-return(1);
-}
diff --git a/src/sbbs2/post.h b/src/sbbs2/post.h
deleted file mode 100644
index 060ec942af3f50250c0caf87f29ea285eee9d9cb..0000000000000000000000000000000000000000
--- a/src/sbbs2/post.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* POST.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "gen_defs.h"
-
-
-typedef struct {                        /* Message data */
-	ulong	offset, 					/* Offset to header (in bytes) */
-			number; 					/* Number of message */
-	ushort	to, 						/* CRC-16 of to username */
-			from,						/* CRC-16 of from username */
-			subj;						/* CRC-16 of subject */
-			} post_t;
-
-#ifdef SBBS
-post_t HUGE16 *loadposts(ulong *posts, uint subnum, ulong ptr, uint mode);
-#else
-ulong loadposts(post_t HUGE16 **post, uint subnum, ulong ptr, uint mode);
-#endif
-int  searchposts(uint subnum, post_t HUGE16 *post, long start, long msgs
-     ,char *search);
-void showposts_toyou(post_t HUGE16 *post, ulong start, ulong posts);
diff --git a/src/sbbs2/postmsg.c b/src/sbbs2/postmsg.c
deleted file mode 100644
index 4034d0a1f090f64f27a8490170c53141132fd459..0000000000000000000000000000000000000000
--- a/src/sbbs2/postmsg.c
+++ /dev/null
@@ -1,308 +0,0 @@
-#line 1 "POSTMSG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Posts a message on subboard number sub, with 'top' as top of message.    */
-/* Returns 1 if posted, 0 if not.                                           */
-/****************************************************************************/
-char postmsg(uint subnum, smbmsg_t *remsg, int wm_mode)
-{
-	char	str[256],touser[256],title[LEN_TITLE+1],buf[SDT_BLOCK_LEN]
-			,top[256],c;
-	ushort	xlat,msgattr;
-	int 	i,j,n,x,file,storage;
-	ulong	l,length,offset,crc=0xffffffff;
-	FILE	*instream;
-	smbmsg_t msg,tmpmsg;
-
-if(remsg) {
-	sprintf(title,"%.*s",LEN_TITLE,remsg->subj);
-	if(sub[subnum]->misc&SUB_INET)	// All Internet posts to "All" 05/20/97
-		touser[0]=0;
-	else if(remsg->hdr.attr&MSG_ANONYMOUS)
-		strcpy(touser,text[Anonymous]);
-	else
-		strcpy(touser,remsg->from);
-	msgattr=(remsg->hdr.attr&MSG_PRIVATE);
-	sprintf(top,text[RegardingByTo],title,touser,remsg->to
-		,timestr((time_t *)&remsg->hdr.when_written.time)
-		,zonestr(remsg->hdr.when_written.zone)); }
-else {
-	title[0]=0;
-	touser[0]=0;
-	top[0]=0;
-	msgattr=0; }
-
-if(useron.rest&FLAG('P')) {
-    bputs(text[R_Post]);
-    return(0); }
-
-if((sub[subnum]->misc&(SUB_QNET|SUB_FIDO|SUB_PNET|SUB_INET))
-	&& (useron.rest&FLAG('N'))) {
-    bputs(text[CantPostOnSub]);
-    return(0); }
-
-if(useron.ptoday>=level_postsperday[useron.level]) {
-	bputs(text[TooManyPostsToday]);
-	return(0); }
-
-bprintf(text[Posting],grp[sub[subnum]->grp]->sname,sub[subnum]->lname);
-action=NODE_PMSG;
-nodesync();
-
-if(!(msgattr&MSG_PRIVATE) && (sub[subnum]->misc&SUB_PONLY
-	|| (sub[subnum]->misc&SUB_PRIV && !noyes(text[PrivatePostQ]))))
-	msgattr|=MSG_PRIVATE;
-
-if(sys_status&SS_ABORT)
-	return(0);
-
-if(!(sub[subnum]->misc&SUB_INET)	// Prompt for TO: user
-	&& (sub[subnum]->misc&SUB_TOUSER || msgattr&MSG_PRIVATE || touser[0])) {
-	if(!touser[0] && !(msgattr&MSG_PRIVATE))
-		strcpy(touser,"All");
-    bputs(text[PostTo]);
-	i=LEN_ALIAS;
-	if(sub[subnum]->misc&(SUB_PNET|SUB_INET))
-		i=60;
-	if(sub[subnum]->misc&SUB_FIDO)
-		i=35;
-	if(sub[subnum]->misc&SUB_QNET)
-		i=25;
-	getstr(touser,i,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
-	if(stricmp(touser,"ALL")
-	&& !(sub[subnum]->misc&(SUB_PNET|SUB_FIDO|SUB_QNET|SUB_INET|SUB_ANON))) {
-		if(sub[subnum]->misc&SUB_NAME) {
-			if(!userdatdupe(useron.number,U_NAME,LEN_NAME,touser,0)) {
-				bputs(text[UnknownUser]);
-				return(0); } }
-		else {
-			if((i=finduser(touser))==0)
-				return(0);
-			username(i,touser); } }
-	if(sys_status&SS_ABORT)
-		return(0); }
-
-if(!touser[0])
-	strcpy(touser,"All");       // Default to ALL
-
-if(!stricmp(touser,"SYSOP") && !SYSOP)  // Change SYSOP to user #1
-	username(1,touser);
-
-if(msgattr&MSG_PRIVATE && !stricmp(touser,"ALL")) {
-    bputs(text[NoToUser]);
-    return(0); }
-if(msgattr&MSG_PRIVATE)
-	wm_mode|=WM_PRIVATE;
-
-if(sub[subnum]->misc&SUB_AONLY
-	|| (sub[subnum]->misc&SUB_ANON && useron.exempt&FLAG('A')
-		&& !noyes(text[AnonymousQ])))
-	msgattr|=MSG_ANONYMOUS;
-
-if(sub[subnum]->mod_ar[0] && chk_ar(sub[subnum]->mod_ar,useron))
-	msgattr|=MSG_MODERATED;
-
-if(sub[subnum]->misc&SUB_SYSPERM && sub_op(subnum))
-	msgattr|=MSG_PERMANENT;
-
-if(msgattr&MSG_PRIVATE)
-	bputs(text[PostingPrivately]);
-
-if(msgattr&MSG_ANONYMOUS)
-	bputs(text[PostingAnonymously]);
-
-if(sub[subnum]->misc&SUB_NAME)
-	bputs(text[UsingRealName]);
-
-sprintf(str,"%sINPUT.MSG",node_dir);
-if(!writemsg(str,top,title,wm_mode,subnum,touser)) {
-    bputs(text[Aborted]);
-    return(0); }
-
-bputs(text[WritingIndx]);
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
-	return(0); }
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=sub[subnum]->maxcrcs;
-	smb.status.max_msgs=sub[subnum]->maxmsgs;
-	smb.status.max_age=sub[subnum]->maxage;
-	smb.status.attr=sub[subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
-	if((i=smb_create(&smb))!=0) {
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		return(0); } }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-    return(0); }
-
-if((i=smb_getstatus(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-    return(0); }
-
-length=flength(str)+2;	 /* +2 for translation string */
-
-if(length&0xfff00000UL) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LEN,str,length);
-    return(0); }
-
-if(smb.status.attr&SMB_HYPERALLOC) {
-	offset=smb_hallocdat(&smb);
-	storage=SMB_HYPERALLOC; }
-else {
-	if((i=smb_open_da(&smb))!=0) {
-		smb_unlocksmbhdr(&smb);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		return(0); }
-	if(sub[subnum]->misc&SUB_FAST) {
-		offset=smb_fallocdat(&smb,length,1);
-		storage=SMB_FASTALLOC; }
-	else {
-		offset=smb_allocdat(&smb,length,1);
-		storage=SMB_SELFPACK; }
-	smb_close_da(&smb); }
-
-if((file=open(str,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	smb_freemsgdat(&smb,offset,length,1);
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
-	return(0); }
-
-setvbuf(instream,NULL,_IOFBF,2*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-while(!feof(instream)) {
-	memset(buf,0,x);
-	j=fread(buf,1,x,instream);
-	if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
-		buf[j-1]=buf[j-2]=0;	/* Convert to NULL */
-	if(sub[subnum]->maxcrcs) {
-		for(i=0;i<j;i++)
-			crc=ucrc32(buf[i],crc); }
-	fwrite(buf,j,1,smb.sdt_fp);
-	x=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-crc=~crc;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-msg.hdr.attr=msg.idx.attr=msgattr;
-msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone;
-if(remsg) {
-	msg.hdr.thread_orig=remsg->hdr.number;
-	if(!remsg->hdr.thread_first) {
-		remsg->hdr.thread_first=smb.status.last_msg+1;
-		if((i=smb_lockmsghdr(&smb,remsg))!=0)
-			errormsg(WHERE,ERR_LOCK,smb.file,i);
-		else {
-			i=smb_putmsghdr(&smb,remsg);
-			smb_unlockmsghdr(&smb,remsg);
-			if(i)
-				errormsg(WHERE,ERR_WRITE,smb.file,i); } }
-	else {
-		l=remsg->hdr.thread_first;
-		while(1) {
-			tmpmsg.idx.offset=0;
-			if(!loadmsg(&tmpmsg,l))
-				break;
-			if(tmpmsg.hdr.thread_next && tmpmsg.hdr.thread_next!=l) {
-				l=tmpmsg.hdr.thread_next;
-				smb_unlockmsghdr(&smb,&tmpmsg);
-				smb_freemsgmem(&tmpmsg);
-				continue; }
-			tmpmsg.hdr.thread_next=smb.status.last_msg+1;
-			if((i=smb_putmsghdr(&smb,&tmpmsg))!=0)
-				errormsg(WHERE,ERR_WRITE,smb.file,i);
-			smb_unlockmsghdr(&smb,&tmpmsg);
-			smb_freemsgmem(&tmpmsg);
-			break; } } }
-
-
-if(sub[subnum]->maxcrcs) {
-	i=smb_addcrc(&smb,crc);
-	if(i) {
-		smb_freemsgdat(&smb,offset,length,1);
-		smb_unlocksmbhdr(&smb);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		bputs("\1r\1h\1iDuplicate message!\r\n");
-		return(0); } }
-
-msg.hdr.offset=offset;
-
-smb_hfield(&msg,RECIPIENT,strlen(touser),touser);
-strlwr(touser);
-msg.idx.to=crc16(touser);
-
-strcpy(str,sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias);
-smb_hfield(&msg,SENDER,strlen(str),str);
-strlwr(str);
-msg.idx.from=crc16(str);
-
-sprintf(str,"%u",useron.number);
-smb_hfield(&msg,SENDEREXT,strlen(str),str);
-
-smb_hfield(&msg,SUBJECT,strlen(title),title);
-strcpy(str,title);
-strlwr(str);
-remove_re(str);
-msg.idx.subj=crc16(str);
-
-smb_dfield(&msg,TEXT_BODY,length);
-
-smb_unlocksmbhdr(&smb);
-i=smb_addmsghdr(&smb,&msg,storage);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-
-smb_freemsgmem(&msg);
-if(i) {
-	smb_freemsgdat(&smb,offset,length,1);
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-	return(0); }
-
-useron.ptoday++;
-useron.posts++;
-logon_posts++;
-putuserrec(useron.number,U_POSTS,5,itoa(useron.posts,str,10));
-putuserrec(useron.number,U_PTODAY,5,itoa(useron.ptoday,str,10));
-bprintf(text[Posted],grp[sub[subnum]->grp]->sname
-    ,sub[subnum]->lname);
-sprintf(str,"Posted on %s %s",grp[sub[subnum]->grp]->sname,sub[subnum]->lname);
-logline("P+",str);
-if(sub[subnum]->misc&SUB_FIDO && sub[subnum]->echomail_sem[0]) /* semaphore */
-	if((file=nopen(sub[subnum]->echomail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-        close(file);
-return(1);
-}
diff --git a/src/sbbs2/putmsg.c b/src/sbbs2/putmsg.c
deleted file mode 100644
index eae2dc7313ca239d4def2529b9a8e12b5279c29d..0000000000000000000000000000000000000000
--- a/src/sbbs2/putmsg.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#line 1 "PUTMSG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Outputs a NULL terminated string locally and remotely (if applicable)	*/
-/* checking for message aborts, pauses, ANSI escape and ^A sequences.		*/
-/* Changes local text attributes if necessary. Max length of str is 4 gig	*/
-/* Returns the last char of the buffer access.. 0 if not aborted.           */
-/* If P_SAVEATR bit is set in mode, the attributes set by the message       */
-/* will be the current attributes after the message is displayed, otherwise */
-/* the attributes prior to diplaying the message are always restored.       */
-/* Ignores Ctrl-Z's                                                         */
-/****************************************************************************/
-char putmsg(char HUGE16 *str, int mode)
-{
-	uchar	tmpatr,tmp2[256],tmp3[128],*p,exatr=0;
-	int 	orgcon=console,i;
-	ulong	l=0,sys_status_sav=sys_status;
-
-tmpatr=curatr;	/* was lclatr(-1) */
-if(!(mode&P_SAVEATR))
-	attr(LIGHTGRAY);
-while(str[l] && (mode&P_NOABORT || !msgabort()) && online) {
-	if(str[l]==1) {		/* Ctrl-Ax sequence */
-		if(str[l+1]=='"' && !(sys_status&SS_NEST_PF)) {  /* Quote a file */
-			l+=2;
-			i=0;
-			while(i<12 && isprint(str[l]) && str[l]!='\\' && str[l]!='/')
-				tmp2[i++]=str[l++];
-			tmp2[i]=0;
-			sys_status|=SS_NEST_PF; 	/* keep it only one message deep! */
-			sprintf(tmp3,"%s%s",text_dir,tmp2);
-			printfile(tmp3,0);
-			sys_status&=~SS_NEST_PF; }
-		else if(toupper(str[l+1])=='Z')             /* Ctrl-AZ==EOF */
-			break;
-		else {
-			ctrl_a(str[l+1]);
-			l+=2; } }
-	else if((str[l]=='`' || str[l]=='�') && str[l+1]=='[') {   
-		outchar(ESC); /* Convert `[ and �[ to ESC[ */
-		l++; }
-	else if(sys_misc&SM_PCBOARD && str[l]=='@' && str[l+1]=='X'
-		&& isxdigit(str[l+2]) && isxdigit(str[l+3])) {
-		sprintf(tmp2,"%.2s",str+l+2);
-		attr(ahtoul(tmp2));
-		exatr=1;
-		l+=4; }
-	else if(sys_misc&SM_WILDCAT && str[l]=='@' && str[l+3]=='@'
-		&& isxdigit(str[l+1]) && isxdigit(str[l+2])) {
-		sprintf(tmp2,"%.2s",str+l+1);
-		attr(ahtoul(tmp2));
-		// exatr=1;
-		l+=4; }
-	else if(sys_misc&SM_RENEGADE && str[l]=='|' && isdigit(str[l+1])
-		&& !(useron.misc&(RIP|WIP))) {
-		sprintf(tmp2,"%.2s",str+l+1);
-		i=atoi(tmp2);
-		if(i>=16) { 				 /* setting background */
-			i-=16;
-			i<<=4;
-			i|=(curatr&0x0f); } 	/* leave foreground alone */
-		else
-			i|=(curatr&0xf0);		/* leave background alone */
-		attr(i);
-		exatr=1;
-		l+=2;	/* Skip |x */
-		if(isdigit(str[l]))
-			l++; }	/* Skip second digit if it exists */
-	else if(sys_misc&SM_CELERITY && str[l]=='|' && isalpha(str[l+1])
-		&& !(useron.misc&(RIP|WIP))) {
-		switch(str[l+1]) {
-			case 'k':
-				attr((curatr&0xf0)|BLACK);
-				break;
-			case 'b':
-				attr((curatr&0xf0)|BLUE);
-				break;
-			case 'g':
-				attr((curatr&0xf0)|GREEN);
-				break;
-			case 'c':
-				attr((curatr&0xf0)|CYAN);
-				break;
-			case 'r':
-				attr((curatr&0xf0)|RED);
-				break;
-			case 'm':
-				attr((curatr&0xf0)|MAGENTA);
-				break;
-			case 'y':
-				attr((curatr&0xf0)|YELLOW);
-				break;
-			case 'w':
-				attr((curatr&0xf0)|LIGHTGRAY);
-				break;
-			case 'd':
-				attr((curatr&0xf0)|BLACK|HIGH);
-				break;
-			case 'B':
-				attr((curatr&0xf0)|BLUE|HIGH);
-				break;
-			case 'G':
-				attr((curatr&0xf0)|GREEN|HIGH);
-				break;
-			case 'C':
-				attr((curatr&0xf0)|CYAN|HIGH);
-				break;
-			case 'R':
-				attr((curatr&0xf0)|RED|HIGH);
-				break;
-			case 'M':
-				attr((curatr&0xf0)|MAGENTA|HIGH);
-				break;
-			case 'Y':   /* Yellow */
-				attr((curatr&0xf0)|YELLOW|HIGH);
-				break;
-			case 'W':
-				attr((curatr&0xf0)|LIGHTGRAY|HIGH);
-				break;
-			case 'S':   /* swap foreground and background */
-				attr((curatr&0x07)<<4);
-				break; }
-		exatr=1;
-		l+=2;	/* Skip |x */
-		}  /* Skip second digit if it exists */
-	else if(sys_misc&SM_WWIV && str[l]==3 && isdigit(str[l+1])) {
-		exatr=1;
-		switch(str[l+1]) {
-			default:
-				attr(LIGHTGRAY);
-				break;
-			case '1':
-				attr(CYAN|HIGH);
-				break;
-			case '2':
-				attr(BROWN|HIGH);
-				break;
-			case '3':
-				attr(MAGENTA);
-				break;
-			case '4':
-				attr(LIGHTGRAY|HIGH|(BLUE<<4));
-				break;
-			case '5':
-				attr(GREEN);
-				break;
-			case '6':
-				attr(RED|HIGH|BLINK);
-				break;
-			case '7':
-				attr(BLUE|HIGH);
-				break;
-			case '8':
-				attr(BLUE);
-				break;
-			case '9':
-				attr(CYAN);
-				break; }
-		l+=2; }
-	else {
-		if(exatr && str[l]==LF) 	/* clear at newline for extra attr codes */
-			attr(LIGHTGRAY);
-		if(lclaes()) {
-			if(str[l]=='A' || str[l]=='B' || str[l]=='H' || str[l]=='J'
-				|| str[l]=='f' || str[l]=='u')    /* ANSI anim */
-				lncntr=0;			/* so defeat pause */
-			if(str[l]=='"') {
-				l++;				/* don't pass on keyboard reassignment */
-				continue; } }
-		if(str[l]=='!' && str[l+1]=='|' && useron.misc&(RIP|WIP)) /* RIP */
-			lncntr=0;				/* so defeat pause */
-		if(str[l]==ESC && str[l+1]=='$')    /* WIP command */
-			lncntr=0;
-		if(str[l]=='@' && !(mode&P_NOATCODES)) {
-			i=atcodes((char *)str+l);	/* returns 0 if not valid @ code */
-			l+=i;					/* i is length of code string */
-			if(i)					/* if valid string, go to top */
-				continue; }
-		if(str[l]!=26)
-			outchar(str[l]);
-		l++; } }
-//curatr=lclatr(-1);		01/29/96
-if(!(mode&P_SAVEATR)) {
-	console=orgcon;
-	attr(tmpatr); }
-
-/* Restore original settings of Forced Pause On/Off */
-sys_status&=~(SS_PAUSEOFF|SS_PAUSEON);
-sys_status|=(sys_status_sav&(SS_PAUSEOFF|SS_PAUSEON));
-return(str[l]);
-}
diff --git a/src/sbbs2/putnode.c b/src/sbbs2/putnode.c
deleted file mode 100644
index 6e9a5a6f56f42cf4baed37bce335d7c7efc8ae1d..0000000000000000000000000000000000000000
--- a/src/sbbs2/putnode.c
+++ /dev/null
@@ -1,135 +0,0 @@
-#line 1 "PUTNODE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(uint number, node_t node)
-{
-	char str[256],firston[25];
-
-if(!(sys_status&SS_NODEDAB))
-	return;
-if(!number || number>sys_nodes) {
-	errormsg(WHERE,ERR_CHK,"node number",number);
-	return; }
-if(number==node_num) {
-	if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-		&& text[NodeActionMain+node.action][0]) {
-		node.misc|=NODE_EXT;
-		memset(str,0,128);
-		sprintf(str,text[NodeActionMain+node.action]
-			,useron.alias
-			,useron.level
-			,getage(useron.birth)
-			,useron.sex
-			,useron.comp
-			,useron.note
-			,unixtodstr(useron.firston,firston)
-			,node.aux&0xff
-			,node.connection
-			);
-		putnodeext(number,str); }
-	else
-		node.misc&=~NODE_EXT; }
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	errormsg(WHERE,ERR_WRITE,"nodefile",number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-
-/****************************************************************************/
-/* Creates a short message for node 'num' than contains 'strin'             */
-/****************************************************************************/
-void putnmsg(int num, char *strin)
-{
-    char str[256];
-    int file,i;
-    node_t node;
-
-sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,num);
-if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT);
-    return; }
-lseek(file,0L,SEEK_END);	// Instead of opening with O_APPEND
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,i);
-    return; }
-close(file);
-getnodedat(num,&node,0);
-if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-    && !(node.misc&NODE_NMSG)) {
-    getnodedat(num,&node,1);
-    node.misc|=NODE_NMSG;
-    putnodedat(num,node); }
-}
-
-void putnodeext(uint number, char *ext)
-{
-    char str[256];
-    int count=0;
-
-if(!(sys_status&SS_NODEDAB))
-    return;
-if(!number || number>sys_nodes) {
-    errormsg(WHERE,ERR_CHK,"node number",number);
-    return; }
-number--;   /* make zero based */
-while(count<LOOP_NODEDAB) {
-    if(count>10)
-        mswait(55);
-    lseek(node_ext,(long)number*128L,SEEK_SET);
-    if(lock(node_ext,(long)number*128L,128)==-1) {
-        count++;
-        continue; }
-    if(write(node_ext,ext,128)==128)
-        break;
-    count++; }
-unlock(node_ext,(long)number*128L,128);
-if(count>(LOOP_NODEDAB/2) && count!=LOOP_NODEDAB) {
-    sprintf(str,"NODE.EXB COLLISION - Count: %d",count);
-    logline("!!",str); }
-if(count==LOOP_NODEDAB) {
-    errormsg(WHERE,ERR_WRITE,"NODE.EXB",number+1);
-    return; }
-}
-
-/****************************************************************************/
-/* Creates a short message for 'usernumber' than contains 'strin'           */
-/****************************************************************************/
-void putsmsg(int usernumber, char *strin)
-{
-    char str[256];
-    int file,i;
-    node_t node;
-
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-    return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-    close(file);
-    errormsg(WHERE,ERR_WRITE,str,i);
-    return; }
-close(file);
-for(i=1;i<=sys_nodes;i++) {     /* flag node if user on that msg waiting */
-    getnodedat(i,&node,0);
-    if(node.useron==usernumber
-        && (node.status==NODE_INUSE || node.status==NODE_QUIET)
-        && !(node.misc&NODE_MSGW)) {
-        getnodedat(i,&node,1);
-        node.misc|=NODE_MSGW;
-        putnodedat(i,node); } }
-}
-
diff --git a/src/sbbs2/qwk.c b/src/sbbs2/qwk.c
deleted file mode 100644
index d5e598e93f0fb7f0d39c76ed92eb9e5d28ca27fe..0000000000000000000000000000000000000000
--- a/src/sbbs2/qwk.c
+++ /dev/null
@@ -1,942 +0,0 @@
-#line 1 "QWK.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************/
-/* Functions that pertain solely to the QWK packets */
-/****************************************************/
-
-#include "sbbs.h"
-#include "etext.h"
-#include "post.h"
-#include "qwk.h"
-
-time_t qwkmail_time;
-
-/****************************************************************************/
-/* Removes ctrl-a codes from the string 'instr'                             */
-/****************************************************************************/
-void remove_ctrl_a(char *instr)
-{
-	char str[512];
-	uint i,j,k;
-
-j=strlen(instr);
-for(k=i=0;i<j;i++) {
-	if(instr[i]==1)
-		i++;
-	else str[k++]=instr[i]; }
-str[k]=0;
-strcpy(instr,str);
-}
-
-
-/****************************************************************************/
-/* Converts a long to an msbin real number. required for QWK NDX file		*/
-/****************************************************************************/
-float ltomsbin(long val)
-{
-	converter t;
-	int   sign, exp;	/* sign and exponent */
-
-t.f[0]=(float)val;
-sign=t.uc[3]/0x80;
-exp=((t.ui[1]>>7)-0x7f+0x81)&0xff;
-t.ui[1]=(t.ui[1]&0x7f)|(sign<<7)|(exp<<8);
-return(t.f[0]);
-}
-
-int route_circ(char *via, char *id)
-{
-	char str[256],*p,*sp;
-
-strcpy(str,via);
-p=str;
-while(*p && *p<=SP)
-	p++;
-while(*p) {
-	sp=strchr(p,'/');
-	if(sp) *sp=0;
-	if(!stricmp(p,id))
-		return(1);
-	if(!sp)
-		break;
-	p=sp+1; }
-return(0);
-}
-
-int qwk_route(char *inaddr, char *fulladdr)
-{
-	char node[10],str[256],*p;
-	int file,i;
-	FILE *stream;
-
-fulladdr[0]=0;
-sprintf(str,"%.255s",inaddr);
-p=strrchr(str,'/');
-if(p) p++;
-else p=str;
-sprintf(node,"%.8s",p);                 /* node = destination node */
-truncsp(node);
-
-for(i=0;i<total_qhubs;i++)				/* Check if destination is our hub */
-	if(!stricmp(qhub[i]->id,node))
-        break;
-if(i<total_qhubs) {
-	strcpy(fulladdr,node);
-	return(0); }
-
-i=matchuser(node);						/* Check if destination is a node */
-if(i) {
-	getuserrec(i,U_REST,8,str);
-	if(ahtoul(str)&FLAG('Q')) {
-		strcpy(fulladdr,node);
-		return(i); } }
-
-sprintf(node,"%.8s",inaddr);            /* node = next hop */
-p=strchr(node,'/');
-if(p) *p=0;
-truncsp(node);							
-
-if(strchr(inaddr,'/')) {                /* Multiple hops */
-
-	for(i=0;i<total_qhubs;i++)			/* Check if next hop is our hub */
-		if(!stricmp(qhub[i]->id,node))
-			break;
-	if(i<total_qhubs) {
-		strcpy(fulladdr,inaddr);
-		return(0); }
-
-	i=matchuser(node);					/* Check if next hop is a node */
-	if(i) {
-		getuserrec(i,U_REST,8,str);
-		if(ahtoul(str)&FLAG('Q')) {
-			strcpy(fulladdr,inaddr);
-			return(i); } } }
-
-p=strchr(node,SP);
-if(p) *p=0;
-
-sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
-if((stream=fnopen(&file,str,O_RDONLY))==NULL)
-	return(0);
-
-strcat(node,":");
-fulladdr[0]=0;
-while(!feof(stream)) {
-	if(!fgets(str,256,stream))
-		break;
-	if(!strnicmp(str+9,node,strlen(node))) {
-		fclose(stream);
-		truncsp(str);
-		sprintf(fulladdr,"%s/%s",str+9+strlen(node),inaddr);
-		break; } }
-
-fclose(stream);
-if(!fulladdr[0])			/* First hop not found in ROUTE.DAT */
-	return(0);
-
-sprintf(node,"%.8s",fulladdr);
-p=strchr(node,'/');
-if(p) *p=0;
-truncsp(node);
-
-for(i=0;i<total_qhubs;i++)				/* Check if first hop is our hub */
-	if(!stricmp(qhub[i]->id,node))
-        break;
-if(i<total_qhubs)
-	return(0);
-
-i=matchuser(node);						/* Check if first hop is a node */
-if(i) {
-	getuserrec(i,U_REST,8,str);
-	if(ahtoul(str)&FLAG('Q'))
-		return(i); }
-fulladdr[0]=0;
-return(0);
-}
-
-
-/* Via is in format: NODE/NODE/... */
-void update_qwkroute(char *via)
-{
-	static uint total_nodes;
-	static char **qwk_node;
-	static char **qwk_path;
-	static time_t *qwk_time;
-	char str[256],*p,*tp,node[9];
-	int i,file;
-	time_t t;
-	FILE *stream;
-
-if(via==NULL) {
-	if(!total_nodes)
-		return;
-	sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
-	if((stream=fnopen(&file,str,O_WRONLY|O_CREAT|O_TRUNC))!=NULL) {
-		t=time(NULL);
-		t-=(90L*24L*60L*60L);
-		for(i=0;i<total_nodes;i++)
-			if(qwk_time[i]>t)
-				fprintf(stream,"%s %s:%s\r\n"
-					,unixtodstr(qwk_time[i],str),qwk_node[i],qwk_path[i]);
-		fclose(stream); }
-	else
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    for(i=0;i<total_nodes;i++) {
-        FREE(qwk_node[i]);
-        FREE(qwk_path[i]); }
-	if(qwk_node) {
-		FREE(qwk_node);
-		qwk_node=NULL; }
-	if(qwk_path) {
-		FREE(qwk_path);
-		qwk_path=NULL; }
-	if(qwk_time) {
-		FREE(qwk_time);
-		qwk_time=NULL; }
-    total_nodes=0;
-    return; }
-
-if(!total_nodes) {
-	sprintf(str,"%sQNET\\ROUTE.DAT",data_dir);
-	if((stream=fnopen(&file,str,O_RDONLY))!=NULL) {
-		while(!feof(stream)) {
-			if(!fgets(str,255,stream))
-				break;
-			truncsp(str);
-			t=dstrtounix(str);
-			p=strchr(str,':');
-            if(!p) continue;
-			*p=0;
-			sprintf(node,"%.8s",str+9);
-			tp=strchr(node,SP); 		/* change "node bbs:" to "node:" */
-			if(tp) *tp=0;
-			for(i=0;i<total_nodes;i++)
-				if(!stricmp(qwk_node[i],node))
-					break;
-			if(i<total_nodes && qwk_time[i]>t)
-				continue;
-			if(i==total_nodes) {
-				if((qwk_node=REALLOC(qwk_node,sizeof(char *)*(i+1)))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,str,9*(i+1));
-					break; }
-				if((qwk_path=REALLOC(qwk_path,sizeof(char *)*(i+1)))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,str,128*(i+1));
-					break; }
-				if((qwk_time=REALLOC(qwk_time,sizeof(time_t)*(i+1)))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,str,sizeof(time_t)*(i+1));
-					break; }
-				if((qwk_node[i]=MALLOC(9))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,str,9);
-					break; }
-				if((qwk_path[i]=MALLOC(128))==NULL) {
-					errormsg(WHERE,ERR_ALLOC,str,128);
-					break; }
-				total_nodes++; }
-			strcpy(qwk_node[i],node);
-			p++;
-			while(*p && *p<=SP) p++;
-			sprintf(qwk_path[i],"%.127s",p);
-			qwk_time[i]=t; }
-		fclose(stream); } }
-
-strupr(via);
-p=strchr(via,'/');   /* Skip uplink */
-
-while(p && *p) {
-	p++;
-	sprintf(node,"%.8s",p);
-	tp=strchr(node,'/');
-	if(tp) *tp=0;
-	tp=strchr(node,SP); 		/* no spaces allowed */
-	if(tp) *tp=0;
-	truncsp(node);
-	for(i=0;i<total_nodes;i++)
-		if(!stricmp(qwk_node[i],node))
-			break;
-	if(i==total_nodes) {		/* Not in list */
-		if((qwk_node=REALLOC(qwk_node,sizeof(char *)*(total_nodes+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,9*(total_nodes+1));
-			break; }
-		if((qwk_path=REALLOC(qwk_path,sizeof(char *)*(total_nodes+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,128*(total_nodes+1));
-			break; }
-		if((qwk_time=REALLOC(qwk_time,sizeof(time_t)*(total_nodes+1)))
-			==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,sizeof(time_t)*(total_nodes+1));
-			break; }
-		if((qwk_node[total_nodes]=MALLOC(9))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,9);
-			break; }
-		if((qwk_path[total_nodes]=MALLOC(128))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,128);
-			break; }
-		total_nodes++; }
-	sprintf(qwk_node[i],"%.8s",node);
-	sprintf(qwk_path[i],"%.*s",(uint)((p-1)-via),via);
-	qwk_time[i]=time(NULL);
-	p=strchr(p,'/'); }
-}
-
-/****************************************************************************/
-/* Successful download of QWK packet										*/
-/****************************************************************************/
-void qwk_success(ulong msgcnt, char bi, char prepack)
-{
-	char	str[128];
-	int 	i;
-	ulong	l,msgs,deleted=0;
-	mail_t	*mail;
-	smbmsg_t msg;
-
-if(!prepack) {
-	logline("D-","Downloaded QWK packet");
-	posts_read+=msgcnt;
-
-	if(useron.rest&FLAG('Q')) {
-		sprintf(str,"%sQNET\\%.8s.OUT\\",data_dir,useron.alias);
-		delfiles(str,"*.*"); }
-
-	sprintf(str,"%sFILE\\%04u.QWK",data_dir,useron.number);
-	remove(str);
-
-	if(!bi) {
-		batch_download(-1);
-		delfiles(temp_dir,"*.*"); } }
-
-if(useron.rest&FLAG('Q'))
-	useron.qwk|=(QWK_EMAIL|QWK_ALLMAIL|QWK_DELMAIL);
-if(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL)) {
-	sprintf(smb.file,"%sMAIL",data_dir);
-	smb.retry_time=smb_retry_time;
-	if((i=smb_open(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		return; }
-
-	msgs=loadmail(&mail,useron.number,0
-		,useron.qwk&QWK_ALLMAIL ? LM_QWK : LM_UNREAD|LM_QWK);
-
-	if((i=smb_locksmbhdr(&smb))!=0) {			  /* Lock the base, so nobody */
-		if(msgs)
-			FREE(mail);
-		smb_close(&smb);
-		errormsg(WHERE,ERR_LOCK,smb.file,i);	/* messes with the index */
-        return; }
-
-	if((i=smb_getstatus(&smb))!=0) {
-		if(msgs)
-			FREE(mail);
-		smb_close(&smb);
-		errormsg(WHERE,ERR_READ,smb.file,i);
-		return; }
-
-	/* Mark as READ and DELETE */
-	for(l=0;l<msgs;l++) {
-		if(mail[l].time>qwkmail_time)
-			continue;
-		msg.idx.offset=0;
-		if(!loadmsg(&msg,mail[l].number))
-			continue;
-		if(!(msg.hdr.attr&MSG_READ)) {
-			if(thisnode.status==NODE_INUSE)
-                telluser(msg);
-			msg.hdr.attr|=MSG_READ;
-			msg.idx.attr=msg.hdr.attr;
-			smb_putmsg(&smb,&msg); }
-		if(!(msg.hdr.attr&MSG_PERMANENT)
-			&& ((msg.hdr.attr&MSG_KILLREAD && msg.hdr.attr&MSG_READ)
-			|| (useron.qwk&QWK_DELMAIL))) {
-			msg.hdr.attr|=MSG_DELETE;
-			msg.idx.attr=msg.hdr.attr;
-			if((i=smb_putmsg(&smb,&msg))!=0)
-				errormsg(WHERE,ERR_WRITE,smb.file,i);
-			else
-				deleted++; }
-		smb_freemsgmem(&msg);
-		smb_unlockmsghdr(&smb,&msg); }
-
-	if(deleted && sys_misc&SM_DELEMAIL)
-		delmail(useron.number,MAIL_YOUR);
-	smb_close(&smb);
-	if(msgs)
-		FREE(mail); }
-
-}
-
-/****************************************************************************/
-/* QWK mail packet section													*/
-/****************************************************************************/
-void qwk_sec()
-{
-	uchar	str[256],tmp2[256],ch,bi=0
-			,*AttemptedToDownloadQWKpacket="Attempted to download QWK packet";
-	int 	s;
-	uint	i,j,k;
-	ulong	msgcnt,l;
-	time_t	*sav_ptr;
-	file_t	fd;
-
-getusrdirs();
-fd.dir=total_dirs;
-if((sav_ptr=(time_t *)MALLOC(sizeof(time_t)*total_subs))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(time_t)*total_subs);
-	return; }
-for(i=0;i<total_subs;i++)
-	sav_ptr[i]=sub[i]->ptr;
-for(i=0;i<total_prots;i++)
-	if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron))
-		bi++;				/* number of bidirectional protocols configured */
-if(useron.rest&FLAG('Q'))
-	getusrsubs();
-delfiles(temp_dir,"*.*");
-while(online) {
-	if((useron.misc&(WIP|RIP) || !(useron.misc&EXPERT))
-		&& !(useron.rest&FLAG('Q')))
-		menu("QWK");
-	action=NODE_TQWK;
-	ASYNC;
-	bputs(text[QWKPrompt]);
-	strcpy(str,"?UDCSPQ\r");
-	if(bi)
-		strcat(str,"B");
-	ch=getkeys(str,0);
-	if(ch>SP)
-		logch(ch,0);
-	if(sys_status&SS_ABORT || ch=='Q' || ch==CR)
-		break;
-	if(ch=='?') {
-		if((useron.misc&(WIP|RIP) || !(useron.misc&EXPERT))
-			&& !(useron.rest&FLAG('Q')))
-			continue;
-		menu("QWK");
-		continue; }
-	if(ch=='S') {
-		new_scan_cfg(SUB_NSCAN);
-		delfiles(temp_dir,"*.*");
-		continue; }
-	if(ch=='P') {
-		new_scan_ptr_cfg();
-		for(i=0;i<total_subs;i++)
-			sav_ptr[i]=sub[i]->ptr;
-		delfiles(temp_dir,"*.*");
-		continue; }
-	if(ch=='C') {
-		while(online) {
-			CLS;
-			bputs("\1n\1gQWK Settings:\1n\r\n\r\n");
-			bprintf("A) %-30s: %s\r\n"
-				,"Ctrl-A Color Codes"
-				,useron.qwk&QWK_EXPCTLA
-				? "Expand to ANSI" : useron.qwk&QWK_RETCTLA ? "Leave in"
-				: "Strip");
-			bprintf("T) %-30s: %s\r\n"
-				,"Archive Type"
-				,useron.tmpext);
-			bprintf("E) %-30s: %s\r\n"
-				,"Include E-mail Messages"
-				,useron.qwk&QWK_EMAIL ? "Un-read Only"
-				: useron.qwk&QWK_ALLMAIL ? text[Yes] : text[No]);
-			bprintf("I) %-30s: %s\r\n"
-				,"Include File Attachments"
-				,useron.qwk&QWK_ATTACH ? text[Yes] : text[No]);
-			bprintf("D) %-30s: %s\r\n"
-				,"Delete E-mail Automatically"
-				,useron.qwk&QWK_DELMAIL ? text[Yes]:text[No]);
-			bprintf("F) %-30s: %s\r\n"
-				,"Include New Files List"
-				,useron.qwk&QWK_FILES ? text[Yes]:text[No]);
-			bprintf("N) %-30s: %s\r\n"
-				,"Include Index Files"
-				,useron.qwk&QWK_NOINDEX ? text[No]:text[Yes]);
-			bprintf("C) %-30s: %s\r\n"
-				,"Include Control Files"
-				,useron.qwk&QWK_NOCTRL ? text[No]:text[Yes]);
-			bprintf("Y) %-30s: %s\r\n"
-				,"Include Messages from You"
-				,useron.qwk&QWK_BYSELF ? text[Yes]:text[No]);
-			bprintf("Z) %-30s: %s\r\n"
-				,"Include Time Zone (TZ)"
-				,useron.qwk&QWK_TZ ? text[Yes]:text[No]);
-			bprintf("V) %-30s: %s\r\n"
-				,"Include Message Path (VIA)"
-				,useron.qwk&QWK_VIA ? text[Yes]:text[No]);
-			//bprintf("Q) Quit\r\n\r\n");
-			bputs(text[UserDefaultsWhich]);
-			ch=getkeys("AQEDFIOQTYNCZV",0);
-			if(sys_status&SS_ABORT || !ch || ch=='Q')
-				break;
-			switch(ch) {
-				case 'A':
-					if(!(useron.qwk&(QWK_EXPCTLA|QWK_RETCTLA)))
-						useron.qwk|=QWK_EXPCTLA;
-					else if(useron.qwk&QWK_EXPCTLA) {
-						useron.qwk&=~QWK_EXPCTLA;
-						useron.qwk|=QWK_RETCTLA; }
-					else
-						useron.qwk&=~(QWK_EXPCTLA|QWK_RETCTLA);
-					break;
-				case 'T':
-					for(i=0;i<total_fcomps;i++)
-						uselect(1,i,"Archive Types",fcomp[i]->ext,fcomp[i]->ar);
-					s=uselect(0,0,0,0,0);
-					if(s>=0) {
-						strcpy(useron.tmpext,fcomp[s]->ext);
-						putuserrec(useron.number,U_TMPEXT,3,useron.tmpext); }
-					break;
-				case 'E':
-					if(!(useron.qwk&(QWK_EMAIL|QWK_ALLMAIL)))
-						useron.qwk|=QWK_EMAIL;
-					else if(useron.qwk&QWK_EMAIL) {
-						useron.qwk&=~QWK_EMAIL;
-						useron.qwk|=QWK_ALLMAIL; }
-					else
-						useron.qwk&=~(QWK_EMAIL|QWK_ALLMAIL);
-					break;
-				case 'I':
-					useron.qwk^=QWK_ATTACH;
-                    break;
-				case 'D':
-					useron.qwk^=QWK_DELMAIL;
-					break;
-				case 'F':
-					useron.qwk^=QWK_FILES;
-					break;
-				case 'N':   /* NO IDX files */
-					useron.qwk^=QWK_NOINDEX;
-                    break;
-				case 'C':
-					useron.qwk^=QWK_NOCTRL;
-                    break;
-				case 'Z':
-					useron.qwk^=QWK_TZ;
-                    break;
-				case 'V':
-					useron.qwk^=QWK_VIA;
-                    break;
-				case 'Y':   /* Yourself */
-					useron.qwk^=QWK_BYSELF;
-					break; }
-			putuserrec(useron.number,U_QWK,8,ultoa(useron.qwk,str,16)); }
-		delfiles(temp_dir,"*.*");
-		continue; }
-
-
-	if(ch=='B') {   /* Bidirectional QWK and REP packet transfer */
-		sprintf(str,"%s%s.QWK",temp_dir,sys_id);
-		if(!fexist(str) && !pack_qwk(str,&msgcnt,0)) {
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i];
-			remove(str);
-			last_ns_time=ns_time;
-			continue; }
-		bprintf(text[UploadingREP],sys_id);
-		menu("BIPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(tmp2,"Q");
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron)) {
-				sprintf(tmp,"%c",prot[i]->mnemonic);
-				strcat(tmp2,tmp); }
-		ch=getkeys(tmp2,0);
-		if(ch=='Q' || sys_status&SS_ABORT) {
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
-			last_ns_time=ns_time;
-            continue; }
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->bicmd[0] && prot[i]->mnemonic==ch
-				&& chk_ar(prot[i]->ar,useron))
-				break;
-		if(i<total_prots) {
-			batup_total=1;
-			batup_dir[0]=total_dirs;
-			sprintf(batup_name[0],"%s.REP",sys_id);
-			batdn_total=1;
-			batdn_dir[0]=total_dirs;
-			sprintf(batdn_name[0],"%s.QWK",sys_id);
-			if(!create_batchdn_lst() || !create_batchup_lst()
-				|| !create_bimodem_pth()) {
-				batup_total=batdn_total=0;
-				continue; }
-			sprintf(str,"%s%s.QWK",temp_dir,sys_id);
-			sprintf(tmp2,"%s.QWK",sys_id);
-			padfname(tmp2,fd.name);
-			sprintf(str,"%sBATCHDN.LST",node_dir);
-			sprintf(tmp2,"%sBATCHUP.LST",node_dir);
-			j=protocol(cmdstr(prot[i]->bicmd,str,tmp2,NULL),0);
-			batdn_total=batup_total=0;
-			if(prot[i]->misc&PROT_DSZLOG) {
-				if(!checkprotlog(fd)) {
-					logline("D!",AttemptedToDownloadQWKpacket);
-					last_ns_time=ns_time;
-					for(i=0;i<total_subs;i++)
-						sub[i]->ptr=sav_ptr[i]; } /* re-load saved pointers */
-				else {
-					qwk_success(msgcnt,1,0);
-					for(i=0;i<total_subs;i++)
-						sav_ptr[i]=sub[i]->ptr; } }
-			else if(j) {
-				logline("D!",AttemptedToDownloadQWKpacket);
-				last_ns_time=ns_time;
-				for(i=0;i<total_subs;i++)
-					sub[i]->ptr=sav_ptr[i]; }
-			else {
-				qwk_success(msgcnt,1,0);
-				for(i=0;i<total_subs;i++)
-					sav_ptr[i]=sub[i]->ptr; }
-			sprintf(str,"%s%s.QWK",temp_dir,sys_id);
-			remove(str);
-			unpack_rep();
-			delfiles(temp_dir,"*.*");
-			//autohangup();
-			}
-		else {
-			last_ns_time=ns_time;
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i]; } }
-
-	else if(ch=='D') {   /* Download QWK Packet of new messages */
-		sprintf(str,"%s%s.QWK",temp_dir,sys_id);
-		if(!fexist(str) && !pack_qwk(str,&msgcnt,0)) {
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i];
-			last_ns_time=ns_time;
-			remove(str);
-			continue; }
-		if(online==ON_LOCAL) {			/* Local QWK packet creation */
-			bputs(text[EnterPath]);
-			if(!getstr(str,60,K_LINE|K_UPPER)) {
-				for(i=0;i<total_subs;i++)
-					sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
-				last_ns_time=ns_time;
-				continue; }
-			backslashcolon(str);
-			sprintf(tmp2,"%s%s.QWK",str,sys_id);
-			if(fexist(tmp2)) {
-				for(i=0;i<10;i++) {
-					sprintf(tmp2,"%s%s.QW%d",str,sys_id,i);
-					if(!fexist(tmp2))
-						break; }
-				if(i==10) {
-					bputs(text[FileAlreadyThere]);
-					last_ns_time=ns_time;
-					for(i=0;i<total_subs;i++)
-						sub[i]->ptr=sav_ptr[i];
-					continue; } }
-			sprintf(tmp,"%s%s.QWK",temp_dir,sys_id);
-			if(mv(tmp,tmp2,0)) { /* unsuccessful */
-				for(i=0;i<total_subs;i++)
-					sub[i]->ptr=sav_ptr[i];
-				last_ns_time=ns_time; }
-			else {
-				bprintf(text[FileNBytesSent],tmp2,ultoac(flength(tmp2),tmp));
-				qwk_success(msgcnt,0,0);
-				for(i=0;i<total_subs;i++)
-					sav_ptr[i]=sub[i]->ptr; }
-			continue; }
-
-		/***************/
-		/* Send Packet */
-		/***************/
-		menu("DLPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(tmp2,"Q");
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
-				sprintf(tmp,"%c",prot[i]->mnemonic);
-				strcat(tmp2,tmp); }
-		ungetkey(useron.prot);
-		ch=getkeys(tmp2,0);
-		if(ch=='Q' || sys_status&SS_ABORT) {
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i];   /* re-load saved pointers */
-			last_ns_time=ns_time;
-			continue; }
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->dlcmd[0] && prot[i]->mnemonic==ch
-				&& chk_ar(prot[i]->ar,useron))
-				break;
-		if(i<total_prots) {
-			sprintf(str,"%s%s.QWK",temp_dir,sys_id);
-			sprintf(tmp2,"%s.QWK",sys_id);
-			padfname(tmp2,fd.name);
-			j=protocol(cmdstr(prot[i]->dlcmd,str,nulstr,NULL),0);
-			if(prot[i]->misc&PROT_DSZLOG) {
-				if(!checkprotlog(fd)) {
-					last_ns_time=ns_time;
-					for(i=0;i<total_subs;i++)
-						sub[i]->ptr=sav_ptr[i]; } /* re-load saved pointers */
-                else {
-					qwk_success(msgcnt,0,0);
-					for(i=0;i<total_subs;i++)
-						sav_ptr[i]=sub[i]->ptr; } }
-			else if(j) {
-				logline("D!",AttemptedToDownloadQWKpacket);
-				last_ns_time=ns_time;
-				for(i=0;i<total_subs;i++)
-					sub[i]->ptr=sav_ptr[i]; }
-			else {
-				qwk_success(msgcnt,0,0);
-				for(i=0;i<total_subs;i++)
-					sav_ptr[i]=sub[i]->ptr; }
-			autohangup(); }
-		else {	 /* if not valid protocol (hungup?) */
-			for(i=0;i<total_subs;i++)
-				sub[i]->ptr=sav_ptr[i];
-			last_ns_time=ns_time; } }
-
-	else if(ch=='U') { /* Upload REP Packet */
-/*
-		if(useron.rest&FLAG('Q') && useron.rest&FLAG('P')) {
-			bputs(text[R_Post]);
-			continue; }
-*/
-
-		delfiles(temp_dir,"*.*");
-		bprintf(text[UploadingREP],sys_id);
-		for(k=0;k<total_fextrs;k++)
-			if(!stricmp(fextr[k]->ext,useron.tmpext)
-				&& chk_ar(fextr[k]->ar,useron))
-				break;
-		if(k>=total_fextrs) {
-			bputs(text[QWKExtractionFailed]);
-			errorlog("Couldn't extract REP packet - configuration error");
-			continue; }
-
-		if(online==ON_LOCAL) {		/* Local upload of rep packet */
-			bputs(text[EnterPath]);
-			if(!getstr(str,60,K_LINE|K_UPPER))
-				continue;
-			backslashcolon(str);
-			sprintf(tmp,"%s.REP",sys_id);
-			strcat(str,tmp);
-			sprintf(tmp,"%s%s.REP",temp_dir,sys_id);
-			if(!mv(str,tmp,0))
-				unpack_rep();
-			delfiles(temp_dir,"*.*");
-            continue; }
-
-		/******************/
-		/* Receive Packet */
-		/******************/
-		menu("ULPROT");
-		mnemonics(text[ProtocolOrQuit]);
-		strcpy(tmp2,"Q");
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->ulcmd[0] && chk_ar(prot[i]->ar,useron)) {
-				sprintf(tmp,"%c",prot[i]->mnemonic);
-				strcat(tmp2,tmp); }
-		ch=getkeys(tmp2,0);
-		if(ch=='Q' || sys_status&SS_ABORT)
-			continue;
-		for(i=0;i<total_prots;i++)
-			if(prot[i]->ulcmd[0] && prot[i]->mnemonic==ch
-				&& chk_ar(prot[i]->ar,useron))
-				break;
-		if(i>=total_prots)	/* This shouldn't happen */
-			continue;
-		sprintf(str,"%s%s.REP",temp_dir,sys_id);
-		protocol(cmdstr(prot[i]->ulcmd,str,nulstr,NULL),0);
-		unpack_rep();
-		delfiles(temp_dir,"*.*");
-		//autohangup();
-		} }
-delfiles(temp_dir,"*.*");
-FREE(sav_ptr);
-}
-
-void qwksetptr(uint subnum, char *buf, int reset)
-{
-	long	l;
-	ulong	last;
-
-if(buf[2]=='/' && buf[5]=='/') {    /* date specified */
-	l=dstrtounix(buf);
-	sub[subnum]->ptr=getmsgnum(subnum,l);
-	return; }
-l=atol(buf);
-if(l>=0)							  /* ptr specified */
-	sub[subnum]->ptr=l;
-else if(l) {						  /* relative ptr specified */
-	getlastmsg(subnum,&last,0);
-	if(-l>last)
-		sub[subnum]->ptr=0;
-	else
-		sub[subnum]->ptr=last+l; }
-else if(reset)
-	getlastmsg(subnum,&sub[subnum]->ptr,0);
-}
-
-
-/****************************************************************************/
-/* Process a QWK Config line												*/
-/****************************************************************************/
-void qwkcfgline(char *buf,uint subnum)
-{
-	char	str[128];
-	int 	x,y;
-	long	l;
-	ulong	qwk=useron.qwk,last;
-	file_t	f;
-
-sprintf(str,"%.25s",buf);
-strupr(str);
-bprintf("\1n\r\n\1b\1hQWK Control [\1c%s\1b]: \1g%s\r\n"
-	,subnum==INVALID_SUB ? "Mail":sub[subnum]->qwkname,str);
-
-if(subnum!=INVALID_SUB) {					/* Only valid in sub-boards */
-
-	if(!strncmp(str,"DROP ",5)) {              /* Drop from new-scan */
-		l=atol(str+5);
-		if(!l)
-			sub[subnum]->misc&=~SUB_NSCAN;
-		else {
-			x=l/1000;
-			y=l-(x*1000);
-			if(x>=usrgrps || y>=usrsubs[x]) {
-				bprintf(text[QWKInvalidConferenceN],l);
-				sprintf(str,"Invalid conference number %lu",l);
-				logline("Q!",str); }
-			else
-				sub[usrsub[x][y]]->misc&=~SUB_NSCAN; }
-		return; }
-
-	if(!strncmp(str,"ADD YOURS ",10)) {               /* Add to new-scan */
-		sub[subnum]->misc|=(SUB_NSCAN|SUB_YSCAN);
-		qwksetptr(subnum,str+10,0);
-		return; }
-
-	else if(!strncmp(str,"YOURS ",6)) {
-		sub[subnum]->misc|=(SUB_NSCAN|SUB_YSCAN);
-		qwksetptr(subnum,str+6,0);
-		return; }
-
-	else if(!strncmp(str,"ADD ",4)) {               /* Add to new-scan */
-        sub[subnum]->misc|=SUB_NSCAN;
-        sub[subnum]->misc&=~SUB_YSCAN;
-		qwksetptr(subnum,str+4,0);
-		return; }
-
-	if(!strncmp(str,"RESET ",6)) {             /* set msgptr */
-		qwksetptr(subnum,str+6,1);
-		return; }
-
-	if(!strncmp(str,"SUBPTR ",7)) {
-		qwksetptr(subnum,str+7,1);
-		return; }
-	}
-
-if(!strncmp(str,"RESETALL ",9)) {              /* set all ptrs */
-	for(x=0;x<usrgrps;x++)
-		for(y=0;y<usrsubs[x];y++)
-			if(sub[usrsub[x][y]]->misc&SUB_NSCAN)
-				qwksetptr(usrsub[x][y],str+9,1); }
-
-else if(!strncmp(str,"ALLPTR ",7)) {              /* set all ptrs */
-	for(x=0;x<usrgrps;x++)
-		for(y=0;y<usrsubs[x];y++)
-			if(sub[usrsub[x][y]]->misc&SUB_NSCAN)
-				qwksetptr(usrsub[x][y],str+7,1); }
-
-else if(!strncmp(str,"FILES ",6)) {                 /* files list */
-	if(!strncmp(str+6,"ON ",3))
-		useron.qwk|=QWK_FILES;
-	else if(str[8]=='/' && str[11]=='/') {      /* set scan date */
-		useron.qwk|=QWK_FILES;
-		ns_time=dstrtounix(str+6); }
-	else
-		useron.qwk&=~QWK_FILES; }
-
-else if(!strncmp(str,"OWN ",4)) {                   /* message from you */
-	if(!strncmp(str+4,"ON ",3))
-		useron.qwk|=QWK_BYSELF;
-	else
-		useron.qwk&=~QWK_BYSELF;
-	return; }
-
-else if(!strncmp(str,"NDX ",4)) {                   /* include indexes */
-	if(!strncmp(str+4,"OFF ",4))
-		useron.qwk|=QWK_NOINDEX;
-	else
-		useron.qwk&=~QWK_NOINDEX; }
-
-else if(!strncmp(str,"CONTROL ",8)) {               /* exclude ctrl files */
-	if(!strncmp(str+8,"OFF ",4))
-		useron.qwk|=QWK_NOCTRL;
-	else
-		useron.qwk&=~QWK_NOCTRL; }
-
-else if(!strncmp(str,"VIA ",4)) {                   /* include @VIA: */
-	if(!strncmp(str+4,"ON  ",3))
-		useron.qwk|=QWK_VIA;
-	else
-		useron.qwk&=~QWK_VIA; }
-
-else if(!strncmp(str,"TZ ",3)) {                    /* include @TZ: */
-	if(!strncmp(str+3,"ON ",3))
-		useron.qwk|=QWK_TZ;
-    else
-		useron.qwk&=~QWK_TZ; }
-
-else if(!strncmp(str,"ATTACH ",7)) {                /* file attachments */
-	if(!strncmp(str+7,"ON ",3))
-        useron.qwk|=QWK_ATTACH;
-    else
-        useron.qwk&=~QWK_ATTACH; }
-
-else if(!strncmp(str,"DELMAIL ",8)) {               /* delete mail */
-	if(!strncmp(str+8,"ON ",3))
-		useron.qwk|=QWK_DELMAIL;
-	else
-		useron.qwk&=~QWK_DELMAIL; }
-
-else if(!strncmp(str,"CTRL-A ",7)) {                /* Ctrl-a codes  */
-	if(!strncmp(str+7,"KEEP ",5)) {
-		useron.qwk|=QWK_RETCTLA;
-		useron.qwk&=~QWK_EXPCTLA; }
-	else if(!strncmp(str+7,"EXPAND ",7)) {
-		useron.qwk|=QWK_EXPCTLA;
-		useron.qwk&=~QWK_RETCTLA; }
-	else
-		useron.qwk&=~(QWK_EXPCTLA|QWK_RETCTLA); }
-
-else if(!strncmp(str,"MAIL ",5)) {                  /* include e-mail */
-	if(!strncmp(str+5,"ALL ",4)) {
-		useron.qwk|=QWK_ALLMAIL;
-		useron.qwk&=~QWK_EMAIL; }
-	else if(!strncmp(str+5,"ON ",3)) {
-		useron.qwk|=QWK_EMAIL;
-		useron.qwk&=~QWK_ALLMAIL; }
-	else
-		useron.qwk&=~(QWK_ALLMAIL|QWK_EMAIL); }
-
-else if(!strncmp(str,"FREQ ",5)) {                  /* file request */
-	padfname(str+5,f.name);
-	strupr(f.name);
-	for(x=0;x<usrlibs;x++) {
-		for(y=0;y<usrdirs[x];y++)
-			if(findfile(usrdir[x][y],f.name))
-				break;
-		if(y<usrdirs[x])
-			break; }
-	if(x>=usrlibs) {
-		bprintf("\r\n%s",f.name);
-		bputs(text[FileNotFound]); }
-	else {
-		f.dir=usrdir[x][y];
-		getfileixb(&f);
-		f.size=0;
-        getfiledat(&f);
-		if(f.size==-1L)
-			bprintf(text[FileIsNotOnline],f.name);
-		else
-			addtobatdl(f); } }
-
-else bputs("\1r\1h\1iUnrecognized Control Command!\1n\r\n");
-
-if(qwk!=useron.qwk)
-	putuserrec(useron.number,U_QWK,8,ultoa(useron.qwk,tmp,16));
-}
-
-
diff --git a/src/sbbs2/qwk.h b/src/sbbs2/qwk.h
deleted file mode 100644
index d1b48dcb701ad3443dfdffcfc3dce0e79face124..0000000000000000000000000000000000000000
--- a/src/sbbs2/qwk.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* QWK.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-typedef union {
-	uchar	uc[10];
-	ushort	ui[5];
-	ulong	ul[2];
-	float	f[2];
-	double	d[1]; } converter;
-
-#define LEN_QWKBUF	20000	/* 20k buffer for each message */
-#define TAGLINE 	(1<<5)	/* Place tagline at end of qwk message */
-#define TO_QNET 	(1<<6)	/* Sending to hub */
-#define REP 		(1<<7)	/* It's a REP packet */
-#define VIA 		(1<<8)	/* Include VIA */
-#define TZ			(1<<9)	/* Include TZ */
-
-void qwk_success(ulong msgcnt, char bi, char prepack);
-char pack_qwk(char *packet, ulong *msgcnt, int prepack);
-void unpack_qwk(char *packet, uint hubnum);
-char pack_rep(uint hubnum);
-void unpack_rep(void);
-void remove_ctrl_a(char *instr);
-ulong msgtoqwk(smbmsg_t msg, FILE *qwk_fp, int mode, int subnum
-	, int conf);
-char qwktomsg(FILE *qwk_fp, uchar *hdrblk, char fromhub, uint subnum
-	, uint touser);
-void qwkcfgline(char *buf,uint subnum);
-float	ltomsbin(long val);
-int qwk_route(char *inaddr, char *fulladdr);
-int route_circ(char *via, char *id);
-void update_qwkroute(char *via);
-
-extern time_t qwkmail_time;
diff --git a/src/sbbs2/qwknodes/make.bat b/src/sbbs2/qwknodes/make.bat
deleted file mode 100755
index dc1d6ab6016d4faf43a6d74f993009a779bc84f8..0000000000000000000000000000000000000000
--- a/src/sbbs2/qwknodes/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -N -ml -C -I..;..\smb;..\rio qwknodes.c ..\ars.c ..\scfglib1.c ..\scfgvars.c ..\smb\smblib.c
diff --git a/src/sbbs2/qwknodes/qwknodes.c b/src/sbbs2/qwknodes/qwknodes.c
deleted file mode 100644
index 2a063c32cc962bea97660a0ef4600861def1071b..0000000000000000000000000000000000000000
--- a/src/sbbs2/qwknodes/qwknodes.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/* QWKNODES.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Generates QWKnet node list or ROUTE.DAT file from Synchronet message base */
-
-#include "sbbs.h"
-#include "crc32.h"
-#include "crc16.c"
-
-unsigned _stklen=10000;
-smb_t	 smb;
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct date date;
-	struct time curtime;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	if(sys_misc&SM_EURODATE)
-		sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
-			,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
-	else
-		sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-			,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	uchar c;
-
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-void stripctrla(uchar *str)
-{
-	uchar out[256];
-	int i,j;
-
-for(i=j=0;str[i];i++) {
-	if(str[i]==1)
-		i++;
-	else
-		out[j++]=str[i]; }
-out[j]=0;
-strcpy(str,out);
-}
-
-
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stderr));
-}
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-void bail(int code)
-{
-exit(code);
-}
-
-
-char *loadmsgtail(smbmsg_t msg)
-{
-	char	*buf=NULL;
-	ushort	xlat;
-	int 	i;
-	long	l=0,length;
-
-for(i=0;i<msg.hdr.total_dfields;i++) {
-	if(msg.dfield[i].type!=TEXT_TAIL)
-		continue;
-	fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-		,SEEK_SET);
-	fread(&xlat,2,1,smb.sdt_fp);
-	if(xlat!=XLAT_NONE) 		/* no translations supported */
-		continue;
-	length=msg.dfield[i].length-2;
-	if((buf=REALLOC(buf,l+msg.dfield[i].length+1))==NULL)
-		return(buf);
-	l+=fread(buf+l,1,length,smb.sdt_fp);
-	buf[l]=0; }
-return(buf);
-}
-
-
-void gettag(smbmsg_t msg, char *tag)
-{
-	char *buf,*p;
-
-tag[0]=0;
-buf=loadmsgtail(msg);
-if(buf==NULL)
-	return;
-truncsp(buf);
-stripctrla(buf);
-p=strrchr(buf,LF);
-if(!p) p=buf;
-else p++;
-if(!strnicmp(p," � Synchronet � ",16))
-	p+=16;
-if(!strnicmp(p," * Synchronet * ",16))
-    p+=16;
-while(*p && *p<=SP) p++;
-strcpy(tag,p);
-FREE(buf);
-}
-
-
-#define FEED   (1<<0)
-#define LOCAL  (1<<1)
-#define APPEND (1<<2)
-#define TAGS   (1<<3)
-
-#define ROUTE  (1<<1)
-#define NODES  (1<<2)
-#define USERS  (1<<3)
-
-char *usage="\nusage: qwknodes [/opts] cmds"
-			"\n"
-			"\n cmds: r  =  create ROUTE.DAT"
-			"\n       u  =  create USERS.DAT"
-			"\n       n  =  create NODES.DAT"
-			"\n"
-			"\n opts: f  =  format addresses for nodes that feed from this system"
-			"\n       a  =  append existing output files"
-			"\n       t  =  include tag lines in NODES.DAT"
-			"\n       l  =  include local users in USERS.DAT"
-			"\n       m# =  maximum message age set to # days"
-			"\n";
-
-void main(int argc, char **argv)
-{
-	char			str[256],tmp[128],tag[256],addr[256],*p;
-	int 			i,j,mode=0,cmd=0,o_mode,max_age=0;
-	ushort			smm,sbl;
-	ulong			*crc=NULL,curcrc,total_crcs=0,l;
-	FILE			*route,*users,*nodes;
-	time_t			now;
-	read_cfg_text_t txt;
-	smbstatus_t 	status;
-	smbmsg_t		msg;
-
-txt.openerr="\7\r\nError opening %s for read.\r\n";
-txt.reading="\r\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
-txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
-
-fprintf(stderr,"\nSynchronet QWKnet Node/Route/User List  v1.20  "
-	"Developed 1995-1997 Rob Swindell\n");
-
-
-for(i=1;i<argc;i++)
-	for(j=0;argv[i][j];j++)
-		switch(toupper(argv[i][j])) {
-			case '/':
-			case '-':
-				while(argv[i][++j])
-					switch(toupper(argv[i][j])) {
-						case 'F':
-							mode|=FEED;
-							break;
-						case 'L':
-							mode|=LOCAL;
-							break;
-						case 'A':
-							mode|=APPEND;
-							break;
-						case 'T':
-							mode|=TAGS;
-							break;
-						case 'M':
-							j++;
-							max_age=atoi(argv[i]+j);
-							while(isdigit(argv[i][j+1])) j++;
-							break;
-						default:
-							printf(usage);
-							exit(1); }
-				j--;
-				break;
-			case 'R':
-				cmd|=ROUTE;
-				break;
-			case 'U':
-				cmd|=USERS;
-				break;
-			case 'N':
-				cmd|=NODES;
-				break;
-			default:
-				printf(usage);
-				exit(1); }
-
-if(!cmd) {
-	printf(usage);
-	exit(1); }
-
-if(mode&APPEND)
-	o_mode=O_WRONLY|O_CREAT|O_APPEND;
-else
-	o_mode=O_WRONLY|O_CREAT|O_TRUNC;
-
-if(cmd&NODES)
-	if((nodes=fnopen(&i,"NODES.DAT",o_mode))==NULL) {
-		printf("\7\nError opening NODES.DAT\n");
-		exit(1); }
-
-if(cmd&USERS)
-	if((users=fnopen(&i,"USERS.DAT",o_mode))==NULL) {
-		printf("\7\nError opening USERS.DAT\n");
-        exit(1); }
-
-if(cmd&ROUTE)
-	if((route=fnopen(&i,"ROUTE.DAT",o_mode))==NULL) {
-		printf("\7\nError opening ROUTE.DAT\n");
-        exit(1); }
-
-if(!node_dir[0]) {
-	p=getenv("SBBSNODE");
-	if(p==NULL) {
-		printf("\7\nSBBSNODE environment variable not set.\n");
-		exit(1); }
-	strcpy(node_dir,p); }
-
-strupr(node_dir);
-
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,ctrl_dir,40))
-		strcpy(ctrl_dir,str); }
-backslash(ctrl_dir);
-
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str);
-	if(_fullpath(str,data_dir,40))
-		strcpy(data_dir,str); }
-backslash(data_dir);
-read_msgs_cfg(txt);
-
-now=time(NULL);
-smm=crc16("smm");
-sbl=crc16("sbl");
-fprintf(stderr,"\n\n");
-for(i=0;i<total_subs;i++) {
-	if(!(sub[i]->misc&SUB_QNET))
-		continue;
-	fprintf(stderr,"%-*s  %s\n"
-		,LEN_GSNAME,grp[sub[i]->grp]->sname,sub[i]->lname);
-	sprintf(smb.file,"%s%s",sub[i]->data_dir,sub[i]->code);
-	smb.retry_time=30;
-	if((j=smb_open(&smb))!=0) {
-		printf("smb_open returned %d\n",j);
-		continue; }
-	if((j=smb_locksmbhdr(&smb))!=0) {
-		printf("smb_locksmbhdr returned %d\n",j);
-		smb_close(&smb);
-		continue; }
-	if((j=smb_getstatus(&smb))!=0) {
-		printf("smb_getstatus returned %d\n",j);
-		smb_close(&smb);
-		continue; }
-	smb_unlocksmbhdr(&smb);
-	msg.offset=status.total_msgs;
-	if(!msg.offset) {
-		smb_close(&smb);
-		printf("Empty.\n");
-		continue; }
-	while(!kbhit() && !ferror(smb.sid_fp) && msg.offset) {
-		msg.offset--;
-		fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-		if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
-			break;
-		fprintf(stderr,"%-5lu\r",msg.offset+1);
-		if(msg.idx.to==smm || msg.idx.to==sbl)
-			continue;
-		if(max_age && now-msg.idx.time>((ulong)max_age*24UL*60UL*60UL))
-			continue;
-		if((j=smb_lockmsghdr(&smb,&msg))!=0) {
-			printf("smb_lockmsghdr returned %d\n",j);
-			break; }
-		if((j=smb_getmsghdr(&smb,&msg))!=0) {
-			printf("smb_getmsghdr returned %d\n",j);
-            break; }
-		smb_unlockmsghdr(&smb,&msg);
-		if((mode&LOCAL && msg.from_net.type==NET_NONE)
-			|| msg.from_net.type==NET_QWK) {
-			if(msg.from_net.type!=NET_QWK)
-				msg.from_net.addr="";
-			if(cmd&USERS) {
-				sprintf(str,"%s%s",msg.from_net.addr,msg.from);
-				curcrc=crc32(str); }
-			else
-				curcrc=crc32(msg.from_net.addr);
-			for(l=0;l<total_crcs;l++)
-				if(curcrc==crc[l])
-					break;
-			if(l==total_crcs) {
-				total_crcs++;
-				if((crc=(ulong *)REALLOC(crc
-					,sizeof(ulong)*total_crcs))==NULL) {
-					printf("Error allocating %lu bytes\n"
-						,sizeof(ulong)*total_crcs);
-					break; }
-				crc[l]=curcrc;
-				if(cmd&ROUTE && msg.from_net.type==NET_QWK) {
-					strcpy(addr,msg.from_net.addr);
-					if(mode&FEED) {
-						p=strrchr(addr,'/');
-						if(!p)
-							p=addr;
-						else
-							*(p++)=0;
-						sprintf(str,"%s %s:%s%c%s"
-							,unixtodstr(msg.hdr.when_written.time,tmp)
-							,p,sys_id,p==addr ? 0 : '/'
-							,addr);
-						fprintf(route,"%s\r\n",str); }
-					else {
-						p=strrchr(addr,'/');
-						if(p) {
-							*(p++)=0;
-						fprintf(route,"%s %s:%.*s\r\n"
-							,unixtodstr(msg.hdr.when_written.time,str)
-							,p
-							,(uint)(p-addr)
-							,addr); } } }
-				if(cmd&USERS) {
-					if(msg.from_net.type!=NET_QWK)
-						strcpy(str,sys_id);
-					else if(mode&FEED)
-						sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
-					else
-						strcpy(str,msg.from_net.addr);
-					p=strrchr(str,'/');
-                    if(p)
-						fprintf(users,"%-25.25s  %-8.8s  %s  (%s)\r\n"
-							,msg.from,p+1
-							,unixtodstr(msg.hdr.when_written.time,tmp)
-							,str);
-					else
-						fprintf(users,"%-25.25s  %-8.8s  %s\r\n"
-							,msg.from,str
-							,unixtodstr(msg.hdr.when_written.time,tmp)); }
-				if(cmd&NODES && msg.from_net.type==NET_QWK) {
-					if(mode&TAGS)
-						gettag(msg,tag);
-					if(mode&FEED)
-						sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
-					else
-						strcpy(str,msg.from_net.addr);
-					p=strrchr(str,'/');
-					if(p) {
-						if(mode&TAGS)
-							fprintf(nodes,"%-8.8s  %s\r\n"
-								,p+1
-								,tag);
-						else
-							fprintf(nodes,"%-8.8s  %s  (%s)\r\n"
-								,p+1
-								,unixtodstr(msg.hdr.when_written.time,tmp)
-								,str); }
-					else
-						fprintf(nodes,"%-8.8s  %s\r\n"
-							,str
-							,mode&TAGS
-							? tag
-							: unixtodstr(msg.hdr.when_written.time,tmp)); }
-				} }
-		smb_freemsgmem(&msg); }
-
-	smb_close(&smb);
-	if(kbhit()) {
-		getch();
-		fprintf(stderr,"Key pressed.\n");
-		break; } }
-fprintf(stderr,"Done.\n");
-}
-
diff --git a/src/sbbs2/qwktomsg.c b/src/sbbs2/qwktomsg.c
deleted file mode 100644
index e3d43dd12b797b0688c869a7f4fd5ad6939abd71..0000000000000000000000000000000000000000
--- a/src/sbbs2/qwktomsg.c
+++ /dev/null
@@ -1,350 +0,0 @@
-#line 1 "QWKTOMSG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-
-/****************************************************************************/
-/* Converts a QWK message packet into a message. The 'qwkbuf' pointer       */
-/* points to the message header and 'str' is the file to output to.         */
-/* Returns the 1 on success or 0 if failure.								*/
-/****************************************************************************/
-char qwktomsg(FILE *qwk_fp, uchar *hdrblk, char fromhub, uint subnum
-	, uint touser)
-{
-	uchar	str[256],*body,*tail,col=0,lastch=0,*p,*lzhbuf,qwkbuf[128];
-	int 	file,i,j,k,lzh=0,storage,skip=0;
-	ushort	xlat;
-	long	l,bodylen,taillen,length;
-	ulong	crc,block,blocks;
-	smbmsg_t	msg;
-
-memset(&msg,0,sizeof(smbmsg_t));		/* Initialize message header */
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=smb_ver();
-
-blocks=atol(hdrblk+116);
-if(blocks<2)
-	return(0);
-
-if(subnum!=INVALID_SUB
-	&& (hdrblk[0]=='*' || hdrblk[0]=='+' || sub[subnum]->misc&SUB_PONLY))
-	msg.idx.attr|=MSG_PRIVATE;
-if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_AONLY)
-	msg.idx.attr|=MSG_ANONYMOUS;
-if(subnum==INVALID_SUB && sys_misc&SM_DELREADM)
-	msg.idx.attr|=MSG_KILLREAD;
-if((fromhub || useron.rest&FLAG('Q')) &&
-	(hdrblk[0]=='*' || hdrblk[0]=='-' || hdrblk[0]=='`'))
-	msg.idx.attr|=MSG_READ;
-
-if(subnum!=INVALID_SUB && !fromhub && sub[subnum]->mod_ar[0]
-	&& chk_ar(sub[subnum]->mod_ar,useron))
-	msg.idx.attr|=MSG_MODERATED;
-if(subnum!=INVALID_SUB && !fromhub && sub[subnum]->misc&SUB_SYSPERM
-	&& sub_op(subnum))
-	msg.idx.attr|=MSG_PERMANENT;
-
-msg.hdr.attr=msg.idx.attr;
-
-date.da_mon=((hdrblk[8]&0xf)*10)+(hdrblk[9]&0xf);
-date.da_day=((hdrblk[11]&0xf)*10)+(hdrblk[12]&0xf);
-date.da_year=((hdrblk[14]&0xf)*10)+(hdrblk[15]&0xf);
-if(date.da_year<Y2K_2DIGIT_WINDOW)
-	date.da_year+=100;
-date.da_year+=1900;
-curtime.ti_hour=((hdrblk[16]&0xf)*10)+(hdrblk[17]&0xf);
-curtime.ti_min=((hdrblk[19]&0xf)*10)+(hdrblk[20]&0xf);
-curtime.ti_sec=0;
-msg.hdr.when_written.time=dostounix(&date,&curtime);
-if(!(useron.rest&FLAG('Q')) && !fromhub)
-	msg.hdr.when_written.zone=sys_timezone;
-msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_imported.zone=sys_timezone;
-
-hdrblk[116]=0; /* don't bleed number-of-blocks and re-msg-num fields together */
-msg.hdr.thread_orig=atol(hdrblk+108);
-
-if((uint)subnum==INVALID_SUB) { 		/* E-mail */
-	msg.idx.to=touser;
-
-/***					Unnecessary code in v2.10a
-	if(!touser) {
-		sprintf(str,"%25.25s",hdrblk+21);
-		truncsp(str);
-		for(i=0;i<total_qhubs;i++)
-			if(!stricmp(qhub[i]->id,str))
-				break;
-		if(i==total_qhubs) {
-			errormsg(WHERE,ERR_CHK,str,0);
-			return(0); }
-		smb_hfield(&msg,RECIPIENT,strlen(str),str); }
-	else {
-***/
-		username(touser,str);
-		smb_hfield(&msg,RECIPIENT,strlen(str),str);
-		sprintf(str,"%u",touser);
-		smb_hfield(&msg,RECIPIENTEXT,strlen(str),str); }
-
-else {
-	sprintf(str,"%25.25s",hdrblk+21);     /* To user */
-	truncsp(str);
-	smb_hfield(&msg,RECIPIENT,strlen(str),str);
-	strlwr(str);
-	msg.idx.to=crc16(str); }
-
-fread(qwkbuf,1,128,qwk_fp);
-
-if(useron.rest&FLAG('Q') || fromhub) {      /* QWK Net */
-	if(!strnicmp(qwkbuf,"@VIA:",5)) {
-		p=strchr(qwkbuf,'\xe3');
-		if(p) {
-			*p=0;
-			skip=strlen(qwkbuf)+1; }
-		truncsp(qwkbuf);
-		p=qwkbuf+5; 					/* Skip "@VIA:" */
-		while(*p && *p<=SP) p++;		/* Skip any spaces */
-		if(route_circ(p,sys_id)) {
-			smb_freemsgmem(&msg);
-			bprintf("\r\nCircular message path: %s\r\n",p);
-			sprintf(str,"Circular message path: %s from %s"
-				,p,fromhub ? qhub[fromhub-1]->id:useron.alias);
-			errorlog(str);
-			return(0); }
-		sprintf(str,"%s/%s"
-			,fromhub ? qhub[fromhub-1]->id : useron.alias,p);
-		strupr(str);
-		update_qwkroute(str); }
-	else {
-		if(fromhub)
-			strcpy(str,qhub[fromhub-1]->id);
-		else
-			strcpy(str,useron.alias); }
-	strupr(str);
-	j=NET_QWK;
-	smb_hfield(&msg,SENDERNETTYPE,2,&j);
-	smb_hfield(&msg,SENDERNETADDR,strlen(str),str);
-	sprintf(str,"%25.25s",hdrblk+46);  /* From user */
-	truncsp(str);
-	if(!strnicmp(qwkbuf+skip,"@TZ:",4)) {
-		p=strchr(qwkbuf+skip,'\xe3');
-		i=skip;
-		if(p) {
-			*p=0;
-			skip+=strlen(qwkbuf+i)+1; }
-		p=qwkbuf+i+4;					/* Skip "@TZ:" */
-		while(*p && *p<=SP) p++;		/* Skip any spaces */
-		msg.hdr.when_written.zone=(short)ahtoul(p); }
-	}
-else {
-	sprintf(str,"%u",useron.number);
-	smb_hfield(&msg,SENDEREXT,strlen(str),str);
-	if((uint)subnum!=INVALID_SUB && sub[subnum]->misc&SUB_NAME)
-		strcpy(str,useron.name);
-	else
-		strcpy(str,useron.alias); }
-
-smb_hfield(&msg,SENDER,strlen(str),str);
-if((uint)subnum==INVALID_SUB) {
-	if(useron.rest&FLAG('Q') || fromhub)
-		msg.idx.from=0;
-	else
-		msg.idx.from=useron.number; }
-else {
-	strlwr(str);
-	msg.idx.from=crc16(str); }
-
-sprintf(str,"%25.25s",hdrblk+71);   /* Subject */
-truncsp(str);
-remove_re(str);
-smb_hfield(&msg,SUBJECT,strlen(str),str);
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-/********************************/
-/* Convert the QWK message text */
-/********************************/
-
-bodylen=0;
-if((body=LMALLOC((blocks-1L)*128L*2L))==NULL) {
-	smb_freemsgmem(&msg);
-	errormsg(WHERE,ERR_ALLOC,"QWK msg",(blocks-1L)*128L*2L);
-	return(0); }
-
-taillen=0;
-if((tail=LMALLOC((blocks-1L)*128L))==NULL) {
-	LFREE(body);
-	smb_freemsgmem(&msg);
-	errormsg(WHERE,ERR_ALLOC,"QWK msg",(blocks-1L)*128L);
-    return(0); }
-
-for(block=1;block<blocks;block++) {
-	if(block>1)
-		if(!fread(qwkbuf,1,128,qwk_fp))
-			break;
-	for(k=skip;k<128;k++,skip=0) {
-		if(qwkbuf[k]==0)
-			continue;
-		if(!taillen && qwkbuf[k]==SP && col==3 && bodylen>=3
-			&& body[bodylen-3]=='-' && body[bodylen-2]=='-'
-			&& body[bodylen-1]=='-') {
-			bodylen-=3;
-			strcpy(tail,"--- ");
-			taillen=4;
-			col++;
-			continue; }
-		if(qwkbuf[k]==0xE3) {		/* expand 0xe3 to crlf */
-			if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-'
-				&& body[bodylen-2]=='-' && body[bodylen-1]=='-') {
-				bodylen-=3;
-				strcpy(tail,"---");
-				taillen=3; }
-			col=0;
-			if(taillen) {
-				tail[taillen++]=CR;
-				tail[taillen++]=LF; }
-			else {
-				body[bodylen++]=CR;
-				body[bodylen++]=LF; }
-			continue; }
-		if(!fromhub && qwkbuf[k]==7 && useron.rest&FLAG('B'))   /* beep res */
-			continue;
-		if(!fromhub && (qwkbuf[k]==1 || qwkbuf[k]==ESC) /* ANSI restriction */
-			&& useron.rest&FLAG('A'))
-			continue;
-		if(qwkbuf[k]!=1 && lastch!=1)
-			col++;
-		if(lastch==1 && !validattr(qwkbuf[k])) {
-			if(taillen) taillen--;
-			else		bodylen--;
-			lastch=0;
-			continue; }
-		lastch=qwkbuf[k];
-		if(taillen)
-			tail[taillen++]=qwkbuf[k];
-		else
-			body[bodylen++]=qwkbuf[k]; } }
-
-while(bodylen && body[bodylen-1]==SP) bodylen--; /* remove trailing spaces */
-if(bodylen>=2 && body[bodylen-2]==CR && body[bodylen-1]==LF)
-	bodylen-=2;
-
-while(taillen && tail[taillen-1]<=SP) taillen--; /* remove trailing garbage */
-
-/*****************/
-/* Calculate CRC */
-/*****************/
-
-if(smb.status.max_crcs) {
-	crc=0xffffffffUL;
-	for(l=0;l<bodylen;l++)
-		crc=ucrc32(body[l],crc);
-	crc=~crc;
-
-	/*******************/
-	/* Check for dupes */
-	/*******************/
-
-	j=smb_addcrc(&smb,crc);
-	if(j) {
-		if(j==1) {
-			bprintf("\r\nDuplicate message\r\n");
-			logline(subnum==INVALID_SUB ? "E!":"P!","Duplicate message"); }
-		else
-			errormsg(WHERE,ERR_CHK,smb.file,j);
-
-		smb_freemsgmem(&msg);
-		LFREE(body);
-		LFREE(tail);
-		return(0); } }
-
-bputs(text[WritingIndx]);
-
-/*************************************/
-/* Write SMB message header and text */
-/*************************************/
-
-if(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_LZH && bodylen
-	&& bodylen+2+taillen+2>=SDT_BLOCK_LEN
-	&& (lzhbuf=(char *)LMALLOC(bodylen*2))!=NULL) {
-	length=lzh_encode((uchar *)body,bodylen,(uchar *)lzhbuf);
-	if(length>1L
-		&& smb_datblocks(length+4L+taillen+2L)
-			<smb_datblocks(bodylen+2L+taillen+2L)) {
-		bodylen=length; 	/* Compressable */
-		length+=4L;
-		lzh=1;
-		LFREE(body);
-		body=lzhbuf; }
-	else {					/* Non-compressable */
-		length=bodylen+2L;
-		LFREE(lzhbuf); } }
-else
-	length=bodylen+2L;					 /* +2 for translation string */
-
-if(taillen)
-	length+=taillen+2L;
-
-if(length&0xfff00000UL) {
-	errormsg(WHERE,ERR_LEN,"REP msg",length);
-	smb_freemsgmem(&msg);
-	LFREE(body);
-	LFREE(tail);
-	return(0); }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	FREE(body);
-	FREE(tail);
-	return(0); }
-
-if(smb.status.attr&SMB_HYPERALLOC) {
-	msg.hdr.offset=smb_hallocdat(&smb);
-	storage=SMB_HYPERALLOC; }
-else {
-	if((i=smb_open_da(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,i);
-		FREE(body);
-		FREE(tail);
-		return(0); }
-	if((subnum==INVALID_SUB && sys_misc&SM_FASTMAIL)
-		|| (subnum!=INVALID_SUB && sub[subnum]->misc&SUB_FAST)) {
-		msg.hdr.offset=smb_fallocdat(&smb,length,1);
-		storage=SMB_FASTALLOC; }
-	else {
-		msg.hdr.offset=smb_allocdat(&smb,length,1);
-		storage=SMB_SELFPACK; }
-	smb_close_da(&smb); }
-
-if(msg.hdr.offset && msg.hdr.offset<1L) {
-	smb_unlocksmbhdr(&smb);
-	errormsg(WHERE,ERR_READ,smb.file,msg.hdr.offset);
-	smb_freemsgmem(&msg);
-	FREE(body);
-	FREE(tail); }
-fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
-if(lzh) {
-	xlat=XLAT_LZH;
-	fwrite(&xlat,2,1,smb.sdt_fp); }
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-fwrite(body,bodylen,1,smb.sdt_fp);
-smb_dfield(&msg,TEXT_BODY,bodylen+2+(lzh ? 2:0));
-if(taillen) {
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	fwrite(tail,taillen,1,smb.sdt_fp);
-	smb_dfield(&msg,TEXT_TAIL,taillen+2); }
-fflush(smb.sdt_fp);
-smb_unlocksmbhdr(&smb);
-
-if((i=smb_addmsghdr(&smb,&msg,storage))!=0)
-	errormsg(WHERE,ERR_WRITE,smb.file,i);
-
-smb_freemsgmem(&msg);
-
-LFREE(body);
-LFREE(tail);
-
-return(1);
-}
diff --git a/src/sbbs2/readmsgs.c b/src/sbbs2/readmsgs.c
deleted file mode 100644
index ceaa73bc29d9558f372219ccc28205b16325c14c..0000000000000000000000000000000000000000
--- a/src/sbbs2/readmsgs.c
+++ /dev/null
@@ -1,1070 +0,0 @@
-#line 1 "READMSGS.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "post.h"
-
-char movemsg(smbmsg_t msg, uint subnum);
-void editmsg(smbmsg_t *msg, uint subnum);
-
-int sub_op(uint subnum)
-{
-return(SYSOP || (sub[subnum]->op_ar[0] && chk_ar(sub[subnum]->op_ar,useron)));
-}
-
-
-void listmsgs(int subnum, post_t HUGE16 *post, long i, long posts)
-{
-	char ch;
-	int j;
-	smbmsg_t msg;
-
-
-bputs(text[MailOnSystemLstHdr]);
-msg.total_hfields=0;
-while(i<posts && !msgabort()) {
-	if(msg.total_hfields)
-		smb_freemsgmem(&msg);
-	msg.total_hfields=0;
-	msg.idx.offset=post[i].offset;
-	if(!loadmsg(&msg,post[i].number))
-		break;
-	smb_unlockmsghdr(&smb,&msg);
-	if(msg.hdr.attr&MSG_DELETE)
-		ch='-';
-	else if((!stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name))
-		&& !(msg.hdr.attr&MSG_READ))
-		ch='!';
-	else if(msg.hdr.number>sub[subnum]->ptr)
-		ch='*';
-	else
-		ch=' ';
-	bprintf(text[SubMsgLstFmt],(long)i+1
-		,msg.hdr.attr&MSG_ANONYMOUS && !sub_op(subnum)
-		? text[Anonymous] : msg.from
-		,msg.to
-		,ch
-		,msg.subj);
-	smb_freemsgmem(&msg);
-	msg.total_hfields=0;
-	i++; }
-}
-
-char *binstr(uchar *buf, ushort length)
-{
-	static char str[128];
-	char tmp[128];
-	int i;
-
-str[0]=0;
-for(i=0;i<length;i++)
-	if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
-		break;
-if(i==length)		/* not binary */
-	return(buf);
-for(i=0;i<length;i++) {
-	sprintf(tmp,"%02X ",buf[i]);
-	strcat(str,tmp); }
-return(str);
-}
-
-
-void msghdr(smbmsg_t msg)
-{
-	int i;
-
-for(i=0;i<msg.total_hfields;i++)
-	bprintf("hfield[%u].type       %02Xh\r\n"
-			"hfield[%u].length     %d\r\n"
-			"hfield[%u]_dat        %s\r\n"
-			,i,msg.hfield[i].type
-			,i,msg.hfield[i].length
-			,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
-}
-
-/****************************************************************************/
-/****************************************************************************/
-post_t HUGE16 *loadposts(ulong *posts, uint subnum, ulong ptr, uint mode)
-{
-	char name[128];
-	ushort aliascrc,namecrc,sysop;
-	int i,file,skip;
-	ulong l=0,total,alloc_len;
-	smbmsg_t msg;
-	idxrec_t idx;
-	post_t HUGE16 *post;
-
-if(posts==NULL)
-	return(NULL);
-
-(*posts)=0;
-
-if((i=smb_locksmbhdr(&smb))!=0) {				/* Be sure noone deletes or */
-	errormsg(WHERE,ERR_LOCK,smb.file,i);		/* adds while we're reading */
-	return(NULL); }
-
-total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); /* total msgs in sub */
-
-if(!total) {			/* empty */
-	smb_unlocksmbhdr(&smb);
-	return(NULL); }
-
-strcpy(name,useron.name);
-strlwr(name);
-namecrc=crc16(name);
-strcpy(name,useron.alias);
-strlwr(name);
-aliascrc=crc16(name);
-sysop=crc16("sysop");
-
-rewind(smb.sid_fp);
-
-alloc_len=sizeof(post_t)*total;
-#ifdef __OS2__
-	while(alloc_len%4096)
-		alloc_len++;
-#endif
-if((post=(post_t HUGE16 *)LMALLOC(alloc_len))==NULL) {	/* alloc for max */
-	smb_unlocksmbhdr(&smb);
-	errormsg(WHERE,ERR_ALLOC,smb.file,sizeof(post_t *)*sub[subnum]->maxmsgs);
-	return(NULL); }
-while(!feof(smb.sid_fp)) {
-	skip=0;
-	if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-
-	if(idx.number<=ptr)
-		continue;
-
-	if(idx.attr&MSG_READ && mode&LP_UNREAD) /* Skip read messages */
-        continue;
-
-	if(idx.attr&MSG_DELETE) {		/* Pre-flagged */
-		if(mode&LP_REP) 			/* Don't include deleted msgs in REP pkt */
-			continue;
-		if(!(sys_misc&SM_SYSVDELM)) /* Noone can view deleted msgs */
-			continue;
-		if(!(sys_misc&SM_USRVDELM)	/* Users can't view deleted msgs */
-			&& !sub_op(subnum)) 	/* not sub-op */
-			continue;
-		if(!sub_op(subnum)			/* not sub-op */
-			&& idx.from!=namecrc && idx.from!=aliascrc) /* not for you */
-			continue; }
-
-	if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED)
-		&& (mode&LP_REP || !sub_op(subnum)))
-		break;
-
-	if(idx.attr&MSG_PRIVATE && !(mode&LP_PRIVATE)
-		&& !sub_op(subnum) && !(useron.rest&FLAG('Q'))) {
-		if(idx.to!=namecrc && idx.from!=namecrc
-			&& idx.to!=aliascrc && idx.from!=aliascrc
-			&& (useron.number!=1 || idx.to!=sysop))
-			continue;
-		if(!smb_lockmsghdr(&smb,&msg)) {
-			if(!smb_getmsghdr(&smb,&msg)) {
-				if(stricmp(msg.to,useron.alias)
-					&& stricmp(msg.from,useron.alias)
-					&& stricmp(msg.to,useron.name)
-					&& stricmp(msg.from,useron.name)
-					&& (useron.number!=1 || stricmp(msg.to,"sysop")
-					|| msg.from_net.type))
-					skip=1;
-				smb_freemsgmem(&msg); }
-			smb_unlockmsghdr(&smb,&msg); }
-		if(skip)
-            continue; }
-
-
-	if(!(mode&LP_BYSELF) && (idx.from==namecrc || idx.from==aliascrc)) {
-		msg.idx=idx;
-		if(!smb_lockmsghdr(&smb,&msg)) {
-			if(!smb_getmsghdr(&smb,&msg)) {
-				if(!stricmp(msg.from,useron.alias)
-					|| !stricmp(msg.from,useron.name))
-					skip=1;
-				smb_freemsgmem(&msg); }
-			smb_unlockmsghdr(&smb,&msg); }
-		if(skip)
-			continue; }
-
-	if(!(mode&LP_OTHERS)) {
-		if(idx.to!=namecrc && idx.to!=aliascrc
-			&& (useron.number!=1 || idx.to!=sysop))
-			continue;
-		msg.idx=idx;
-		if(!smb_lockmsghdr(&smb,&msg)) {
-			if(!smb_getmsghdr(&smb,&msg)) {
-				if(stricmp(msg.to,useron.alias) && stricmp(msg.to,useron.name)
-					&& (useron.number!=1 || stricmp(msg.to,"sysop")
-					|| msg.from_net.type))
-					skip=1;
-				smb_freemsgmem(&msg); }
-			smb_unlockmsghdr(&smb,&msg); }
-		if(skip)
-            continue; }
-
-	post[l].offset=idx.offset;
-	post[l].number=idx.number;
-	post[l].to=idx.to;
-	post[l].from=idx.from;
-	post[l].subj=idx.subj;
-	l++; }
-smb_unlocksmbhdr(&smb);
-if(!l) {
-	LFREE(post);
-	post=NULL; }
-(*posts)=l;
-return(post);
-}
-
-
-/****************************************************************************/
-/* Reads posts on subboard sub. 'mode' determines new-posts only, browse,   */
-/* or continuous read.                                                      */
-/* Returns 0 if normal completion, 1 if aborted.                            */
-/* Called from function main_sec                                            */
-/****************************************************************************/
-char scanposts(uint subnum, char mode, char *find)
-{
-	char	str[256],str2[256],str3[256],reread=0,mismatches=0
-			,done=0,domsg=1,HUGE16 *buf,*p;
-	int 	file,i,j,usub,ugrp,reads=0;
-	uint	lp=0;
-	long	curpost;
-	ulong	msgs,last,posts,l;
-	post_t	HUGE16 *post;
-	smbmsg_t	msg;
-
-cursubnum=subnum;	/* for ARS */
-if(!chk_ar(sub[subnum]->read_ar,useron)) {
-	bprintf("\1n\r\nYou can't read messages on %s %s\r\n"
-			,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
-	return(0); }
-msg.total_hfields=0;				/* init to NULL, specify not-allocated */
-if(!(mode&SCAN_CONST))
-	lncntr=0;
-if((msgs=getlastmsg(subnum,&last,0))==0) {
-	if(mode&(SCAN_NEW|SCAN_TOYOU))
-		bprintf(text[NScanStatusFmt]
-			,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,0L,0L);
-	else
-		bprintf(text[NoMsgsOnSub]
-			,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
-	return(0); }
-if(mode&SCAN_NEW && sub[subnum]->ptr>=last && !(mode&SCAN_BACK)) {
-	if(sub[subnum]->ptr>last)
-		sub[subnum]->ptr=sub[subnum]->last=last;
-	bprintf(text[NScanStatusFmt]
-		,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,0L,msgs);
-	return(0); }
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
-	return(0); }
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-
-if(!(mode&SCAN_TOYOU)
-	&& (!mode || mode&SCAN_FIND || !(sub[subnum]->misc&SUB_YSCAN)))
-	lp=LP_BYSELF|LP_OTHERS;
-if(mode&SCAN_TOYOU)
-	lp|=LP_UNREAD;
-post=loadposts(&posts,subnum,0,lp);
-if(mode&SCAN_NEW) { 		  /* Scanning for new messages */
-	for(curpost=0;curpost<posts;curpost++)
-		if(sub[subnum]->ptr<post[curpost].number)
-			break;
-	bprintf(text[NScanStatusFmt]
-		,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts-curpost,msgs);
-	if(!posts) {		  /* no messages at all */
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		return(0); }
-	if(curpost==posts) {  /* no new messages */
-        if(!(mode&SCAN_BACK)) {
-			if(post)
-				LFREE(post);
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-			return(0); }
-		curpost=posts-1; } }
-else {
-	if(mode&SCAN_TOYOU)
-		bprintf(text[NScanStatusFmt]
-		   ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts,msgs);
-	if(!posts) {
-		if(!(mode&SCAN_TOYOU))
-			bprintf(text[NoMsgsOnSub]
-				,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-        return(0); }
-	if(mode&SCAN_FIND) {
-		bprintf(text[SearchSubFmt]
-			,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts);
-		domsg=1;
-		curpost=0; }
-	else if(mode&SCAN_TOYOU)
-		curpost=0;
-	else {
-		for(curpost=0;curpost<posts;curpost++)
-			if(post[curpost].number>=sub[subnum]->last)
-				break;
-		if(curpost==posts)
-			curpost=posts-1;
-
-		domsg=1; } }
-
-if(useron.misc&RIP)
-	menu("MSGSCAN");
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-	return(0); }
-if((i=smb_getstatus(&smb))!=0) {
-	smb_close(&smb);
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-	return(0); }
-smb_unlocksmbhdr(&smb);
-last=smb.status.last_msg;
-
-action=NODE_RMSG;
-if(mode&SCAN_CONST) {   /* update action */
-    getnodedat(node_num,&thisnode,1);
-    thisnode.action=NODE_RMSG;
-    putnodedat(node_num,thisnode); }
-while(online && !done) {
-
-	action=NODE_RMSG;
-	if((i=heapcheck())!=_HEAPOK) {
-		errormsg(WHERE,ERR_CHK,"heap",i);
-		break; }
-
-	if(mode&(SCAN_CONST|SCAN_FIND) && sys_status&SS_ABORT)
-		break;
-
-	if(post==NULL)	/* Been unloaded */
-		post=loadposts(&posts,subnum,0,lp);   /* So re-load */
-
-	if(!posts) {
-        done=1;
-        continue; }
-
-	while(curpost>=posts) curpost--;
-
-    for(ugrp=0;ugrp<usrgrps;ugrp++)
-        if(usrgrp[ugrp]==sub[subnum]->grp)
-            break;
-    for(usub=0;usub<usrsubs[ugrp];usub++)
-        if(usrsub[ugrp][usub]==subnum)
-            break;
-    usub++;
-    ugrp++;
-
-	msg.idx.offset=post[curpost].offset;
-	msg.idx.number=post[curpost].number;
-	msg.idx.to=post[curpost].to;
-	msg.idx.from=post[curpost].from;
-	msg.idx.subj=post[curpost].subj;
-
-	if((i=smb_locksmbhdr(&smb))!=0) {
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-		break; }
-	if((i=smb_getstatus(&smb))!=0) {
-		smb_unlocksmbhdr(&smb);
-		errormsg(WHERE,ERR_READ,smb.file,i);
-		break; }
-	smb_unlocksmbhdr(&smb);
-
-	if(smb.status.last_msg!=last) { 	/* New messages */
-		last=smb.status.last_msg;
-		if(post) {
-			LFREE((void *)post); }
-		post=loadposts(&posts,subnum,0,lp);   /* So re-load */
-		if(!posts)
-			break;
-		for(curpost=0;curpost<posts;curpost++)
-			if(post[curpost].number==msg.idx.number)
-				break;
-		if(curpost>(posts-1))
-			curpost=(posts-1);
-		continue; }
-
-	if(msg.total_hfields)
-		smb_freemsgmem(&msg);
-	msg.total_hfields=0;
-
-	if(!loadmsg(&msg,post[curpost].number)) {
-		if(mismatches>5) {	/* We can't do this too many times in a row */
-			errormsg(WHERE,ERR_CHK,smb.file,post[curpost].number);
-			break; }
-		if(post)
-			LFREE(post);
-		post=loadposts(&posts,subnum,0,lp);
-		if(!posts)
-			break;
-		if(curpost>(posts-1))
-			curpost=(posts-1);
-		mismatches++;
-		continue; }
-	smb_unlockmsghdr(&smb,&msg);
-
-	mismatches=0;
-
-	if(domsg) {
-
-		if(!reread && mode&SCAN_FIND) { 			/* Find text in messages */
-			buf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS);
-			if(!buf) {
-				if(curpost<posts-1) curpost++;
-				else done=1;
-                continue; }
-			strupr((char *)buf);
-			if(!strstr((char *)buf,find) && !strstr(msg.subj,find)) {
-				FREE(buf);
-				if(curpost<posts-1) curpost++;
-				else done=1;
-                continue; }
-			FREE(buf); }
-
-		if(mode&SCAN_CONST)
-			bprintf(text[ZScanPostHdr],ugrp,usub,curpost+1,posts);
-
-		if(!reads && mode)
-            CRLF;
-
-		show_msg(msg
-			,msg.from_ext && !strcmp(msg.from_ext,"1") && !msg.from_net.type
-				? 0:P_NOATCODES);
-
-		reads++;	/* number of messages actually read during this sub-scan */
-
-		/* Message is to this user and hasn't been read, so flag as read */
-		if((!stricmp(msg.to,useron.name) || !stricmp(msg.to,useron.alias)
-			|| (useron.number==1 && !stricmp(msg.to,"sysop")
-			&& !msg.from_net.type))
-			&& !(msg.hdr.attr&MSG_READ)) {
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;
-			if(!smb_locksmbhdr(&smb)) { 			  /* Lock the entire base */
-				if(loadmsg(&msg,msg.idx.number)) {
-					msg.hdr.attr|=MSG_READ;
-					msg.idx.attr=msg.hdr.attr;
-					if((i=smb_putmsg(&smb,&msg))!=0)
-						errormsg(WHERE,ERR_WRITE,smb.file,i);
-					smb_unlockmsghdr(&smb,&msg); }
-				smb_unlocksmbhdr(&smb); }
-			if(!msg.total_hfields) {				/* unsuccessful reload */
-				domsg=0;
-				continue; } }
-
-		sub[subnum]->last=post[curpost].number;
-
-		if(sub[subnum]->ptr<post[curpost].number && !(mode&SCAN_TOYOU)) {
-            posts_read++;
-			sub[subnum]->ptr=post[curpost].number; } }
-	else domsg=1;
-    if(mode&SCAN_CONST) {
-		if(curpost<posts-1) curpost++;
-            else done=1;
-        continue; }
-	if(useron.misc&WIP)
-		menu("MSGSCAN");
-	ASYNC;
-	bprintf(text[ReadingSub],ugrp,grp[sub[subnum]->grp]->sname
-		,usub,sub[subnum]->sname,curpost+1,posts);
-	sprintf(str,"ABCDFILMPQRTY?<>[]{}-+.,");
-	if(sub_op(subnum))
-		strcat(str,"O");
-	reread=0;
-	l=getkeys(str,posts);
-	if(l&0x80000000L) {
-		if((long)l==-1) { /* ctrl-c */
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			if(post)
-				LFREE(post);
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-            return(1); }
-		curpost=(l&~0x80000000L)-1;
-		reread=1;
-        continue; }
-	switch(l) {
-		case 'A':   /* Reply to last message */
-			domsg=0;
-			if(!chk_ar(sub[subnum]->post_ar,useron)) {
-				bputs(text[CantPostOnSub]);
-				break; }
-			quotemsg(msg,0);
-			if(post)
-				LFREE(post);
-			post=NULL;
-			postmsg(subnum,&msg,WM_QUOTE);
-//			  post=loadposts(&posts,subnum,0,lp);
-			if(mode&SCAN_TOYOU)
-				domsg=1;
-			break;
-		case 'B':   /* Skip sub-board */
-			if(mode&SCAN_NEW && !noyes(text[RemoveFromNewScanQ]))
-				sub[subnum]->misc&=~SUB_NSCAN;
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			if(post)
-				LFREE(post);
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-			return(0);
-		case 'C':   /* Continuous */
-			mode|=SCAN_CONST;
-			if(curpost<posts-1) curpost++;
-			else done=1;
-			break;
-		case 'D':       /* Delete message on sub-board */
-			domsg=0;
-			if(!sub_op(subnum) && !(sub[subnum]->misc&SUB_DEL)) {
-				bputs(text[CantDeletePosts]);
-				break; }
-			if(!sub_op(subnum)) {
-				if(stricmp(sub[subnum]->misc&SUB_NAME
-					? useron.name : useron.alias, msg.from)
-				&& stricmp(sub[subnum]->misc&SUB_NAME
-					? useron.name : useron.alias, msg.to)) {
-					bprintf(text[YouDidntPostMsgN],curpost+1);
-					break; } }
-			if(msg.hdr.attr&MSG_PERMANENT) {
-				bputs("\1n\r\nMessage is marked permanent.\r\n");
-				domsg=0;
-				break; }
-			if(post)
-				LFREE(post);
-			post=NULL;
-
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			msg.total_hfields=0;
-			msg.idx.offset=0;
-			if(loadmsg(&msg,msg.idx.number)) {
-				msg.idx.attr^=MSG_DELETE;
-				msg.hdr.attr=msg.idx.attr;
-				if((i=smb_putmsg(&smb,&msg))!=0)
-					errormsg(WHERE,ERR_WRITE,smb.file,i);
-				smb_unlockmsghdr(&smb,&msg);
-				if(i==0 && msg.idx.attr&MSG_DELETE) {
-					sprintf(str,"Removed post from %s %s"
-						,grp[sub[subnum]->grp]->sname,sub[subnum]->lname);
-					logline("P-",str);
-					if(!stricmp(sub[subnum]->misc&SUB_NAME
-						? useron.name : useron.alias, msg.from))
-						useron.posts=adjustuserrec(useron.number
-							,U_POSTS,5,-1); } }
-			domsg=1;
-			if((sys_misc&SM_SYSVDELM		// anyone can view delete msgs
-				|| (sys_misc&SM_USRVDELM	// sys/subops can view deleted msgs
-				&& sub_op(subnum)))
-				&& curpost<posts-1)
-				curpost++;
-			if(curpost>=posts-1)
-				done=1;
-			break;
-
-		case 'F':   /* find text in messages */
-			domsg=0;
-			bprintf(text[StartWithN],curpost+2);
-			if((i=getnum(posts))<0)
-				break;
-			if(i)
-				i--;
-			else
-				i=curpost+1;
-			bputs(text[SearchStringPrompt]);
-			if(!getstr(str,40,K_LINE|K_UPPER))
-				break;
-			searchposts(subnum,post,(long)i,posts,str);
-			break;
-		case 'I':   /* Sub-board information */
-			domsg=0;
-			subinfo(subnum);
-			break;
-		case 'L':   /* List messages */
-			domsg=0;
-			bprintf(text[StartWithN],curpost+1);
-			if((i=getnum(posts))<0)
-				break;
-			if(i) i--;
-			else i=curpost;
-			listmsgs(subnum,post,i,posts);
-			break;
-		case 'M':   /* Reply to last post in mail */
-			domsg=0;
-			if(msg.hdr.attr&MSG_ANONYMOUS && !sub_op(subnum)) {
-				bputs(text[CantReplyToAnonMsg]);
-				break; }
-			if(!sub_op(subnum) && msg.hdr.attr&MSG_PRIVATE
-				&& stricmp(msg.to,useron.name)
-				&& stricmp(msg.to,useron.alias))
-				break;
-			sprintf(str2,text[Regarding]
-				,msg.subj
-				,timestr((time_t *)&msg.hdr.when_written.time));
-			if(msg.from_net.type==NET_FIDO)
-				sprintf(str,"%s @%s",msg.from
-					,faddrtoa(*(faddr_t *)msg.from_net.addr));
-			else if(msg.from_net.type==NET_INTERNET)
-				strcpy(str,msg.from_net.addr);
-			else if(msg.from_net.type)
-				sprintf(str,"%s@%s",msg.from,msg.from_net.addr);
-			else
-				strcpy(str,msg.from);
-			bputs(text[Email]);
-			if(!getstr(str,60,K_EDIT|K_AUTODEL))
-				break;
-			if(post)
-				LFREE(post);
-			post=NULL;
-			quotemsg(msg,1);
-			if(msg.from_net.type==NET_INTERNET
-				&& (!strcmp(str,msg.from_net.addr) || strchr(str,'@')))
-				inetmail(str,msg.subj,WM_QUOTE|WM_NETMAIL);
-			else {
-				p=strrchr(str,'@');
-				if(p)								/* FidoNet or QWKnet */
-					netmail(str,msg.subj,WM_QUOTE);
-				else {
-					i=atoi(str);
-					if(!i) {
-						if(sub[subnum]->misc&SUB_NAME)
-							i=userdatdupe(0,U_NAME,LEN_NAME,str,0);
-						else
-							i=matchuser(str); }
-					email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE); } }
-//			  post=loadposts(&posts,subnum,0,lp);
-			break;
-		case 'P':   /* Post message on sub-board */
-			domsg=0;
-			if(!chk_ar(sub[subnum]->post_ar,useron))
-				bputs(text[CantPostOnSub]);
-			else {
-				if(post)
-					LFREE(post);
-				post=NULL;
-				postmsg(subnum,0,0);
-//				  post=loadposts(&posts,subnum,0,lp);
-				}
-			break;
-		case 'Q':   /* Quit */
-			if(msg.total_hfields)
-				smb_freemsgmem(&msg);
-			if(post)
-				LFREE(post);
-			smb_close(&smb);
-			smb_stack(&smb,SMB_STACK_POP);
-			return(1);
-		case 'R':   /* re-read last message */
-			reread=1;
-			break;
-		case 'T':   /* List titles of next ten messages */
-			domsg=0;
-			if(!posts)
-				break;
-			if(curpost>=posts-1) {
-				 done=1;
-				 break; }
-			i=curpost+11;
-			if(i>posts)
-				i=posts;
-			listmsgs(subnum,post,curpost+1,i);
-			curpost=i-1;
-			if(sub[subnum]->ptr<post[curpost].number)
-				sub[subnum]->ptr=post[curpost].number;
-			break;
-		case 'Y':   /* Your messages */
-			domsg=0;
-			showposts_toyou(post,0,posts);
-			break;
-		case '-':
-			if(curpost>0) curpost--;
-			reread=1;
-			break;
-		case 'O':   /* Operator commands */
-			while(online) {
-				if(!(useron.misc&EXPERT))
-					menu("SYSMSCAN");
-				bprintf("\r\n\1y\1hOperator: \1w");
-				strcpy(str,"?CEHMPQUV");
-				if(SYSOP)
-					strcat(str,"S");
-				switch(getkeys(str,0)) {
-					case '?':
-						if(useron.misc&EXPERT)
-							menu("SYSMSCAN");
-						continue;
-					case 'P':   /* Purge user */
-						purgeuser(sub[subnum]->misc&SUB_NAME
-							? userdatdupe(0,U_NAME,LEN_NAME,msg.from,0)
-							: matchuser(msg.from));
-						break;
-					case 'C':   /* Change message attributes */
-						i=chmsgattr(msg.hdr.attr);
-						if(msg.hdr.attr==i)
-							break;
-						if(msg.total_hfields)
-							smb_freemsgmem(&msg);
-						msg.total_hfields=0;
-						msg.idx.offset=0;
-						if(loadmsg(&msg,msg.idx.number)) {
-							msg.hdr.attr=msg.idx.attr=i;
-							if((i=smb_putmsg(&smb,&msg))!=0)
-								errormsg(WHERE,ERR_WRITE,smb.file,i);
-							smb_unlockmsghdr(&smb,&msg); }
-						break;
-					case 'E':   /* edit last post */
-						if(post)
-							LFREE(post);
-						post=NULL;
-						editmsg(&msg,subnum);
-//						  post=loadposts(&posts,subnum,0,lp);
-						break;
-					case 'H':   /* View message header */
-						msghdr(msg);
-						domsg=0;
-						break;
-					case 'M':   /* Move message */
-						domsg=0;
-						if(post)
-							LFREE(post);
-						post=NULL;
-						if(msg.total_hfields)
-							smb_freemsgmem(&msg);
-						msg.total_hfields=0;
-						msg.idx.offset=0;
-						if(!loadmsg(&msg,msg.idx.number)) {
-							errormsg(WHERE,ERR_READ,smb.file,msg.idx.number);
-							break; }
-						sprintf(str,text[DeletePostQ],msg.hdr.number,msg.subj);
-						if(movemsg(msg,subnum) && yesno(str)) {
-							msg.idx.attr|=MSG_DELETE;
-							msg.hdr.attr=msg.idx.attr;
-							if((i=smb_putmsg(&smb,&msg))!=0)
-								errormsg(WHERE,ERR_WRITE,smb.file,i); }
-						smb_unlockmsghdr(&smb,&msg);
-//						  post=loadposts(&posts,subnum,0,lp);
-						break;
-
-					case 'Q':
-						break;
-					case 'S':   /* Save/Append message to another file */
-/*	05/26/95
-						if(!yesno(text[SaveMsgToFile]))
-							break;
-*/
-						bputs(text[FileToWriteTo]);
-						if(getstr(str,40,K_LINE|K_UPPER))
-							msgtotxt(msg,str,1,1);
-						break;
-					case 'U':   /* User edit */
-						useredit(sub[subnum]->misc&SUB_NAME
-							? userdatdupe(0,U_NAME,LEN_NAME,msg.from,0)
-							: matchuser(msg.from),0);
-						break;
-					case 'V':   /* Validate message */
-						if(msg.total_hfields)
-							smb_freemsgmem(&msg);
-						msg.total_hfields=0;
-						msg.idx.offset=0;
-						if(loadmsg(&msg,msg.idx.number)) {
-							msg.idx.attr|=MSG_VALIDATED;
-							msg.hdr.attr=msg.idx.attr;
-							if((i=smb_putmsg(&smb,&msg))!=0)
-								errormsg(WHERE,ERR_WRITE,smb.file,i);
-							smb_unlockmsghdr(&smb,&msg); }
-						break;
-					default:
-						continue; }
-				break; }
-			break;
-		case '.':   /* Thread forward */
-			l=msg.hdr.thread_first;
-			if(!l) l=msg.hdr.thread_next;
-			if(!l) {
-				domsg=0;
-				break; }
-			for(i=0;i<posts;i++)
-				if(l==post[i].number)
-					break;
-			if(i<posts)
-				curpost=i;
-			break;
-		case ',':   /* Thread backwards */
-			if(!msg.hdr.thread_orig) {
-				domsg=0;
-				break; }
-			for(i=0;i<posts;i++)
-				if(msg.hdr.thread_orig==post[i].number)
-					break;
-			if(i<posts)
-				curpost=i;
-			break;
-		case '>':   /* Search Title forward */
-			for(i=curpost+1;i<posts;i++)
-				if(post[i].subj==msg.idx.subj)
-					break;
-			if(i<posts)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case '<':   /* Search Title backward */
-			for(i=curpost-1;i>-1;i--)
-				if(post[i].subj==msg.idx.subj)
-					break;
-            if(i>-1)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case '}':   /* Search Author forward */
-			strcpy(str,msg.from);
-			for(i=curpost+1;i<posts;i++)
-				if(post[i].from==msg.idx.from)
-					break;
-			if(i<posts)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case '{':   /* Search Author backward */
-			strcpy(str,msg.from);
-			for(i=curpost-1;i>-1;i--)
-				if(post[i].from==msg.idx.from)
-					break;
-			if(i>-1)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case ']':   /* Search To User forward */
-			strcpy(str,msg.to);
-			for(i=curpost+1;i<posts;i++)
-				if(post[i].to==msg.idx.to)
-					break;
-			if(i<posts)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case '[':   /* Search To User backward */
-			strcpy(str,msg.to);
-			for(i=curpost-1;i>-1;i--)
-				if(post[i].to==msg.idx.to)
-					break;
-			if(i>-1)
-				curpost=i;
-			else
-				domsg=0;
-			break;
-		case 0: /* Carriage return - Next Message */
-		case '+':
-			if(curpost<posts-1) curpost++;
-			else done=1;
-			break;
-		case '?':
-			menu("MSGSCAN");
-			domsg=0;
-			break;	} }
-if(msg.total_hfields)
-	smb_freemsgmem(&msg);
-if(post)
-	LFREE(post);
-if(!(mode&(SCAN_CONST|SCAN_TOYOU|SCAN_FIND)) && !(sub[subnum]->misc&SUB_PONLY)
-	&& reads && chk_ar(sub[subnum]->post_ar,useron)
-	&& !(useron.rest&FLAG('P'))) {
-    sprintf(str,text[Post],grp[sub[subnum]->grp]->sname
-        ,sub[subnum]->lname);
-    if(!noyes(str))
-		postmsg(subnum,0,0); }
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-return(0);
-}
-
-/****************************************************************************/
-/* This function will search the specified sub-board for messages that      */
-/* contain the string 'search'.                                             */
-/* Returns number of messages found.                                        */
-/****************************************************************************/
-int searchsub(uint subnum,char *search)
-{
-	int 	i,found;
-	ulong	l,posts,total;
-	post_t	HUGE16 *post;
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
-	return(0); }
-total=getposts(subnum);
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-post=loadposts(&posts,subnum,0,LP_BYSELF|LP_OTHERS);
-bprintf(text[SearchSubFmt]
-	,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts,total);
-found=searchposts(subnum,post,0,posts,search);
-if(posts)
-	LFREE(post);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-return(found);
-}
-
-/****************************************************************************/
-/* Will search the messages pointed to by 'msg' for the occurance of the    */
-/* string 'search' and display any messages (number of message, author and  */
-/* title). 'msgs' is the total number of valid messages.                    */
-/* Returns number of messages found.                                        */
-/****************************************************************************/
-int searchposts(uint subnum, post_t HUGE16 *post, long start, long posts
-	, char *search)
-{
-	char	HUGE16 *buf,ch;
-	ushort	xlat;
-	int 	i,j;
-	long	l,length,found=0;
-	smbmsg_t msg;
-
-msg.total_hfields=0;
-for(l=start;l<posts && !msgabort();l++) {
-	msg.idx.offset=post[l].offset;
-	if(!loadmsg(&msg,post[l].number))
-		continue;
-	smb_unlockmsghdr(&smb,&msg);
-	buf=smb_getmsgtxt(&smb,&msg,1);
-	if(!buf) {
-		smb_freemsgmem(&msg);
-		continue; }
-	strupr((char *)buf);
-	if(strstr((char *)buf,search) || strstr(msg.subj,search)) {
-		if(!found)
-			CRLF;
-		if(msg.hdr.attr&MSG_DELETE)
-			ch='-';
-		else if((!stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name))
-			&& !(msg.hdr.attr&MSG_READ))
-			ch='!';
-		else if(msg.hdr.number>sub[subnum]->ptr)
-			ch='*';
-		else
-			ch=' ';
-		bprintf(text[SubMsgLstFmt],l+1
-			,(msg.hdr.attr&MSG_ANONYMOUS) && !sub_op(subnum) ? text[Anonymous]
-			: msg.from
-			,msg.to
-			,ch
-			,msg.subj);
-		found++; }
-	FREE(buf);
-	smb_freemsgmem(&msg); }
-
-return(found);
-}
-
-/****************************************************************************/
-/* Will search the messages pointed to by 'msg' for message to the user on  */
-/* Returns number of messages found.                                        */
-/****************************************************************************/
-void showposts_toyou(post_t HUGE16 *post, ulong start, ulong posts)
-{
-	char	str[128];
-	ushort	namecrc,aliascrc,sysop;
-	int 	i;
-	ulong	l,found;
-    smbmsg_t msg;
-
-strcpy(str,useron.alias);
-strlwr(str);
-aliascrc=crc16(str);
-strcpy(str,useron.name);
-strlwr(str);
-namecrc=crc16(str);
-sysop=crc16("sysop");
-msg.total_hfields=0;
-for(l=start,found=0;l<posts && !msgabort();l++) {
-
-	if((useron.number!=1 || post[l].to!=sysop)
-		&& post[l].to!=aliascrc && post[l].to!=namecrc)
-		continue;
-
-	if(msg.total_hfields)
-		smb_freemsgmem(&msg);
-	msg.total_hfields=0;
-	msg.idx.offset=post[l].offset;
-	if(!loadmsg(&msg,post[l].number))
-		continue;
-	smb_unlockmsghdr(&smb,&msg);
-	if((useron.number==1 && !stricmp(msg.to,"sysop") && !msg.from_net.type)
-		|| !stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name)) {
-		if(!found)
-			CRLF;
-		found++;
-		bprintf(text[SubMsgLstFmt],l+1
-			,(msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
-			? text[Anonymous] : msg.from
-			,msg.to
-			,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_READ ? ' ' : '*'
-			,msg.subj); } }
-
-if(msg.total_hfields)
-	smb_freemsgmem(&msg);
-}
-
-/****************************************************************************/
-/* This function will search the specified sub-board for messages that		*/
-/* are sent to the currrent user.											*/
-/* returns number of messages found 										*/
-/****************************************************************************/
-int searchsub_toyou(uint subnum)
-{
-	int 	i;
-	ulong	l,posts,total;
-	post_t	HUGE16 *post;
-
-if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
-	errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
-	return(0); }
-total=getposts(subnum);
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=smb_retry_time;
-if((i=smb_open(&smb))!=0) {
-	smb_stack(&smb,SMB_STACK_POP);
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	return(0); }
-post=loadposts(&posts,subnum,0,0);
-bprintf(text[SearchSubFmt]
-	,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,total);
-if(posts) {
-	if(post)
-		LFREE(post);
-	post=loadposts(&posts,subnum,0,LP_BYSELF|LP_OTHERS);
-	showposts_toyou(post,0,posts); }
-if(post)
-	LFREE(post);
-smb_close(&smb);
-smb_stack(&smb,SMB_STACK_POP);
-return(posts);
-}
-
-
diff --git a/src/sbbs2/rio/riodefs.h b/src/sbbs2/rio/riodefs.h
deleted file mode 100644
index fa5e54f148a48c6533c860f1b9946e5e8b95cd2c..0000000000000000000000000000000000000000
--- a/src/sbbs2/rio/riodefs.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* RIODEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _RIODEFS_H
-#define _RIODEFS_H
-
-
-/************************/
-/* Remote I/O Constants */
-/************************/
-
-                            /* i/o mode and state flags */
-#define CTSCK	0x1000		/*.check cts (mode only) */
-#define RTSCK	0x2000		/*.check rts (mode only) */
-#define TXBOF	0x0800		/*.transmit buffer overflow (outcom only) */
-#define ABORT	0x0400		/*.check for ^C (mode), aborting (state) */
-#define PAUSE	0x0200		/*.check for ^S (mode), pausing (state) */
-#define NOINP	0x0100		/*.input buffer empty (incom only) */
-
-                            /* status flags */
-#define DCD 	0x0080		/*.DCD on */
-#define RI		0x0040		/*.Ring indicate */
-#define DSR 	0x0020		/*.Dataset ready */
-#define CTS 	0x0010		/*.CTS on */
-#define FERR	0x0008		/*.Frameing error */
-#define PERR	0x0004		/*.Parity error */
-#define OVRR	0x0002		/*.Overrun */
-#define RXLOST	0x0001		/*.Receive buffer overflow */
-
-/* rioctl() arguments */
-/* returns mode or state flags in high 8 bits, status flags in low 8 bits */
-
-                            /* the following return mode in high 8 bits */
-#define IOMODE	0x0000		/*.no operation */
-#define IOSM	0x0001		/*.i/o set mode flags */
-#define IOCM	0x0002		/*.i/o clear mode flags */
-
-#define GVERS	0x0007		/*.get version */
-#define GUART	0x0107		/*.get uart */
-#define GIRQN	0x0207		/*.get IRQ number */
-#define GBAUD	0x0307		/*.get baud */
-
-                            /* the following return state in high 8 bits */
-#define IOSTATE 0x0004		/*.no operation */
-#define IOSS	0x0005		/*.i/o set state flags */
-#define IOCS	0x0006		/*.i/o clear state flags */
-#define IOFB	0x0308		/*.i/o buffer flush */
-#define IOFI	0x0208		/*.input buffer flush */
-#define IOFO	0x0108		/*.output buffer flush */
-#define IOCE	0x0009		/* i/o clear error flags */
-
-
-                            /* return count (16bit) */
-#define RXBC	0x000a		/*.get receive buffer count */
-#define RXBS	0x010a		/*.get receive buffer size */
-#define TXBC	0x000b		/*.get transmit buffer count */
-#define TXBS	0x010b		/*.get transmit buffer size */
-#define TXBF	0x020b		/*.get transmit buffer free space */
-#define TXSYNC	0x000c		/*.sync transmition (seconds<<8|0x0c) */
-#define IDLE    0x000d      /* suspend communication routines */
-#define RESUME  0x010d      /* return from suspended state */
-#define RLERC   0x000e      /* read line error count and clear */
-#define CPTON   0x0110      /* set input translation flag for ctrl-p on */
-#define CPTOFF  0x0010      /* set input translation flag for ctrl-p off */
-#define GETCPT  0x8010      /* return the status of ctrl-p translation */
-#define MSR     0x0011      /* read modem status register */
-#define FIFOCTL 0x0012		/*.FIFO UART control */
-#define TSTYPE  0x0013      /* Time-slice API type */
-#define GETTST  0x8013      /* Get Time-slice API type */
-
-#define I14DB   0x001d      /* DigiBoard int 14h driver */
-#define I14PC   0x011d      /* PC int 14h driver */
-#define I14PS   0x021d      /* PS/2 int 14h driver */
-#define I14FO   0x031d      /* FOSSIL int 14h driver */
-
-#define SMSMK   0x0014      /* set modem status mask */
-#define SMLCR   0x0015      /* set modem line control register */
-#define LFN81	0x0315		/*.set line format N81 */
-#define LFE71	0x1A15		/*.set line format E71 */
-#define SRXHL   0x001E      /* set receive flow control high limit */
-#define SRXLL   0x001F      /* set receive flow control low limit */
-#define IGCLS   0x0020      /* input gate close */
-#define IGOPN   0xFF20      /* input gate open */
-
-
-                            /* ivhctl() arguments */
-#define INT29R	0x0001		/* copy int 29h output to remote */
-#define INT29L	0x0002		/* Use _putlc for int 29h */
-#define INT16	0x0010		/* return remote chars to int 16h calls */
-#define INTCLR	0x0000		/* release int 16h, int 29h */
-
-#define TS_INT28	 1
-#define TS_WINOS2    2
-#define TS_NODV      4
-
-#define RIO_OUTCOM_STKLEN	4096	/* outcom_thread() stack size	*/
-#define RIO_OUTCOM_BUFLEN	4096	/* outcom() buffer length		*/
-#define RIO_INCOM_BUFLEN	1024	/* incom() buffer length		*/
-
-
-#endif	/* Don't add anything after this line */
diff --git a/src/sbbs2/rio/riolib.c b/src/sbbs2/rio/riolib.c
deleted file mode 100644
index 18cee97d54849730e1371dcaca499137036170a7..0000000000000000000000000000000000000000
--- a/src/sbbs2/rio/riolib.c
+++ /dev/null
@@ -1,965 +0,0 @@
-/* RIOLIB.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Remote communications Input/Output Library for OS/2 and Win32 */
-
-#define RIOLIB_VER	100
-
-#ifdef __OS2__
-	#define INCL_DOSDEVICES
-	#define INCL_DOSDEVIOCTL
-	#define INCL_DOS
-	#include <os2.h>
-
-#else	// Win32
-
-	#include <windows.h>
-#endif
-
-#include <time.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <process.h>
-#include "riolib.h"
-#include "riodefs.h"
-
-int rio_handle=-1;
-
-int rio_abort=0,rio_aborted=0;
-int inbufbot,inbuftop;
-int outbufbot,outbuftop;
-char inbuf[RIO_INCOM_BUFLEN];
-char outbuf[RIO_OUTCOM_BUFLEN];
-
-/****************************************************************************/
-/* OS/2 Specific															*/
-/****************************************************************************/
-
-#ifdef __OS2__
-
-HEV rio_sem;
-
-typedef struct {	/* Packet for Get/Set Device Control Block Parms */
-
-	ushort	wr_timeout;
-	ushort	rd_timeout;
-	uchar	flags1;
-	uchar	flags2;
-	uchar	flags3;
-	uchar	err_char;
-	uchar	brk_char;
-	uchar	xon_char;
-	uchar	xoff_char;
-
-	} async_dcb_t;
-
-typedef struct {	/* Parameter Packet for Extended Set Bit Rate */
-
-	ulong rate;
-	uchar frac;
-
-	} setrate_t;
-
-typedef struct {	/* Data Packet for Extended Query Bit Rate */
-
-	ulong cur_rate;
-	uchar cur_rate_frac;
-	ulong min_rate;
-	uchar min_rate_frac;
-	ulong max_rate;
-	uchar max_rate_frac;
-
-	} getrate_t;
-
-typedef struct {	/* Data Packet for Query Number of Chars Queue */
-
-	ushort	cur,
-			max;
-
-	} getqueue_t;
-
-typedef struct {	/* Parameter Packet for Set Modem Control Signals */
-
-	uchar	on;
-	uchar	off;
-
-	} setmdmctrl_t;
-
-typedef struct {	/* Parameter Packet for Set Line Characteristics */
-
-	uchar	data;
-	uchar	parity;
-	uchar	stop;
-
-	} setline_t;
-
-#else
-
-/****************************************************************************/
-/* Win32 Specific															*/
-/****************************************************************************/
-
-HANDLE	rio_event;
-
-#endif
-
-/************************************************************************/
-/* Opens COM port, ignoring IRQ argument								*/
-/* Returns 0 on no error												*/
-/************************************************************************/
-int rioini(int com, int unused)
-{
-	char		str[64];
-#ifdef __OS2__
-	async_dcb_t async_dcb;
-#else // Win32
-	DCB 		dcb;
-	COMMTIMEOUTS timeouts;
-#endif
-
-#ifdef __WATOMC__
-	char		*stack;
-#endif
-
-inbufbot=inbuftop=outbufbot=outbuftop=0;	/* clear our i/o buffers */
-
-if(!com) { /* Close port */
-	if(rio_handle>=0) {
-#ifdef __OS2__
-		close(rio_handle);
-		rio_handle=-1;	 /* signal outcom_thread() to end */
-		DosPostEventSem(rio_sem);
-#else // Win32
-		CloseHandle((HANDLE)rio_handle);
-		rio_handle=-1;
-		SetEvent(rio_event);
-#endif
-		return(0); }
-	return(-2); }
-
-sprintf(str,"COM%u",com);
-#ifdef __OS2__
-if(rio_handle==-1) {	/* Not already opened */
-	if((rio_handle=open(str,O_RDWR|O_BINARY,0))==-1)
-		return(-1); }
-#else // Win32
-if(rio_handle==-1) {	/* Not already opened */
-	if((rio_handle=(int)CreateFile(str
-		,GENERIC_READ|GENERIC_WRITE 	/* Access */
-		,0								/* Share mode */
-		,NULL							/* Security attributes */
-		,OPEN_EXISTING					/* Create access */
-		,FILE_ATTRIBUTE_NORMAL			/* File attributes */
-		,NULL							/* Template */
-		))==(int)INVALID_HANDLE_VALUE)
-		return(-1); }
-#endif
-
-#ifdef __OS2__
-
-if(DosDevIOCtl(rio_handle
-	,IOCTL_ASYNC, 0x73	/* Query Device Control Block (DCB) Parms */
-	,NULL
-	,0
-	,NULL
-	,&async_dcb
-	,sizeof(async_dcb)
-	,NULL))
-	return(-6);
-
-async_dcb.flags2&=~(1<<1);	/* Disable Automatic Recv XON/XOFF flow ctrl */
-/* Extended Hardware Buffering (16550 FIFO) */
-if(async_dcb.flags3&((1<<4)|(1<<3))) {			/* Supported */
-	async_dcb.flags3&=~((1<<3)|(1<<6)|(1<<5));	/* Set to 1 char trgr lvl */
-	async_dcb.flags3|=((1<<4)|(1<<7)); }		/* Set to 16 char tx buf */
-async_dcb.flags3|=((1<<2)|(1<<1));				/* No-Wait read timeout */
-async_dcb.flags3&=~(1<<0);						/* Normal write timeout */
-async_dcb.wr_timeout=499;						/* 5 seconds? */
-DosDevIOCtl(rio_handle
-	,IOCTL_ASYNC, 0x53	/* Set Device Control Block (DCB) Parms */
-	,(void *)&async_dcb
-	,sizeof(async_dcb)
-	,NULL
-	,NULL
-	,0
-	,NULL);
-
-if(DosCreateEventSem(NULL,&rio_sem,0,0))
-	return(-5);
-
-#else // Win32
-
-if(GetCommState((HANDLE)rio_handle,&dcb)!=TRUE)
-	return(-6);
-
-dcb.fBinary=1;			// No EOF check
-dcb.fDtrControl=DTR_CONTROL_ENABLE;
-dcb.fDsrSensitivity=FALSE;
-dcb.fOutX=0;			// No Xon/Xoff out
-dcb.fInX=0; 			// No Xon/Xoff in
-dcb.fErrorChar=FALSE;	// No character replacement
-dcb.fNull=0;			// No null stripping
-dcb.fAbortOnError=0;	// Continue to communicate even if error detected
-
-SetCommState((HANDLE)rio_handle,&dcb);
-
-if(GetCommTimeouts((HANDLE)rio_handle,&timeouts)!=TRUE)
-	return(-7);
-
-timeouts.ReadIntervalTimeout=MAXDWORD;
-timeouts.ReadTotalTimeoutMultiplier=0;
-timeouts.ReadTotalTimeoutConstant=0;		// No-wait read timeout
-timeouts.WriteTotalTimeoutMultiplier=0;
-timeouts.WriteTotalTimeoutConstant=5000;	// 5 seconds
-SetCommTimeouts((HANDLE)rio_handle,&timeouts);
-
-SetupComm((HANDLE)rio_handle,4096,4096);	/* Init Rx and Tx buffer sizes */
-
-if((rio_event=CreateEvent(NULL			/* Security attributes */
-	,TRUE								/* Manual reset */
-	,FALSE								/* Non-signaled by default */
-	,NULL								/* Event name */
-	))==NULL)
-	return(-5);
-
-#endif
-
-#ifdef __WATCOMC__
-stack=malloc(RIO_OUTCOM_STACK);
-if(stack==NULL)
-	return(-4);
-if(_beginthread(outcom_thread,stack,RIO_OUTCOM_STKLEN,NULL)==-1)
-	return(-3);
-#else
-if(_beginthread(outcom_thread,RIO_OUTCOM_STKLEN,NULL)==(ulong)-1)
-	return(-3);
-#endif
-
-
-return(0);
-}
-
-/************************************************************************/
-/* Raise or lower DTR													*/
-/* If onoff is 0, drop and exit, 1 raise and exit, >1 drop and wait 	*/
-/* up to x seconds for DCD to drop, return 0 on success, 1 on failure	*/
-/************************************************************************/
-int dtr(char onoff)
-{
-#ifdef __OS2__
-	setmdmctrl_t setmdmctrl;
-	ulong start;
-	ushort w;
-	uchar c;
-
-if(onoff==1) {
-	setmdmctrl.on=1;
-	setmdmctrl.off=0xff; }
-else {
-	setmdmctrl.on=0;
-	setmdmctrl.off=0xfe; }
-
-DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x46	/* Set Modem Ctrl Signals */
-	,&setmdmctrl
-	,sizeof(setmdmctrl)
-	,NULL
-	,&w
-	,sizeof(short)
-	,NULL);
-
-if(onoff<=1)
-	return(0);
-
-start=time(NULL);
-while(time(NULL)-start<=onoff) {
-	DosDevIOCtl(rio_handle
-		,IOCTL_ASYNC, 0x67					/* Get Modem Input Signals */
-		,NULL
-		,0
-		,NULL
-		,&c
-		,1
-		,NULL);
-	if(!(c&DCD))	/* DCD is low */
-		return(0);
-	DosSleep(1); }
-
-#else // Win32
-
-	ulong l,start;
-
-if(onoff==1)
-	EscapeCommFunction((HANDLE)rio_handle,SETDTR);
-else
-	EscapeCommFunction((HANDLE)rio_handle,CLRDTR);
-
-if(onoff<=1)
-	return(0);
-
-start=time(NULL);
-while(time(NULL)-start<=onoff) {
-	GetCommModemStatus((HANDLE)rio_handle,&l);
-	if(!(l&MS_RLSD_ON)) // DCD is low
-		return(0);
-	Sleep(1000); }
-
-#endif
-
-return(1); /* Dropping DTR failed to lower DCD */
-}
-
-
-
-/************************************************************************/
-/* Returns the current DTE rate of the currently open COM port			*/
-/************************************************************************/
-long rio_getbaud(void)
-{
-#ifdef __OS2__
-	getrate_t getrate;
-
-if(DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x63 /* Extended Query Bit Rate */
-	,NULL
-	,0
-	,NULL
-	,&getrate
-	,sizeof(getrate)
-	,NULL)==0)
-	return(getrate.cur_rate);
-
-#else // Win32
-
-	DCB dcb;
-
-if(GetCommState((HANDLE)rio_handle,&dcb)==TRUE) {
-	switch(dcb.BaudRate) {
-		case CBR_110:
-			return(110);
-		case CBR_300:
-			return(300);
-		case CBR_600:
-			return(600);
-		case CBR_1200:
-			return(1200);
-		case CBR_2400:
-			return(2400);
-		case CBR_4800:
-			return(4800);
-		case CBR_9600:
-			return(9600);
-		case CBR_14400:
-			return(14400);
-		case CBR_19200:
-			return(19200);
-		case CBR_38400:
-			return(38400);
-		case CBR_56000:
-			return(56000);
-		case CBR_57600:
-			return(57600);
-		case CBR_115200:
-			return(115200);
-		case CBR_128000:
-			return(128000);
-		case CBR_256000:
-			return(256000);
-		default:
-			return(dcb.BaudRate); } }
-
-#endif
-
-return(-1); // Error
-}
-
-
-/************************************************************************/
-/* Sets the current DTE rate											*/
-/* Returns 0 on success 												*/
-/************************************************************************/
-int setbaud(int rate)
-{
-#ifdef __OS2__
-	setrate_t setrate;
-	APIRET	ret;
-
-setrate.rate=rate;
-setrate.frac=0;
-
-ret=DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x43	/* Extended Set Bit Rate */
-	,&setrate
-	,sizeof(setrate)
-	,NULL
-	,NULL
-	,0
-	,NULL);
-
-if(ret)
-	return(ret);
-
-if(rio_getbaud()!=rate) 	/* Make sure it actually changed rates */
-	return(-1);
-
-#else // Win32
-
-	DCB dcb;
-
-if(GetCommState((HANDLE)rio_handle,&dcb)!=TRUE)
-	return(-1);
-dcb.BaudRate=rate;
-if(SetCommState((HANDLE)rio_handle,&dcb)!=TRUE)
-	return(-1);
-
-#endif
-
-return(0);
-}
-
-/************************************************************************/
-/* Return next incoming character from COM port, NOINP if none avail.	*/
-/* Uses a linear buffer.												*/
-/************************************************************************/
-int incom(void)
-{
-	char c;
-
-if(inbufbot!=inbuftop) {
-	c=inbuf[inbufbot];
-	inbufbot++;
-	if(inbufbot==inbuftop)
-		inbufbot=inbuftop=0;
-	if(rio_abort && c==3) { 		/* Ctrl-C */
-		rio_aborted=1;
-		rioctl(IOFO);
-		return(NOINP); }
-	return(c); }
-
-inbufbot=0;
-#ifdef __OS2__
-inbuftop=read(rio_handle,inbuf,RIO_INCOM_BUFLEN);
-#else // Win32
-ReadFile((HANDLE)rio_handle,inbuf,RIO_INCOM_BUFLEN,(DWORD *)&inbuftop,NULL);
-#endif
-if(inbuftop<=0 || inbuftop>RIO_INCOM_BUFLEN) {
-	inbuftop=0;
-	return(NOINP); }
-else
-	return(inbuf[inbufbot++]);
-}
-
-/************************************************************************/
-/* Return number of chars in our input buffer							*/
-/************************************************************************/
-int inbufcnt(void)
-{
-return(inbuftop-inbufbot);
-}
-
-/************************************************************************/
-/* Place a character into outbound buffer, return TXBOF on buffer		*/
-/* overflow, 0 on success.												*/
-/************************************************************************/
-int outcom(int ch)
-{
-	int i=outbuftop+1;
-
-if(i==RIO_OUTCOM_BUFLEN)
-	i=0;
-if(i==outbufbot)
-	return(TXBOF);
-outbuf[outbuftop++]=ch;
-if(outbuftop==RIO_OUTCOM_BUFLEN)
-	outbuftop=0;
-#ifdef __OS2__
-DosPostEventSem(rio_sem);	 // Enable output
-#else // Win32
-SetEvent(rio_event);
-#endif
-return(0);
-}
-
-/************************************************************************/
-/************************************************************************/
-void outcom_thread(void *unused)
-{
-	int i,top;
-	ulong l;
-
-while(rio_handle>=0) {
-	if(outbufbot==outbuftop) {
-#ifdef __OS2__
-		DosResetEventSem(rio_sem,&l);
-		DosWaitEventSem(rio_sem,10000);  /* every 10 seconds */
-#else // Win32
-		ResetEvent(rio_event);
-		WaitForSingleObject(rio_event,10000);
-#endif
-		continue; }
-	top=outbuftop;
-	if(top<outbufbot)
-		i=RIO_OUTCOM_BUFLEN-outbufbot;
-	else
-		i=top-outbufbot;
-#ifdef __OS2__
-	i=write(rio_handle,outbuf+outbufbot,i);
-#else // Win32
-	WriteFile((HANDLE)rio_handle,outbuf+outbufbot,i,(DWORD *)&i,NULL);
-#endif
-	if(i>0 && i<=RIO_OUTCOM_BUFLEN-outbufbot)
-		outbufbot+=i;
-	if(outbufbot==RIO_OUTCOM_BUFLEN)
-		outbufbot=0; }
-_endthread();
-}
-
-/************************************************************************/
-/* Return number of chars in our output buffer							*/
-/************************************************************************/
-int outbufcnt(void)
-{
-if(outbuftop>=outbufbot)
-    return(outbuftop-outbufbot);
-return(outbuftop+(RIO_OUTCOM_BUFLEN-outbufbot));
-}
-
-/************************************************************************/
-/************************************************************************/
-int rio_getstate(void)
-{
-#ifdef __OS2__
-	uchar c;
-	ushort state=0,w;
-	getqueue_t getqueue;
-
-if(rio_abort && !rio_aborted) {
-	DosDevIOCtl(rio_handle
-		,IOCTL_ASYNC, 0x68 /* Query # of chars in rx queue */
-		,NULL
-		,0
-		,NULL
-		,&getqueue
-		,sizeof(getqueue)
-		,NULL);
-	if(getqueue.cur && read(rio_handle,&c,1)==1) {
-		if(c==3) { /* ctrl-c */
-			rio_aborted=1;
-			rioctl(IOFO); }
-		else
-			if(inbuftop<RIO_INCOM_BUFLEN)  /* don't overflow input buffer */
-				inbuf[inbuftop++]=c; } }
-
-if(rio_aborted)
-    state|=ABORT;
-
-#if 0	// just to see if things speed up
-DosDevIOCtl(rio_handle
-	,IOCTL_ASYNC, 0x6D	/* Query COM Error */
-	,NULL
-	,0
-	,NULL
-	,&w
-	,sizeof(short)
-	,NULL);
-state|=w&0xf;	/* FERR|PERR|OVRR|RXLOST */
-#endif
-
-DosDevIOCtl(rio_handle
-	,IOCTL_ASYNC, 0x67	/* Query Modem Input Signals */
-	,NULL
-	,0
-	,NULL
-	,&c
-	,sizeof(char)
-	,NULL);
-state|=c&0xf0;	/* DCD|RI|DSR|CTS */
-
-#else // Win32
-
-	uchar c;
-	ushort state=0;
-	int i;
-	ulong l;
-	COMSTAT comstat;
-
-if(rio_abort && !rio_aborted) {
-	ClearCommError((HANDLE)rio_handle,&l,&comstat);
-	if(comstat.cbInQue) {
-		ReadFile((HANDLE)rio_handle,&c,1,(DWORD *)&i,NULL);
-		if(i==1) {
-			if(c==3) { /* Ctrl-C */
-				rio_aborted=1;
-				rioctl(IOFO); }
-			else
-				if(inbuftop<RIO_INCOM_BUFLEN)  /* don't overflow input buffer */
-					inbuf[inbuftop++]=c; } } }
-
-GetCommModemStatus((HANDLE)rio_handle,(DWORD *)&state);  /* DCD|RI|DSR|CTS */
-if(rio_aborted)
-    state|=ABORT;
-
-#endif
-
-return(state);
-}
-
-
-/************************************************************************/
-/************************************************************************/
-int rioctl(ushort action)
-{
-#ifdef __OS2__
-	async_dcb_t 	async_dcb;
-	getqueue_t		getqueue;
-	setline_t		setline;
-#else // Win32
-	COMMPROP		commprop;
-	COMSTAT 		comstat;
-	DCB 			dcb;
-	ulong			l;
-#endif
-	uchar c;
-	ushort mode,w;
-	clock_t start;
-
-switch(action) {
-	case GVERS: 	/* Get version */
-		return(RIOLIB_VER);
-	case GUART: 	/* Get UART I/O address, not available */
-		return(0xffff);
-	case GIRQN: 	/* Get IRQ number, not available */
-		return((int)rio_handle);
-	case GBAUD: 	/* Get current bit rate */
-		return(rio_getbaud());
-	case RXBC:		/* Get receive buffer count */
-#ifndef __OS2__ // Win32
-		ClearCommError((HANDLE)rio_handle,&l,&comstat);
-		return(comstat.cbInQue+inbufcnt());
-#endif
-		/* Fall-through if OS/2 */
-	case RXBS:		/* Get receive buffer size */
-#ifdef __OS2__
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x68 /* Query # of chars in rx queue */
-			,NULL
-			,0
-			,NULL
-			,&getqueue
-			,sizeof(getqueue)
-			,NULL);
-		if(action==RXBC)
-			return(getqueue.cur+inbufcnt());
-		/* RXBS */
-		return(getqueue.max+RIO_INCOM_BUFLEN);
-#else
-		GetCommProperties((HANDLE)rio_handle,&commprop);
-		return(commprop.dwCurrentRxQueue+RIO_INCOM_BUFLEN);
-#endif
-	case TXBC:		/* Get transmit buffer count */
-#ifndef __OS2__ // Win32
-		ClearCommError((HANDLE)rio_handle,&l,&comstat);
-		return(comstat.cbOutQue+outbufcnt());
-#endif
-		/* Fall-through if OS/2 */
-	case TXBS:		/* Get transmit buffer size */
-	case TXBF:		/* Get transmit buffer free space */
-#ifdef __OS2__
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x69	/* Query # of chars in tx queue */
-			,NULL
-			,0
-			,NULL
-			,&getqueue
-			,sizeof(getqueue)
-			,NULL);
-		if(action==TXBC)
-			return(getqueue.cur+outbufcnt());
-		else if(action==TXBS)
-			return(getqueue.max+RIO_OUTCOM_BUFLEN);
-		/* TXBF */
-		return((getqueue.max-getqueue.cur)+(RIO_OUTCOM_BUFLEN-outbufcnt()));
-#else
-		GetCommProperties((HANDLE)rio_handle,&commprop);
-		if(action==TXBS)
-			return(commprop.dwCurrentTxQueue+RIO_OUTCOM_BUFLEN);
-		/* TXBF */
-		ClearCommError((HANDLE)rio_handle,&l,&comstat);
-		return((commprop.dwCurrentTxQueue-comstat.cbOutQue)
-			+(RIO_OUTCOM_BUFLEN-outbufcnt()));
-#endif
-	case IOSTATE:
-		return(rio_getstate());
-	case IOFI:		/* Flush input buffer */
-	case IOFO:		/* Flush output buffer */
-	case IOFB:		/* Flush both buffers */
-#ifdef __OS2__
-		c=0;
-		if((action&IOFI)==IOFI) {
-			DosDevIOCtl(rio_handle
-				,IOCTL_GENERAL, DEV_FLUSHINPUT
-				,&c
-				,sizeof(char)
-				,NULL
-				,&w
-				,sizeof(short)
-				,NULL);
-			inbufbot=inbuftop=0;
-			}	   /* Clear our input buffer too */
-		c=0;
-		if((action&IOFO)==IOFO) {
-			DosDevIOCtl(rio_handle
-				,IOCTL_GENERAL, DEV_FLUSHOUTPUT
-				,&c
-				,sizeof(char)
-				,NULL
-				,&w
-				,sizeof(short)
-                ,NULL);
-			outbufbot=outbuftop=0;
-			}	 /* Clear our output buffer too */
-#else // Win32
-		l=0;
-		if((action&IOFI)==IOFI)
-			l|=(PURGE_RXABORT|PURGE_RXCLEAR);
-		if((action&IOFO)==IOFO)
-			l|=(PURGE_TXABORT|PURGE_TXCLEAR);
-		PurgeComm((HANDLE)rio_handle,l);
-#endif
-		return(rio_getstate());
-	case LFN81:
-	case LFE71:
-#ifdef __OS2__
-		setline.stop=0; /* 1 stop bit */
-		if(action==LFN81) {
-			setline.data=8;
-			setline.parity=0; } /* No parity */
-		else {
-			setline.data=7;
-			setline.parity=2; } /* Even parity */
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x42	/* Set Line Characteristics */
-			,&setline
-			,sizeof(setline)
-			,NULL
-			,NULL
-			,0
-			,NULL);
-#else // Win32
-		GetCommState((HANDLE)rio_handle,&dcb);
-		if(action==LFN81) {
-			dcb.Parity=NOPARITY;
-			dcb.ByteSize=8;
-			dcb.StopBits=ONESTOPBIT; }
-		else {
-			dcb.Parity=EVENPARITY;
-			dcb.ByteSize=7;
-			dcb.StopBits=ONESTOPBIT; }
-		SetCommState((HANDLE)rio_handle,&dcb);
-#endif
-		return(0);
-	case FIFOCTL:
-#ifdef __OS2__
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x73	/* Query Device Control Block (DCB) Parms */
-			,NULL
-			,0
-			,NULL
-			,&async_dcb
-			,sizeof(async_dcb)
-			,NULL);
-
-		/* Extended Hardware Buffering (16550 FIFO) */
-		if(async_dcb.flags3&(1<<4)) {					/* Supported */
-			c=0xc0;
-			if(async_dcb.flags3&(1<<7))
-				c|=0x0c;
-			return(c); }
-#else // Win32
-		// Not supported under Win32?
-#endif
-		return(0);
-	}
-
-if((action&0xff)<=IOCM) {	/* Get/Set/Clear mode */
-	mode=0;
-
-#ifdef __OS2__
-	DosDevIOCtl(rio_handle
-		,IOCTL_ASYNC, 0x73	/* Query Device Control Block (DCB) Parms */
-		,NULL
-		,0
-		,NULL
-		,&async_dcb
-		,sizeof(async_dcb)
-		,NULL);
-	if(async_dcb.flags1&(1<<3)) /* Output CTS handshaking */
-		mode|=CTSCK;
-	if(async_dcb.flags2&(1<<0)) /* Automatic Xmit Control Flow Xon/Xoff */
-		mode|=PAUSE;
-	if(async_dcb.flags2&(1<<7)	/* RTS Input handshaking */
-		&& !(async_dcb.flags2&(1<<6)))
-		mode|=RTSCK;
-	if(rio_abort)
-		mode|=ABORT;
-
-	if(action==IOMODE)
-		return(mode);
-
-	if((action&0xff)==IOCM) 	/* Clear mode */
-		mode&=~(action&0xff00);
-	else						/* Set mode */
-		mode|=(action&0xff00);
-
-	if(mode&CTSCK)
-		async_dcb.flags1|=(1<<3);
-	else
-		async_dcb.flags1&=~(1<<3);
-	if(mode&PAUSE) {
-		async_dcb.flags2|=(1<<0);	/* xmit flow control */
-		async_dcb.xon_char=17;		/* Ctrl-Q */
-		async_dcb.xoff_char=19; }	/* Ctrl-S */
-	else
-		async_dcb.flags2&=~(1<<0);
-	if(mode&RTSCK) {
-		async_dcb.flags2|=(1<<7);
-		async_dcb.flags2&=~(1<<6); }
-	else
-		async_dcb.flags2&=~((1<<7)|(1<<6));
-	if(mode&ABORT)
-		rio_abort=1;
-	else
-		rio_abort=0;
-
-	DosDevIOCtl(rio_handle
-		,IOCTL_ASYNC, 0x53	/* Set Device Control Block (DCB) Parms */
-		,&async_dcb
-		,sizeof(async_dcb)
-		,NULL
-		,NULL
-		,0
-		,NULL);
-
-#else // Win32
-
-	GetCommState((HANDLE)rio_handle,&dcb);
-	if(dcb.fOutxCtsFlow)
-		mode|=CTSCK;
-	if(dcb.fOutX)
-		mode|=PAUSE;
-	if(dcb.fRtsControl==RTS_CONTROL_HANDSHAKE)
-		mode|=RTSCK;
-
-	if(rio_abort)
-		mode|=ABORT;
-
-	if(action==IOMODE)
-        return(mode);
-
-	if((action&0xff)==IOCM) 	/* Clear mode */
-		mode&=~(action&0xff00);
-	else						/* Set mode */
-        mode|=(action&0xff00);
-
-	if(mode&CTSCK)
-		dcb.fOutxCtsFlow=1;
-	else
-		dcb.fOutxCtsFlow=0;
-	if(mode&PAUSE) {
-		dcb.fOutX=1;
-		dcb.XonChar=17; 	/* Ctrl-Q */
-		dcb.XoffChar=19; }	/* Ctrl-S */
-	else
-		dcb.fOutX=0;
-	if(mode&RTSCK)
-		dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
-	else
-		dcb.fRtsControl=RTS_CONTROL_ENABLE;
-	if(mode&ABORT)
-		rio_abort=1;
-	else
-        rio_abort=0;
-
-	SetCommState((HANDLE)rio_handle,&dcb);
-
-#endif
-
-	return(mode); }
-
-if((action&0xff)==IOSS) {	/* Set state */
-
-	if(action&ABORT)
-		rio_aborted=1;
-
-#ifdef __OS2__
-	if(action&PAUSE)
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x47	/* Behave as if XOFF Received */
-			,NULL
-			,0
-			,NULL
-			,&w
-			,sizeof(short)
-            ,NULL);
-#else // Win32
-	if(action&PAUSE)
-		EscapeCommFunction((HANDLE)rio_handle,SETXOFF);
-#endif
-
-	return(rio_getstate()); }
-
-if((action&0xff)==IOCS) {	/* Clear state */
-
-	if(action&ABORT)
-		rio_aborted=0;
-
-#ifdef __OS2__
-	if(action&PAUSE)
-		DosDevIOCtl(rio_handle
-			,IOCTL_ASYNC, 0x48	/* Behave as if XON Received */
-			,NULL
-			,0
-			,NULL
-			,&w
-			,sizeof(short)
-            ,NULL);
-#else // Win32
-	if(action&PAUSE)
-		EscapeCommFunction((HANDLE)rio_handle,SETXON);
-#endif
-    return(rio_getstate()); }
-
-if((action&0xff)==TXSYNC) { /* Synchronize transmition */
-    c=action>>8;            /* Number of seconds */
-	w=110+(c*1000); 		/* Number of milliseconds */
-	start=clock();
-	while(clock()-start<w) {
-		if(!outbufcnt()) {
-#ifdef __OS2__
-			DosDevIOCtl(rio_handle
-				,IOCTL_ASYNC, 0x69	/* Query # of chars in tx queue */
-				,NULL
-				,0
-				,NULL
-				,&getqueue
-				,sizeof(getqueue)
-				,NULL);
-			if(getqueue.cur==0) 	/* Empty outbound queue */
-				return(0);
-#else // Win32
-			ClearCommError((HANDLE)rio_handle,&l,&comstat);
-			if(comstat.cbOutQue==0) /* Empty outbound queue */
-				return(0);
-#endif
-			}
-#ifdef __OS2__
-		DosSleep(1);
-#else // Win32
-		Sleep(1);
-#endif
-		}
-	return(1); }
-
-return(0);
-}
-
-/* End of file */
diff --git a/src/sbbs2/rio/riolib.h b/src/sbbs2/rio/riolib.h
deleted file mode 100644
index 26718cb5c7292966f68b716d1498c25e7f89bff9..0000000000000000000000000000000000000000
--- a/src/sbbs2/rio/riolib.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* RIOLIB.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _RIOLIB_H
-#define _RIOLIB_H
-
-#include "gen_defs.h"
-
-int 	rioini(int com,int irq);		/* initialize com,irq */
-int 	setbaud(int rate);				/* set baud rate */
-int 	rioctl(ushort action);			/* remote i/o control */
-int 	dtr(char onoff);				/* set/reset dtr */
-int 	outcom(int ch); 				/* send character */
-int 	incom(void);					/* receive character */
-int 	ivhctl(int intcode);			/* local i/o redirection */
-
-/* Win32 and OS/2 versions only */
-
-long	rio_getbaud(void);				/* get current baud rate */
-int 	rio_getstate(void); 			/* get current current state */
-void	outcom_thread(void *);
-
-extern	int rio_handle;
-
-#endif	/* Don't add anything after this line */
diff --git a/src/sbbs2/sbbs.h b/src/sbbs2/sbbs.h
deleted file mode 100644
index b805601adfb7d971491b6dec1bf60fd557816380..0000000000000000000000000000000000000000
--- a/src/sbbs2/sbbs.h
+++ /dev/null
@@ -1,472 +0,0 @@
-/* SBBS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _SBBS_H
-#define _SBBS_H
-
-/****************************/
-/* Standard library headers */
-/****************************/
-
-#include <io.h>
-#ifdef __TURBOC__
-	#include <dir.h>
-	#include <alloc.h>
-#else
-	#include <malloc.h>
-#endif
-
-#include <dos.h>
-#include <mem.h>
-#include <time.h>
-#include <errno.h>
-#include <stdio.h>
-#include <conio.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <share.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <process.h>
-#include <sys\stat.h>
-
-#ifdef __OS2__
-	#define INCL_BASE
-    #include <os2.h>
-#else
-	#include <bios.h>
-#endif
-
-#define GLOBAL extern	/* turn vars.c and scfgvars.c files into headers */
-#ifdef SBBS
-#include "vars.c"
-#endif
-#include "smblib.h"
-#include "ars_defs.h"
-#include "scfgvars.c"
-#include "scfglib.h"
-#include "riolib.h"
-#include "riodefs.h"
-
-/***********************************************/
-/* Prototypes of functions used ONLY with SBBS */
-/***********************************************/
-
-
-void lputc(int);
-int  lclatr(int);
-uint lkbrd(int);
-int  lclaes(void);
-void lclxy(int,int);
-int  lclwx(void);
-int  lclwy(void);
-long lputs(char FAR16 *);
-
-#ifndef __FLAT__
-
-/* LCLOLL.ASM */
-int  lclini(int);
-
-#endif
-
-/* COMIO.C */
-void putcom(char *str);			/* Send string to com port */
-void putcomch(char ch);			/* Send single char to com port */
-void mdmcmd(char *str); 		/* Send translated modem command to COM */
-char getmdmstr(char *str, int sec);  /* Returns chars  */
-void hangup(void);				/* Hangup modem							*/
-void offhook(void);				/* Takes phone offhook					*/
-void checkline(void);			/* Checks if remote user has hungup		*/
-void comini(void);				/* initializes com port and sets baud   */
-void setrate(void); 			/* sets baud rate for current connect	*/
-
-/* DATIO.C */
-void getuserdat(user_t *user); 	/* Fill userdat struct with user data   */
-void putuserdat(user_t user);	/* Put userdat struct into user file	*/
-void getuserrec(int usernumber, int start, char length, char *str);
-void putuserrec(int usernumber, int start, char length, char *str);
-ulong adjustuserrec(int usernumber, int start, char length, long adj);
-void subtract_cdt(long amt);
-void getrec(char *instr,int start,int length,char *outstr);
-								/* Retrieve a record from a string		*/
-void putrec(char *outstr,int start,int length,char *instr);
-								/* Place a record into a string			*/
-uint matchuser(char *str);		/* Checks for a username match		*/
-uint finduser(char *str);
-uint lastuser(void);
-char getage(char *birthdate);
-
-int 	sub_op(uint subnum);
-ulong	getlastmsg(uint subnum, ulong *ptr, time_t *t);
-time_t	getmsgtime(uint subnum, ulong ptr);
-ulong	getmsgnum(uint subnum, time_t t);
-ulong getposts(uint subnum);
-
-int  getfiles(uint dirnum);
-int  dir_op(uint dirnum);
-int  getuserxfers(int fromuser, int destuser, char *fname);
-void rmuserxfers(int fromuser, int destuser, char *fname);
-char *username(int usernumber, char *str);
-uint gettotalfiles(uint dirnum);
-void getnodeext(uint number, char *str);
-void putnodeext(uint number, char *str);
-void getnodedat(uint number, node_t *node, char lock);
-void putnodedat(uint number, node_t node);
-void putusername(int number, char *name);
-void nodesync(void);
-void getmsgptrs(void);
-void putmsgptrs(void);
-void getusrsubs(void);
-void getusrdirs(void);
-uint userdatdupe(uint usernumber, uint offset, uint datlen, char *dat
-	, char del);
-void gettimeleft(void);
-
-/* FILIO.C */
-char addfiledat(file_t *f);
-void getfileixb(file_t *f);
-void getfiledat(file_t *f);
-void putfiledat(file_t f);
-char uploadfile(file_t *f);
-void downloadfile(file_t f);
-void removefiledat(file_t f);
-void fileinfo(file_t f);
-void openfile(file_t f);
-void closefile(file_t f);
-void update_uldate(file_t f);
-void putextdesc(uint dirnum, ulong datoffset, char *ext);
-void getextdesc(uint dirnum, ulong datoffset, char *ext);
-void viewfilecontents(file_t f);
-
-/* STR.C */
-void userlist(char subonly);
-char gettmplt(char *outstr, char *template, int mode);
-void sif(char *fname, char *answers, long len);	/* Synchronet Inteface File */
-void sof(char *fname, char *answers, long len);
-void create_sif_dat(char *siffile, char *datfile);
-void read_sif_dat(char *siffile, char *datfile);
-void printnodedat(uint number, node_t node);
-void reports(void);
-char inputnstime(time_t *dt);
-char chkpass(char *pass, user_t user);
-char *cmdstr(char *instr, char *fpath, char *fspec, char *outstr);
-void getcomputer(char *computer);
-void subinfo(uint subnum);
-void dirinfo(uint dirnum);
-char trashcan(char *insearch, char *name);
-#ifdef SBBS
-char *decrypt(ulong [],char *);
-#endif
-
-/* MSGIO.C */
-void automsg(void);
-char writemsg(char *str, char *top, char *title, int mode, int subnum
-	,char *dest);
-char putmsg(char HUGE16 *str, int mode);
-char msgabort(void);
-void email(int usernumber, char *top, char *title, char mode);
-void forwardmail(smbmsg_t *msg, ushort usernum);
-char postmsg(uint subnum, smbmsg_t *msg, int wm_mode);
-void removeline(char *str, char *str2, char num, char skip);
-ulong msgeditor(char *buf, char *top, char *title);
-void editfile(char *path);
-void getsmsg(int usernumber);
-void putsmsg(int usernumber, char *strin);
-void getnmsg(void);
-void putnmsg(int num, char *strin);
-int loadmsg(smbmsg_t *msg, ulong number);
-char HUGE16 *loadmsgtxt(smbmsg_t msg, int tails);
-ushort chmsgattr(ushort attr);
-void show_msgattr(ushort attr);
-void show_msghdr(smbmsg_t msg);
-void show_msg(smbmsg_t msg, int mode);
-void msgtotxt(smbmsg_t msg, char *str, int header, int tails);
-void quotemsg(smbmsg_t msg, int tails);
-void putmsg_fp(FILE *fp, long length, int mode);
-void editmsg(smbmsg_t *msg, uint subnum);
-void remove_re(char *str);
-void remove_ctrl_a(char *instr);
-
-/* MAIL.C */
-
-ulong loadmail(mail_t **mail, uint usernumber, int which, int mode);
-int getmail(int usernumber, char sent);
-int delmail(uint usernumber,int which);
-void delfattach(uint to, char *title);
-void telluser(smbmsg_t msg);
-void delallmail(uint usernumber);
-void readmail(uint usernumber, int sent);
-
-void bulkmail(uchar *ar);
-
-/* CONIO.C */
-int  bputs(char *str);				/* BBS puts function */
-int  rputs(char *str);				/* BBS raw puts function */
-int  lprintf(char *fmt, ...);		/* local printf */
-int  bprintf(char *fmt, ...);		/* BBS printf function */
-int  rprintf(char *fmt, ...);		/* BBS raw printf function */
-int  getstr(char *str,int length, long mode);
-void outchar(char ch);			/* Output a char - check echo and emu.  */
-char r0dentch(char ch);			/* Converts CH to r0dent CH				*/
-char getkey(long mode); 		 /* Waits for a key hit local or remote  */
-void ungetkey(char ch);			/* Places 'ch' into the input buffer    */
-char inkey(int mode);				/* Returns key if one has been hit		*/
-char yesno(char *str);
-char noyes(char *str);
-void printfile(char *str, int mode);
-void printtail(char *str, int lines, int mode);
-void menu(char *code);
-long getkeys(char *str, ulong max);
-long getnum(ulong max);
-void center(char *str);
-int  uselect(int add, int n, char *title, char *item, char *ar);
-void statusline(void);
-void pause(void);
-void waitforsysop(char on);
-void riosync(char abortable);
-char validattr(char a);
-char stripattr(char *str);
-void redrwstr(char *strin, int i, int l, char mode);
-void mnemonics(char *str);
-void attr(int atr);				/* Change local and remote text attributes */
-void ctrl_a(char x);			/* Peforms the Ctrl-Ax attribute changes */
-int  atcodes(char *code);
-char *ansi(char atr);			/* Returns ansi escape sequence for atr */
-int  whos_online(char listself);/* Lists active nodes, returns active nodes */
-
-/* LOGONOFF.C */
-int login(char *str, char *pw);
-char logon(void);
-void logout(void);
-void logoff(void);
-void newuser(void);					/* Get new user							*/
-void backout(void);
-
-/* BBSIO.C */
-char scanposts(uint subnum, char newscan, char *find);	/* Scan sub-board */
-int  searchsub(uint subnum, char *search);	/* Search for string on sub */
-int  searchsub_toyou(uint subnum);
-char text_sec(void);						/* Text sections */
-
-/* CHAT.C */
-void localchat(void);
-void chatsection(void);
-void nodepage(void);
-void nodemsg(void);
-void guruchat(char *line, char *guru, int gurunum);
-char guruexp(char **ptrptr, char *line);
-void localguru(char *guru, int gurunum);
-void packchatpass(char *pass, node_t *node);
-char *unpackchatpass(char *pass, node_t node);
-void sysop_page(void);
-void privchat(void);
-
-/* MAIN.C */
-void printstatslog(uint node);
-ulong logonstats(void);
-void logoffstats(void);
-void getstats(char node, stats_t *stats);
-
-/* MISC.C */
-void bail(int code);			/* Exit 								*/
-char *ultoac(ulong l,char *str);
-int  bstrlen(char *str);
-int  nopen(char *str, int access);
-FILE *fnopen(int *file, char *str,int access);
-char *sectostr(uint sec, char *str);		/* seconds to HH:MM:SS */
-void truncsp(char *str);		/* Truncates white spaces off end of str */
-ulong ahtoul(char *str);	/* Converts ASCII hex to ulong */
-int  pstrcmp(char **str1, char **str2);  /* Compares pointers to pointers */
-int  strsame(char *str1, char *str2);	/* Compares number of same chars */
-void errormsg(int line, char *file, char action, char *object, ulong access);
-int  mv(char *src, char *dest, char copy); /* fast file move/copy function */
-char chksyspass(int local);
-char *timestr(time_t *intime);  /* ASCII representation of time_t */
-char *zonestr(short zone);
-void dv_pause(void);
-void secwait(int sec);
-time_t ftimetounix(struct ftime f);
-struct ftime unixtoftime(time_t unix);
-time_t dstrtounix(char *str);	/* ASCII date (MM/DD/YY) to unix conversion */
-char *unixtodstr(time_t unix, char *str); /* Unix time to ASCII date */
-char *hexplus(uint num, char *str); 	/* Hex plus for 3 digits up to 9000 */
-uint hptoi(char *str);
-int chk_ar(char *str, user_t user); /* checks access requirements */
-ushort crc16(char *str);
-ulong  _crc32(char *str);
-void ucrc16(uchar ch, ushort *rcrc);
-int kbd_state(void);
-
-#ifndef __FLAT__
-long lread(int file, char HUGE16 *buf, long bytes);   /* Reads >32k files */
-long lfread(char huge *buf, long bytes, FILE *fp);
-long lwrite(int file, char HUGE16 *buf, long bytes);   /* Writes >32k files */
-#endif
-
-/* XFER.C */
-int listfile(char *fname, char HUGE16 *buf, uint dirnum
-	, char *search, char letter, ulong datoffset);
-int  listfiles(uint dirnum, char *filespec, int tofile, char mode);
-int  listfileinfo(uint dirnum, char *filespec, char mode);
-void batchmenu(void);
-void temp_xfer(void);
-void batch_add_list(char *list);
-void notdownloaded(ulong size, time_t start, time_t end);
-int viewfile(file_t f, int ext);
-
-/* XFERMISC.C */
-void seqwait(uint devnum);
-void listfiletofile(char *fname, char HUGE16 *buf, uint dirnum, int file);
-void upload(uint dirnum);
-char bulkupload(uint dirnum);
-void extract(uint dirnum);
-char *getfilespec(char *str);
-int  delfiles(char *path, char *spec);
-char findfile(uint dirnum, char *filename);
-char fexist(char *filespec);
-long flength(char *filespec);
-long fdate(char *filespec);
-long fdate_dir(char *filespec);
-char *padfname(char *filename, char *str);
-char *unpadfname(char *filename, char *str);
-char filematch(char *filename, char *filespec);
-int  protocol(char *cmdline, int cd);
-void autohangup(void);
-char checkprotlog(file_t f);
-char checkfname(char *fname);
-void viewfiles(uint dirnum, char *fspec);
-char addtobatdl(file_t f);
-int  fnamecmp_a(char **str1, char **str2);	 /* for use with resort() */
-int  fnamecmp_d(char **str1, char **str2);
-int  fdatecmp_a(uchar **buf1, uchar **buf2);
-int  fdatecmp_d(uchar **buf1, uchar **buf2);
-void resort(uint dirnum);
-int  create_batchup_lst(void);
-int  create_batchdn_lst(void);
-int  create_bimodem_pth(void);
-void batch_upload(void);
-void batch_download(int xfrprot);
-void start_batch_download(void);
-ulong create_filelist(char *name, char mode);
-
-/* XTRN.C */
-int  external(char *cmdline,char mode); /* Runs external program */
-void xtrndat(char *name, char *dropdir, uchar type, ulong tleft);
-char xtrn_sec(void);					/* The external program section  */
-void exec_xtrn(uint xtrnnum);			/* Executes online external program */
-void user_event(char event);			/* Executes user event(s) */
-char xtrn_access(uint xnum);			/* Does useron have access to xtrn? */
-char *temp_cmd(void);					/* Returns temp file command line */
-
-/* LOGIO.C */
-void logentry(char *code,char *entry);
-void log(char *str);				/* Writes 'str' to node log */
-void logch(char ch, char comma);	/* Writes 'ch' to node log */
-void logline(char *code,char *str); /* Writes 'str' on it's own line in log */
-void logofflist(void);              /* List of users logon activity */
-void errorlog(char *text);			/* Logs errors to ERROR.LOG and NODE.LOG */
-#if DEBUG
-void dlog(int line, char *file, char *text);	/* Debug log file */
-#endif
-
-/* QWK.C */
-void	qwk_sec(void);
-char	pack_qwk(char *packet, ulong *msgcnt, int prepack);
-void	unpack_qwk(char *packet,uint hubnum);
-
-
-/* FIDO.C */
-void	netmail(char *into, char *subj, char mode);
-void	qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub);
-
-void inetmail(char *into, char *subj, char mode);
-void qnetmail(char *into, char *subj, char mode);
-
-/* USEREDIT.C */
-void useredit(int usernumber, int local);
-void maindflts(user_t user);
-void purgeuser(int usernumber);
-
-/* INITDATA.C */
-void initdata(void);
-
-/* VER.C */
-void ver(void);
-
-/* MAIN_SEC.C */
-void main_sec(void);
-void scanallsubs(char mode);
-void scansubs(char mode);
-void new_scan_cfg(ulong misc);
-void new_scan_ptr_cfg(void);
-
-/* XFER_SEC.C */
-void xfer_sec(void);
-void scanalldirs(char mode);
-void scandirs(char mode);
-
-/* MSWAIT.OBJ */
-
-void mswait(int msecs);
-
-#ifdef __OS2__
-#define beep(f,d) DosBeep(f,d)
-#else
-void beep(int freq, int dur);
-#endif
-
-void backslash(char *str);
-void backslashcolon(char *str);
-void getlines(void);
-void strip_ctrl(char *str);
-void strip_exascii(char *str);
-
-char wfc_events(time_t lastnodechk);
-void catsyslog(int crash);
-char waitforcall(void);
-void quicklogonstuff(void);
-char terminal(void);
-void startup(int argc, char *argv[]);
-
-void crack_attempt(void);
-
-/*********************/
-/* OS specific stuff */
-/*********************/
-
-#ifdef __FLAT__
-
-#define lread(f,b,l) read(f,b,l)
-#define lfread(b,l,f) fread(b,l,f)
-#define lwrite(f,b,l) write(f,b,l)
-#define lfwrite(b,l,f) fwrite(b,l,f)
-
-#endif
-
-#if (__BORLANDC__ > 0x0410)
-#define _chmod(p,f,a) _rtl_chmod(p,f,a) 	// _chmod obsolete in 4.x
-#endif
-
-#if defined(__OS2__)
-	#define lclini(x)	window(1,1,80,x)
-	#define lclaes()	conaes()
-    #define nosound() ;
-#elif defined(__WIN32__)
-	#define lclini(x)	window(1,1,80,x)
-	#define lclxy(x,y)	gotoxy(x,y)
-	#define lclwy() 	wherey()
-	#define lclwx() 	wherex()
-	#define lputs		cputs
-    #define nosound() ;
-#elif defined(__FLAT__)
-    #define mswait(x) delay(x)
-#endif
-
-#ifndef __OS2__
-	#define outcon(ch) lputc(ch)
-#endif
-
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/sbbs_src.doc b/src/sbbs2/sbbs_src.doc
deleted file mode 100644
index 00e265731777b4c4f42ea5f384a33eb5ac9aa06b..0000000000000000000000000000000000000000
--- a/src/sbbs2/sbbs_src.doc
+++ /dev/null
@@ -1,660 +0,0 @@
-       Synchronet BBS Software and Utilities C Source Code Documentation
-       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-			Created April 1997, Rob Swindell
-		      Updated September 1997, Rob Swindell
-		      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Official Synchronet Web Site:
-	http://www.weedpuller.com/synchronet
-Latest version of the source code and this document stored at:
-	ftp://ftp.weedpuller.com/synchronet
-Post public questions are comments on the freelance Synchronet listserv:
-	mailto:synchronet@freelance.com
-Send bug fixes or comments
-	mailto:sbbs@weedpuller.com
-
-I no-longer monitor any BBS-related newsgroups (too flakey and spam-ridden).
-
-History
-=======
-
-The Synchronet BBS software project began in December of 1990 when I started
-writing my very own BBS program from the ground up. While it is true that I ran
-Wayne Bell's WWIV BBS software for a number of years and an illicit copy of the
-WWIV source code was my first exposure to the C Programming Language, I didn't
-steal, borrow, or otherwise copy the WWIV source code for use in Synchronet in
-any way. I did refer to Wayne's code from time to time when implementing
-WWIV-compatible features like WWIV color codes, but I didn't need (or want) to
-copy his source. I do wish to take this moment, however, to extend my
-appreciation to Wayne Bell for his contributions to the BBS and hacker
-communities, and for personally inspiring me to write a better BBS! ;-)
-
-In 1992, Synchronet became a commercial venture for me (under the company name
-Digital Dynamics) and was my sole source of income for over three years. The
-commercialization of the Internet, and in paticular, the Wolrd Wide Web, has
-all but eliminated the commercial BBS software market and in 1996, I officially
-announced the end of Digital Dynamics (in the "Digital Manifesto"). In February
-of 1997, my own BBS, Vertrauen, was abruptly shut-down. This time for good.
-From September of 1988 to February of 1997, Vertrauen (German for "Trust")
-answered the phone at 714-529-9525 24 hours a day, 7 days a week. It went from
-a 1 line "pirate" BBS running WWIV on an 8mhz 8088 to a 7 node Synchronet
-BBS running on two 66mhz 486s connected to a Novell NetWare 3.12 file server
-with many gigabytes of disk space, 7 CD-ROMS, Planet Connect Fidonet feed, the
-whole nine yards - pretty much everything except Internet access (never could
-justify the monthly costs of a full-time connection).
-
-Today, I personally have very little interest in BBSs (using or operating them)
-and my programming interests have been focused elsewhere for quite some time
-(Internet communication products). For this reason, I am releasing the
-complete source code (in C) for Synchronet BBS software and all other Digital
-Dynamics' utilites. Since I expect no futher income from Synchronet BBS
-software and have no plans on enhancing or supporting the product in any way, I
-thought the least I could do was to package up, document, and publicly release
-the source code for others to continue enhancing as they wish.
-
-
-Disclaimer
-==========
-
-The accompanying source code (and this documentation) are not intended for the
-beginning, or possibly even intermediate, programmer. You must have a healthy
-knowledge of DOS, MAKEFILES, and the C Programming Language for this source
-code to be of any use to you. Of course, beginners are encouraged to learn
-(hopefully with the help of a friend or two) from the included projects - just
-don't get too irritated if things don't compile and link the first time.
-
-It is my hope that a hand full of capable young hackers will take Synchronet
-into new directions. Hopefully, retaining the original name (Synchronet) in
-some form, although there is no way for me to enforce this. I assume that some
-will make minor modifications and re-release compiled versions under their name
-with no credit to my work or the history of Synchronet, but while that isn't
-"cool", it isn't illegal either. I am releasing the rights to every piece of
-code accompanying this document to the public domain. That means that anyone
-and everyone can do with it whatever they like as far as I'm concerned.
-
-I, Rob Swindell, author of Synchronet, owner of Digital Dynamics, hereby
-relinquish the copyright of Synchronet BBS software and all Synchronet-related
-Digital Dynamics' utilities to the public domain. I am offering no warranties
-of any kind. Use at your own risk.
-
-
-Required Tools				Version 		Project(s)
-==============				------- 		----------
-
-Borland C++ for DOS and Windows 	3.1			SBBS.EXE
-								SBJ.EXE
-								SBL.EXE
-								SCB.EXE
-								SMM.EXE
-								UTI*.EXE
-								ADDFILES.EXE
-								DELFILES.EXE
-								DUPEFIND.EXE
-								FILELIST.EXE
-								SMBACTIV.EXE
-
-  Note: Newer versions of Borland C++ tended to create larger, more memory
-	hungry executables, so I stayed with 3.1 for these 16-bit DOS versions
-	(where available DOS memory was a never ending issue with sysops).
-	Newer versions of Borland C++ will work (with slight changes to the
-	appropriate MAKEFILEs) for the above projects. The last five projects
-	listed above are built with MAKEFILE.BC (i.e. make -fmakefile.bc)
-	instead of MAKEFILE (used for Watcom).
-
-Borland C++ for DOS, Windows, and Win32 4.5			SCFG.EXE
-								SCFG32.EXE
-								BAJA.EXE
-								BAJA32.EXE
-								SBBS4W32.EXE
-								INSTALL.EXE
-								QWKNODES.EXE
-								SBBSECHO.EXE
-								SMB2SBL.EXE
-								SBL2SMB.EXE
-								SMB2SMM.EXE
-								SMM2SMB.EXE
-								NODE.COM
-								SLOG.EXE
-								DSTSEDIT.EXE
-								ANS2MSG.EXE
-                                                                MSG2ANS.EXE
-								EXECSBBS.COM
-
-  Note: SBBS4W32.EXE, the 32-bit Windows version of Synchronet, is incomplete.
-	Again, newer versions of Borland C++ (4.51, 5.x, etc) will probably
-	work fine with slight changes to the appropriate MAKEFILEs. SCFG32.EXE
-	is a native Win32 app that also runs under DOS (using Borland's DOS
-	extender) - I don't know why the gettext/puttext is messed up.
-	You'll need EXE2BIN.EXE (included with MS-DOS) to create EXECSBBS.COM.
-
-
-Borland C++ for OS/2			2.0			SBBS4OS2.EXE
-								SCFG4OS2.EXE
-								SBBSECHO.EXE
-								ADDFILES.EXE
-								BAJA4OS2.EXE
-								DELFILES.EXE
-								DUPEFIND.EXE
-								FILELIST.EXE
-								INSTALL.EXE
-								NODE.EXE
-								SLOG.EXE
-								CHKSMB.EXE
-								FIXSMB.EXE
-								SMBUTIL.EXE
-								SMBACTIV.EXE
-								DSTSEDIT.EXE
-								ANS2MSG.EXE
-								MSG2ANS.EXE
-								EXECSBBS.EXE
-								
-  Note: Watcom makefiles are available for many of these projects and have
-	the advantage of being able to be built from any environment (DOS,
-	Windows, or OS/2) and create executables that run under all those
-	environments. Borland C++ for OS/2, on the otherhand, can only be
-	used in an OS/2 environment and can only create OS/2 executables.
-	While Borland's C++ compilers definitely compile faster, the resulting
-	exectubles created by Watcom C++ are usually smaller and faster.
-	Any of the projects that don't already have support for Borland C++
-	for OS/2, can probably be easily modified to do so (this excludes
-	XSDK apps). Most popular executables are already supported.
-
-
-Watcom C++				10.0a			ADDFILES.EXE
-								AUTONODE.EXE
-								DELFILES.EXE
-								DUPEFIND.EXE
-								FILELIST.EXE
-								SBBSECHO.EXE
-								SMBUTIL.EXE
-								SMBACTIV.EXE
-
-  Note: All flavors (16-bit DOS, 32-bit DOS, 32-bit OS/2, and 32-bit Windows)
-	Love the cross-platform capabilites of Watcom C++!
-	The NT\*.EXE files are Win32 executables that run native under either
-	Windows 95 or Windows NT.
-	The DOSX\*.EXE and DOS4G\*.EXE files are extended DOS executables that
-	need DOS4G.EXE or DOS4GW.EXE (included with Watcom C++) in the search
-	path. (Sorry 'bout the inconsistency in the sub-directory names,
-	there's no difference between DOSX and DOS4G except that I used to have
-	some extended DOS Borland projects write to the DOSX directories).
-
-	*** IMPORTANT ***
-	1) It is important that you delete all the files from the DOS and OS2
-	   destination sub-directories (use CLEANALL.BAT) if you've previously
-	   built a project using Borland C++ and wish to re-build it using
-	   Watcom. The .OBJ files are NOT compatible between Watcom and Borland
-	   (without some special effort).
-	2) You must copy \WATCOM\SRC\STARTUP\WILDARGV.C from the Watcom C++
-	   installation directory (or CD-ROM) into the SBBS\SMB\SMBUTIL
-	   directory before attempting a Watcom build on the SMBUTIL project.
-	   It's a copyrighted file, so I couldn't include it.
-
-	Watcom can be/could have been used for some of the Borland-only
-	projects, but due to its slow compile speed, I only used it for the
-	projects that needed the best extended DOS support (DOS4G blows away
-	Borland's DOS extender) and cross-platform compile (it was a pain to
-	boot OS/2 every time I needed to build an OS/2 executable with Borland
-	C++ for OS/2). Plus, Watcom's text-mode screen-libraries were sorely
-	lacking (hence no CFG.EXE projects are built with Watcom).
-
-Tool Notes
-==========
-
-As noted aboved, Borland C++ v4.5 (or possibly newer versions) may be used for
-SBBS.EXE (and other BC v3.1 projects), but you will have less available DOS
-memory (the executable will consume more memory).
-
-Borland C++ v4.5 can also be used for many of the Watcom compiled utilities.
-If you find MAKEFILE.BC in any of the Watcom compiled project directories, you
-can use this makefile to build a 16-bit DOS, 32-bit OS/2, and in some cases
-32-bit DOS executable with Borland C++. Likewise, any *.WAT makefiles (and most
-of the MAEKALL.BAT files) are intended for use with Watcom C++.
-
-
-Project Notes
-=============
-
-Most projects are built via MAKEFILE and/or .BAT/.CMD file. If you find a
-MAKEALL.BAT or MAKEALL.CMD (for OS/2) file in any of the project directories,
-this batch file is used to compile and link versions for all supported
-platforms (e.g. DOS-16, DOS-32, OS/2, Win32, etc).
-
-If a MAKEFILE or *.MAK file doesn't exist in the project directory, there may
-be a simple MAKE.BAT/MAKE.CMD to build the executable. The simplest projects
-may not include any type of MAKEFILE, BAT, or CMD file, but just require a
-basic CC command line to compile and link into an executable (only the most
-independant and smallest projects fit into this category).
-
-The MAKEALL.BAT file in the source ROOT directory is used to build ALL
-Borland C++ DOS and Win32 projects.
-
-The MAKEALL.CMD file in the source ROOT directory is used to build ALL
-Borland C++ OS/2 projects.
-
-The WMAKEALL.BAT file in the source ROOT directory is used to build ALL
-Watcom C++ DOS, DOS4G, OS/2 and Win32 projects.
-
-Sub-directories are usually used to house the output files (.OBJ, .EXE, .MAP,
-etc) for each supported platform. Sub-directories with the name DOS are used
-for 16-bit DOS output files; sub-directories of DOSX, DOS32, or DOS4G are used
-for 32-bit extended DOS output files; sub-directories of OS2 contain 32-bit
-OS/2 output files; subdirectories of NT or W32 contain 32-bit Windows
-(Windows NT or Windows 95) output files. In the more simple projects (e.g.
-BAJA*.EXE), no sub-directories are utilized.
-
-The makefiles (MAKEFILE.*, *.MAK, *.BC, *.WAT) are setup for my environment.
-You will most likely need to make changes to these makefiles for your
-environment. For reference purposes, these are the path locations of the
-various tools in my environment:
-
-Path			Tool
-----			----
-N:\BC31 		Borland C++ for DOS and Windows v3.1
-N:\BC45 		Borland C++ for DOS, Windows, and Win32 v4.5
-C:\BCOS2		Borland C++ for OS/2 v2.0
-N:\WATCOM		Watcom C++ v10.0a
-
-My system PATH environment variable contains N:\BC45\BIN, N:\WATCOM\BINB,
-and N:\WATCOM\BIN. So if you see references (without path) to BCC, then that
-would indicate Borland C++ v4.5. MAKE and MAKER are Borland's MAKE utilities
-(included with Borland C++ v4.5, the latter being the 16-bit real mode
-version). WMAKE is the Watcom MAKE utility.
-
-My N:\BCxx\BIN\TURBOC.CFG file contains:
-
--IN:\BCxx\INCLUDE
--LN:\BCxx\LIB
-
-I've made an effort to eliminate the project drive letter (N:) from all
-MAKEFILEs and BATch files, but some references may still remain. If you only
-have one hard disk on your system (C:) or your projects are stored on the same
-drive the compiler(s) is/are installed on, then simply eliminating any drive
-letter specifications is suggested.
-
-Efforts have been made to eliminate all compiler warnings, but in some cases
-warnings may persist. Especially when using a different compiler or version
-than I have used. Any warnings in the source code I'm releasing may be safely
-ignored. If you or anyone else has modified the code, then warnings in the
-modified files should be investigated at your discretion.
-
-
-Directory Hierachry
-===================
-
-If extracted correctly, the archive that contained this document should have
-created a directory hierarchy similar to the following:
-
-�� SBBS ����������� ADDFILES ������� DOS
-�		 �		  �� DOSX
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� ALLUSERS
-�		 �� ANS2MSG
-�		 �� AUTONODE
-�		 �� BAJA
-�		 �� DCDWATCH
-�		 �� DELFILES ������� DOS
-�		 �		  �� DOSX
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� DOS
-�		 �� DSTSEDIT
-�		 �� DUPEFIND ������� DOS
-�		 �		  �� DOSX
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� ECHO ����������� DOS
-�		 �		  �� DOS4G
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� EXECDOS
-�		 �� EXECSBBS ������� DOS
-�		 �		  �� OS2
-�		 �� FILELIST ������� DOS
-�		 �		  �� DOSX
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� INSTALL �������� DOS
-�		 �		  �� OS2
-�		 �� MLABELS
-�		 �� MSG2ANS
-�		 �� MSWAIT ��������� DOS
-�		 �� NODE ����������� DOS
-�		 �		  �� OS2
-�		 �� OS2
-�		 �� QWKNODES
-�		 �� RIO
-�		 �� SBL
-�		 �� SBJ
-�		 �� SCB
-�		 �� SCFG ����������� DOS
-�		 �		  �� DOS32
-�		 �		  �� OS2
-�		 �� SDK
-�		 �� SLOG ����������� DOS
-�		 �		  �� OS2
-�		 �� SMB ������������ CHKSMB ��������� DOS
-�		 �		  �		   �� OS2
-�		 �		  �� FIXSMB ��������� DOS
-�		 �		  �		   �� OS2
-�		 �		  �� SMBUTIL �������� DOS
-�		 �				   �� DOS4G
-�		 �				   �� NT
-�		 �				   �� OS2
-�		 �� SMBACTIV ������� DOS
-�		 �		  �� DOSX
-�		 �		  �� NT
-�		 �		  �� OS2
-�		 �� SMM
-�		 �� UTI
-�		 �� W32
-�� MSWAIT ��������� DOS
-�� SPAWNO
-�� STP
-�� TONE
-�� UIFC
-
-Directory Descriptions
-----------------------
-SBBS\		Synchronet source code and shared header files
-SBBS\SMB\	Synchronet Message Base library and header files
-...\CHKSMB\	Source for utility to check Synchronet message bases for errors
-...\FIXSMB\	Source for utility to rebuild Synchronet message base indices
-...\SMBUTIL\	Synchronet message base maintenance utility (SMBUTIL) source
-SBBS\RIO\	OS/2 and Win32 Remote I/O library source and header files
-SBBS\SDK\	Synchronet External program SDK (XSDK) source and header files
-SBBS\SMM\	Synchronet Match Maker and utility source
-SBBS\SCB\	Synchronet Callback source
-SBBS\SBJ\	Synchronet Blackjack source
-SBBS\SBL\	Synchronet BBS List source
-SBBS\UTI\	Synchronet UTI driver (for PostLink/RelayNet/RIME) source
-SBBS\SCFG\	Synchronet Configuration program source
-SBBS\BAJA\	Synchronet shell/module compiler (BAJA.EXE) source
-SBBS\ECHO\	SBBSecho (FidoNet echomail program) source
-SBBS\EXECDOS\	Synchronet for OS/2's EXECDOS.EXE source
-SBBS\EXECSBBS\	EXECSBBS.COM/EXE (for SBBS4DOS/OS2) source
-SBBS\DCDWATCH\	DCDWATCH.EXE source
-SBBS\ADDFILES\	ADDFILES.EXE source
-SBBS\DELFILES\	DELFILES.EXE source
-SBBS\DUPEFIND\	DUPEFIND.EXE source
-SBBS\FILELIST\	FILELIST.EXE source
-SBBS\ALLUSERS\	ALLUSERS.EXE source
-SBBS\MLABELS\	MLABLES.EXE source
-SBBS\ANS2MSG\	ANS2MSG.EXE source
-SBBS\MSG2ANS\	MSG2ANS.EXE source
-SBBS\AUTONODE\	AUTONODE.EXE source
-SBBS\SMBACTIV\	SMBACTIV.EXE source
-SBBS\QWKNODES\	QWKNODES.EXE source
-SBBS\SLOG\	SLOG.EXE source
-SBBS\NODE\	NODE.COM/EXE source
-SBBS\DSTSEDIT\	DSTSEDIT.EXE source
-SBBS\INSTALL\	INSTALL.EXE source
-MSWAIT\ 	MSWAIT\DOS\MSWAIT.OBJ (millisecond wait) source
-SPAWNO\ 	Ralf Brown's EMS/XMS/disk swapping replacement for spawn...()
-STP\		Synchronet Transfer Protocols (X/Y/Zmodem) [incomplete]
-TONE\		Tone generator (used for external sysop chat pager)
-UIFC\		User Interface library source and header files (for *CFG.EXE)
-
-Note: If you don't recognize the name of a program or utility, see SYSOP.DOC.
-Note: Source code for SBBS\DOS\RCIOL.OBJ is not provided because I don't have
-      it (the consultant that developed this module never supplied me with the
-      latest version of the source code).
-
-
-C Header File Notes
-===================
-
-SBBS\SBBS.H
------------
-This is the main shared header file for Synchronet and Synchronet related
-utilities. This header file contains prototypes for most all functions
-contained in SBBS.EXE. But, more importantly, it #includes SMBLIB.H (which
-indirectly #includes SMBDEFS.H), ARS_DEFS.H (which indirectly #includes
-GEN_DEFS.H), SCFGVARS.C (which indirectly #includes SBBSDEFS.H, which
-indirectly #includes NODEDEFS.H), SCFGLIB.H, RIOLIB.H, RIODEFS.H, and if "SBBS"
-is defined (only in the MAKEFILE for SBBS) VARS.C (which indirectly #includes
-text.h). So, as you can see, SBBS.H pretty much covers it in the header file
-department for Synchronet and its related utilities. The only header files
-that SBBS.H doesn't directly or indirectly #include are QWK.H, POST.H, ETEXT.H,
-CMDSHELL.H, and SPAWNO.H. You will find this header file is the most commonly
-#included header file in SBBS modules and Sycnhronet related utilities. The
-comments are quite antiquated and may be safely ignored (e.g. /* DATIO.H */).
-
-SBBS\SBBSDEFS.H
----------------
-This file contains most constants, macros, and type definitions used for
-Synchronet and its utilities. Since it is indirectly #included with SBBS.H,
-you won't find it specifically #included very often.
-
-SBBS\SCFGLIB.H
---------------
-Contains type defintions and function protoypes only used in the initialization
-of Synchronet's configuration structures. Used by the SBBS and SCFG projects
-and all utilities that read Synchronet's configuration (*.CNF) files.
-
-SBBS\GEN_DEFS.H
----------------
-A small header file that contains general application independant constant
-defintions and macros. This header file is #included directly or indirectly
-with nearly every project.
-
-SBBS\ARS_DEFS.H
----------------
-Synchronet's Access Requirement Strings function prototype and constants.
-This function prototype and constants were broken out for use in the SBBS\BAJA
-(shell/module compiler) project.
-
-SBBS\CMDSHELL.H
----------------
-Contains constants, typedefs, and function prototypes specific to Synchronet's
-command shell/module interpreter. Also used in the SBBS\BAJA (shell/module
-compiler) project.
-
-SBBS\POST.H
------------
-Contains type defintions for post_t and shared function prototypes for
-the SBBS and SBBSecho projects.
-
-SBBS\QWK.H
-----------
-Contains constants, type definitions, and function prototypes only used in
-the QWK related portions of the SBBS project.
-
-SBBS\TEXT.H
------------
-Contains constant defintions (via enum) for every text item in Synchronet's
-TEXT.DAT file. Since this header file is indirectly #included with SBBS.H
-in the SBBS project, you won't find it specifically #included very often.
-
-SBBS\ETEXT.H
-------------
-Contains extern variable declarations for the encrypted text strings in the
-SBBS project. This file is automatically created (along with ETEXT.C) from
-ETEXT.DAT by the GENETEXT.EXE utility. The encrypted text strings are left
-over from the commercial version of SBBS.
-
-SBBS\VARS.C
------------
-This is a dual-purpose file. If GLOBAL isn't defined, then it's a C source
-file for all of Synchronet's global variables. SBBS.H automatically #defines
-GLOBAL to extern and #includes this file to automatically declare all global
-variables as extern. This eliminates the double-entry work of creating
-separate definitions and declarations for global variables. This file is
-only used in the SBBS project.
-
-SBBS\RIO\RIOLIB.H
------------------
-This file contains function prototypes for the Remote I/O Library API. This API
-is consistent between DOS, OS/2 and Win32 versions.
-
-SBBS\RIO\RIODEFS.H
-------------------
-Contains constants required for using the Remote I/O Library.
-
-SBBS\SMB\SMBLIB.H
------------------
-Contains constants and function prototypes for the Synchronet Message Base
-Library.
-
-SBBS\SMB\SMBDEFS.H
-------------------
-Contains constants and type definitions required for using the Synchronet
-Message Base Library.
-
-SBBS\SMB\CRC32.H
-----------------
-Standard 32-bit CRC table and macro. Also included in BAJA, SBBSecho, and
-other projects.
-
-SBBS\SCFG\SCFG.H
-----------------
-Contains constant defintions, macros, global variable declarations, and
-function prototypes for modules in the SCFG project.
-
-SBBS\ECHO\SBBSECHO.H
---------------------
-Contains constants, type definitions, and function prototypes for the
-SBBSecho project.
-
-SBBS\UTI\UTI.H
---------------
-Small header file containing global variable declarations, constants, macros,
-and a function prototype for modules in the UTI driver project.
-
-SBBS\SDK\XSDK.H
----------------
-Main header file for Synchronet external programs using the External
-program SDK (XSDK). This header file #includes XSDKVARS.C (global variable
-declarations) which indirectly #includes XSDKDEFS.H (constants and type
-defintions).
-
-UIFC\UIFC.H
------------
-Contains constants, macros, type definitions, and function prototypes for
-the local console User Interface library. Used by the SCFG, SCBCFG, SMMCFG
-and ECHOCFG projects.
-
-SPWANO\SPANWO.H
----------------
-Ralf Brown's spawno function prototypes. Used for swaping SBBS.EXE (16-bit
-DOS) out of memory.
-
-
-C Source File Notes
-===================
-
-Overlays
---------
-The SBBS project (SBBS.EXE/SBBS4OS2.EXE/SBBS4W32.EXE) contains the largest
-number of C source files and has the longest history. For a few years, SBBS.EXE
-was a small 16-bit DOS executable that executed completely in memory (no
-overlays). With each additional group of features, the executable file
-(SBBS.EXE) inevitably increased in size and memory consumption. At one point I
-started compiling two separate versions of SBBS.EXE, one with some of the
-modules overlaid (dynamically swapped to/from disk), and another without
-overlays (faster, but consumed more memory). This was the time with I began to
-split off less-commonly called functions into modules that were specifically
-overlaid (and given a filename ending in OVL.C, e.g. MAIN.C contains
-non-overlaid code, and MAIN_OVL.C contains overlaid code).
-
-As the exectuable grew larger and my knowledge and experience with optimization
-of overlaid modules grew, I stopped making the non-overlaid version
-altogether. The performance difference had become negligible and the memory
-consumption of the non-overlaid version was unwieldly. Anyway, the point of
-this little story is to help explain why so many of the filenames end in OVL.
-Eventually, I ended up overlaying most of the modules (not just the ones named
-with OVL). But still, you'll find that the code in the modules with the OVL
-names is of the less-frequently executed variety. Only the 16-bit versions of
-SBBS.EXE and SCFG.EXE use overlaid modules. All other projects (and the 32-bit
-versions of SBBS/SCFG) do not explicitly use overlays.
-
-Hi/Mid/Low Level
-----------------
-The modules with filenames containing HI (e.g. XFER_HI.C) contain high-level
-code (mostly user-interface type functions); modules with filenames containing
-MID (e.g. CON_MID.C) contain mid-level code (larger functions that don't
-contain direct user-interfaces;, and modules with filenames containing LO
-(e.g. XFER_LO.C) contain low-level code (smaller functions called frequently
-from mid or high level code).
-
-Comments
---------
-Please excuse the sparse comments; I never planned on giving the source code
-out. The source code that was originally distributed freely (SMB library and
-XSDK) is better commented.
-
-
-C Source Content Notes
-======================
-
-First off, make sure you're using an editor with tab stops set to 4 spaces
-for *.C and *.H files (QEdit works nicely), otherwise the source will be mostly
-unreadable (don't try to print the files without first exanding all tabs to
-4 space tabstops). All MAKEFILES and other text files use 8 space tab stops.
-
-If you're an experienced C programmer, the first thing you'll notice when
-examining any of the source code is my somewhat unique style. It's your basic
-K&R style C with significantly compressed whitespace. Most notably, I don't
-put closing curly braces (}) on their own line (except at the end of a
-function). Instead, I use consitent indentation to indicate nested logic and
-control flow. Also, I don't indent the base code of a function, but I do indent
-automatic variables. And I don't put white space between any operators except
-&& and ||. This style comes from the usefulness of getting as much code as
-possible in an 80x25 window (and saving printer paper). You'll notice, I do use
-blank lines to enhance readability, but there are no strict rules I follow in
-the blank line department. If my style really bugs you and you just can't get
-used to it, then run the source through a C beautifier or other such C
-formatting utility (but don't cry if it doesn't compile after that).
-
-Example (K&R style):
-
-main()
-{
-    char line[MAXLINE];
-    int found = 0;
-
-    while (getline(line, MAXLINE) > 0)
-	if (strindex(line, pattern) >= 0) {
-	    printf("%s", line);
-	    found++;
-	}
-    return found;
-}
-
-Example (my style):
-
-main()
-{
-    char line[MAXLINE];
-    int found=0;
-
-while(getline(line,MAXLINE)>0)
-    if(strindex(line,pattern)>=0) {
-	printf("%s",line);
-	found++; }
-return(found);
-}
-
-If you find blocks of code contained in "#if 0" and "#endif" or "/***" and
-"***/", you can safely ignore or even delete this code (the compiler is
-ignoring it). For some reason, I found it necessary or preferable to remove or
-replace the code in question but wished to leave the old code temporarily
-intact in case I changed my mind... I'm not going to be changing me mind. :-)
-
-I've deleted all sections of code refering to registration numbers, keys, etc.
-If you find some code remaining that appears to require a registration number
-or key of some sort, it probably can be safely ignored (unless you've found it
-impeding the operation of the program) - but there shouldn't be any.
-
-
-Last Minute Updates
-===================
-
-The UTI, FIXSMB, QWKNODES, and SBL2SMB/SMB2SBL projects were all converted from
-SMBLIB 1.x to 2.x at the last minute. They all compile, but haven't been
-tested. The differences between SMBLIB 1.x and 2.x are mainly in the calling
-conventions, so these programs should run fine, but I suppose you never know
-what could've happened.
-
-/* End of SBBS_SRC.DOC */
diff --git a/src/sbbs2/sbbsdefs.h b/src/sbbs2/sbbsdefs.h
deleted file mode 100644
index 93304c26d15cce3b3e93b7ca4bfd011c7fac0904..0000000000000000000000000000000000000000
--- a/src/sbbs2/sbbsdefs.h
+++ /dev/null
@@ -1,1330 +0,0 @@
-/* SBBSDEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/************************************************************/
-/* Constants, macros, and typedefs for use ONLY with SBBS	*/
-/************************************************************/
-
-#ifndef _SBBSDEFS_H
-#define _SBBSDEFS_H
-
-#include "gen_defs.h"
-#include "nodedefs.h"
-#include <time.h>
-
-/*************/
-/* Constants */
-/*************/
-
-#define VERSION 	"2.30"  /* Version: Major.minor  */
-#define REVISION	'C'
-#define BETA		" beta"     /* Space if non-beta, " �eta" otherwise */
-
-#define Y2K_2DIGIT_WINDOW	70
-
-/************/
-/* Maximums */
-/************/
-
-#define MAX_NODES		250
-
-#ifdef __FLAT__
-#define MAX_FILES	  10000 /* Maximum number of files per dir			*/
-#define MAX_SYSMAIL   50000 /* Maximum number of total emails in system */
-#else
-#define MAX_FILES	   1000 /* Maximum number of files per dir			*/
-#define MAX_SYSMAIL    5000 /* Maximum number of total emails in system */
-#endif
-#define MAX_USERXFER	500 /* Maximum number of dest. users of usrxfer */
-
-
-#define LEN_DIR 63			/* Maximum length of directory paths		*/
-#define LEN_CMD 63			/* Maximum length of command lines			*/
-
-							/* Lengths of various strings				*/
-#define LEN_GSNAME	15		/* Group/Lib short name						*/
-#define LEN_GLNAME	40		/* Group/Lib long name						*/
-#define LEN_SSNAME	25		/* Sub/Dir short name						*/
-#define LEN_SLNAME	40		/* Sub/Dir long name						*/
-
-								/* User Questions						*/
-#define UQ_ALIASES	(1L<<0) 	/* Ask for alias						*/
-#define UQ_LOCATION (1L<<1) 	/* Ask for location 					*/
-#define UQ_ADDRESS	(1L<<2) 	/* Ask for address						*/
-#define UQ_PHONE	(1L<<3) 	/* Ask for phone number 				*/
-#define UQ_HANDLE	(1L<<4) 	/* Ask for chat handle					*/
-#define UQ_DUPHAND	(1L<<5) 	/* Search for duplicate handles 		*/
-#define UQ_SEX		(1L<<6) 	/* Ask for sex :)						*/
-#define UQ_BIRTH	(1L<<7) 	/* Ask for birth date					*/
-#define UQ_COMP 	(1L<<8) 	/* Ask for computer type				*/
-#define UQ_MC_COMP	(1L<<9) 	/* Multiple choice computer type		*/
-#define UQ_REALNAME (1L<<10)	/* Ask for real name					*/
-#define UQ_DUPREAL	(1L<<11)	/* Search for duplicate real names		*/
-#define UQ_COMPANY	(1L<<12)	/* Ask for company name 				*/
-#define UQ_NOEXASC	(1L<<13)	/* Don't allow ex-ASCII in user text    */
-#define UQ_CMDSHELL (1L<<14)	/* Ask for command shell				*/
-#define UQ_XEDIT	(1L<<15)	/* Ask for external editor				*/
-#define UQ_NODEF	(1L<<16)	/* Don't ask for default settings       */
-#define UQ_NOCOMMAS (1L<<17)	/* Do not require commas in location	*/
-
-
-								/* Different bits in sys_misc				*/
-#define SM_CLOSED	(1L<<0) 	/* System is clsoed to New Users			*/
-#define SM_SYSSTAT	(1L<<1) 	/* Sysops activity included in statistics	*/
-#define SM_NOBEEP	(1L<<2) 	/* No beep sound locally					*/
-#define SM_PWEDIT	(1L<<3) 	/* Allow users to change their passwords	*/
-#define SM_TIMED_EX (1L<<4) 	/* Timed event must run exclusively 		*/
-#define SM_ANON_EM	(1L<<5) 	/* Allow anonymous e-mail					*/
-#define SM_LISTLOC	(1L<<6) 	/* Use location of caller in user lists 	*/
-#define SM_WILDCAT	(1L<<7) 	/* Expand Wildcat color codes in messages	*/
-#define SM_PCBOARD	(1L<<8) 	/* Expand PCBoard color codes in messages	*/
-#define SM_WWIV 	(1L<<9) 	/* Expand WWIV color codes in messages		*/
-#define SM_CELERITY (1L<<10)	/* Expand Celerity color codes in messages	*/
-#define SM_RENEGADE (1L<<11)	/* Expand Renegade color codes in messages */
-#define SM_ECHO_PW	(1L<<12)	/* Echo passwords locally					*/
-#define SM_REQ_PW	(1L<<13)	/* Require passwords locally				*/
-#define SM_L_SYSOP	(1L<<14)	/* Allow local sysop logon/commands 		*/
-#define SM_R_SYSOP	(1L<<15)	/* Allow remote sysop logon/commands		*/
-#define SM_QUOTE_EM (1L<<16)	/* Allow quoting of e-mail					*/
-#define SM_EURODATE (1L<<17)	/* Europian date format (DD/MM/YY)			*/
-#define SM_MILITARY (1L<<18)	/* Military time format 					*/
-#define SM_TIMEBANK (1L<<19)	/* Allow time bank functions				*/
-#define SM_FILE_EM	(1L<<20)	/* Allow file attachments in E-mail 		*/
-#define SM_SHRTPAGE (1L<<21)	/* Short sysop page 						*/
-#define SM_TIME_EXP (1L<<22)	/* Set to expired values if out-of-time 	*/
-#define SM_FASTMAIL (1L<<23)	/* Fast e-mail storage mode 				*/
-#define SM_QVALKEYS (1L<<24)	/* Quick validation keys enabled			*/
-#define SM_ERRALARM (1L<<25)	/* Error beeps on							*/
-#define SM_FWDTONET (1L<<26)	/* Allow forwarding of e-mail to netmail	*/
-#define SM_DELREADM (1L<<27)	/* Delete read mail automatically			*/
-#define SM_NOCDTCVT (1L<<28)	/* No credit to minute conversions allowed	*/
-#define SM_DELEMAIL (1L<<29)	/* Physically remove deleted e-mail immed.	*/
-#define SM_USRVDELM (1L<<30)	/* Users can see deleted msgs				*/
-#define SM_SYSVDELM (1L<<31)	/* Sysops can see deleted msgs				*/
-
-							/* Different bits in node_misc				*/
-#define NM_ANSALARM (1<<0)	/* Alarm locally on answer					*/
-#define NM_WFCSCRN  (1<<1)	/* Wait for call screen                     */
-#define NM_WFCMSGS	(1<<2)	/* Include total messages/files on WFC		*/
-#define NM_LCL_EDIT (1<<3)	/* Use local editor to create messages		*/
-#define NM_EMSOVL	(1<<4)	/* Use expanded memory of overlays			*/
-#define NM_WINOS2	(1<<5)	/* Use Windows/OS2 time slice API call		*/
-#define NM_INT28	(1<<6)	/* Make int 28 DOS idle calls				*/
-#define NM_NODV 	(1<<7)	/* Don't detect and use DESQview API        */
-#define NM_NO_NUM	(1<<8)	/* Don't allow logons by user number        */
-#define NM_LOGON_R	(1<<9)	/* Allow logons by user real name			*/
-#define NM_LOGON_P	(1<<10) /* Secure logons (always ask for password)	*/
-#define NM_NO_LKBRD (1<<11) /* No local keyboard (at all)				*/
-#define NM_SYSPW	(1<<12) /* Protect WFC keys and Alt keys with SY:	*/
-#define NM_NO_INACT (1<<13) /* No local inactivity alert/logoff 		*/
-#define NM_NOBEEP	(1<<14) /* Don't beep locally                       */
-#define NM_LOWPRIO	(1<<15) /* Always use low priority input			*/
-#define NM_7BITONLY (1L<<16) /* Except 7-bit input only (E71 terminals) */
-#define NM_RESETVID (1L<<17) /* Reset video mode between callers?		*/
-
-							/* Miscellaneous Modem Settings (mdm_misc)  */
-#define MDM_CTS 	 (1<<0) /* Use hardware send flow control			*/
-#define MDM_RTS 	 (1<<1) /* Use hardware recv flow control			*/
-#define MDM_STAYHIGH (1<<2) /* Stay at highest DTE rate 				*/
-#define MDM_CALLERID (1<<3) /* Supports Caller ID						*/
-#define MDM_DUMB	 (1<<4) /* Just watch DCD for answer - dumb modem	*/
-#define MDM_NODTR	 (1<<5) /* Don't drop DTR for hang-up               */
-#define MDM_KNOWNRES (1<<6) /* Allow known result codes only			*/
-#define MDM_VERBAL	 (1<<7) /* Use verbal result codes					*/
-
-									/* Bit values for level_misc[x] 	*/
-#define LEVEL_EXPTOLVL (1<<0)		/* Expire to level_expireto[x]		*/
-#define LEVEL_EXPTOVAL (1<<1)		/* Expire to val[level_expireto[x]] */
-
-									/* Bit values for prot[x].misc */
-#define PROT_DSZLOG (1<<0)          /* Supports DSZ Log */
-
-									/* Bit values in netmail_misc */
-
-#define NMAIL_ALLOW 	(1<<0)		/* Allow NetMail */
-#define NMAIL_CRASH 	(1<<1)		/* Default netmail to crash */
-#define NMAIL_HOLD		(1<<2)		/* Default netmail to hold */
-#define NMAIL_KILL		(1<<3)		/* Default netmail to kill after sent */
-#define NMAIL_ALIAS 	(1<<4)		/* Use Aliases in NetMail */
-#define NMAIL_FILE		(1<<5)		/* Allow file attachments */
-#define NMAIL_DIRECT	(1<<6)		/* Default netmail to direct */
-
-									/* Attribute bits for fido msg header */
-#define FIDO_PRIVATE	(1<<0)		/* Private message */
-#define FIDO_CRASH		(1<<1)		/* Crash-mail (send immediately) */
-#define FIDO_RECV		(1<<2)		/* Received successfully */
-#define FIDO_SENT		(1<<3)		/* Sent successfully */
-#define FIDO_FILE		(1<<4)		/* File attached */
-#define FIDO_INTRANS	(1<<5)		/* In transit */
-#define FIDO_ORPHAN 	(1<<6)		/* Orphan */
-#define FIDO_KILLSENT	(1<<7)		/* Kill it after sending it */
-#define FIDO_LOCAL		(1<<8)		/* Created locally - on this system */
-#define FIDO_HOLD		(1<<9)		/* Hold - don't send it yet */
-#define FIDO_FREQ		(1<<11) 	/* File request */
-#define FIDO_RRREQ		(1<<12) 	/* Return receipt request */
-#define FIDO_RR 		(1<<13) 	/* This is a return receipt */
-#define FIDO_AUDIT		(1<<14) 	/* Audit request */
-#define FIDO_FUPREQ 	(1<<15) 	/* File update request */
-
-									/* Bit values for sub[x].misc */
-#define SUB_NSCAN	(1L<<0) 		/* Scan this sub-board for new msgs */
-#define SUB_YSCAN	(1L<<1) 		/* Scan for new messages to you only */
-#define SUB_SSCAN	(1L<<2) 		/* Scan this sub-board for msgs to you */
-#define SUB_QNET	(1L<<3) 		/* Sub-board is netted via QWK network */
-#define SUB_PNET	(1L<<4) 		/* Sub-board is netted via PostLink */
-#define SUB_FIDO	(1L<<5) 		/* Sub-board is netted via FidoNet */
-#define SUB_PRIV	(1L<<6) 		/* Allow private posts on sub */
-#define SUB_PONLY	(1L<<7) 		/* Private posts only */
-#define SUB_ANON	(1L<<8) 		/* Allow anonymous posts on sub */
-#define SUB_AONLY	(1L<<9) 		/* Anonymous only */
-#define SUB_NAME	(1L<<10)		/* Must use real names */
-#define SUB_DEL 	(1L<<11)		/* Allow users to delete messages */
-#define SUB_DELLAST (1L<<12)		/* Allow users to delete last msg only */
-#define SUB_FORCED	(1L<<13)		/* Sub-board is forced scanning */
-#define SUB_NOTAG	(1L<<14)		/* Don't add tag or origin lines */
-#define SUB_TOUSER	(1L<<15)		/* Prompt for to user on posts */
-#define SUB_ASCII	(1L<<16)		/* ASCII characters only */
-#define SUB_QUOTE	(1L<<17)		/* Allow online quoting */
-#define SUB_NSDEF	(1L<<18)		/* New-Scan on by default */
-#define SUB_INET	(1L<<19)		/* Sub-board is netted via Internet */
-#define SUB_FAST	(1L<<20)		/* Fast storage mode */
-#define SUB_KILL	(1L<<21)		/* Kill read messages automatically */
-#define SUB_KILLP	(1L<<22)		/* Kill read pvt messages automatically */
-#define SUB_SYSPERM (1L<<23)		/* Sysop messages are permament */
-#define SUB_GATE	(1L<<24)		/* Gateway between Network types */
-#define SUB_LZH 	(1L<<25)		/* Use LZH compression for msgs */
-#define SUB_SSDEF	(1L<<26)		/* Default ON for Scan for Your msgs */
-#define SUB_HYPER	(1L<<27)		/* Hyper allocation */
-
-                                    /* Bit values for dir[x].misc */
-#define DIR_FCHK	(1L<<0) 		/* Check for file existance */
-#define DIR_RATE	(1L<<1) 		/* Force uploads to be rated G,R, or X */
-#define DIR_MULT	(1L<<2) 		/* Ask for multi-disk numbering */
-#define DIR_DUPES	(1L<<3) 		/* Search this dir for upload dupes */
-#define DIR_FREE	(1L<<4) 		/* Free downloads */
-#define DIR_TFREE	(1L<<5) 		/* Time to download is free */
-#define DIR_CDTUL	(1L<<6) 		/* Credit Uploads */
-#define DIR_CDTDL	(1L<<7) 		/* Credit Downloads */
-#define DIR_ANON	(1L<<8) 		/* Anonymous uploads */
-#define DIR_AONLY	(1L<<9) 		/* Anonymous only */
-#define DIR_ULDATE	(1L<<10)		/* Include upload date in listing */
-#define DIR_DIZ 	(1L<<11)		/* FILE_ID.DIZ and DESC.SDI support */
-#define DIR_NOSCAN	(1L<<12)		/* Don't new-scan this directory */
-#define DIR_NOAUTO	(1L<<13)		/* Don't auto-add this directory */
-#define DIR_ULTIME	(1L<<14)		/* Deduct time during uploads */
-#define DIR_CDTMIN	(1L<<15)		/* Give uploader minutes instead of cdt */
-#define DIR_SINCEDL (1L<<16)		/* Purge based on days since last dl */
-#define DIR_MOVENEW (1L<<17)		/* Files marked as new when moved */
-
-                                    /* Bit values for file_t.misc */
-#define FM_EXTDESC  (1<<0)          /* Extended description exists */
-#define FM_ANON 	(1<<1)			/* Anonymous upload */
-
-enum {								/* errormsg() codes */
-	 ERR_OPEN						/* opening a file */
-	,ERR_CLOSE						/* close a file */
-	,ERR_FDOPEN 					/* associating a stream with fd */
-	,ERR_READ						/* reading from file */
-	,ERR_WRITE						/* writing to file */
-	,ERR_REMOVE 					/* removing a file */
-	,ERR_ALLOC						/* allocating memory */
-	,ERR_CHK						/* checking */
-	,ERR_LEN						/* file length */
-	,ERR_EXEC						/* executing */
-	,ERR_CHDIR						/* changing directory */
-	,ERR_CREATE 					/* creating */
-	,ERR_LOCK						/* locking */
-	,ERR_UNLOCK 					/* unlocking */
-	};
-
-enum {                              /* Values for dir[x].sort */
-     SORT_NAME_A                    /* Sort by filename, ascending */
-    ,SORT_NAME_D                    /* Sort by filename, descending */
-    ,SORT_DATE_A                    /* Sort by upload date, ascending */
-    ,SORT_DATE_D                    /* Sort by upload date, descending */
-    };
-
-enum {
-	 clr_mnehigh
-	,clr_mnelow
-	,clr_mnecmd
-	,clr_inputline
-	,clr_err
-	,clr_nodenum
-	,clr_nodeuser
-	,clr_nodestatus
-	,clr_filename
-	,clr_filecdt
-	,clr_filedesc
-	,clr_filelsthdrbox
-	,clr_filelstline
-	,clr_chatlocal
-	,clr_chatremote
-	,clr_multichat
-	,TOTAL_COLORS };
-
-enum {								/* Values for xtrn_t.type			*/
-	 XTRN_NONE						/* No data file needed				*/
-	,XTRN_SBBS						/* Synchronet external				*/
-	,XTRN_WWIV						/* WWIV external					*/
-	,XTRN_GAP						/* Gap door 						*/
-	,XTRN_RBBS						/* RBBS, QBBS, or Remote Access 	*/
-	,XTRN_WILDCAT					/* Wildcat							*/
-	,XTRN_PCBOARD					/* PCBoard							*/
-	,XTRN_SPITFIRE					/* SpitFire 						*/
-	,XTRN_UTI						/* UTI Doors - MegaMail 			*/
-	,XTRN_SR						/* Solar Realms 					*/
-	,XTRN_RBBS1 					/* DORINFO1.DEF always				*/
-	,XTRN_TRIBBS					/* TRIBBS.SYS						*/
-	};
-
-enum {								/* Values for xtrn_t.event			*/
-	 EVENT_NONE 					/* Only accessible by menu			*/
-	,EVENT_LOGON					/* Execute during logon sequence	*/
-	,EVENT_LOGOFF					/* Execute during logoff sequence	*/
-	,EVENT_NEWUSER					/* Execute during newuser app.		*/
-	,EVENT_BIRTHDAY 				/* Execute on birthday				*/
-	};
-
-									/* Misc bits for event_t.misc		*/
-#define EVENT_EXCL	(1L<<0) 		/* Exclusive						*/
-#define EVENT_FORCE (1L<<1) 		/* Force users off-line for event	*/
-
-									/* Mode bits for QWK stuff */
-#define A_EXPAND	(1<<0)			/* Expand to ANSI sequences */
-#define A_LEAVE 	(1<<1)			/* Leave in */
-#define A_STRIP 	(1<<2)			/* Strip out */
-
-									/* Bits in xtrn_t.misc				*/
-#define MULTIUSER	(1L<<0) 		/* allow multi simultaneous users	*/
-#define ANSI		(1L<<1) 		/* user must have ANSI, same as ^^^ */
-#define IO_INTS 	(1L<<2) 		/* Intercept I/O interrupts 		*/
-#define MODUSERDAT	(1L<<3) 		/* Program can modify user data 	*/
-#define WWIVCOLOR	(1L<<4) 		/* Program uses WWIV color codes	*/
-#define EVENTONLY	(1L<<5) 		/* Program executes as event only	*/
-#define STARTUPDIR	(1L<<6) 		/* Create drop file in start-up dir */
-#define REALNAME	(1L<<7) 		/* Use real name in drop file		*/
-#define SWAP		(1L<<8) 		/* Swap for this door				*/
-#define FREETIME	(1L<<9) 		/* Free time while in this door 	*/
-#define QUICKBBS	(1L<<10)		/* QuickBBS style editor			*/
-#define EXPANDLF	(1L<<11)		/* Expand LF to CRLF editor 		*/
-#define QUOTEALL	(1L<<12)		/* Automatically quote all of msg	*/
-#define QUOTENONE	(1L<<13)		/* Automatically quote none of msg	*/
-
-									/* Bits in user.qwk 				*/
-#define QWK_FILES	(1L<<0) 		/* Include new files list			*/
-#define QWK_EMAIL	(1L<<1) 		/* Include unread e-mail			*/
-#define QWK_ALLMAIL (1L<<2) 		/* Include ALL e-mail				*/
-#define QWK_DELMAIL (1L<<3) 		/* Delete e-mail after download 	*/
-#define QWK_BYSELF	(1L<<4) 		/* Include messages from self		*/
-#define QWK_UNUSED	(1L<<5) 		/* Currently unused 				*/
-#define QWK_EXPCTLA (1L<<6) 		/* Expand ctrl-a codes to ascii 	*/
-#define QWK_RETCTLA (1L<<7) 		/* Retain ctrl-a codes				*/
-#define QWK_ATTACH	(1L<<8) 		/* Include file attachments 		*/
-#define QWK_NOINDEX (1L<<9) 		/* Do not create index files in QWK */
-#define QWK_TZ		(1L<<10)		/* Include "@TZ" time zone in msgs  */
-#define QWK_VIA 	(1L<<11)		/* Include "@VIA" seen-bys in msgs  */
-#define QWK_NOCTRL	(1L<<12)		/* No extraneous control files		*/
-
-#define INVALID_DIR 0xffff          /* Invalid directory value          */
-#define INVALID_SUB 0xffff			/* Invalid sub-board value			*/
-
-#define KEY_BUFSIZE 1024	/* Size of keyboard input buffer			*/
-#define SAVE_LINES	 4		/* Maximum number of lines to save			*/
-#define LINE_BUFSIZE 512	/* Size of line output buffer               */
-
-
-#define TABSIZE		4		/* Tab Size									*/
-
-#define SWAP_NONE	0x80	/* Allow no swapping for executables		*/
-
-#define DSTSDABLEN	50		/* Length of DSTS.DAB file					*/
-
-							/* Console I/O Bits	(console)				*/
-#define CON_R_ECHO	 (1<<0)	/* Echo remotely							*/
-#define CON_R_ECHOX	 (1<<1)	/* Echo X's to remote user					*/
-#define CON_R_INPUT  (1<<2)	/* Accept input remotely					*/
-#define CON_L_ECHO	 (1<<3)	/* Echo locally              				*/
-#define CON_L_ECHOX	 (1<<4) /* Echo X's locally							*/
-#define CON_L_INPUT  (1<<5)	/* Accept input locally						*/
-#define CON_RAW_IN   (1<<8) /* Raw input mode - no editing capabilities */
-#define CON_ECHO_OFF (1<<10)/* Remote & Local echo disabled for ML/MF	*/
-#define CON_UPARROW  (1<<11)/* Up arrow hit - move up one line			*/
-
-							/* Number of milliseconds                   */
-#define DELAY_HANGUP 250    /* Delay before modem drops carrier         */
-#define DELAY_MDMTLD 500    /* Delay to give each ~ in modem strings    */
-#define DELAY_SPIN   10     /* Delay for the spinning cursor            */
-#define DELAY_AUTOHG 1500	/* Delay for auto-hangup (xfer) 			*/
-
-#define SEC_LOGON	1800	/* 30 minutes allowed to logon				*/
-#define SEC_BILLING   90	/* under 2 minutes per billing call 		*/
-#define SEC_OK		   5	/* Attempt to get an OK response from modem */
-#define SEC_ANSI	   5	/* Attempt to get a valid ANSI response 	*/
-#define SEC_ANSWER	  30	/* Retries to get an answer code from modem */
-#define SEC_CID 	  10	/* Ten second pause for caller ID			*/
-#define SEC_RING	   6	/* Maximum seconds between rings			*/
-
-#define LOOP_NOPEN	  50	/* Retries before file access denied		*/
-#define LOOP_NODEDAB  50	/* Retries on NODE.DAB locking/unlocking	*/
-
-							/* String lengths							*/
-#define LEN_ALIAS		25	/* User alias								*/
-#define LEN_NAME		25	/* User name								*/
-#define LEN_HANDLE		8	/* User chat handle 						*/
-#define LEN_NOTE		30	/* User note								*/
-#define LEN_COMP		30	/* User computer description				*/
-#define LEN_COMMENT 	60	/* User comment 							*/
-#define LEN_NETMAIL 	60	/* NetMail forwarding address				*/
-#define LEN_PASS		 8	/* User password							*/
-#define LEN_PHONE		12	/* User phone number						*/
-#define LEN_BIRTH		 8	/* Birthday in MM/DD/YY format				*/
-#define LEN_ADDRESS 	30	/* User address 							*/
-#define LEN_LOCATION	30	/* Location (City, State)					*/
-#define LEN_ZIPCODE 	10	/* Zip/Postal code							*/
-#define LEN_MODEM		 8	/* User modem type description				*/
-#define LEN_FDESC		58	/* File description 						*/
-#define LEN_FCDT		 9	/* 9 digits for file credit values			*/
-#define LEN_TITLE		70	/* Message title							*/
-#define LEN_MAIN_CMD	40	/* Storage in user.dat for custom commands	*/
-#define LEN_XFER_CMD	40
-#define LEN_SCAN_CMD	40
-#define LEN_MAIL_CMD	40
-#define LEN_CID 		25	/* Caller ID (phone number) 				*/
-#define LEN_ARSTR		40	/* Max length of Access Requirement string	*/
-#define LEN_CHATACTCMD	 9	/* Chat action command						*/
-#define LEN_CHATACTOUT	65	/* Chat action output string				*/
-
-/****************************************************************************/
-/* This is a list of offsets into the USER.DAT file for different variables */
-/* that are stored (for each user)											*/
-/****************************************************************************/
-#define U_ALIAS 	0					/* Offset to alias */
-#define U_NAME		(U_ALIAS+LEN_ALIAS) /* Offset to name */
-#define U_HANDLE	(U_NAME+LEN_NAME)
-#define U_NOTE		(U_HANDLE+LEN_HANDLE+2)
-#define U_COMP		(U_NOTE+LEN_NOTE)
-#define U_COMMENT	(U_COMP+LEN_COMP+2)
-
-#define U_NETMAIL	(U_COMMENT+LEN_COMMENT+2)
-
-#define U_ADDRESS	(U_NETMAIL+LEN_NETMAIL+2)
-#define U_LOCATION	(U_ADDRESS+LEN_ADDRESS)
-#define U_ZIPCODE	(U_LOCATION+LEN_LOCATION)
-
-#define U_PASS		(U_ZIPCODE+LEN_ZIPCODE+2)
-#define U_PHONE  	(U_PASS+8) 			/* Offset to phone-number */
-#define U_BIRTH  	(U_PHONE+12)		/* Offset to users birthday	*/
-#define U_MODEM     (U_BIRTH+8)
-#define U_LASTON	(U_MODEM+8)
-#define U_FIRSTON	(U_LASTON+8)
-#define U_EXPIRE    (U_FIRSTON+8)
-#define U_PWMOD     (U_EXPIRE+8)
-
-#define U_LOGONS    (U_PWMOD+8+2)
-#define U_LTODAY    (U_LOGONS+5)
-#define U_TIMEON    (U_LTODAY+5)
-#define U_TEXTRA  	(U_TIMEON+5)
-#define U_TTODAY    (U_TEXTRA+5)
-#define U_TLAST     (U_TTODAY+5)
-#define U_POSTS     (U_TLAST+5)
-#define U_EMAILS    (U_POSTS+5)
-#define U_FBACKS    (U_EMAILS+5)
-#define U_ETODAY	(U_FBACKS+5)
-#define U_PTODAY	(U_ETODAY+5)
-
-#define U_ULB       (U_PTODAY+5+2)
-#define U_ULS       (U_ULB+10)
-#define U_DLB       (U_ULS+5)
-#define U_DLS       (U_DLB+10)
-#define U_CDT		(U_DLS+5)
-#define U_MIN		(U_CDT+10)
-
-#define U_LEVEL 	(U_MIN+10+2)	/* Offset to Security Level    */
-#define U_FLAGS1	(U_LEVEL+2) 	/* Offset to Flags */
-#define U_TL		(U_FLAGS1+8)	/* Offset to unused field */
-#define U_FLAGS2	(U_TL+2)
-#define U_EXEMPT	(U_FLAGS2+8)
-#define U_REST		(U_EXEMPT+8)
-#define U_ROWS		(U_REST+8+2)	/* Number of Rows on user's monitor */
-#define U_SEX		(U_ROWS+2)		/* Sex, Del, ANSI, color etc.		*/
-#define U_MISC		(U_SEX+1)		/* Miscellaneous flags in 8byte hex */
-#define U_OLDXEDIT	(U_MISC+8)		/* External editor (Version 1 method) */
-#define U_LEECH 	(U_OLDXEDIT+2)	/* two hex digits - leech attempt count */
-#define U_CURSUB	(U_LEECH+2) 	/* Current sub (internal code) */
-#define U_CURDIR	(U_CURSUB+8)	/* Current dir (internal code) */
-#define U_CMDSET	(U_CURDIR+8)	/* unused */
-#define U_MAIN_CMD	(U_CMDSET+2+2)	/* unused */
-#define U_XFER_CMD	(U_MAIN_CMD+LEN_MAIN_CMD)		/* unused */
-#define U_SCAN_CMD	(U_XFER_CMD+LEN_XFER_CMD+2) 	/* unused */
-#define U_MAIL_CMD	(U_SCAN_CMD+LEN_SCAN_CMD)		/* unused */
-#define U_FREECDT	(U_MAIL_CMD+LEN_MAIL_CMD+2)
-#define U_FLAGS3	(U_FREECDT+10)	/* Flag set #3 */
-#define U_FLAGS4	(U_FLAGS3+8)	/* Flag set #4 */
-#define U_XEDIT 	(U_FLAGS4+8)	/* External editor (code) */
-#define U_SHELL 	(U_XEDIT+8) 	/* Command shell (code) */
-#define U_QWK		(U_SHELL+8) 	/* QWK settings */
-#define U_TMPEXT	(U_QWK+8)		/* QWK extension */
-#define U_CHAT		(U_TMPEXT+3)	/* Chat settings */
-#define U_NS_TIME	(U_CHAT+8)		/* New-file scan date/time */
-#define U_PROT		(U_NS_TIME+8)	/* Default transfer protocol */
-#define U_UNUSED	(U_PROT+1)
-#define U_LEN		(U_UNUSED+28+2)
-
-/****************************************************************************/
-/* Offsets into DIR .DAT file for different fields for each file 			*/
-/****************************************************************************/
-#define F_CDT		0				/* Offset in DIR#.DAT file for cdts */
-#define F_DESC		(F_CDT+LEN_FCDT)/* Description						*/
-#define F_ULER		(F_DESC+LEN_FDESC+2)   /* Uploader					*/
-#define F_TIMESDLED (F_ULER+30+2) 	/* Number of times downloaded 		*/
-#define F_OPENCOUNT	(F_TIMESDLED+5+2)
-#define F_MISC		(F_OPENCOUNT+3+2)
-#define F_ALTPATH	(F_MISC+1)		/* Two hex digit alternate path */
-#define F_LEN		(F_ALTPATH+2+2) /* Total length of all fdat in file */
-
-#define F_IXBSIZE	22				/* Length of each index entry		*/
-
-
-#define SIF_MAXBUF  0x7000			/* Maximum buffer size of SIF data */
-
-/* NOTE: Do not change the values of the following block of defines!	*/
-
-#define DELETED 	(1L<<0) 		/* Bit values for user.misc 		*/
-#define ANSI		(1L<<1) 		/* Supports ANSI terminal emulation */
-#define COLOR		(1L<<2) 		/* Send color codes 				*/
-#define RIP 		(1L<<3) 		/* Supports RIP terminal emulation	*/
-#define UPAUSE		(1L<<4) 		/* Pause on every screen full		*/
-#define SPIN		(1L<<5) 		/* Spinning cursor - Same as K_SPIN */
-#define INACTIVE	(1L<<6) 		/* Inactive user slot				*/
-#define EXPERT		(1L<<7) 		/* Expert menu mode 				*/
-#define ANFSCAN 	(1L<<8) 		/* Auto New file scan				*/
-#define CLRSCRN 	(1L<<9) 		/* Clear screen before each message */
-#define QUIET		(1L<<10)		/* Quiet mode upon logon			*/
-#define BATCHFLAG	(1L<<11)		/* File list allow batch dl flags	*/
-#define NETMAIL 	(1L<<12)		/* Forward e-mail to fidonet addr	*/
-#define CURSUB		(1L<<13)		/* Remember current sub-board/dir	*/
-#define ASK_NSCAN	(1L<<14)		/* Ask for newscanning upon logon	*/
-#define NO_EXASCII	(1L<<15)		/* Don't send extended ASCII        */
-#define ASK_SSCAN	(1L<<16)		/* Ask for messages to you at logon */
-#define AUTOTERM	(1L<<17)		/* Autodetect terminal type 		*/
-#define COLDKEYS	(1L<<18)		/* No hot-keys						*/
-#define EXTDESC 	(1L<<19)		/* Extended file descriptions		*/
-#define AUTOHANG	(1L<<20)		/* Auto-hang-up after transfer		*/
-#define WIP 		(1L<<21)		/* Supports WIP terminal emulation	*/
-
-#define CLREOL      256     /* Character to erase to end of line 		*/
-#define HIGH        8       /* High intensity for curatr             */
-
-							/* Online status (online)					*/
-#define ON_LOCAL	1	 	/* Online locally							*/
-#define ON_REMOTE   2  		/* Online remotely							*/
-#define ON_XFER		3		/* Online remotely - transferring file		*/
-#define ON_WFC		4		/* Online waiting for a call				*/
-
-							/* Varios SYSTEM parameters for sys_status	*/
-#define SS_LOGOPEN	(1L<<0)	/* Node's Log file is open          		*/
-#define SS_INITIAL  (1L<<1)	/* The bbs data has been initialized.       */
-#define SS_TMPSYSOP (1L<<2)	/* Temporary Sysop Status					*/
-#define SS_USERON   (1L<<3)	/* A User is logged on to the BBS			*/
-#define SS_LCHAT    (1L<<4) /* Local chat in progress					*/
-#define SS_CAP		(1L<<5)	/* Capture is on							*/
-#define SS_ANSCAP	(1L<<6) /* Capture ANSI codes too					*/
-#define SS_FINPUT	(1L<<7) /* Using file for input 					*/
-#define SS_COMISR	(1L<<8) /* Com port ISR is installed				*/
-#define SS_DAILY	(1L<<9) /* Execute System Daily Event on logoff 	*/
-#define SS_INUEDIT	(1L<<10) /* Inside Alt-Useredit section 			*/
-#define SS_ABORT	(1L<<11) /* Global abort input or output flag		*/
-#define SS_SYSPAGE	(1L<<12) /* Paging sysop							*/
-#define SS_SYSALERT (1L<<13) /* Notify sysop when users hangs up		*/
-#define SS_GURUCHAT (1L<<14) /* Guru chat in progress					*/
-#define SS_NODEDAB	(1L<<15) /* NODE.DAB operations are okay			*/
-#define SS_EVENT	(1L<<16) /* Time shortened due to upcoming event	*/
-#define SS_PAUSEON	(1L<<17) /* Pause on, overriding user default		*/
-#define SS_PAUSEOFF (1L<<18) /* Pause off, overriding user default		*/
-#define SS_IN_CTRLP (1L<<19) /* Inside ctrl-p send node message func	*/
-#define SS_NEWUSER	(1L<<20) /* New User online 						*/
-#define SS_MDMDEBUG (1L<<21) /* Modem debug output						*/
-#define SS_NEST_PF	(1L<<22) /* Nested in printfile function			*/
-#define SS_DCDHIGH	(1L<<23) /* Assume DCD is high always				*/
-#define SS_SPLITP	(1L<<24) /* Split-screen private chat				*/
-#define SS_NEWDAY	(1L<<25) /* Date changed while online				*/
-
-								/* Bits in 'mode' for getkey and getstr     */
-#define K_UPPER 	(1L<<0) 	/* Converts all letters to upper case		*/
-#define K_UPRLWR	(1L<<1) 	/* Upper/Lower case automatically			*/
-#define K_NUMBER	(1L<<2) 	/* Allow numbers only						*/
-#define K_WRAP		(1L<<3) 	/* Allows word wrap 						*/
-#define K_MSG		(1L<<4) 	/* Allows ANSI, ^N ^A ^G					*/
-#define K_SPIN		(1L<<5) 	/* Spinning cursor (same as SPIN)			*/
-#define K_LINE		(1L<<6) 	/* Input line (inverse color)				*/
-#define K_EDIT		(1L<<7) 	/* Edit string passed						*/
-#define K_CHAT		(1L<<8) 	/* In chat multi-chat						*/
-#define K_NOCRLF	(1L<<9) 	/* Don't print CRLF after string input      */
-#define K_ALPHA 	(1L<<10)	/* Only allow alphabetic characters 		*/
-#define K_GETSTR	(1L<<11)	/* getkey called from getstr()				*/
-#define K_LOWPRIO	(1L<<12)	/* low priority input						*/
-#define K_NOEXASC	(1L<<13)	/* No extended ASCII allowed				*/
-#define K_E71DETECT (1L<<14)	/* Detect E-7-1 terminal type				*/
-#define K_AUTODEL	(1L<<15)	/* Auto-delete text (used with K_EDIT)		*/
-#define K_COLD		(1L<<16)	/* Possible cold key mode					*/
-#define K_NOECHO	(1L<<17)	/* Don't echo input                         */
-
-							/* Bits in 'mode' for putmsg and printfile  */
-#define P_NOABORT  	(1<<0)  /* Disallows abortion of a message          */
-#define P_SAVEATR   (1<<1)  /* Save the new current attributres after	*/
-							/* msg has printed. */
-#define P_NOATCODES (1<<2)	/* Don't allow @ codes                      */
-#define P_OPENCLOSE (1<<3)	/* Open and close the file					*/
-
-							/* Bits in 'mode' for listfiles             */
-#define FL_ULTIME   (1<<0)  /* List files by upload time                */
-#define FL_DLTIME   (1<<1)  /* List files by download time              */
-#define FL_NO_HDR   (1<<2)  /* Don't list directory header              */
-#define FL_FINDDESC (1<<3)  /* Find text in description                 */
-#define FL_EXFIND   (1<<4)	/* Find text in description - extended info */
-#define FL_VIEW     (1<<5)	/* View ZIP/ARC/GIF etc. info               */
-
-							/* Bits in the mode of writemsg and email() */
-#define WM_EXTDESC	(1<<0)	/* Writing extended file description		*/
-#define WM_EMAIL	(1<<1)	/* Writing e-mail							*/
-#define WM_NETMAIL	(1<<2)	/* Writing NetMail							*/
-#define WM_ANON 	(1<<3)	/* Writing anonymous message				*/
-#define WM_FILE 	(1<<4)	/* Attaching a file to the message			*/
-#define WM_NOTOP	(1<<5)	/* Don't add top because we need top line   */
-#define WM_QUOTE	(1<<6)	/* Quote file available 					*/
-#define WM_QWKNET	(1<<7)	/* Writing QWK NetMail (25 char title)		*/
-#define WM_PRIVATE	(1<<8)	/* Private (for creating MSGINF file)		*/
-
-							/* Bits in the mode of loadposts()			*/
-#define LP_BYSELF	(1<<0)	/* Include messages sent by self			*/
-#define LP_OTHERS	(1<<1)	/* Include messages sent to others			*/
-#define LP_UNREAD	(1<<2)	/* Un-read messages only					*/
-#define LP_PRIVATE	(1<<3)	/* Include all private messages 			*/
-#define LP_REP		(1<<4)	/* Packing REP packet						*/
-
-							/* Bits in the mode of loadmail()			*/
-#define LM_UNREAD	(1<<0)	/* Include un-read mail only				*/
-#define LM_QWK		(1<<1)	/* Loading for a QWK packet 				*/
-
-enum {						/* readmail and delmailidx which types		*/
-	 MAIL_YOUR				/* mail sent to you */
-	,MAIL_SENT				/* mail you have sent */
-	,MAIL_ANY				/* mail sent to or from you */
-	,MAIL_ALL				/* all mail (ignores usernumber arg) */
-	};
-
-#if 0
-							/* Message mode bits						*/
-#define MSG_PERM	1		/* Permanent - non-purgable message (post)  */
-#define MSG_FORWARD 1       /* Forwarded message (mail)                 */
-#define MSG_ANON	2		/* Anonymous message						*/
-#define MSG_PRIVATE 4		/* Private posted message					*/
-#define MSG_READ	8		/* Private post has been read				*/
-#define MSG_FILE	16		/* File attached							*/
-
-#endif
-
-							/* Bits in the mode of external()           */
-#define EX_CC       (1<<0)	/* Use command.com to load other process    */
-#define EX_OUTR     (1<<1)  /* Copy DOS output to remote                */
-#define EX_OUTL 	(1<<2)	/* Use _lputc() for local DOS output		*/
-#define EX_INR		(1<<3)	/* Trap int 16h keyboard input requests     */
-#define EX_WWIV 	(1<<4)	/* Expand WWIV color codes to ANSI sequence */
-#define EX_SWAP 	(1<<5)	/* Swap out for this external				*/
-#define EX_OS2		(1<<6)	/* Executing an OS/2 pgm from SBBS4OS2		*/
-#define EX_POPEN	(1<<7)	/* Leave COM port open						*/
-
-#define OS2_POPEN	(1<<0)	/* Leave COM port open						*/
-
-enum {						/* Values for 'mode' in listfileinfo        */
-	 FI_INFO            	/* Just list file information               */
-	,FI_REMOVE           	/* Remove/Move/Edit file information        */
-	,FI_DOWNLOAD         	/* Download files                           */
-	,FI_OLD              	/* Search/Remove files not downloaded since */
-	,FI_OLDUL	 			/* Search/Remove files uploaded before      */
-	,FI_OFFLINE   			/* Search/Remove files not online			*/
-	,FI_USERXFER  			/* User Xfer Download                       */
-	,FI_CLOSE 	  			/* Close any open records					*/
-	};
-
-#define L_LOGON     1       /* Logon List maintenance                   */
-#define LOL_SIZE    81      /* Length of each logon list entry          */
-
-#define CHAT_ECHO	(1<<0)	/* Multinode chat echo						*/
-#define CHAT_ACTION (1<<1)	/* Chat actions 							*/
-#define CHAT_NOPAGE (1<<2)	/* Can't be paged                           */
-#define CHAT_NOACT	(1<<3)	/* No activity alerts						*/
-#define CHAT_SPLITP (1<<4)	/* Split screen private chat				*/
-
-							/* Bits in mode of scanposts() function 	*/
-#define SCAN_CONST	(1<<0)	/* Continuous message scanning				*/
-#define SCAN_NEW	(1<<1)	/* New scanning								*/
-#define SCAN_BACK	(1<<2)	/* Scan the last message if no new			*/
-#define SCAN_TOYOU	(1<<3)	/* Scan for messages to you 				*/
-#define SCAN_FIND	(1<<4)	/* Scan for text in messages				*/
-#define SCAN_UNREAD (1<<5)	/* Find un-read messages to you 			*/
-
-							/* Bits in misc of chan_t					*/
-#define CHAN_PW 	(1<<0)	/* Can be password protected				*/
-#define CHAN_GURU	(1<<1)	/* Guru joins empty channel 				*/
-
-enum {						/* Values of mode for userlist function     */
-	 UL_ALL					/* List all users in userlist				*/
-	,UL_SUB      			/* List all users with access to cursub     */
-	,UL_DIR					/* List all users with access to curdir 	*/
-	};
-
-
-#define BO_LEN		16		/* BACKOUT.DAB record length				*/
-
-#define BO_OPENFILE 0		/* Backout types */
-
-
-/**********/
-/* Macros */
-/**********/
-
-#define CRLF			{ outchar(CR); outchar(LF); }
-#define SYSOP			(useron.level>=90 || sys_status & SS_TMPSYSOP)
-#define REALSYSOP		(useron.level>=90)
-#define FLAG(x) 		(long)(1L<<(x-'A'))
-#define CLS         	outchar(FF)
-#define WHERE       	__LINE__,__FILE__
-#define SAVELINE		{ slatr[slcnt]=latr; \
-							sprintf(slbuf[slcnt<SAVE_LINES ? slcnt++ : slcnt] \
-							,"%.*s",lbuflen,lbuf); \
-							lbuflen=0; }
-#define RESTORELINE 	{ lbuflen=0; attr(slatr[--slcnt]); \
-							bputs(slbuf[slcnt]); \
-							curatr=lclatr(-1); }
-#define RIOSYNC(x)		{ if(online==ON_REMOTE) riosync(x); }
-#define SYNC			{ getnodedat(node_num,&thisnode,0); \
-						  RIOSYNC(0); \
-						  nodesync(); }
-#define ASYNC			{ getnodedat(node_num,&thisnode,0); \
-						  RIOSYNC(1); \
-						  nodesync(); }
-#define DCDHIGH 		(sys_status&SS_DCDHIGH || rioctl(IOSTATE)&DCD)
-#define ANSI_SAVE() 	bputs("\x1b[s")
-#define ANSI_RESTORE()	bputs("\x1b[u")
-#define GOTOXY(x,y)     bprintf("\x1b[%d;%dH",y,x)
-#define TM_YEAR(yy)		((yy)%100)
-
-extern	long crc32tbl[];
-#define ucrc32(ch,crc) (crc32tbl[(crc^ch)&0xff]^(crc>>8))
-
-#ifdef __FLAT__
-#define TEXTWINDOW		window(1,1,80,node_scrnlen-1)
-#define STATUSLINE		window(1,node_scrnlen,80,node_scrnlen)
-#else
-#define TEXTWINDOW
-#define STATUSLINE
-#endif
-
-#define ucrc32(ch,crc)	(crc32tbl[(crc^ch)&0xff]^(crc>>8))
-
-#ifdef __WATCOMC__
-
-	#if !defined(__COLORS)
-	#define __COLORS
-
-	enum COLORS {
-		BLACK,			/* dark colors */
-		BLUE,
-		GREEN,
-		CYAN,
-		RED,
-		MAGENTA,
-		BROWN,
-		LIGHTGRAY,
-		DARKGRAY,		/* light colors */
-		LIGHTBLUE,
-		LIGHTGREEN,
-		LIGHTCYAN,
-		LIGHTRED,
-		LIGHTMAGENTA,
-		YELLOW,
-		WHITE
-	};
-	#endif
-
-	#define BLINK		128 /* blink bit */
-
-	#define ffblk find_t
-    #define findfirst(x,y,z) _dos_findfirst(x,z,y)
-	#define findnext(x) _dos_findnext(x)
-#endif
-
-#if DEBUG	/* if DEBUG, call function */
-#define DLOG(where,txt) dlog(where,txt)
-#else		/* else, do nothing - function isn't even valid */
-#define DLOG(where,txt)
-#endif
-
-
-/********************/
-/* Type Definitions */
-/********************/
-
-typedef struct {						/* Users information */
-	ushort	number, 					/* Number */
-			uls,						/* Number of uploads */
-			dls,						/* Number of downloads */
-			posts,						/* Number of posts */
-			emails,						/* Number of emails */
-			fbacks,						/* Number of emails sent to sysop */
-			etoday,						/* Emails today */
-			ptoday,						/* Posts today */
-			timeon,						/* Total time on */
-			textra,						/* Extra time for today */
-			logons,						/* Total logons */
-			ttoday,						/* Time on today */
-			tlast,						/* Time on last call */
-			ltoday, 					/* Logons today */
-			xedit,						/* External editor (1 based) */
-			shell;						/* Command shell */
-	uchar	level,						/* Security level */
-			sex,						/* Sex - M or F */
-			rows,               		/* Rows of text */
-			prot,						/* Default transfer protocol */
-			alias[LEN_ALIAS+1], 		/* Alias */
-			name[LEN_NAME+1],			/* Name - Real */
-			handle[LEN_HANDLE+1],		/* Chat handle */
-			comp[LEN_COMP+1],			/* Computer type */
-			note[LEN_NOTE+1],			/* Public notice about this user */
-			address[LEN_ADDRESS+1], 	/* Street Address */
-			location[LEN_LOCATION+1],	/* Location of user */
-			zipcode[LEN_ZIPCODE+1], 	/* Zip/Postal code */
-			pass[LEN_PASS+1],			/* Password - not case sensitive */
-			birth[LEN_BIRTH+1], 		/* Birthday in MM/DD/YY format */
-			phone[LEN_PHONE+1],			/* Phone number xxx-xxx-xxxx format */
-			modem[LEN_MODEM+1],			/* Modem type - 8 chars max */
-			netmail[LEN_NETMAIL+1], 	/* NetMail forwarding address */
-			leech,						/* Leech attempt counter */
-			tmpext[4],					/* QWK Packet extension */
-			comment[LEN_COMMENT+1], 	/* Private comment about user */
-			cursub[9],					/* Current sub-board internal code */
-			curdir[9];					/* Current directory internal code */
-	ulong	misc,						/* Misc. bits - ANSI, Deleted etc. */
-			qwk,						/* QWK settings */
-			chat,						/* Chat defaults */
-			flags1, 					/* Flag set #1 */
-			flags2, 					/* Flag set #2 */
-			flags3, 					/* Flag set #3 */
-			flags4, 					/* Flag set #4 */
-			exempt,						/* Exemption Flags */
-			rest,						/* Restriction Flags */
-			ulb,						/* Total bytes uploaded */
-			dlb,						/* Total bytes downloaded */
-			cdt,						/* Credits */
-			min,						/* Minutes */
-			freecdt;					/* Free credits (renewed daily) */
-	time_t	firston,					/* Date/Time first called */
-			laston, 					/* Last logoff date/time */
-			expire, 					/* Expiration date */
-			pwmod,						/* Password last modified */
-			ns_time;					/* Date/Time of last new file scan */
-			} user_t;
-
-typedef struct {						/* File (transfers) Data */
-	uchar   name[13],					/* Name of file FILENAME.EXT */
-			desc[LEN_FDESC+1],			/* Uploader's Description */
-			uler[LEN_ALIAS+1],			/* User who uploaded */
-			opencount,					/* Times record is currently open */
-			path[LEN_DIR+1];			/* Alternate DOS path */
-	time_t  date,						/* File date/time */
-			dateuled,					/* Date/Time (Unix) Uploaded */
-			datedled;					/* Date/Time (Unix) Last downloaded */
-	ushort	dir,						/* Directory file is in */
-			altpath,
-			timesdled,					/* Total times downloaded */
-			timetodl;					/* How long transfer time */
-	long	datoffset,					/* Offset into .DAT file */
-			size,						/* Size of file */
-			misc;						/* Miscellaneous bits */
-	ulong	cdt;						/* Credit value for this file */
-			} file_t;
-
-typedef struct {						/* Mail data (taken from index) */
-	ulong	offset, 					/* Offset to header (in bytes) */
-			number, 					/* Number of message */
-			time;						/* Time imported */
-	ushort	to, 						/* To user # */
-			from,						/* From user # */
-			subj,						/* CRC-16 of subject */
-			attr;						/* Attributes */
-			} mail_t;
-
-typedef struct {						/* System/Node Statistics */
-	ulong 	logons,						/* Total Logons on System */
-			ltoday,						/* Total Logons Today */
-			timeon,						/* Total Time on System */
-			ttoday,						/* Total Time Today */
-			uls,						/* Total Uploads Today */
-			ulb,						/* Total Upload Bytes Today */
-			dls,						/* Total Downloads Today */
-			dlb,						/* Total Download Bytes Today */
-			ptoday,						/* Total Posts Today */
-			etoday,						/* Total Emails Today */
-			ftoday; 					/* Total Feedbacks Today */
-	ushort	nusers; 					/* Total New Users Today */
-			} stats_t;
-
-typedef struct {						/* FidoNet address */
-	ushort	zone,						/* Zone */
-			net,						/* Network */
-			node,						/* Node */
-			point;						/* Point */
-			} faddr_t;
-
-typedef struct {                        /* Message sub board info */
-	uchar	
-#ifdef SCFG
-			lname[LEN_SLNAME+1],		/* Short name - used for prompts */
-			sname[LEN_SSNAME+1],		/* Long name - used for listing */
-			ar[LEN_ARSTR+1],			/* Access requirements */
-			read_ar[LEN_ARSTR+1],		/* Read requirements */
-			post_ar[LEN_ARSTR+1],		/* Post requirements */
-			op_ar[LEN_ARSTR+1], 		/* Operator requirements */
-			mod_ar[LEN_ARSTR+1],		/* Moderated user requirements */
-			qwkname[11],				/* QWK name - only 10 chars */
-			data_dir[LEN_DIR+1],		/* Data file directory */
-			origline[51],				/* Optional EchoMail origin line */
-			echomail_sem[LEN_DIR+1],	/* EchoMail semaphore for this sub */
-			tagline[81],				/* Optional QWK net tag line */
-#else
-			*lname,
-			*sname,
-			*ar,
-			*read_ar,
-			*post_ar,
-			*op_ar,
-			*mod_ar,
-			*qwkname,
-			*data_dir,
-			*origline,
-			*echomail_sem,
-			*tagline,
-#endif
-			code[9];					/* Eight character code */
-#ifndef SBBS
-	uchar	echopath[LEN_DIR+1];		/* EchoMail path */
-#endif
-	ushort	grp,						/* Which group this sub belongs to */
-			ptridx, 					/* Index into pointer file */
-			qwkconf,					/* QWK conference number */
-			maxage; 					/* Max age of messages (in days) */
-	ulong	misc,						/* Miscellaneous flags */
-			maxmsgs,					/* Max number of messages allowed */
-			maxcrcs;					/* Max number of CRCs to keep */
-#ifdef SBBS
-	ulong	ptr,						/* Highest read message */
-			last;						/* Last read message */
-#endif
-	faddr_t faddr;						/* FidoNet address */
-			} sub_t;
-
-typedef struct {                        /* Message group info */
-	uchar
-#ifdef SCFG
-			lname[LEN_GLNAME+1],		/* Short name */
-			sname[LEN_GSNAME+1],		/* Long name */
-			ar[LEN_ARSTR+1];			/* Access requirements */
-			
-#else
-			*lname,
-			*sname,
-			*ar;
-#endif
-			} grp_t;
-
-typedef struct {                        /* Transfer Directory Info */
-	uchar								/* Eight character code */
-#ifdef SCFG
-			lname[LEN_SLNAME+1],		/* Short name - used for prompts */
-			sname[LEN_SSNAME+1],		/* Long name - used for listing */
-			ar[LEN_ARSTR+1],			/* Access Requirements */
-			ul_ar[LEN_ARSTR+1], 		/* Upload Requirements */
-			dl_ar[LEN_ARSTR+1], 		/* Download Requirements */
-			ex_ar[LEN_ARSTR+1], 		/* Exemption Requirements (credits) */
-			op_ar[LEN_ARSTR+1], 		/* Operator Requirements */
-			path[LEN_DIR+1],			/* Path to directory for files */
-			exts[41],   		        /* Extensions allowed */
-			upload_sem[LEN_DIR+1],		/* Upload semaphore file */
-			data_dir[LEN_DIR+1],		/* Directory where data is stored */
-#else
-			*lname,
-			*sname,
-			*ar,
-			*ul_ar,
-			*dl_ar,
-			*ex_ar,
-			*op_ar,
-			*path,
-			*exts,
-			*upload_sem,
-			*data_dir,
-#endif
-			code[9],
-			seqdev, 					/* Sequential access device number */
-			sort;						/* Sort type */
-	ushort	maxfiles,					/* Max number of files allowed */
-			maxage, 					/* Max age of files (in days) */
-			up_pct, 					/* Percentage of credits on uloads */
-			dn_pct, 					/* Percentage of credits on dloads */
-			lib;						/* Which library this dir is in */
-	ulong	misc;						/* Miscellaneous bits */
-			} dir_t;
-
-typedef struct {                        /* Transfer Library Information */
-	uchar
-#ifdef SCFG
-			lname[LEN_GLNAME+1],		/* Short Name - used for prompts */
-			sname[LEN_GSNAME+1],		/* Long Name - used for listings */
-			ar[LEN_ARSTR+1];			/* Access Requirements */
-#else
-			*lname,
-			*sname,
-			*ar;
-#endif
-	ushort	offline_dir;				/* Offline file directory */
-			} lib_t;
-
-typedef struct {                        /* Gfile Section Information */
-	uchar								/* Eight character code */
-#ifdef SCFG
-			name[41],					/* Name of section */
-			ar[LEN_ARSTR+1],			/* Access requirements */
-#else
-			*name,
-			*ar,
-#endif
-			code[9];
-			} txtsec_t;
-
-typedef struct {						/* External Section Information */
-	uchar
-#ifdef SCFG
-			name[41],					/* Name of section */
-			ar[LEN_ARSTR+1],			/* Access requirements */
-#else
-			*name,
-			*ar,
-#endif
-			code[9];					/* Eight character code */
-			} xtrnsec_t;
-
-typedef struct {						/* Swappable executable */
-#ifdef SCFG
-	uchar	cmd[LEN_CMD+1]; 			/* Program name */
-#else
-	uchar	*cmd;
-#endif
-			} swap_t;
-
-typedef struct {						/* OS/2 executable */
-#ifdef SCFG
-	uchar	name[13];					/* Program name */
-#else
-	uchar	*name;
-#endif
-	ulong	misc;						/* See OS2PGM_* */
-
-			} os2pgm_t;
-
-typedef struct {						/* External Program Information */
-	uchar
-#ifdef SCFG
-			name[41],					/* Name of External */
-			ar[LEN_ARSTR+1],			/* Access Requirements */
-			run_ar[LEN_ARSTR+1],		/* Run Requirements */
-			cmd[LEN_CMD+1], 			/* Command line */
-			clean[LEN_CMD+1],			/* Clean-up command line */
-			path[LEN_DIR+1],			/* Start-up path */
-#else
-			*name,
-			*ar,
-			*run_ar,
-			*cmd,
-			*clean,
-			*path,
-#endif
-			type,						/* What type of external program */
-            event,                      /* Execute upon what event */
-			textra, 					/* Extra time while in this program */
-			maxtime,					/* Maximum time allowed in this door */
-			code[9];					/* Internal code for program */
-	ushort	sec;						/* Section this program belongs to */
-	ulong	cost,						/* Cost to run in credits */
-			misc;						/* Misc. bits - ANSI, DOS I/O etc. */
-			} xtrn_t;
-
-typedef struct {						/* External Page program info */
-#ifdef SCFG
-	uchar	cmd[LEN_CMD+1], 			/* Command line */
-			ar[LEN_ARSTR+1];			/* ARS for this chat page */
-#else
-	uchar	*cmd,
-			*ar;
-#endif
-	ulong	misc;						/* Intercept I/O */
-			} page_t;
-
-
-typedef struct {						/* Chat action set */
-#ifdef SCFG
-	uchar	name[26];					/* Name of set */
-#else
-	uchar	*name;
-#endif
-			} actset_t;
-
-typedef struct {						/* Chat action info */
-#ifdef SCFG
-	uchar	cmd[LEN_CHATACTCMD+1],		/* Command word */
-			out[LEN_CHATACTOUT+1];		/* Output */
-#else
-	uchar	*cmd,
-			*out;
-#endif
-	ushort	actset; 					/* Set this action belongs to */
-			} chatact_t;
-
-typedef struct {						/* Gurus */
-	uchar
-#ifdef SCFG
-			name[26],
-			ar[LEN_ARSTR+1],
-#else
-			*name,
-			*ar,
-#endif
-			code[9];
-
-			} guru_t;
-
-typedef struct {						/* Chat Channel Information */
-	uchar
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access requirements */
-			name[26],					/* Channel description */
-#else
-			*ar,
-			*name,
-#endif
-			code[9];
-	ushort	actset, 					/* Set of actions used in this chan */
-			guru;						/* Guru file number */
-	ulong	cost,						/* Cost to join */
-			misc;						/* Misc. bits CHAN_* definitions */
-			} chan_t;
-
-typedef struct {                        /* Modem Result codes info */
-	ushort	code,						/* Numeric Result Code */
-			cps,    		            /* Average Transfer CPS */
-			rate;   		            /* DCE Rate (Modem to Modem) */
-#ifdef SCFG
-	uchar   str[LEN_MODEM+1];   		/* String to use for description */
-#else
-	uchar	*str;
-#endif
-			} mdm_result_t;
-
-typedef struct {                        /* Transfer Protocol information */
-	uchar	mnemonic,					/* Letter to select this protocol */
-#ifdef SCFG
-			name[26],					/* Name of protocol */
-			ar[LEN_ARSTR+1],			/* ARS */
-			ulcmd[LEN_CMD+1],			/* Upload command line */
-			dlcmd[LEN_CMD+1],			/* Download command line */
-			batulcmd[LEN_CMD+1],		/* Batch upload command line */
-			batdlcmd[LEN_CMD+1],		/* Batch download command line */
-			blindcmd[LEN_CMD+1],		/* Blind upload command line */
-			bicmd[LEN_CMD+1];			/* Bidirectional command line */
-#else
-			*ar,
-			*name,
-			*ulcmd,
-			*dlcmd,
-			*batulcmd,
-			*batdlcmd,
-			*blindcmd,
-			*bicmd;
-#endif
-	ulong	misc;						/* Miscellaneous bits */
-			} prot_t;
-
-typedef struct {                        /* Extractable file types */
-	uchar	ext[4], 					/* Extension */
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access Requirements */
-			cmd[LEN_CMD+1]; 			/* Command line */
-#else
-			*ar,
-			*cmd;
-#endif
-			} fextr_t;
-
-typedef struct {						/* Compressable file types */
-	uchar	ext[4], 					/* Extension */
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access Requirements */
-			cmd[LEN_CMD+1]; 			/* Command line */
-#else
-			*ar,
-			*cmd;
-#endif
-			} fcomp_t;
-
-typedef struct {                        /* Viewable file types */
-	uchar	ext[4], 					/* Extension */
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access Requirements */
-			cmd[LEN_CMD+1]; 			/* Command line */
-#else
-			*ar,
-			*cmd;
-#endif
-			} fview_t;
-
-typedef struct {                        /* Testable file types */
-	uchar	ext[4], 					/* Extension */
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access requirement */
-			cmd[LEN_CMD+1], 			/* Command line */
-			workstr[41];				/* String to display while working */
-#else
-			*ar,
-			*cmd,
-			*workstr;
-#endif
-			} ftest_t;
-
-typedef struct {						/* Download events */
-	uchar	ext[4],
-#ifdef SCFG
-			ar[LEN_ARSTR+1],			/* Access requirement */
-			cmd[LEN_CMD+1], 			/* Command line */
-			workstr[41];				/* String to display while working */
-#else
-			*ar,
-			*cmd,
-			*workstr;
-#endif
-			} dlevent_t;
-
-typedef struct {						/* External Editors */
-	uchar
-#ifdef SCFG
-			name[41],					/* Name (description) */
-			ar[LEN_ARSTR+1],			/* Access Requirement */
-			lcmd[LEN_CMD+1],			/* Local command line */
-			rcmd[LEN_CMD+1],			/* Remote command line */
-#else
-			*name,
-			*ar,
-			*lcmd,
-			*rcmd,
-#endif
-			code[9];
-	ulong	misc;						/* Misc. bits */
-	uchar	type;						/* Drop file type */
-			} xedit_t;
-
-
-typedef struct {						/* Generic Timed Event */
-	uchar	code[9],					/* Internal code */
-			days,						/* Days to run event */
-#ifdef SCFG
-			dir[LEN_DIR+1], 			/* Start-up directory */
-			cmd[LEN_CMD+1]; 			/* Command line */
-#else
-			*dir,
-			*cmd;
-#endif
-	ushort	node,						/* Node to execute event */
-			time;						/* Time to run event */
-	ulong	misc;						/* Misc bits */
-#ifndef SCFG
-	time_t	last;						/* Last time event ran */
-#endif
-			} event_t;
-
-typedef struct {						/* QWK Network Hub */
-	uchar	id[9],						/* System ID of Hub */
-			*mode,						/* Mode for Ctrl-A codes for ea. sub */
-			days,						/* Days to call-out on */
-#ifdef SCFG
-			call[LEN_CMD+1],			/* Call-out command line to execute */
-			pack[LEN_CMD+1],			/* Packing command line */
-			unpack[LEN_CMD+1];			/* Unpacking command line */
-#else
-			*call,
-			*pack,
-			*unpack;
-#endif
-	ushort	time,						/* Time to call-out */
-			node,						/* Node to do the call-out */
-			freq,						/* Frequency of call-outs */
-			subs,						/* Number Sub-boards carried */
-			*sub,						/* Number of local sub-board for ea. */
-			*conf;						/* Conference number of ea. */
-#ifndef SCFG
-	time_t	last;						/* Last network attempt */
-#endif
-			} qhub_t;
-
-typedef struct {						/* PCRelay/PostLink Hub */
-	uchar	days,						/* Days to call-out on */
-#ifdef SCFG
-			name[11],					/* Site Name of Hub */
-			call[LEN_CMD+1];			/* Call-out command line to execute */
-#else
-			*call;
-#endif
-	ushort	time,						/* Time to call-out */
-			node,						/* Node to do the call-out */
-			freq;						/* Frequency of call-outs */
-#ifndef SCFG
-	time_t	last;						/* Last network attempt */
-#endif
-			} phub_t;
-
-
-typedef struct {						/* FidoNet msg header */
-	uchar	from[36],					/* From user */
-			to[36], 					/* To user */
-			subj[72],					/* Message title */
-			time[20];					/* Time in goof-ball ASCII format */
-	short	read,						/* Times read */
-			destnode,					/* Destination node */
-			orignode,					/* Origin node */
-			cost,						/* Cost in pennies */
-			orignet,					/* Origin net */
-			destnet,					/* Destination net */
-			destzone,					/* Destination zone */
-			origzone,					/* Origin zone */
-			destpoint,					/* Destination point */
-			origpoint,					/* Origin point */
-			re, 						/* Message number regarding */
-			attr,						/* Attributes - see FIDO_* */
-			next;						/* Next message number in stream */
-			} fmsghdr_t;
-
-
-typedef struct {						/* Command Shells */
-	uchar
-#ifdef SCFG
-			name[41],					/* Name (description) */
-			ar[LEN_ARSTR+1],			/* Access Requirement */
-#else
-			*name,
-			*ar,
-#endif
-			code[9];
-	ulong	misc;
-			} shell_t;
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/scb/makefile b/src/sbbs2/scb/makefile
deleted file mode 100644
index 5e3dea3f819848d5fdca81934b1f0bea562ad078..0000000000000000000000000000000000000000
--- a/src/sbbs2/scb/makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-
-# Macros
-CC	= bcc
-LD	= tlink
-SDK	= ..\sdk
-MSWAIT	= ..\..\mswait\dos
-INCLUDE = \bc31\include;$(SDK);..
-LIB     = \bc31\lib
-MODEL	= l
-CFLAGS  = -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LDFLAGS = /n /c
-OBJS	= xsdk.obj xsdkvars.obj $(MSWAIT)\mswait$(MODEL).obj ..\dos\rciol.obj
-HEADERS = $(SDK)\xsdk.h $(SDK)\xsdkdefs.h $(SDK)\xsdkvars.c scb.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-scb.exe: $(OBJS) scb.obj
-    	@echo Linking $< ...
-	$(LD) $(LDFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) scb.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-
-# All .obj modules
-scb.obj: $(HEADERS)
-
-xsdk.obj: $(SDK)\xsdk.c $(HEADERS)
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $(SDK)\$*.c
-
-xsdkvars.obj: $(SDK)\xsdkvars.c $(SDK)\xsdkdefs.h
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $(SDK)\$*.c
diff --git a/src/sbbs2/scb/scb.c b/src/sbbs2/scb/scb.c
deleted file mode 100644
index 661528cf1c33db5d8a9333f84c5f1b9597c8ba8b..0000000000000000000000000000000000000000
--- a/src/sbbs2/scb/scb.c
+++ /dev/null
@@ -1,920 +0,0 @@
-/* SCB */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "xsdk.h"
-#include "scb.h"
-
-/* RCIOLL.ASM */
-
-int  rioini(int com,int irq);          /* initialize com,irq */
-int  setbaud(int rate);                /* set baud rate */
-int  rioctl(int action);               /* remote i/o control */
-int  dtr(char onoff);                  /* set/reset dtr */
-int  outcom(int ch);                   /* send character */
-int  incom(void);                      /* receive character */
-int  ivhctl(int intcode);              /* local i/o redirection */
-
-/************************/
-/* Remote I/O Constants */
-/************************/
-
-							/* i/o mode and state flags */
-#define CTSCK 0x1000     	/* check cts (mode only) */
-#define RTSCK 0x2000		/* check rts (mode only) */
-#define TXBOF 0x0800		/* transmit buffer overflow (outcom only) */
-#define ABORT 0x0400     	/* check for ^C (mode), aborting (state) */
-#define PAUSE 0x0200     	/* check for ^S (mode), pausing (state) */
-#define NOINP 0x0100     	/* input buffer empty (incom only) */
-
-							/* status flags */
-#define RIODCD	0x80		/* DCD on */
-#define RI		0x40		/* Ring indicate */
-#define DSR 	0x20		/* Dataset ready */
-#define CTS 	0x10       	/* CTS on */
-#define FERR 	0x08		/* Frameing error */
-#define PERR 	0x04		/* Parity error */
-#define OVRR 	0x02		/* Overrun */
-#define RXLOST 	0x01       	/* Receive buffer overflow */
-
-/* rioctl() arguments */
-/* returns mode or state flags in high 8 bits, status flags in low 8 bits */
-
-							/* the following return mode in high 8 bits */
-#define IOMODE 0        	/* no operation */
-#define IOSM 1          	/* i/o set mode flags */
-#define IOCM 2          	/* i/o clear mode flags */
-							/* the following return state in high 8 bits */
-#define IOSTATE 4       	/* no operation */
-#define IOSS 5          	/* i/o set state flags */
-#define IOCS 6          	/* i/o clear state flags */
-#define IOFB 0x308      	/* i/o buffer flush */
-#define IOFI 0x208      	/* input buffer flush */
-#define IOFO 0x108      	/* output buffer flush */
-#define IOCE 9          	/* i/o clear error flags */
-
-							/* return count (16bit)	*/
-#define RXBC	0x0a		/* get receive buffer count */
-#define TXBC	0x0b		/* get transmit buffer count */
-#define TXSYNC  0x0c        /* sync transmition (seconds<<8|0x0c) */
-#define IDLE	0x0d		/* suspend communication routines */
-#define RESUME  0x10d		/* return from suspended state */
-#define RLERC	0x000e		/* read line error count and clear */
-#define CPTON	0x0110		/* set input translation flag for ctrl-p on */
-#define CPTOFF	0x0010		/* set input translation flag for ctrl-p off */
-#define GETCPT	0x8010		/* return the status of ctrl-p translation */
-#define MSR 	0x0011		/* read modem status register */
-#define FIFOCTL 0x0012		/* FIFO UART control */
-#define TSTYPE	0x0013		/* Time-slice API type */
-#define GETTST  0x8013      /* Get Time-slice API type */
-
-
-#define I14DB	0x001d		/* DigiBoard int 14h driver */
-#define I14PC	0x011d		/* PC int 14h driver */
-#define I14PS	0x021d		/* PS/2 int 14h driver */
-#define I14FO   0x031d      /* FOSSIL int 14h driver */
-
-
-							/* ivhctl() arguments */
-#define INT29R 1         	/* copy int 29h output to remote */
-#define INT29L 2			/* Use _putlc for int 29h */
-#define INT16  0x10      	/* return remote chars to int 16h calls */
-#define INTCLR 0            /* release int 16h, int 29h */
-
-#define LEN_ALIAS		25	/* User alias								*/
-#define LEN_NAME		25	/* User name								*/
-#define LEN_HANDLE		8	/* User chat handle 						*/
-#define LEN_NOTE		30	/* User note								*/
-#define LEN_COMP		30	/* User computer description				*/
-#define LEN_COMMENT 	60	/* User comment 							*/
-#define LEN_NETMAIL 	60	/* NetMail forwarding address				*/
-#define LEN_PASS		 8	/* User password							*/
-#define LEN_PHONE		12	/* User phone number						*/
-#define LEN_BIRTH		 8	/* Birthday in MM/DD/YY format				*/
-#define LEN_ADDRESS 	30	/* User address 							*/
-#define LEN_LOCATION	30	/* Location (City, State)					*/
-#define LEN_ZIPCODE 	10	/* Zip/Postal code							*/
-#define LEN_MODEM		 8	/* User modem type description				*/
-#define LEN_FDESC		58	/* File description 						*/
-#define LEN_TITLE		70	/* Message title							*/
-#define LEN_MAIN_CMD	40	/* Storage in user.dat for custom commands	*/
-#define LEN_XFER_CMD	40
-#define LEN_SCAN_CMD	40
-#define LEN_MAIL_CMD	40
-#define LEN_CID 		25	/* Caller ID (phone number) 				*/
-#define LEN_ARSTR		40	/* Max length of Access Requirement string	*/
-
-/****************************************************************************/
-/* This is a list of offsets into the USER.DAT file for different variables */
-/* that are stored (for each user)											*/
-/****************************************************************************/
-#define U_ALIAS 	0					/* Offset to alias */
-#define U_NAME		(U_ALIAS+LEN_ALIAS) /* Offset to name */
-#define U_HANDLE	(U_NAME+LEN_NAME)
-#define U_NOTE		(U_HANDLE+LEN_HANDLE+2)
-#define U_COMP		(U_NOTE+LEN_NOTE)
-#define U_COMMENT	(U_COMP+LEN_COMP+2)
-
-#define U_NETMAIL	(U_COMMENT+LEN_COMMENT+2)
-
-#define U_ADDRESS	(U_NETMAIL+LEN_NETMAIL+2)
-#define U_LOCATION	(U_ADDRESS+LEN_ADDRESS)
-#define U_ZIPCODE	(U_LOCATION+LEN_LOCATION)
-
-#define U_PASS		(U_ZIPCODE+LEN_ZIPCODE+2)
-#define U_PHONE  	(U_PASS+8) 			/* Offset to phone-number */
-#define U_BIRTH  	(U_PHONE+12)		/* Offset to users birthday	*/
-#define U_MODEM     (U_BIRTH+8)
-#define U_LASTON	(U_MODEM+8)
-#define U_FIRSTON	(U_LASTON+8)
-#define U_EXPIRE    (U_FIRSTON+8)
-#define U_PWMOD     (U_EXPIRE+8)
-
-#define U_LOGONS    (U_PWMOD+8+2)
-#define U_LTODAY    (U_LOGONS+5)
-#define U_TIMEON    (U_LTODAY+5)
-#define U_TEXTRA  	(U_TIMEON+5)
-#define U_TTODAY    (U_TEXTRA+5)
-#define U_TLAST     (U_TTODAY+5)
-#define U_POSTS     (U_TLAST+5)
-#define U_EMAILS    (U_POSTS+5)
-#define U_FBACKS    (U_EMAILS+5)
-#define U_ETODAY	(U_FBACKS+5)
-#define U_PTODAY	(U_ETODAY+5)
-
-#define U_ULB       (U_PTODAY+5+2)
-#define U_ULS       (U_ULB+10)
-#define U_DLB       (U_ULS+5)
-#define U_DLS       (U_DLB+10)
-#define U_CDT		(U_DLS+5)
-#define U_MIN		(U_CDT+10)
-
-#define U_LEVEL 	(U_MIN+10+2)	/* Offset to Security Level    */
-#define U_FLAGS1	(U_LEVEL+2) 	/* Offset to Flags */
-#define U_TL		(U_FLAGS1+8)	/* Offset to unused field */
-#define U_FLAGS2	(U_TL+2)		/* Offset to unused field */
-#define U_EXEMPT	(U_FLAGS2+8)
-#define U_REST		(U_EXEMPT+8)
-#define U_ROWS		(U_REST+8+2)	/* Number of Rows on user's monitor */
-#define U_SEX		(U_ROWS+2)		/* Sex, Del, ANSI, color etc.		*/
-#define U_MISC		(U_SEX+1)		/* Miscellaneous flags in 8byte hex */
-#define U_XEDIT 	(U_MISC+8)		/* External editor */
-#define U_LEECH 	(U_XEDIT+2) 	/* two hex digits - leech attempt count */
-#define U_CURGRP	(U_LEECH+2) 	/* Current group */
-#define U_CURSUB	(U_CURGRP+4)	/* Current sub-board */
-#define U_CURLIB	(U_CURSUB+4)	/* Current library */
-#define U_CURDIR	(U_CURLIB+4)	/* Current directory */
-#define U_CMDSET	(U_CURDIR+4)	/* User's command set */
-#define U_MAIN_CMD	(U_CMDSET+2+2)	/* Custom main command set */
-#define U_XFER_CMD	(U_MAIN_CMD+LEN_MAIN_CMD)
-#define U_SCAN_CMD	(U_XFER_CMD+LEN_XFER_CMD+2)
-#define U_MAIL_CMD	(U_SCAN_CMD+LEN_SCAN_CMD)
-#define U_FREECDT	(U_MAIL_CMD+LEN_MAIL_CMD+2)  /* Unused bytes */
-#define U_FLAGS3	(U_FREECDT+10)	/* Unused bytes */
-#define U_FLAGS4	(U_FLAGS3+8)
-#define U_UNUSED1	(U_FLAGS4+8)
-#define U_UNUSED2	(U_UNUSED1+22+2)
-#define U_LEN       (U_UNUSED2+48+2)
-
-enum {
-	 PHONE_OKAY
-	,PHONE_INVALID
-	,PHONE_LD
-	};
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-uint asmrev,options=0;
-char canfile[256],result[256]={NULL},tmp[256],
-	 addfile[256],phone_number[81]={NULL},flags1[81],flags2[81],flags3[81],
-	 flags4[81],exempt[81],restrict[81],expiration[81],credits[81],minutes[81],
-	 level[81],bbs_ac[81];
-char *crlf="\r\n";
-extern uint riobp;
-extern int mswtyp;
-char io_int=0,validated=0;		/* i/o interrupts intercepted? yes/no */
-int sysop=0;
-int ldstart[7],ldend[7],min_phone_len,max_phone_len,hangup_time;
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-int lprintf(char *fmat, ...);
-void bail();
-int main();
-void phone_val();
-char *get_user_pw();
-char check_phone(char *insearch);
-void mdmcmd(char *str);
-void putcomch(char ch);
-char getmdmstr(char *str, int sec);
-void mswait(int);
-void moduser();
-void write_info();
-char long_distance(char *number);
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...) {
-	char sbuf[256];
-	int chcount;
-
-chcount=vsprintf(sbuf,fmat,_va_ptr);
-lputs(sbuf);
-return(chcount);
-}
-
-void bail()
-{
-	char str[256];
-	int i;
-
-if(io_int)
-	ivhctl(0);
-else if(!(options&STAY_CONNECTED)) { /* exiting without re-connecting */
-	dtr(10);
-	sprintf(str,"%sHANGUP.NOW",node_dir);
-	if((i=nopen(str,O_CREAT|O_RDWR))!=-1)
-		close(i); }
-if(com_port) {
-	for(i=0;i<5;i++)
-		if(!rioctl(TXBC))		/* wait for rest of output */
-			break;
-		else
-			mswait(1000);
-	rioini(0,0); }
-if(options&ALWAYS_VALIDATE || validated)
-	moduser();
-write_info();
-lputc(FF);
-}
-
-int main()
-{
-	void *v;
-	uchar far *s;
-	char str[128],ch,*p;
-	int i,file;
-	uint base=0xffff;
-	FILE *stream;
-
-node_dir[0]=0;
-
-p=getenv("SBBSNODE");
-if(p)
-	strcpy(node_dir,p);
-
-if(!node_dir[0]) {	  /* node directory not specified */
-	printf("\n\7SBBSNODE environment variable must be set.\n");
-	printf("\nExample: SET SBBSNODE=C:\\SBBS\\NODE1\n");
-	getch();
-	return(1); }
-
-if(node_dir[strlen(node_dir)-1]!='\\')  /* make sure node_dir ends in '\' */
-	strcat(node_dir,"\\");
-
-initdata();                                 /* read XTRN.DAT and more */
-
-if((asmrev=*(&riobp-1))!=23) {
-    printf("Wrong rciol.obj\n");
-    exit(1); }
-
-lclini(0xd<<8); 	 /* Tab expansion, no CRLF expansion */
-
-if(com_port) {
-	lprintf("\r\nInitializing COM port %u: ",com_port);
-	switch(com_base) {
-		case 0xb:
-			lputs("PC BIOS");
-			rioctl(I14PC);
-			break;
-		case 0xffff:
-		case 0xd:
-			lputs("DigiBoard");
-			rioctl(I14DB);
-			break;
-		case 0xe:
-			lputs("PS/2 BIOS");
-			rioctl(I14PS);
-			break;
-		case 0xf:
-			lputs("FOSSIL");
-			rioctl(I14FO);
-			break;
-		case 0:
-			base=com_port;
-			lputs("UART I/O (BIOS), ");
-			if(com_irq)
-				lprintf("IRQ %d",com_irq);
-			else lputs("default IRQ");
-			break;
-		default:
-			base=com_base;
-			lprintf("UART I/O %Xh, ",com_base);
-			if(com_irq)
-				lprintf("IRQ %d",com_irq);
-			else lputs("default IRQ");
-			break; }
-
-	if(base==0xffff)
-		lprintf(" channel %u",com_irq);
-	i=rioini(base,com_irq);
-	if(i) {
-		lprintf(" - Failed! (%d)\r\n",i);
-		exit(1); }
-	if(mdm_misc&MDM_FLOWCTRL)
-		rioctl(IOSM|CTSCK|RTSCK); /* set rts/cts chk */
-	setbaud((uint)(com_rate&0xffffL));
-	msr=&riobp-1; }
-
-rioctl(TSTYPE|mswtyp);	 /* set time-slice API type */
-
-rioctl(CPTON);          /* ctrl-p translation */
-
-i=INT29L;
-if(com_port)
-	i|=(INT29R|INT16);
-ivhctl(i);
-io_int=1;
-
-atexit(bail);
-
-phone_val();
-
-return(0);
-}
-
-/******************************************************************************
- Main phone validation loop.
-******************************************************************************/
-void phone_val()
-{
-	FILE *stream;
-	char user_password[9],str[256],init_attempts=0,callout_attempts=0,*p;
-	int i=0,j,file;
-
-	if((file=nopen("SCB.CFG",O_RDONLY))==-1) {
-		bprintf("ERROR: Opening configuration file\r\n"); exit(1); }
-	if((stream=fdopen(file,"rb"))==NULL) {
-		bprintf("ERROR: Converting configuration file to a stream\r\n");
-		exit(1); }
-	fgets(str,81,stream); truncsp(str); callout_attempts=atoi(str);
-	fgets(str,81,stream); truncsp(str);
-	if(str[0]=='Y') options|=ALWAYS_VALIDATE;
-	if(str[1]=='Y') options|=MODIFY_USER_NOTE;
-	if(str[2]=='Y') options|=START_WITH_0;
-	if(str[3]=='Y') options|=START_WITH_1;
-	if(str[4]=='Y') options|=STAY_CONNECTED;
-	if(str[5]=='Y') options|=SC_LOCAL_ONLY;
-	if(str[6]=='Y') options|=US_PHONE_FORMAT;
-	if(str[7]=='Y') options|=ALLOWED_ONLY;
-	if(str[8]!='N') options|=SAME_AREA_LD;
-	fgets(canfile,81,stream); truncsp(canfile);
-	fgets(addfile,81,stream); truncsp(addfile);
-	fgets(credits,81,stream); truncsp(credits);
-	fgets(str,81,stream); truncsp(str); sysop=atoi(str);
-	fgets(level,81,stream); truncsp(level);
-	fgets(flags1,81,stream); truncsp(flags1);
-	fgets(flags2,81,stream); truncsp(flags2);
-	fgets(exempt,81,stream); truncsp(exempt);
-	fgets(restrict,81,stream); truncsp(restrict);
-	fgets(expiration,81,stream); truncsp(expiration);
-	fgets(minutes,81,stream); truncsp(minutes);
-	fgets(flags3,81,stream); truncsp(flags3);
-	fgets(flags4,81,stream); truncsp(flags4);
-	for(i=0;i<7;i++) {
-		fgets(str,81,stream); ldstart[i]=atoi(str);    /* min since midnight */
-		fgets(str,81,stream); ldend[i]=atoi(str); }
-	fgets(str,81,stream); min_phone_len=atoi(str);
-	fgets(str,81,stream); max_phone_len=atoi(str);
-	fgets(bbs_ac,81,stream); truncsp(bbs_ac);
-	if(fgets(str,81,stream)) {
-		hangup_time=atoi(str);
-		if(hangup_time>90)
-			hangup_time=90; }
-	else
-		hangup_time=30;
-
-	fgets(str,81,stream);		// regnum
-
-	fclose(stream);
-
-	cls();
-	strcpy(result,"Hung up");
-	strcpy(user_password,get_user_pw());
-	bprintf("\1c\1hSynchronet Callback v%s  "
-		"Developed 1995-1997 Rob Swindell\r\n",VERSION);
-	sprintf(str,"%s..\\EXEC\\",ctrl_dir);
-	printfile("SCB.MSG");
-	if(yesno("\r\nDo you need instructions"))
-		printfile("INSTRUCT.MSG");
-	if(!yesno("\r\nContinue with verification")) {
-        options&=~ALWAYS_VALIDATE;
-        cls(); printfile("REFUSED.MSG"); pause();
-        strcpy(result,"Refused");
-        return; }
-/***
-	if(!(options&ALLOW_LD) && yesno("Are you calling long distance")) {
-		bprintf("\r\n\1n\1cSorry, \1h%s \1n\1cwill verify \1y\1hLOCAL "
-			"\1n\1ccalls only!\r\n",sys_name);
-			strcpy(result,"Long Dist"); pause();
-		return; }
-***/
-
-	while(1) {
-		while(1) {
-			bprintf("\r\n\r\n\1n\1cEnter your \1h\1yCOMPLETE \1n\1cphone "
-				"number now. If you are calling long distance, enter\r\n\1h\1y"
-				"ALL \1n\1cof the digits necessary to reach your phone number. "
-				"If you are a \1h\1yLOCAL \1n\1ccall from the BBS, \1h\1yDO NOT"
-				"\1n\1c enter unnecessary digits (your area code, for example)."
-				"\r\n:");
-			getstr(phone_number,20,K_LINE|K_NUMBER);
-			if(yesno("\r\nIs this correct")) break; }
-
-		if(bbs_ac[0]) { 							/* Strip off area code */
-			if(!strncmp(phone_number,bbs_ac,strlen(bbs_ac)))
-				strcpy(phone_number,phone_number+strlen(bbs_ac));
-			else {
-				sprintf(tmp,"1%s",bbs_ac);
-				if(!strncmp(phone_number,tmp,strlen(tmp)))
-					strcpy(phone_number,phone_number+strlen(tmp)); } }
-
-		if(options&US_PHONE_FORMAT &&				/* Add 1 to number */
-			(phone_number[1]=='0' || phone_number[1]=='1') &&
-			strlen(phone_number)>7) {
-			sprintf(tmp,"1%s",phone_number);
-			strcpy(phone_number,tmp); }
-
-		j=check_phone(phone_number);
-
-		if(j==PHONE_LD) {
-			strcpy(result,"Long Dist");
-			pause();
-			return; }
-		if(j==PHONE_OKAY)
-			break;
-		options&=~ALWAYS_VALIDATE;
-		strcpy(result,"Invalid #");
-		bprintf("\r\n\1n\1cReturning you to \1h%s.\1n\r\n",sys_name);
-		return; }
-
-	bprintf("\r\n\r\n\1n\1cDropping Carrier, \1h%s \1n\1cwill call you back "
-		"now.\r\nType \1h\1yATA \1n\1cto answer when your modem rings!\r\n\r\n"
-		,sys_name);
-	if(!com_port) exit(0);
-	mswait(1000);
-	ivhctl(0);		/* put intercepted i/o vectors back */
-	io_int=0;
-
-	for(init_attempts=0;init_attempts<4;init_attempts++) {	 /* 4 attempts */
-		dtr(5);
-		if(!init_attempts) mswait(1000);
-		dtr(1);
-		rioctl(IOFB);
-		for(i=0;i<4;i++) {
-			mdmcmd(mdm_init);
-			if(!getmdmstr(str,10))
-				continue;
-			if(!stricmp(str,mdm_init)) {	/* Echo on? */
-				getmdmstr(str,10);			/* Get OK */
-				mdmcmd("ATE0");             /* Turn echo off */
-				if(!getmdmstr(str,10))
-                    continue; }
-			if(!strcmp(str,"OK")) {         /* Verbal response? */
-				mdmcmd("ATV0");             /* Turn verbal off */
-				if(!getmdmstr(str,10))
-					continue; }
-			if(!strcmp(str,"0"))
-				break;
-			rioctl(IOFB);		/* Send fool-proof init string */
-			mdmcmd("ATE0V0");
-			if(getmdmstr(str,10) && !strcmp(str,"0"))
-				break; }
-		if(i==4)
-			continue;
-		mswait(100);
-		if(mdm_spec[0]) {
-			for(i=0;i<4;i++) {
-				mdmcmd(mdm_spec);
-				if(!getmdmstr(str,10)) continue;
-				if(!strcmp(str,"0")) break; }
-			if(i==4)
-				continue; }
-		break; }
-
-	if(init_attempts==4) {	 /* couldn't init */
-		strcpy(result,"No Init");
-		exit(1); }
-
-	mswait(1000);
-	mdmcmd("ATH");
-	str[0]=0;
-	getmdmstr(str,10);
-	if(strcmp(str,"0")) {
-		strcpy(result,"No Init");
-		exit(1); }
-	if(hangup_time)
-		bprintf("\r\n\1n\1cWaiting \1h%u\1n\1c seconds before dialing..."
-			"\r\n\r\n",hangup_time);
-	mswait(hangup_time*1000);			/* Wait xx seconds before dialing */
-
-	for(i=0;i<callout_attempts;i++) {
-		mswait(5000);
-		rioctl(IOFB);
-		sprintf(str,"%s%s",mdm_dial,phone_number);
-		mdmcmd(str);
-		if(!getmdmstr(str,60)) {
-			mdmcmd("");         /* send CR to abort dial */
-			continue; }
-		if(strcmp(str,"0") && strcmp(str,"2") && strcmp(str,"3")
-			&& strcmp(str,"4") && strcmp(str,"6") && strcmp(str,"7")
-			&& strcmp(str,"8") && strcmp(str,"9"))
-		   break; }
-
-	if(i==callout_attempts) {			/* Couldn't connect */
-		strcpy(result,"No Connect");
-		exit(1); }
-
-	i=INT29L;		/* intercept i/o vectors again */
-	if(com_port)
-		i|=(INT29R|INT16);
-	ivhctl(i);
-	io_int=1;
-
-	if(rioctl(IOSTATE|DCD)) {
-		mswait(5000);	/* wait 5 seconds for MNP to Non-MNP connect */
-		rioctl(IOFB);
-		lncntr=0;
-		i=0; cls();
-		bprintf("\r\n\r\n\1n\1cThis is \1h%s \1n\1ccalling for \1m%s.",
-			sys_name,user_name);
-		while(1) {
-			bprintf("\r\n\r\n\1h\1yEnter your password for verification: ");
-			getstr(str,8,K_UPPER|K_LINE);
-			if(!stricmp(str,user_password)) {
-				validated=1;
-				bprintf("\r\n\r\n\1n\1cYou have now been verified on \1h%s!",
-					sys_name);
-				printfile("VERIFIED.MSG");
-				strcpy(result,"Verified");
-				break; }
-			else {
-				bprintf("\r\n\1r\1hINCORRECT!\1n");
-				if(++i>=4) {
-					bprintf("\r\n\r\n\1r\1hYou have entered an incorrect "
-						"password.  Goodbye.\r\n\r\n"); dtr(5);
-						strcpy(result,"Bad Pass"); return; } } }
-
-		if(!(options&STAY_CONNECTED)) {
-			mswait(2000);
-			for(i=0;i<5;i++) {
-				dtr(5);
-				if(!(rioctl(IOSTATE)&DCD))	/* no carrier detect */
-					break;
-				lprintf("SCB: Dropping DTR failed to lower DCD.\r\n");
-				dtr(1);
-				mswait(2000); }
-			sprintf(str,"%sHANGUP.NOW",node_dir);
-			if((i=nopen(str,O_CREAT|O_RDWR))!=-1)
-				close(i); } }
-}
-
-/******************************************************************************
- Writes the MODUSER.DAT file.
-******************************************************************************/
-void moduser()
-{
-	FILE *stream;
-	char str[512];
-	int file;
-	long expire;
-	time_t now;
-
-	now=time(NULL);
-
-	if(user_expire>now)
-		expire=(user_expire+(atol(expiration)*24L*60L*60L));
-	else
-		expire=(now+(atol(expiration)*24L*60L*60L));
-
-	sprintf(str,"%sMODUSER.DAT",node_dir);
-	if((stream=fopen(str,"wb"))!=NULL) {
-		fprintf(stream,"%s\r\n",credits);
-		fprintf(stream,"%s\r\n",level);
-		fprintf(stream,"\r\n");
-		fprintf(stream,"%s\r\n",flags1);
-		fprintf(stream,"%s\r\n",flags2);
-		fprintf(stream,"%s\r\n",exempt);
-		fprintf(stream,"%s\r\n",restrict);
-		fprintf(stream,"%s\r\n",atol(expiration) ? ultoa(expire,str,16) : "");
-		fprintf(stream,"%s\r\n",minutes);
-		fprintf(stream,"%s\r\n",flags3);
-		fprintf(stream,"%s\r\n",flags4);
-		fclose(stream);
-		}
-	else
-        bprintf("\7\r\nError opening %s for write.\r\n",str);
-	if(addfile[0] && phone_number[0]) {
-        if((file=nopen(addfile,O_WRONLY|O_APPEND|O_CREAT))!=-1) {
-            sprintf(str,"%s^\r\n",phone_number);
-            write(file,str,strlen(str));
-            close(file); }
-        else
-            bprintf("\7\r\nError opening %s for write.\r\n",addfile); }
-	if(sysop) {
-		sprintf(str,"\1c\1hSCB: \1y%s \1n\1cwas validated \1h%.24s\1n\r\n"
-			,user_name,ctime(&now));
-		putsmsg(sysop,str); }
-}
-
-/******************************************************************************
- Writes the log file.
-******************************************************************************/
-void write_info()
-{
-	char str[512];
-	int file;
-	time_t now;
-
-	now=time(NULL);
-	if((file=nopen("SCB.LOG",O_WRONLY|O_APPEND|O_CREAT))!=-1) {
-		sprintf(str,
-			"Node %-3d     : %.24s\r\n"
-			"User Name    : %s\r\n"
-			"Voice Number : %s\r\n"
-			"Modem Number : %s\r\n"
-			"Result       : %s\r\n\r\n"
-			,node_num,ctime(&now),user_name,user_phone,phone_number,result);
-		write(file,str,strlen(str));
-		close(file); }
-	else
-		bprintf("\7\r\nError opening SCB.LOG for write.\r\n");
-	sprintf(str,"%sNODE.LOG",node_dir);
-	if(com_port && (file=nopen(str,O_WRONLY|O_APPEND|O_CREAT))!=-1) {
-		sprintf(str,"cb Result: %s %s\r\n",result,phone_number);
-		write(file,str,strlen(str));
-		close(file); }
-	if(options&MODIFY_USER_NOTE) {
-        sprintf(str,"%sUSER\\USER.DAT",data_dir);
-		if((file=nopen(str,O_WRONLY|O_DENYNONE))!=-1) {
-			lseek(file,(long)((((long)user_number-1L)*U_LEN)+U_NOTE),SEEK_SET);
-            memset(str,'\3',30);
-			sprintf(str,"%s %s",result,phone_number);
-			str[strlen(str)]=3;
-			write(file,str,30);
-            close(file); } }
-}
-
-/******************************************************************************
- Returns the users' password.
-******************************************************************************/
-char *get_user_pw()
-{
-	static char pw[9];
-	char str[256];
-	int file,x;
-
-	sprintf(str,"%sUSER\\USER.DAT",data_dir);
-	if((file=nopen(str,O_RDONLY))==-1) {
-		printf("Unable to open %s.",str); exit(1); }
-	lseek(file,(long)((((long)user_number-1L)*U_LEN)+U_PASS),SEEK_SET);
-	read(file,pw,8);
-	for(x=0;x<8;x++)
-		if(pw[x]==3) break;
-	pw[x]=0;
-	close(file);
-	return(pw);
-}
-
-/******************************************************************************
- Checks the phone number entered.  0=Good, 1=Bad.
-******************************************************************************/
-char check_phone(char *insearch)
-{
-	char str[256],search[256],c,found=0,allowed=0,long_distance=0;
-	int file,day,t;
-	FILE *stream;
-	time_t now;
-	struct date date;
-	struct time curtime;
-	struct tm *tblock;
-
-if(strlen(insearch)<min_phone_len) {
-	printfile("TOOSHORT.MSG");
-	return(PHONE_INVALID); }
-if(strlen(insearch)>max_phone_len) {
-	printfile("TOOLONG.MSG");
-    return(PHONE_INVALID); }
-
-strcpy(str,"ALLOWED.DAT");
-if((file=nopen(str,O_RDONLY|O_TEXT))!=-1)
-	if((stream=fdopen(file,"rt"))!=NULL) {
-		strcpy(search,insearch);
-		strupr(search);
-		while(!feof(stream) && !ferror(stream)) {
-			if(!fgets(str,81,stream))
-				break;
-			truncsp(str);
-			c=strlen(str);
-			if(c && !strncmp(str,search,c)) {
-				allowed=1;
-				break; } }
-	fclose(stream); }
-
-if(!allowed) {
-
-	if(options&ALLOWED_ONLY)
-		long_distance=1;
-	else {
-		strcpy(str,"LDPREFIX.DAT");
-		if((file=nopen(str,O_RDONLY|O_TEXT))!=-1)
-			if((stream=fdopen(file,"rt"))!=NULL) {
-				strcpy(search,insearch);
-				strupr(search);
-				while(!feof(stream) && !ferror(stream)) {
-					if(!fgets(str,81,stream))
-						break;
-					truncsp(str);
-					c=strlen(str);
-					if(c && !strncmp(str,search,c)) {
-						long_distance=1;
-						break; } }
-			fclose(stream); } }
-
-	if(!(options&START_WITH_0) && insearch[0]=='0') {
-		printfile("NO_ZERO.MSG");
-		return(PHONE_LD); }
-	if(!(options&START_WITH_1) && insearch[0]=='1') {
-		printfile("NO_ONE.MSG");
-		return(PHONE_LD); }
-	if(!(options&SAME_AREA_LD) && insearch[0]!='0' && insearch[0]!='1'
-		&& long_distance) {
-		printfile("NO_LD.MSG");
-		return(PHONE_LD); }
-	if((insearch[0]=='1' || insearch[0]=='0' || long_distance) &&
-		(ldstart[day] || ldend[day])) {
-		now=time(NULL);
-		tblock=localtime(&now);
-		day=tblock->tm_wday;
-		unixtodos(now,&date,&curtime);
-		t=(curtime.ti_hour*60)+curtime.ti_min;
-
-		if((ldstart[day]<ldend[day]
-			&& (t<ldstart[day] || t>ldend[day]))
-
-		|| (ldstart[day]>ldend[day]
-			&& (t<ldstart[day] && t>ldend[day]))
-
-			) {
-
-			bprintf("\7\r\n\1n\1gLong distance calls are only allowed between "
-				"\1h%02d:%02d \1n\1gand \1h%02d:%02d\1n\1g.\r\n"
-				,ldstart[day]/60,ldstart[day]%60
-				,ldend[day]/60,ldend[day]%60);
-			printfile("LD_TIME.MSG");
-			return(PHONE_LD); } } }
-
-strcpy(str,canfile);
-if((file=nopen(str,O_RDONLY|O_TEXT))==-1) {
-	if(fexist(str))
-		printf("ERROR: Unable to open %s for read.",str);
-	return(PHONE_OKAY); }
-if((stream=fdopen(file,"rt"))==NULL) {
-	printf("ERROR: Converting %s to a stream.",str);
-	return(PHONE_OKAY); }
-strcpy(search,insearch);
-strupr(search);
-while(!feof(stream) && !ferror(stream) && !found) {
-	if(!fgets(str,81,stream))
-		break;
-	truncsp(str);
-	c=strlen(str);
-	if(c) {
-		c--;
-		strupr(str);
-		if(str[c]=='~') {
-			str[c]=0;
-			if(strstr(search,str))
-				found=1; }
-
-		else if(str[c]=='^') {
-			str[c]=0;
-			if(!strncmp(str,search,c))
-				found=1; }
-
-		else if(!strcmp(str,search))
-			found=1; } }
-fclose(stream);
-if(found) {
-	printfile("PHONECAN.MSG");
-	return(PHONE_INVALID); }
-if(!allowed && options&STAY_CONNECTED && options&SC_LOCAL_ONLY &&
-	(insearch[0]=='1' || insearch[0]=='0'))
-    options&=~STAY_CONNECTED;
-return(PHONE_OKAY);
-}
-
-/****************************************************************************/
-/* Outputs a single character to the COM port								*/
-/****************************************************************************/
-void putcomch(char ch)
-{
-	char 	lch;
-	int 	i=0;
-
-if(!com_port)
-	return;
-while(outcom(ch)&TXBOF && i<1440) {	/* 3 minute pause delay */
-    if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==3) {
-			lputs("local abort (putcomch)\r\n");
-			i=1440;
-			break; }
-		ungetkey(lch); }
-    if(!(rioctl(IOSTATE)&DCD))
-		break;
-	i++;
-	mswait(80); }
-if(i==1440) {						/* timeout - beep flush outbuf */
-	i=rioctl(TXBC);
-	lprintf("timeout(putcomch) %04X %04X\r\n",i,rioctl(IOFO));
-	outcom(7);
-	lputc(7);
-	rioctl(IOCS|PAUSE); }
-}
-
-/****************************************************************************/
-/* Sends string of characters to COM port. Interprets ^M and ~ (pause)		*/
-/* Called from functions waitforcall and offhook							*/
-/****************************************************************************/
-void mdmcmd(char *str)
-{
-	int 	i=0;
-	uint	lch;
-
-lputs("\r\nModem command  : ");
-while(str[i]) {
-	if(str[i]=='~')
-		mswait(500);
-	else {
-		if(i && str[i-1]=='^' && str[i]!='^')  /* control character */
-			putcomch(toupper(str[i])-64);
-		else if(str[i]!='^' || (i && str[i-1]=='^'))
-			putcomch(str[i]);
-		lputc(str[i]); }
-	i++; }
-putcomch(CR);
-i=0;
-while(rioctl(TXSYNC) && i<10) {   /* wait for modem to receive all chars */
-	if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==0x2e03) {
-			lputs("local abort (mdmcmd)\r\n");
-			break; }
-		if(lch==0xff00)
-			bail(1);
-		ungetkey(lch); }
-	i++; }
-if(i==10) {
-	i=rioctl(TXBC);
-	lprintf("\r\n\7timeout(mdmcmd) %04X %04X\r\n",i,rioctl(IOFO)); }
-lputs(crlf);
-}
-/****************************************************************************/
-/* Returns CR terminated string from the COM port. 							*/
-/* Called from function waitforcall 										*/
-/****************************************************************************/
-char getmdmstr(char *str, int sec)
-{
-	uchar	j=0,ch;
-	uint	lch;
-	time_t	start;
-
-lputs("Modem response : ");
-start=time(NULL);
-while(time(NULL)-start<sec && j<81) {
-	if(lkbrd(1)) {
-		lch=lkbrd(0);	/* ctrl-c */
-		if(lch==0x2e03) {
-			lputs("local abort (getmdmstr)\r\n");
-			break; }
-		if(lch==0xff00)
-			bail(1);
-		ungetkey(lch); }
-	if((ch=incom())==CR && j)
-		break;
-	if(ch && (ch<0x20 || ch>0x7f)) /* ignore control characters and ex-ascii */
-		continue;
-	if(ch) {
-		str[j++]=ch;
-		lputc(ch); }
-	else mswait(0); }
-mswait(500);
-str[j]=0;
-lputs(crlf);
-return(j);
-}
diff --git a/src/sbbs2/scb/scb.h b/src/sbbs2/scb/scb.h
deleted file mode 100644
index 1aac129df047a08fa4ebb4edddcd0c0b78021597..0000000000000000000000000000000000000000
--- a/src/sbbs2/scb/scb.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SCB.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet BBS Callback door */
-
-#define VERSION "1.40"
-
-#define ALWAYS_VALIDATE 	(1<<0)
-#define MODIFY_USER_NOTE	(1<<1)
-#define START_WITH_0		(1<<2)
-#define START_WITH_1		(1<<3)
-#define STAY_CONNECTED		(1<<4)
-#define SC_LOCAL_ONLY		(1<<5)
-#define US_PHONE_FORMAT 	(1<<6)
-#define ALLOWED_ONLY		(1<<7)
-#define SAME_AREA_LD		(1<<8)
diff --git a/src/sbbs2/scb/scbcfg.c b/src/sbbs2/scb/scbcfg.c
deleted file mode 100644
index 4058369fe3b1d0228094fec8161eee0ede7f7ecf..0000000000000000000000000000000000000000
--- a/src/sbbs2/scb/scbcfg.c
+++ /dev/null
@@ -1,788 +0,0 @@
-/* SCBCFG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <uifc.h>
-#include <sys\stat.h>
-#include "scb.h"
-
-#define MAX_PRFX	500
-#define LEN_PRFX	20
-
-char **opt;
-char **prfx;
-
-int add();
-void bail(int code);
-void main();
-char fexist(char *filespec);
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-void bail(int code)
-{
-
-if(code)
-	getch();
-uifcbail();
-exit(code);
-}
-
-int add()
-{
-	int i;
-
-i=0;
-strcpy(opt[0],"Add these to the user account");
-strcpy(opt[1],"Remove these from the user account");
-opt[2][0]=0;
-/*
-Add/Remove Flags/Restricts/Exempts:
-
-Select ADD if you want these flags/restricts/exempts added to the
-user upon validation, or select REMOVE to take them away upon
-validation.
-
-*/
-i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Add or Remove From Account",opt);
-return(i);
-}
-
-void main()
-{
-	char str[128],canfile[256],addfile[256],flags1[81]={NULL},
-		 flags2[81]={NULL},flags3[81]={NULL},flags4[81]={NULL},
-		 exempt[81]={NULL},restrict[81]={NULL},expiration[81]={NULL},
-		 credits[81]={NULL},minutes[81]={NULL},level[81]={NULL},
-		 callout_attempts[81]={NULL},sysop[81]={NULL},bbs_ac[81],*p;
-	int file,i,j,k,options=0,ldstart[7]={NULL},ldend[7]={NULL},min_phone_len=7,
-		max_phone_len=11,total_prfxs,dflt,b,hangup_time;
-	FILE *stream;
-
-savnum=0;
-if((opt=(char **)MALLOC(sizeof(char *)*300))==NULL) {
-	cputs("memory allocation error\r\n");
-	bail(1); }
-for(i=0;i<300;i++)
-	if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL) {
-		cputs("memory allocation error\r\n");
-        bail(1); }
-uifcini();
-sprintf(str,"Synchronet Callback v%s",VERSION);
-uscrn(str);
-
-if(!(fexist("SCB.CFG"))) {
-	strcpy(callout_attempts,"5");
-	strcpy(canfile,"\\SBBS\\TEXT\\PHONE.CAN");
-	strcpy(addfile,canfile);
-	options|=MODIFY_USER_NOTE; }
-else {
-	if((file=open("SCB.CFG",O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-		textattr(LIGHTGRAY);
-		clrscr();
-		lprintf("Error opening SCB.CFG\r\n");
-		bail(1); }
-	if((stream=fdopen(file,"rb"))==NULL) {
-		textattr(LIGHTGRAY);
-		clrscr();
-		lprintf("Error fdopen SCB.CFG\r\n");
-		bail(1); }
-	fgets(callout_attempts,81,stream); truncsp(callout_attempts);
-	fgets(str,81,stream); truncsp(str);
-	if(str[0]=='Y') options|=ALWAYS_VALIDATE;
-	if(str[1]=='Y') options|=MODIFY_USER_NOTE;
-	if(str[2]=='Y') options|=START_WITH_0;
-	if(str[3]=='Y') options|=START_WITH_1;
-	if(str[4]=='Y') options|=STAY_CONNECTED;
-	if(str[5]=='Y') options|=SC_LOCAL_ONLY;
-	if(str[6]=='Y') options|=US_PHONE_FORMAT;
-	if(str[7]=='Y') options|=ALLOWED_ONLY;
-	if(str[8]!='N') options|=SAME_AREA_LD;
-	fgets(canfile,81,stream); truncsp(canfile);
-	fgets(addfile,81,stream); truncsp(addfile);
-	fgets(credits,81,stream); truncsp(credits);
-	fgets(sysop,81,stream); truncsp(sysop);
-	fgets(level,81,stream); truncsp(level);
-	fgets(flags1,81,stream); truncsp(flags1);
-	fgets(flags2,81,stream); truncsp(flags2);
-	fgets(exempt,81,stream); truncsp(exempt);
-	fgets(restrict,81,stream); truncsp(restrict);
-	fgets(expiration,81,stream); truncsp(expiration);
-	fgets(minutes,81,stream); truncsp(minutes);
-	fgets(flags3,81,stream); truncsp(flags3);
-	fgets(flags4,81,stream); truncsp(flags4);
-	for(i=0;i<7;i++) {
-		fgets(str,81,stream); ldstart[i]=atoi(str);    /* min since midnight */
-		fgets(str,81,stream); ldend[i]=atoi(str); }
-	fgets(str,81,stream); min_phone_len=atoi(str);
-	fgets(str,81,stream); max_phone_len=atoi(str);
-	fgets(bbs_ac,81,stream); truncsp(bbs_ac);
-	if(fgets(str,81,stream)) {
-		hangup_time=atoi(str);
-		if(hangup_time>90)
-			hangup_time=90; }
-	else
-		hangup_time=30;
-	str[0]=0;
-	fgets(str,81,stream);	// regnum
-	fclose(stream); }
-dflt=0;
-while(1) {
-	helpbuf=
-" Synchronet Callback Configuration \r\n\r\n"
-"Move through the various options using the arrow keys.  Select the\r\n"
-"highlighted options by pressing ENTER.\r\n\r\n";
-	j=0;
-	sprintf(opt[j++],"Toggle Options...");
-	sprintf(opt[j++],"Validation Values...");
-	sprintf(opt[j++],"Allowed Prefix List...");
-	sprintf(opt[j++],"Long Distance Prefix List...");
-	sprintf(opt[j++],"Long Distance Calling Times...");
-	sprintf(opt[j++],"Phone Number Trash Can   %-30.30s",canfile);
-	sprintf(opt[j++],"Validated Phone List     %-30.30s",addfile);
-	sprintf(opt[j++],"Callback Attempts        %-2.2s",callout_attempts);
-	sprintf(opt[j++],"Minimum Phone Length     %u",min_phone_len);
-	sprintf(opt[j++],"Maximum Phone Length     %u",max_phone_len);
-	sprintf(opt[j++],"Wait Before Dialing      %u seconds",hangup_time);
-	sprintf(opt[j++],"BBS Area Code            %-3.3s",bbs_ac);
-	if(sysop[0])
-		sprintf(str,"User #%s",sysop);
-	else
-		sprintf(str,"Disabled");
-	sprintf(opt[j++],"Send Message to Sysop    %-30.30s",str);
-	opt[j][0]=NULL;
-	switch(ulist(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,60,&dflt,0
-	,"Synchronet Callback Configuration",opt)) {
-		case 0:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-40.40s%-3s","Validate if Unable to Verify"
-					,options&ALWAYS_VALIDATE ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s","Put Result in User Note"
-					,options&MODIFY_USER_NOTE ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s"
-					,"Long Distance if not an Allowed Prefix"
-					,options&ALLOWED_ONLY ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s"
-					,"Allow Long Distance (Starting with 0)"
-					,options&START_WITH_0 ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s"
-					,"Allow Long Distance (Starting with 1)"
-					,options&START_WITH_1 ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s"
-					,"Allow Long Distance (Same Area Code)"
-					,options&SAME_AREA_LD ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-3s"
-					,"U.S. Style Phone Format (AAA-PPP-SSSS)"
-					,options&US_PHONE_FORMAT ? "Yes":"No");
-				sprintf(opt[k++],"%-40.40s%-10s","Stay Connected After Callback"
-					,options&STAY_CONNECTED && options&SC_LOCAL_ONLY ?
-					"Local Only" : options&STAY_CONNECTED ? "Yes":"No");
-				opt[k][0]=NULL;
-helpbuf=
-" Toggle Options \r\n\r\n"
-"Validate if Unable to Call Back\r\n"
-"  Setting this to Yes will validate the user even if the board is unable "
-"\r\n"
-"  to call the user back.\r\n"
-"Put Result in User Note\r\n"
-"  When set to Yes, this option will place the phone number, and\r\n"
-"  information pertaining to the call into the user's note.\r\n"
-"Allow Numbers that Start with 0 / Allow Numbers that Start with 1\r\n"
-"  Set these options to Yes to allow SCB to call phone numbers which\r\n"
-"  start with a 0 or a 1 (respectively).\r\n"
-"U.S. Style Phone Format\r\n"
-"  Toggle this option to Yes if you live in an area that uses a phone\r\n"
-"  number format of (AAA) PPP-SSSS.\r\n"
-"Stay Connected After Callback\r\n"
-"  Toggle this option to Yes to allow SCB to stay connected after a\r\n"
-"  callback, Local Only for local numbers, or No to disconnect.";
-
-				j=ulist(0,0,0,0,&j,0,"Toggle Options",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-						options^=ALWAYS_VALIDATE;
-						break;
-					case 1:
-						options^=MODIFY_USER_NOTE;
-						break;
-					case 2:
-						options^=ALLOWED_ONLY;
-						break;
-					case 3:
-						options^=START_WITH_0;
-						break;
-					case 4:
-						options^=START_WITH_1;
-						break;
-					case 5:
-						options^=SAME_AREA_LD;
-                        break;
-					case 6:
-						options^=US_PHONE_FORMAT;
-						break;
-					case 7:
-						if(options&STAY_CONNECTED && options&SC_LOCAL_ONLY) {
-							options^=STAY_CONNECTED;
-							options^=SC_LOCAL_ONLY;
-						} else if(options&STAY_CONNECTED)
-							options^=SC_LOCAL_ONLY;
-						else options^=STAY_CONNECTED;
-						break; } }
-            break;
-		case 1:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Security Level"
-					,level);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Flag Set 1"
-					,flags1);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Flag Set 2"
-					,flags2);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Flag Set 3"
-					,flags3);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Flag Set 4"
-					,flags4);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Exemptions"
-					,exempt);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Restrictions"
-					,restrict);
-				sprintf(opt[k++],"%-30.30s  %-27.27s"
-					,"Days to Extend Expiration"
-					,expiration);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Credits to Add"
-					,credits);
-				sprintf(opt[k++],"%-30.30s  %-27.27s","Minutes to Add"
-					,minutes);
-				opt[k][0]=NULL;
-helpbuf=
-" Validation Values \r\n\r\n"
-"These are the values that will be placed into user accounts that have\r\n"
-"been successfully verified through the Synchronet Callback.";
-
-
-				j=ulist(WIN_ACT,0,0,0,&j,0,"Validation Values",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-helpbuf=
-" Security Level \r\n\r\n"
-"This is the Security level that will be given to users that are called\r\n"
-"back successfully.";
-						uinput(WIN_L2R|WIN_MID|WIN_SAV,0,0,
-							"Security Level",level,2,K_EDIT|K_NUMBER);
-						break;
-					case 1:
-helpbuf=
-" Flag Set 1 \r\n\r\n"
-"These are the different flags to be added to (or removed from) the\r\n"
-"user account.";
-						p=strstr(flags1,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",flags1);
-						if(uinput(WIN_L2R|WIN_MID|WIN_SAV,0,0,"Flag Set 1",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(flags1,"-%s",str);
-						else
-							sprintf(flags1,"%s",str);
-                        break;
-					case 2:
-helpbuf=
-" Flag Set 2 \r\n\r\n"
-"These are the different flags to be added to (or removed from) the\r\n"
-"user account.";
-						p=strstr(flags2,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",flags2);
-						if(uinput(WIN_L2R|WIN_MID|WIN_SAV,0,0,"Flag Set 2",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(flags2,"-%s",str);
-						else
-							sprintf(flags2,"%s",str);
-                        break;
-					case 3:
-helpbuf=
-" Flag Set 3 \r\n\r\n"
-"These are the different flags to be added to (or removed from) the\r\n"
-"user account.";
-						p=strstr(flags3,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",flags3);
-						if(uinput(WIN_L2R|WIN_MID|WIN_SAV,0,0,"Flag Set 3",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(flags3,"-%s",str);
-						else
-							sprintf(flags3,"%s",str);
-                        break;
-					case 4:
-helpbuf=
-" Flag Set 4 \r\n\r\n"
-"These are the different flags to be added to (or removed from) the\r\n"
-"user account.";
-						p=strstr(flags4,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",flags4);
-						if(uinput(WIN_L2R|WIN_MID|WIN_SAV,0,0,"Flag Set 4",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(flags4,"-%s",str);
-						else
-							sprintf(flags4,"%s",str);
-                        break;
-					case 5:
-helpbuf=
-" Exemptions \r\n\r\n"
-"These are the exemption flags that will be added to (or removed from)\r\n"
-"the user account.";
-						p=strstr(exempt,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",exempt);
-						if(uinput(WIN_MID|WIN_SAV,0,0,"Exemptions",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(exempt,"-%s",str);
-						else
-							sprintf(exempt,"%s",str);
-                        break;
-					case 6:
-helpbuf=
-" Restrictions \r\n\r\n"
-"These are the restriction flags that will be added to (or removed\r\n"
-"from) the user account.";
-						p=strstr(restrict,"-");
-						if(p!=NULL) sprintf(str,"%s",p+1);
-						else
-							sprintf(str,"%s",restrict);
-						if(uinput(WIN_MID|WIN_SAV,0,0,"Restrictions",str
-							,26,K_EDIT|K_UPPER|K_ALPHA)<0)
-							break;
-						if(str[0] && add()>0) sprintf(restrict,"-%s",str);
-						else
-							sprintf(restrict,"%s",str);
-                        break;
-					case 7:
-helpbuf=
-" Days to Extend Expiration \r\n\r\n"
-"This is the number of days to extend the expiration date of a user\r\n"
-"account.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Expiration"
-							,expiration,8,K_EDIT|K_UPPER|K_NUMBER);
-                        break;
-					case 8:
-helpbuf=
-" Credits to Add \r\n\r\n"
-"This is the number of credits to add to a user account.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Credits",credits
-							,10,K_EDIT|K_UPPER|K_NUMBER);
-                        break;
-					case 9:
-helpbuf=
-" Minutes to Add \r\n\r\n"
-"This is the number of minutes to add to a user account.";
-						uinput(WIN_MID|WIN_SAV,0,0,"Minutes",minutes
-							,3,K_EDIT|K_UPPER|K_NUMBER);
-						break; } }
-            break;
-		case 2:
-helpbuf=
-" Allowed Prefix List \r\n\r\n"
-"Any phone numbers entered whose prefix matches a number contained\r\n"
-"in this list, will not be affected by long distance restrictions.\r\n"
-"For example, if you are in the 714 code, and you wish to SCB to\r\n"
-"consider all prefixes in the 310 area code local, you would enter 1310\r\n"
-"in the list.";
-
-			total_prfxs=0;
-			if((prfx=(char **)MALLOC(sizeof(char *)*MAX_PRFX))==NULL) {
-				cputs("memory allocation error\r\n");
-				bail(1); }
-			for(i=0;i<MAX_PRFX;i++)
-				if((prfx[i]=(char *)MALLOC(LEN_PRFX+1))==NULL) {
-					cputs("memory allocation error\r\n");
-					bail(1); }
-
-			if(fexist("ALLOWED.DAT")) {
-				if((file=open("ALLOWED.DAT",
-					O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-					textattr(LIGHTGRAY);
-					clrscr();
-					lprintf("Error opening ALLOWED.DAT\r\n");
-					bail(1); }
-				if((stream=fdopen(file,"rb"))==NULL) {
-					textattr(LIGHTGRAY);
-					clrscr();
-					lprintf("Error fdopen ALLOWED.DAT\r\n");
-					bail(1); }
-				while(!feof(stream) && total_prfxs<MAX_PRFX) {
-					if(!fgets(str,81,stream))
-						break;
-					truncsp(str);
-					sprintf(prfx[total_prfxs++],"%.*s",LEN_PRFX,str); }
-				fclose(stream); }
-			i=b=0;
-            while(1) {
-				for(j=0;j<total_prfxs;j++)
-					strcpy(opt[j],prfx[j]);
-                opt[j][0]=NULL;
-				j=WIN_ACT|WIN_SAV;
-				if(total_prfxs)
-                    j|=WIN_DEL;
-				if(total_prfxs<MAX_PRFX)
-					j|=WIN_INS|WIN_INSACT|WIN_XTR;
-				i=ulist(j,0,0,30,&i,&b,"Allowed Prefix List",opt);
-                if((i&0xf000)==MSK_DEL) {
-                    i&=0xfff;
-					total_prfxs--;
-					for(j=i;j<total_prfxs;j++)
-						strcpy(prfx[j],prfx[j+1]);
-					strcpy(prfx[j+1],"");
-                    continue; }
-                if((i&0xf000)==MSK_INS) {
-                    i&=0xfff;
-					if(uinput(WIN_MID|WIN_SAV,0,0,"Enter Prefix",str,LEN_PRFX
-                        ,K_NUMBER)<1)
-                        continue;
-					++total_prfxs;
-					if(total_prfxs)
-						for(j=total_prfxs;j>i;j--)
-							strcpy(prfx[j],prfx[j-1]);
-					strcpy(prfx[i],str);
-                    continue; }
-                if(i==-1) {
-                    if((file=open("ALLOWED.DAT",
-						O_WRONLY|O_BINARY|O_CREAT|O_TRUNC|O_DENYALL,
-						S_IREAD|S_IWRITE))==-1) {
-						textattr(LIGHTGRAY);
-						clrscr();
-                        lprintf("Error opening ALLOWED.DAT\r\n");
-                        bail(1); }
-                    if((stream=fdopen(file,"wb"))==NULL) {
-						textattr(LIGHTGRAY);
-						clrscr();
-                        lprintf("Error fdopen ALLOWED.DAT\r\n");
-                        bail(1); }
-					for(i=0;i<total_prfxs;i++) {
-						fprintf(stream,"%s\r\n",prfx[i]); }
-                    fclose(stream);
-					for(i=0;i<MAX_PRFX;i++)
-						FREE(prfx[i]);
-					FREE(prfx);
-                    break; }
-                /* else CR was hit */
-                uinput(WIN_MID|WIN_SAV,0,0,"Edit Prefix"
-					,prfx[i],LEN_PRFX,K_EDIT|K_NUMBER); }
-            break;
-		case 3:
-helpbuf=
-" Long Distance Prefix List \r\n\r\n"
-"Any phone numbers entered whose prefixes matches a number contained\r\n"
-"in this list, will be considered a long distance number.  For example,\r\n"
-"in the same area code, the phone number 234-5678 is long distance to you,\r\n"
-"so placing 234 in this list will make SCB view calls to that prefix as\r\n"
-"long distance.\r\n"
-"\r\n"
-"If the Long Distance if not an Allowed Prefix toggle option is set to\r\n"
-"Yes, then this list is not used.\r\n";
-
-			total_prfxs=0;
-			if((prfx=(char **)MALLOC(sizeof(char *)*MAX_PRFX))==NULL) {
-				cputs("memory allocation error\r\n");
-				bail(1); }
-			for(i=0;i<MAX_PRFX;i++)
-				if((prfx[i]=(char *)MALLOC(LEN_PRFX+1))==NULL) {
-					cputs("memory allocation error\r\n");
-					bail(1); }
-
-			if(fexist("LDPREFIX.DAT")) {
-				if((file=open("LDPREFIX.DAT",
-					O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-					textattr(LIGHTGRAY);
-					clrscr();
-					lprintf("Error opening LDPREFIX.DAT\r\n");
-					bail(1); }
-				if((stream=fdopen(file,"rb"))==NULL) {
-					textattr(LIGHTGRAY);
-					clrscr();
-					lprintf("Error fdopen LDPREFIX.DAT\r\n");
-					bail(1); }
-				while(!feof(stream) && total_prfxs<MAX_PRFX) {
-					if(!fgets(str,81,stream))
-						break;
-					truncsp(str);
-					sprintf(prfx[total_prfxs++],"%.*s",LEN_PRFX,str); }
-				fclose(stream); }
-			i=b=0;
-            while(1) {
-                for(j=0;j<total_prfxs;j++)
-                    strcpy(opt[j],prfx[j]);
-                opt[j][0]=NULL;
-				j=WIN_ACT|WIN_SAV;
-                if(total_prfxs)
-                    j|=WIN_DEL;
-                if(total_prfxs<MAX_PRFX)
-                    j|=WIN_INS|WIN_INSACT|WIN_XTR;
-				i=ulist(j,0,0,30,&i,&b,"Long Distance Prefix List",opt);
-                if((i&0xf000)==MSK_DEL) {
-                    i&=0xfff;
-                    total_prfxs--;
-                    for(j=i;j<total_prfxs;j++)
-                        strcpy(prfx[j],prfx[j+1]);
-                    strcpy(prfx[j+1],"");
-                    continue; }
-                if((i&0xf000)==MSK_INS) {
-                    i&=0xfff;
-                    if(uinput(WIN_MID|WIN_SAV,0,0,"Enter Prefix",str,LEN_PRFX
-                        ,K_NUMBER)<1)
-                        continue;
-                    ++total_prfxs;
-                    if(total_prfxs)
-                        for(j=total_prfxs;j>i;j--)
-                            strcpy(prfx[j],prfx[j-1]);
-                    strcpy(prfx[i],str);
-                    continue; }
-                if(i==-1) {
-					if((file=open("LDPREFIX.DAT",
-						O_WRONLY|O_BINARY|O_CREAT|O_TRUNC|O_DENYALL,
-						S_IREAD|S_IWRITE))==-1) {
-						textattr(LIGHTGRAY);
-						clrscr();
-						lprintf("Error opening LDPREFIX.DAT\r\n");
-                        bail(1); }
-                    if((stream=fdopen(file,"wb"))==NULL) {
-						textattr(LIGHTGRAY);
-						clrscr();
-						lprintf("Error fdopen LDPREFIX.DAT\r\n");
-                        bail(1); }
-                    for(i=0;i<total_prfxs;i++) {
-                        fprintf(stream,"%s\r\n",prfx[i]); }
-                    fclose(stream);
-                    for(i=0;i<MAX_PRFX;i++)
-                        FREE(prfx[i]);
-                    FREE(prfx);
-                    break; }
-                /* else CR was hit */
-                uinput(WIN_MID|WIN_SAV,0,0,"Edit Prefix"
-                    ,prfx[i],LEN_PRFX,K_EDIT|K_NUMBER); }
-            break;
-		case 4:
-helpbuf=
-" Long Distance Calling Times \r\n\r\n"
-"You are being prompted to specify the beginning and ending times to\r\n"
-"allow long distance verification calls (in military 24-hour format).\r\n"
-"If you wish to allow long distance calls continuously, set both times\r\n"
-"to 00:00.\r\n"
-"\r\n"
-"To disable long distance calls entirely, set the Allow Long Distance\r\n"
-"toggle options to No.";
-
-            j=0;
-            while(1) {
-                k=0;
-				sprintf(opt[k++],"Sunday     From %02d:%02d to %02d:%02d"
-					,ldstart[0]/60,ldstart[0]%60
-					,ldend[0]/60,ldend[0]%60);
-				sprintf(opt[k++],"Monday     From %02d:%02d to %02d:%02d"
-					,ldstart[1]/60,ldstart[1]%60
-					,ldend[1]/60,ldend[1]%60);
-				sprintf(opt[k++],"Tuesday    From %02d:%02d to %02d:%02d"
-					,ldstart[2]/60,ldstart[2]%60
-					,ldend[2]/60,ldend[2]%60);
-				sprintf(opt[k++],"Wednesday  From %02d:%02d to %02d:%02d"
-					,ldstart[3]/60,ldstart[3]%60
-					,ldend[3]/60,ldend[3]%60);
-				sprintf(opt[k++],"Thursday   From %02d:%02d to %02d:%02d"
-					,ldstart[4]/60,ldstart[4]%60
-					,ldend[4]/60,ldend[4]%60);
-				sprintf(opt[k++],"Friday     From %02d:%02d to %02d:%02d"
-					,ldstart[5]/60,ldstart[5]%60
-					,ldend[5]/60,ldend[5]%60);
-				sprintf(opt[k++],"Saturday   From %02d:%02d to %02d:%02d"
-					,ldstart[6]/60,ldstart[6]%60
-					,ldend[6]/60,ldend[6]%60);
-                opt[k][0]=NULL;
-
-				j=ulist(WIN_ACT|WIN_SAV,0,0,0,&j,0
-					,"Long Distance Calling Times",opt);
-                if(j==-1)
-                    break;
-				sprintf(str,"%02d:%02d",ldstart[j]/60,ldstart[j]%60);
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Long Distance Start "
-					"Time",str,5,K_EDIT|K_UPPER)) {
-					ldstart[j]=atoi(str)*60;
-					p=strchr(str,':');
-					if(p)
-						ldstart[j]+=atoi(p+1); }
-				sprintf(str,"%02d:%02d",ldend[j]/60,ldend[j]%60);
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Long Distance End Time",
-					str,5,K_EDIT|K_UPPER)) {
-					ldend[j]=atoi(str)*60;
-					p=strchr(str,':');
-					if(p)
-						ldend[j]+=atoi(p+1); } }
-			break;
-		case 5:
-helpbuf=
-" Phone Can \r\n\r\n"
-"This is the complete path (drive, directory, and filename) where a\r\n"
-"trashcan file of phone numbers will be kept. Any numbers inside of this\r\n"
-"trashcan will not be accepted for callback verification by SCB.";
-			uinput(WIN_MID,0,0,"Phone Can",canfile
-				,30,K_EDIT|K_UPPER);
-            break;
-		case 6:
-helpbuf=
-" Validated Phone List \r\n\r\n"
-"This is the complete path (drive, directory, and filename) where SCB\r\n"
-"will write a list of numbers that have been verified.\r\n"
-"\r\n"
-"Setting this option to the same file as Phone Can will keep users from\r\n"
-"being validated with an already validated phone number.";
-			uinput(WIN_MID|WIN_BOT,0,0,"Phone List",addfile
-				,30,K_EDIT|K_UPPER);
-			break;
-		case 7:
-helpbuf=
-" Callback Attempts \r\n\r\n"
-"This is the number of times SCB will attempt to dial out to a phone\r\n"
-"number.";
-			uinput(WIN_MID|WIN_BOT,0,0,"Callback Attempts",callout_attempts
-				,2,K_EDIT|K_NUMBER);
-            break;
-		case 8:
-helpbuf=
-" Minimum Phone Number Length \r\n\r\n"
-"This is the minimum number of digits SCB will allow for a phone number.";
-			sprintf(str,"%u",min_phone_len);
-			uinput(WIN_MID|WIN_BOT,0,0,"Minimum Phone Length",str
-				,2,K_EDIT|K_NUMBER);
-			min_phone_len=atoi(str);
-            break;
-		case 9:
-helpbuf=
-" Maximum Phone Number Length \r\n\r\n"
-"This is the maximum number of digits SCB will allow for a phone number.";
-			sprintf(str,"%u",max_phone_len);
-			uinput(WIN_MID|WIN_BOT,0,0,"Maximum Phone Length",str
-				,2,K_EDIT|K_NUMBER);
-			max_phone_len=atoi(str);
-            break;
-		case 10:
-helpbuf=
-" Wait Before Dialing \r\n\r\n"
-"When the BBS hangs up prior to calling a user, this is the amount of\r\n"
-"time (in seconds) that the modem will remain hung up before dialing.\r\n"
-"This is used to insure that the user has completely disconnected.\r\n"
-"The default setting here is 30 seconds, maximum is 90 seconds.";
-			sprintf(str,"%u",hangup_time);
-			uinput(WIN_MID|WIN_BOT,0,0,"Wait Before Dialing (in seconds)",str
-				,3,K_EDIT|K_NUMBER);
-			hangup_time=atoi(str);
-			if(hangup_time>90)
-				hangup_time=90;
-			break;
-		case 11:
-helpbuf=
-" BBS Area Code \r\n\r\n"
-"Enter the area code for YOUR BBS here.  A user enters a phone number\r\n"
-"with this area code, SCB will strip off the area code before attempting\r\n"
-"to call the user back (setting this to 0 disables it).";
-            uinput(WIN_MID|WIN_BOT,0,0,"BBS Area Code",bbs_ac
-                ,3,K_EDIT|K_NUMBER);
-            break;
-		case 12:
-helpbuf=
-" Send Message to Sysop \r\n\r\n"
-"If you wish for SCB to send a message to a Sysop when a user has been\r\n"
-"verified, set this to the number of the user who is to receive the\r\n"
-"messages, or set it to 0 to disable this function.";
-			uinput(WIN_MID|WIN_BOT,0,0,"Send Message to Sysop - User #",sysop
-				,4,K_EDIT|K_NUMBER);
-            break;
-
-		case -1:
-helpbuf=
-" Save Configuration File \r\n\r\n"
-"Select Yes to save the config file, No to quit without saving,\r\n"
-"or hit  ESC  to go back to the menu.\r\n\r\n";
-			i=0;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			i=ulist(WIN_MID,0,0,0,&i,0,"Save Config File",opt);
-			if(i==-1) break;
-			if(i) bail(0);
-			if((file=open("SCB.CFG"
-				,O_WRONLY|O_BINARY|O_CREAT|O_DENYALL|O_TRUNC))==-1) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error opening SCB.CFG\r\n");
-				bail(1); }
-			if((stream=fdopen(file,"wb"))==NULL) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error fdopen SCB.CFG\r\n");
-				bail(1); }
-			str[0]=0;
-			fprintf(stream,"%s\r\n",callout_attempts);
-			if(options&ALWAYS_VALIDATE) strcat(str,"Y"); else strcat(str,"N");
-			if(options&MODIFY_USER_NOTE) strcat(str,"Y"); else strcat(str,"N");
-			if(options&START_WITH_0) strcat(str,"Y"); else strcat(str,"N");
-			if(options&START_WITH_1) strcat(str,"Y"); else strcat(str,"N");
-			if(options&STAY_CONNECTED) strcat(str,"Y"); else strcat(str,"N");
-			if(options&SC_LOCAL_ONLY) strcat(str,"Y"); else strcat(str,"N");
-			if(options&US_PHONE_FORMAT) strcat(str,"Y"); else strcat(str,"N");
-			if(options&ALLOWED_ONLY) strcat(str,"Y"); else strcat(str,"N");
-			if(options&SAME_AREA_LD) strcat(str,"Y"); else strcat(str,"N");
-			fprintf(stream,"%s\r\n",str);
-			fprintf(stream,"%s\r\n",canfile);
-			fprintf(stream,"%s\r\n",addfile);
-			fprintf(stream,"%s\r\n",credits);
-			fprintf(stream,"%s\r\n",sysop);
-			fprintf(stream,"%s\r\n",level);
-			fprintf(stream,"%s\r\n",flags1);
-			fprintf(stream,"%s\r\n",flags2);
-			fprintf(stream,"%s\r\n",exempt);
-			fprintf(stream,"%s\r\n",restrict);
-			fprintf(stream,"%s\r\n",expiration);
-			fprintf(stream,"%s\r\n",minutes);
-			fprintf(stream,"%s\r\n",flags3);
-			fprintf(stream,"%s\r\n",flags4);
-			for(i=0;i<7;i++) {
-				fprintf(stream,"%u\r\n",ldstart[i]);
-				fprintf(stream,"%u\r\n",ldend[i]); }
-			fprintf(stream,"%u\r\n",min_phone_len);
-			fprintf(stream,"%u\r\n",max_phone_len);
-			fprintf(stream,"%s\r\n",bbs_ac);
-			fprintf(stream,"%u\r\n",hangup_time);
-			fprintf(stream,"%s\r\n","");    // regnum
-			fclose(stream);
-			bail(0);
-	}
-}
-}
-/****************************************************************************/
-/* Checks the disk drive for the existance of a file. Returns 1 if it 		*/
-/* exists, 0 if it doesn't.													*/
-/* Called from upload														*/
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-	return(1);
-return(0);
-}
diff --git a/src/sbbs2/scb/scbcfg.mak b/src/sbbs2/scb/scbcfg.mak
deleted file mode 100644
index 00d9ddf9fa2c2198d48341d9eca79359a2373cfb..0000000000000000000000000000000000000000
--- a/src/sbbs2/scb/scbcfg.mak
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# Macros
-CC	= bcc
-LD	= tlink
-SDK	= ..\sdk
-UIFC	= ..\..\uifc
-MSWAIT	= ..\..\mswait
-INCLUDE = \bc45\include;$(UIFC)
-LIB	= \bc45\lib
-MODEL	= l
-CFLAGS  = -d -C -w-pro -m$(MODEL) -I$(INCLUDE)
-LDFLAGS = /n /c
-OBJS	= $(MSWAIT)\dos\mswait$(MODEL).obj uifc.obj
-HEADERS = $(UIFC)\uifc.h scb.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-scbcfg.exe: $(OBJS) scbcfg.obj
-    	@echo Linking $< ...
-	$(LD) $(LDFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) scbcfg.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-
-# All .obj modules
-scbcfg.obj: $(HEADERS)
-
-uifc.obj: $(UIFC)\uifc.h $(UIFC)\uifc.c
-	@echo Compiling $(UIFC)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -DSCFG -c $(UIFC)\$*.c
-
diff --git a/src/sbbs2/scfg/makeall.bat b/src/sbbs2/scfg/makeall.bat
deleted file mode 100755
index ccca323002f9af0f880b19466ad6c6bd5109e559..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/makeall.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@echo off
-maker
-maker -DDOS32
diff --git a/src/sbbs2/scfg/makefile b/src/sbbs2/scfg/makefile
deleted file mode 100644
index 0f6343a16a43137c400ba77677d614c6089ceb85..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/makefile
+++ /dev/null
@@ -1,108 +0,0 @@
-##############################################
-# Makefile for Synchronet BBS Config Program #
-# For use with Borland C++ for DOS or OS/2   #
-##############################################
-
-# Macros
-
-INCLUDE = \bc45\include;..;..\..\uifc;..\..\spawno;..\smb;..\rio
-LIB	= \bc45\lib
-MAIN	= $(OS)\scfg.exe
-
-!if $d(DOS32)
-OS	= DOS32
-CC	= \bc45\bin\bcc32
-LD	= \bc45\bin\tlink32
-CFLAGS	= -w-pro -d -C -WX -I$(INCLUDE) -DSCFG
-LFLAGS	= -Tpe -ax -n -c
-MAIN	= $(OS)\scfg32.exe
-!elif $d(__OS2__)
-OS	= OS2
-CC	= c:\bcos2\bin\bcc
-LD	= c:\bcos2\bin\tlink
-CFLAGS	= -w-pro -d -C -I$(INCLUDE) -DSCFG
-LFLAGS	= -Toe -ap -c
-INCLUDE = c:\bcos2\include;..;..\..\uifc;..\..\spawno;..\smb;..\rio
-LIB	= c:\bcos2\lib
-MAIN	= $(OS)\scfg4os2.exe
-!else
-OS      = DOS
-CC	= \bc45\bin\bcc
-LD	= \bc45\bin\tlink
-CFLAGS	= -w-pro -d -C -Y -ml -I$(INCLUDE) -DSCFG
-LFLAGS	= -n -c
-OBJS	= ..\..\mswait\dos\mswait.obj
-!endif
-
-OBJS	= $(OBJS) $(OS)\scfgvars.obj
-OVLOBJS = $(OS)\scfg.obj $(OS)\scfgnode.obj\
-        $(OS)\scfgxfr1.obj $(OS)\scfgxfr2.obj\
-	$(OS)\scfgnet.obj $(OS)\scfgxtrn.obj $(OS)\scfgsys.obj\
-	$(OS)\scfgmsg.obj $(OS)\scfgsub.obj\
-        $(OS)\scfglib1.obj $(OS)\scfglib2.obj $(OS)\scfgchat.obj\
-        $(OS)\uifc.obj $(OS)\scfgmdm.obj $(OS)\smblib.obj\
-        $(OS)\wrcnf1.obj $(OS)\wrcnf2.obj
-HEADERS = scfg.h ..\..\uifc\uifc.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) $(OVLOBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS) $(OVLOBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!elif $d(DOS32)
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0X32.obj $(OBJS) $(OVLOBJS)
-+, $*, $*,$(LIB)\DPMI32 $(LIB)\CW32
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0l.obj $(OBJS) /o $(OVLOBJS)
-+, $*, $*, $(LIB)\overlay.lib $(LIB)\cl.lib $(LIB)\mathl.lib\
-	$(LIB)\emu.lib
-!endif
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib.h ..\scfglib1.c \
-		    ..\scfgvars.c
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib.h ..\scfglib2.c \
-		    ..\scfgvars.c
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Local Menu Routines
-$(OS)\uifc.obj: ..\..\uifc\uifc.c ..\..\uifc\uifc.h
-	@echo Compiling ..\..\uifc\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\..\uifc\$&.c
-
-# SMBLIB Functions 
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling ..\smb\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\smb\$&.c
-
-$(OS)\scfg.obj:       $(HEADERS)
-$(OS)\scfgnode.obj:   $(HEADERS)
-$(OS)\scfgchat.obj:   $(HEADERS)
-$(OS)\scfgmsg.obj:    $(HEADERS)
-$(OS)\scfgsub.obj:    $(HEADERS)
-$(OS)\scfgnet.obj:    $(HEADERS)
-$(OS)\scfgsys.obj:    $(HEADERS)
-$(OS)\scfgxtrn.obj:   $(HEADERS)
-$(OS)\scfgxfr1.obj:   $(HEADERS)
-$(OS)\scfgxfr2.obj:   $(HEADERS)
-$(OS)\scfgmdm.obj:    $(HEADERS)
-$(OS)\wrcnf1.obj:     $(HEADERS)
-$(OS)\wrcnf2.obj:     $(HEADERS)
diff --git a/src/sbbs2/scfg/makehelp.c b/src/sbbs2/scfg/makehelp.c
deleted file mode 100644
index 20a64ad8afcd6d1fca6d272a859174cf57406396..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/makehelp.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* MAKEHELP.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Makes SCFG.HLP for Synchronet configuration program */
-
-#include <stdio.h>
-#include <alloc.h>
-#include <string.h>
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-void main(void)
-{
-	char *files[]={ "SCFG.C"
-				,"SCFGSYS.C"
-				,"SCFGMSG.C"
-				,"SCFGSUB.C"
-				,"SCFGNODE.C"
-				,"SCFGCHAT.C"
-				,"SCFGXFR1.C"
-				,"SCFGXFR2.C"
-				,"SCFGNET.C"
-				,"SCFGXTRN.C"
-				,NULL };
-	char str[256],tmp[256];
-	int i,j,k,line,ixb;
-	long l;
-	FILE *stream,*out;
-
-if((out=fopen("SCFGHELP.DAT","wb"))==NULL) {
-	printf("error opening SCFGHELP.DAT\r\n");
-	return; }
-
-if((ixb=open("SCFGHELP.IXB",O_WRONLY|O_CREAT|O_BINARY,S_IWRITE|S_IREAD))==-1) {
-	printf("error opening SCFGHELP.IXB\r\n");
-	return; }
-
-for(i=0;files[i];i++) {
-	if((stream=fopen(files[i],"rb"))==NULL) {
-		printf("error opening %s\r\n",files[i]);
-		return; }
-	printf("\r\n%s ",files[i]);
-	line=0;
-	while(!feof(stream)) {
-		if(!fgets(str,128,stream))
-			break;
-		line++;
-		if(strstr(str,"SETHELP(WHERE);")) {
-			l=ftell(out);
-			write(ixb,files[i],12);
-			write(ixb,&line,2);
-			write(ixb,&l,4);
-			fgets(str,128,stream);	 /* skip start comment */
-			line++;
-			while(!feof(stream)) {
-				if(!fgets(str,128,stream))
-					break;
-				if(strchr(str,9)) { /* Tab expansion */
-					strcpy(tmp,str);
-					k=strlen(tmp);
-					for(j=l=0;j<k;j++) {
-						if(tmp[j]==9) {
-							str[l++]=32;
-							while(l%4)
-								str[l++]=32; }
-						else
-							str[l++]=tmp[j]; }
-					str[l]=0; }
-				line++;
-				if(strstr(str,"*/"))    /* end comment */
-					break;
-				fputs(str,out); }
-			fputc(0,out); } }
-	fclose(stream); }
-fclose(out);
-printf("\n");
-}
diff --git a/src/sbbs2/scfg/makehelp.exe b/src/sbbs2/scfg/makehelp.exe
deleted file mode 100755
index 7e6a104c4311ee082949d9a5e64ce08aadf21cf2..0000000000000000000000000000000000000000
Binary files a/src/sbbs2/scfg/makehelp.exe and /dev/null differ
diff --git a/src/sbbs2/scfg/scfg.c b/src/sbbs2/scfg/scfg.c
deleted file mode 100644
index 3804fbe01db56259d1a0c68986e35cce1a6425c1..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfg.c
+++ /dev/null
@@ -1,1967 +0,0 @@
-#line 2 "SCFG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************************************/
-/* Synchronet configuration utility 										*/
-/****************************************************************************/
-
-#include "scfg.h"
-
-#ifdef __FLAT__
-	unsigned _stklen=64000;
-#else
-	unsigned _stklen=32000;
-#endif
-
-extern char *wday[];	/* names of weekdays (3 char) */
-extern char uifc_status;
-
-/********************/
-/* Global Variables */
-/********************/
-
-long freedosmem;
-int  no_dirchk=0,no_msghdr=0,forcesave=0,all_msghdr=0;
-char **opt;
-char tmp[256];
-char *nulstr="";
-char **mdm_type;
-char **mdm_file;
-int  mdm_types;
-int  backup_level=3;
-
-read_cfg_text_t txt={
-	"\7\r\nError opening %s for read.\r\n",
-	"","",
-	"\7\r\nError allocating %u bytes of memory\r\n",
-	"\7\r\nERROR: Offset %lu in %s\r\n\r\n" };
-
-char *invalid_code=
-"Invalid Internal Code:\n\n"
-"Internal codes can be up to eight characters in length and can only\n"
-"contain valid DOS filename characters. The code you have entered\n"
-"contains one or more invalid characters.";
-
-char *num_flags=
-"Number of Flags Needed:\n\n"
-"If you want users to be required to have all the flags, select All.\n"
-"\n"
-"If you want users to be required to have any one or more of the flags,\n"
-"select One (Allowed).";
-
-
-void allocfail(uint size)
-{
-cprintf("\7Error allocating %u bytes of memory.\r\n",size);
-bail(1);
-}
-
-time_t checktime(void)
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-int main(int argc, char **argv)
-{
-	char	**mopt,*p;
-	int 	i,j,main_dflt=0,no_emsovl=0,chat_dflt=0;
-	uint	u;
-	long	l;
-	char 	str[129];
-	FILE	*instream;
-#ifndef __FLAT__
-	union	REGS reg;
-#endif
-
-printf("\r\nSynchronet Configuration Util (%s)  v%s%c  Developed 1995-1997 "
-	"Rob Swindell\r\n",
-#ifdef __OS2__
-	"OS/2"
-#elif defined(__FLAT__)
-	"DOS/Win32"
-#else
-	"DOS"
-#endif
-	,VERSION,REVISION);
-
-if(argc>1)
-	strcpy(ctrl_dir,argv[1]);
-else
-	getcwd(ctrl_dir,MAXDIR);
-if(argc>2) {
-	for(i=2;i<argc;i++) {
-		if(!stricmp(argv[i],"/M"))      /* Show free mem */
-			show_free_mem=!show_free_mem;
-		else if(!stricmp(argv[i],"/N")) /* No EMS */
-			no_emsovl=!no_emsovl;
-#if !defined(__FLAT__)
-		else if(!strnicmp(argv[i],"/T",2)) /* Windows/OS2 time slice API */
-			mswtyp=atoi(argv[i]+2);
-#endif
-		else if(!strnicmp(argv[i],"/C",2)) /* Force color mode */
-			uifc_status|=UIFC_COLOR;
-		else if(!strnicmp(argv[i],"/B",2)) /* Backup level */
-			backup_level=atoi(argv[i]+2);
-		else if(!stricmp(argv[i],"/S")) /* No dir checking */
-			no_dirchk=!no_dirchk;
-		else if(!stricmp(argv[i],"/H")) /* No msg header updating */
-			no_msghdr=!no_msghdr;
-		else if(!stricmp(argv[i],"/U")) /* Update all message headers */
-			all_msghdr=!all_msghdr;
-		else if(!stricmp(argv[i],"/F")) /* Force save of config files */
-			forcesave=!forcesave;
-		else {
-			printf("\r\nusage: scfg <ctrl_dir> [/c] [/m] [/n] [/s] [/u] [/h] "
-				"[/t#] [/b#]\r\n"
-				"\r\n"
-				"/c  =  force color mode\r\n"
-				"/m  =  show free memory\r\n"
-				"/n  =  don't use EMS\r\n"
-				"/s  =  don't check directories\r\n"
-				"/f  =  force save of config files\r\n"
-				"/u  =  update all message base status headers\r\n"
-				"/h  =  don't update message base status headers\r\n"
-				"/t# =  set supported time slice APIs to #\r\n"
-				"/b# =  set automatic back-up level (default=3 max=10)\r\n"
-				);
-			exit(0); } } }
-
-if(backup_level>10) backup_level=10;
-
-if(ctrl_dir[strlen(ctrl_dir)-1]!='\\' && ctrl_dir[strlen(ctrl_dir)-1]!=':')
-        strcat(ctrl_dir,"\\");
-
-init_mdms();
-
-uifcini();
-
-#if !defined(__FLAT__)
-if(!no_emsovl) {
-	cputs("\r\nEMS: ");
-	if((i=open("EMMXXXX0",O_RDONLY))==-1)
-		cputs("not installed.");
-	else {
-		close(i);
-		reg.h.ah=0x46;			/* Get EMS version */
-		int86(0x67,&reg,&reg);
-		if(reg.h.ah)
-			cputs("\7error getting version.");
-		else {
-			cprintf("Version %u.%u ",(reg.h.al&0xf0)>>4,reg.h.al&0xf);
-			if(_OvrInitEms(0,0,23))    /* use up to 360K */
-				cprintf("allocation failed."); } }
-	cputs("\r\n"); }
-#endif
-
-#ifdef __FLAT__
-if(putenv("TZ=UCT0"))
-	printf("putenv() failed!\n");
-tzset();
-#endif
-
-if((l=checktime())!=0) {   /* Check binary time */
-	printf("Time problem (%08lx)\n",l);
-    exit(1); }
-
-if((opt=(char **)MALLOC(sizeof(char *)*(MAX_OPTS+1)))==NULL)
-	allocfail(sizeof(char *)*(MAX_OPTS+1));
-for(i=0;i<(MAX_OPTS+1);i++)
-	if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL)
-		allocfail(MAX_OPLN);
-
-if((mopt=(char **)MALLOC(sizeof(char *)*14))==NULL)
-	allocfail(sizeof(char *)*14);
-for(i=0;i<14;i++)
-	if((mopt[i]=(char *)MALLOC(64))==NULL)
-		allocfail(64);
-
-txt.reading=nulstr;
-txt.readit=nulstr;
-
-strcpy(str,argv[0]);
-p=strrchr(str,'\\');
-if(!p) {
-	sprintf(helpdatfile,"..\\EXEC\\SCFGHELP.DAT");
-	sprintf(helpixbfile,"..\\EXEC\\SCFGHELP.IXB"); }
-else {
-	*p=0;
-	sprintf(helpdatfile,"%s\\SCFGHELP.DAT",str);
-	sprintf(helpixbfile,"%s\\SCFGHELP.IXB",str); }
-
-sprintf(str,"Synchronet Configuration for %s v%s",
-#if defined(__OS2__)
-	"OS/2"
-#elif defined(__FLAT__)
-	"DOS/Win32"
-#else
-	"DOS"
-#endif
-	,VERSION);
-if(uscrn(str)) {
-	cprintf("USCRN failed!\r\n");
-	bail(1); }
-i=0;
-strcpy(mopt[i++],"Nodes");
-strcpy(mopt[i++],"System");
-strcpy(mopt[i++],"Networks");
-strcpy(mopt[i++],"File Areas");
-strcpy(mopt[i++],"File Options");
-strcpy(mopt[i++],"Chat Features");
-strcpy(mopt[i++],"Message Areas");
-strcpy(mopt[i++],"Message Options");
-strcpy(mopt[i++],"Command Shells");
-strcpy(mopt[i++],"External Programs");
-strcpy(mopt[i++],"Text File Sections");
-mopt[i][0]=0;
-#ifndef __FLAT__
-freedosmem=farcoreleft();
-#endif
-while(1) {
-#if 0
-	if(freedosmem!=farcoreleft()) {
-		errormsg(WHERE,ERR_CHK,"lost memory",freedosmem-farcoreleft());
-		freedosmem=farcoreleft(); }
-#endif
-	SETHELP(WHERE);
-/*
-Main Configuration Menu:
-
-This is the main menu of the Synchronet configuration utility (SCFG).
-From this menu, you have the following choices:
-
-	Nodes				  : Add, delete, or configure nodes
-	System				  : System-wide configuration options
-	Networks			  : Message networking configuration
-	File Areas			  : File area configuration
-	File Options		  : File area options
-	Chat Features		  : Chat actions, sections, pagers, and gurus
-	Message Areas		  : Message area configuration
-	Message Options 	  : Message and email options
-	External Programs	  : Events, editors, and online programs
-	Text File Sections	  : General text file area
-
-Use the arrow keys and  ENTER  to select an option, or  ESC  to exit.
-*/
-	switch(ulist(WIN_ORG|WIN_MID|WIN_ESC|WIN_ACT,0,0,30,&main_dflt,0
-		,"Configure",mopt)) {
-		case 0:
-			upop("Reading MAIN.CNF...");
-			read_main_cfg(txt);
-			upop(0);
-			node_menu();
-			free_main_cfg();
-			break;
-		case 1:
-			upop("Reading MAIN.CNF...");
-			read_main_cfg(txt);
-			upop("Reading XTRN.CNF...");
-			read_xtrn_cfg(txt);
-			upop(0);
-			sys_cfg();
-			free_xtrn_cfg();
-			free_main_cfg();
-			break;
-		case 2:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-			upop("Reading MSGS.CNF...");
-			read_msgs_cfg(txt);
-			upop(0);
-			net_cfg();
-			free_msgs_cfg();
-			free_main_cfg();
-			break;
-		case 3:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-            upop("Reading FILE.CNF...");
-            read_file_cfg(txt);
-			upop(0);
-            xfer_cfg();
-            free_file_cfg();
-			free_main_cfg();
-            break;
-		case 4:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-            upop("Reading FILE.CNF...");
-            read_file_cfg(txt);
-			upop(0);
-			xfer_opts();
-            free_file_cfg();
-			free_main_cfg();
-            break;
-		case 5:
-            upop("Reading CHAT.CNF...");
-            read_chat_cfg(txt);
-			upop(0);
-            while(1) {
-                i=0;
-                strcpy(opt[i++],"Artificial Gurus");
-                strcpy(opt[i++],"Multinode Chat Actions");
-                strcpy(opt[i++],"Multinode Chat Channels");
-                strcpy(opt[i++],"External Sysop Chat Pagers");
-				opt[i][0]=0;
-                j=ulist(WIN_ORG|WIN_ACT|WIN_CHE,0,0,0,&chat_dflt,0
-                    ,"Chat Features",opt);
-                if(j==-1) {
-                    j=save_changes(WIN_MID);
-                    if(j==-1)
-                        continue;
-                    if(!j)
-                        write_chat_cfg();
-                    break; }
-                switch(j) {
-                    case 0:
-                        guru_cfg();
-                        break;
-                    case 1:
-                        actsets_cfg();
-                        break;
-                    case 2:
-                        chan_cfg();
-                        break;
-                    case 3:
-                        page_cfg();
-                        break; } }
-            free_chat_cfg();
-            break;
-		case 6:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-			upop("Reading MSGS.CNF...");
-			read_msgs_cfg(txt);
-			upop(0);
-			msgs_cfg();
-			free_msgs_cfg();
-			free_main_cfg();
-			break;
-		case 7:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-			upop("Reading MSGS.CNF...");
-            read_msgs_cfg(txt);
-			upop(0);
-			msg_opts();
-			free_msgs_cfg();
-			free_main_cfg();
-			break;
-		case 8:
-			upop("Reading MAIN.CNF...");
-			read_main_cfg(txt);
-			upop(0);
-			shell_cfg();
-			free_main_cfg();
-            break;
-		case 9:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-			upop("Reading XTRN.CNF...");
-			read_xtrn_cfg(txt);
-			upop(0);
-			xprogs_cfg();
-			free_xtrn_cfg();
-			free_main_cfg();
-			break;
-		case 10:
-			upop("Reading MAIN.CNF...");
-            read_main_cfg(txt);
-            upop("Reading FILE.CNF...");
-            read_file_cfg(txt);
-			upop(0);
-            txt_cfg();
-            free_file_cfg();
-			free_main_cfg();
-            break;
-		case -1:
-			i=0;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			SETHELP(WHERE);
-/*
-Exit SCFG:
-
-If you want to exit the Synchronet configuration utility, select Yes.
-Otherwise, select No or hit  ESC .
-*/
-			i=ulist(WIN_MID,0,0,0,&i,0,"Exit SCFG",opt);
-			if(!i)
-				bail(0);
-			break; } }
-}
-
-/****************************************************************************/
-/* Checks the changes variable. If there have been no changes, returns 2.	*/
-/* If there have been changes, it prompts the user to change or not. If the */
-/* user escapes the menu, returns -1, selects Yes, 0, and selects no, 1 	*/
-/****************************************************************************/
-int save_changes(int mode)
-{
-	int i=0;
-
-if(!changes)
-	return(2);
-strcpy(opt[0],"Yes");
-strcpy(opt[1],"No");
-opt[2][0]=0;
-if(mode&WIN_SAV && savdepth)
-	savnum++;
-SETHELP(WHERE);
-/*
-Save Changes:
-
-You have made some changes to the configuration. If you want to save
-these changes, select Yes. If you are positive you DO NOT want to save
-these changes, select No. If you are not sure and want to review the
-configuration before deciding, hit  ESC .
-*/
-i=ulist(mode|WIN_ACT,0,0,0,&i,0,"Save Changes",opt);
-if(mode&WIN_SAV && savdepth)
-	savnum--;
-if(i!=-1)
-	changes=0;
-return(i);
-}
-
-void txt_cfg()
-{
-	static int txt_dflt,bar;
-	char str[81],code[9],done=0,*p;
-	int j,k;
-	uint i;
-	static txtsec_t savtxtsec;
-
-while(1) {
-	for(i=0;i<total_txtsecs;i++)
-		sprintf(opt[i],"%-25s",txtsec[i]->name);
-	opt[i][0]=0;
-	j=WIN_ORG|WIN_ACT|WIN_CHE;
-	if(total_txtsecs)
-		j|=WIN_DEL|WIN_GET;
-	if(total_txtsecs<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savtxtsec.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Text File Sections:
-
-This is a list of General Text File (G-File) Sections configured for
-your system. G-File sections are used to store text files that can be
-viewed freely by the users. Common text file section topics include
-ANSI Artwork, System Information, Game Help Files, and other special
-interest topics.
-
-To add a text file section, select the desired location with the arrow
-keys and hit  INS .
-
-To delete a text file section, select it and hit  DEL .
-
-To configure a text file, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&txt_dflt,&bar,"Text File Sections",opt);
-	if((signed)i==-1) {
-		j=save_changes(WIN_MID);
-		if(j==-1)
-			continue;
-		if(!j)
-			write_file_cfg();
-		return; }
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"ANSI Artwork");
-		SETHELP(WHERE);
-/*
-Text Section Name:
-
-This is the name of this text section.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Text Section Name",str,40
-            ,K_EDIT)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Text Section Internal Code:
-
-Every text file section must have its own unique internal code for
-Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Text Section Internal Code",code,8
-			,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((txtsec=(txtsec_t **)REALLOC(txtsec
-			,sizeof(txtsec_t *)*(total_txtsecs+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_txtsecs+1);
-			total_txtsecs=0;
-			bail(1);
-			continue; }
-		if(total_txtsecs)
-			for(j=total_txtsecs;j>i;j--)
-                txtsec[j]=txtsec[j-1];
-		if((txtsec[i]=(txtsec_t *)MALLOC(sizeof(txtsec_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(txtsec_t));
-			continue; }
-		memset((txtsec_t *)txtsec[i],0,sizeof(txtsec_t));
-		strcpy(txtsec[i]->name,str);
-		strcpy(txtsec[i]->code,code);
-		total_txtsecs++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(txtsec[i]);
-		total_txtsecs--;
-		for(j=i;j<total_txtsecs;j++)
-			txtsec[j]=txtsec[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savtxtsec=*txtsec[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*txtsec[i]=savtxtsec;
-		changes=1;
-        continue; }
-	i=txt_dflt;
-	j=0;
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Name",txtsec[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Access Requirements"
-			,txtsec[i]->ar);
-		sprintf(opt[k++],"%-27.27s%s","Internal Code",txtsec[i]->code);
-		opt[k][0]=0;
-		switch(ulist(WIN_ACT|WIN_MID,0,0,60,&j,0,txtsec[i]->name
-			,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Text Section Name:
-
-This is the name of this text section.
-*/
-				strcpy(str,txtsec[i]->name);	/* save */
-				if(!uinput(WIN_MID|WIN_SAV,0,10
-					,"Text File Section Name"
-					,txtsec[i]->name,40,K_EDIT))
-					strcpy(txtsec[i]->name,str);
-				break;
-			case 1:
-				sprintf(str,"%s Text Section",txtsec[i]->name);
-				getar(str,txtsec[i]->ar);
-				break;
-			case 2:
-				strcpy(str,txtsec[i]->code);
-				SETHELP(WHERE);
-/*
-Text Section Internal Code:
-
-Every text file section must have its own unique internal code for
-Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(txtsec[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-					helpbuf=0; }
-				break; } } }
-}
-
-void shell_cfg()
-{
-	static int shell_dflt,shell_bar;
-	char str[81],code[9],done=0,*p;
-	int j,k;
-	uint i;
-	static shell_t savshell;
-
-while(1) {
-	for(i=0;i<total_shells;i++)
-		sprintf(opt[i],"%-25s",shell[i]->name);
-	opt[i][0]=0;
-	j=WIN_ORG|WIN_ACT|WIN_CHE;
-	if(total_shells)
-		j|=WIN_DEL|WIN_GET;
-	if(total_shells<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savshell.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Command Shells:
-
-This is a list of Command Shells configured for your system.
-Command shells are the programmable command and menu structures which
-are available for your BBS.
-
-To add a command shell section, select the desired location with the arrow
-keys and hit  INS .
-
-To delete a command shell, select it and hit  DEL .
-
-To configure a command shell, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&shell_dflt,&shell_bar,"Command Shells",opt);
-	if((signed)i==-1) {
-		j=save_changes(WIN_MID);
-		if(j==-1)
-			continue;
-		if(!j)
-			write_main_cfg();
-		return; }
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"Menu Shell");
-		SETHELP(WHERE);
-/*
-Command Shell Name:
-
-This is the descriptive name of this command shell.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Command Shell Name",str,40
-            ,K_EDIT)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Command Shell Internal Code:
-
-Every command shell must have its own unique internal code for
-Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-
-This code will be the base filename used to load the shell from your
-EXEC directory. e.g. A shell with an internal code of MYBBS would
-indicate a Baja shell file named MYBBS.BIN in your EXEC directory.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Command Shell Internal Code",code,8
-			,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((shell=(shell_t **)REALLOC(shell
-			,sizeof(shell_t *)*(total_shells+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_shells+1);
-			total_shells=0;
-			bail(1);
-			continue; }
-		if(total_shells)
-			for(j=total_shells;j>i;j--)
-				shell[j]=shell[j-1];
-		if((shell[i]=(shell_t *)MALLOC(sizeof(shell_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(shell_t));
-			continue; }
-		memset((shell_t *)shell[i],0,sizeof(shell_t));
-		strcpy(shell[i]->name,str);
-		strcpy(shell[i]->code,code);
-		total_shells++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(shell[i]);
-		total_shells--;
-		for(j=i;j<total_shells;j++)
-			shell[j]=shell[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savshell=*shell[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*shell[i]=savshell;
-		changes=1;
-        continue; }
-	i=shell_dflt;
-	j=0;
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Name",shell[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Access Requirements"
-			,shell[i]->ar);
-		sprintf(opt[k++],"%-27.27s%s","Internal Code",shell[i]->code);
-		opt[k][0]=0;
-		SETHELP(WHERE);
-/*
-Command Shell:
-
-A command shell is a programmed command and menu structure that you or
-your users can use to navigate the BBS. For every command shell
-configured here, there must be an associated .BIN file in your EXEC
-directory for Synchronet to execute.
-
-Command shell files are created by using the Baja command shell compiler
-to turn Baja source code (.SRC) files into binary files (.BIN) for
-Synchronet to interpret. See the example .SRC files in the TEXT
-directory and the documentation for the Baja compiler for more details.
-*/
-		switch(ulist(WIN_ACT|WIN_MID,0,0,60,&j,0,shell[i]->name
-			,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Command Shell Name:
-
-This is the descriptive name of this command shell.
-*/
-				strcpy(str,shell[i]->name);    /* save */
-				if(!uinput(WIN_MID|WIN_SAV,0,10
-					,"Command Shell Name"
-					,shell[i]->name,40,K_EDIT))
-					strcpy(shell[i]->name,str);
-				break;
-			case 1:
-				sprintf(str,"%s Command Shell",shell[i]->name);
-				getar(str,shell[i]->ar);
-				break;
-			case 2:
-				strcpy(str,shell[i]->code);
-				SETHELP(WHERE);
-/*
-Command Shell Internal Code:
-
-Every command shell must have its own unique internal code for
-Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-
-This code will be the base filename used to load the shell from your
-EXEC directory. e.g. A shell with an internal code of MYBBS would
-indicate a Baja shell file named MYBBS.BIN in your EXEC directory.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(shell[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-					helpbuf=0; }
-				break; } } }
-}
-
-/****************************************************************************/
-/* Deletes all files in dir 'path' that match file spec 'spec'              */
-/****************************************************************************/
-int delfiles(char *inpath, char *spec)
-{
-    char str[256],path[128],done,c;
-    int files=0;
-    struct ffblk ff;
-
-strcpy(path,inpath);
-c=strlen(path);
-if(path[c-1]!='\\' && path[c-1]!=':')
-    strcat(path,"\\");
-sprintf(str,"%s%s",path,spec);
-done=findfirst(str,&ff,0);
-while(!done) {
-    sprintf(str,"%s%s",path,ff.ff_name);
-    if(remove(str))
-        errormsg(WHERE,ERR_REMOVE,str,0);
-    else
-        files++;
-    done=findnext(&ff); }
-return(files);
-}
-
-int whichlogic()
-{
-	int i;
-
-i=0;
-strcpy(opt[0],"Greater than or Equal");
-strcpy(opt[1],"Equal");
-strcpy(opt[2],"Not Equal");
-strcpy(opt[3],"Less than");
-opt[4][0]=0;
-if(savdepth)
-	savnum++;
-SETHELP(WHERE);
-/*
-Select Logic for Requirement:
-
-This menu allows you to choose the type of logic evaluation to use
-in determining if the requirement is met. If, for example, the user's
-level is being evaluated and you select Greater than or Equal from
-this menu and set the required level to 50, the user must have level
-50 or higher to meet this requirement. If you selected Equal from
-this menu and set the required level to 50, the user must have level
-50 exactly. If you select Not equal and level 50, then the user
-must have any level BUT 50. And if you select Less than from this
-menu and level 50, the user must have a level below 50.
-*/
-i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Select Logic",opt);
-if(savdepth)
-	savnum--;
-return(i);
-}
-
-int whichcond()
-{
-	int i;
-
-i=0;
-strcpy(opt[0],"AND (Both/All)");
-strcpy(opt[1],"OR  (Either/Any)");
-opt[2][0]=0;
-if(savdepth)
-	savnum++;
-SETHELP(WHERE);
-/*
-Select Logic for Multiple Requirements:
-
-If you wish this new parameter to be required along with the other
-parameters, select AND to specify that both or all of the
-parameter requirments must be met.
-
-If you wish this new parameter to only be required if the other
-parameter requirements aren't met, select OR to specify that either
-or any of the parameter requirements must be met.
-*/
-i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Multiple Requirement Logic",opt);
-if(savdepth)
-	savnum--;
-return(i);
-}
-
-
-void getar(char *desc, char *inar)
-{
-	static int curar;
-	char str[128],ar[128];
-	int i,j,len,done=0,n;
-
-strcpy(ar,inar);
-while(!done) {
-	len=strlen(ar);
-	if(len>=30) {	  /* Needs to be shortened */
-		str[0]=0;
-		n=strlen(ar);
-		for(i=0;i<n;i++) {					/* Shorten operators */
-			if(!strncmp(ar+i,"AND",3)) {
-				strcat(str,"&");
-				i+=2; }
-			else if(!strncmp(ar+i,"NOT",3)) {
-				strcat(str,"!");
-				i+=2; }
-			else if(!strncmp(ar+i,"EQUAL",5)) {
-				strcat(str,"=");
-				i+=4; }
-			else if(!strncmp(ar+i,"EQUALS",6)) {
-				strcat(str,"=");
-				i+=5; }
-			else if(!strncmp(ar+i,"EQUAL TO",8)) {
-				strcat(str,"=");
-				i+=7; }
-			else if(!strncmp(ar+i,"OR",2)) {
-				strcat(str,"|");
-				i+=1; }
-			else
-				strncat(str,ar+i,1); }
-		strcpy(ar,str);
-		len=strlen(ar); }
-
-	if(len>=30) {
-		str[0]=0;
-		n=strlen(ar);
-		for(i=0;i<n;i++) {					/* Remove spaces from ! and = */
-			if(!strncmp(ar+i," ! ",3)) {
-				strcat(str,"!");
-				i+=2; }
-			else if(!strncmp(ar+i,"= ",2)) {
-				strcat(str,"=");
-                i++; }
-			else if(!strncmp(ar+i," = ",3)) {
-				strcat(str,"=");
-				i+=2; }
-			else
-				strncat(str,ar+i,1); }
-		strcpy(ar,str);
-        len=strlen(ar); }
-
-	if(len>=30) {
-		str[0]=0;
-		n=strlen(ar);
-		for(i=0;i<n;i++) {					/* Remove spaces from & and | */
-			if(!strncmp(ar+i," & ",3)) {
-				strcat(str," ");
-				i+=2; }
-			else if(!strncmp(ar+i," | ",3)) {
-				strcat(str,"|");
-				i+=2; }
-			else
-				strncat(str,ar+i,1); }
-		strcpy(ar,str);
-        len=strlen(ar); }
-
-	if(len>=30) {					/* change week days to numbers */
-        str[0]=0;
-        n=strlen(ar);
-		for(i=0;i<n;i++) {
-			for(j=0;j<7;j++)
-                if(!strnicmp(ar+i,wday[j],3)) {
-                    strcat(str,itoa(j,tmp,10));
-					i+=2;
-					break; }
-			if(j==7)
-				strncat(str,ar+i,1); }
-        strcpy(ar,str);
-        len=strlen(ar); }
-
-	if(len>=30) {				  /* Shorten parameters */
-		str[0]=0;
-		n=strlen(ar);
-		for(i=0;i<n;i++) {
-			if(!strncmp(ar+i,"AGE",3)) {
-				strcat(str,"$A");
-				i+=2; }
-			else if(!strncmp(ar+i,"BPS",3)) {
-				strcat(str,"$B");
-				i+=2; }
-			else if(!strncmp(ar+i,"PCR",3)) {
-				strcat(str,"$P");
-				i+=2; }
-			else if(!strncmp(ar+i,"RIP",3)) {
-				strcat(str,"$*");
-				i+=2; }
-			else if(!strncmp(ar+i,"SEX",3)) {
-				strcat(str,"$S");
-				i+=2; }
-			else if(!strncmp(ar+i,"UDR",3)) {
-				strcat(str,"$K");
-				i+=2; }
-			else if(!strncmp(ar+i,"DAY",3)) {
-				strcat(str,"$W");
-                i+=2; }
-			else if(!strncmp(ar+i,"ANSI",4)) {
-				strcat(str,"$[");
-                i+=3; }
-			else if(!strncmp(ar+i,"UDFR",4)) {
-				strcat(str,"$D");
-				i+=3; }
-			else if(!strncmp(ar+i,"FLAG",4)) {
-				strcat(str,"$F");
-				i+=3; }
-			else if(!strncmp(ar+i,"NODE",4)) {
-				strcat(str,"$N");
-				i+=3; }
-			else if(!strncmp(ar+i,"NULL",4)) {
-				strcat(str,"$0");
-                i+=3; }
-			else if(!strncmp(ar+i,"TIME",4)) {
-				strcat(str,"$T");
-				i+=3; }
-			else if(!strncmp(ar+i,"USER",4)) {
-				strcat(str,"$U");
-				i+=3; }
-			else if(!strncmp(ar+i,"REST",4)) {
-				strcat(str,"$Z");
-                i+=3; }
-			else if(!strncmp(ar+i,"LOCAL",5)) {
-				strcat(str,"$G");
-				i+=4; }
-			else if(!strncmp(ar+i,"LEVEL",5)) {
-				strcat(str,"$L");
-                i+=4; }
-			else if(!strncmp(ar+i,"TLEFT",5)) {
-				strcat(str,"$R");
-				i+=4; }
-			else if(!strncmp(ar+i,"TUSED",5)) {
-				strcat(str,"$O");
-				i+=4; }
-			else if(!strncmp(ar+i,"EXPIRE",6)) {
-				strcat(str,"$E");
-				i+=5; }
-			else if(!strncmp(ar+i,"CREDIT",6)) {
-				strcat(str,"$C");
-                i+=5; }
-			else if(!strncmp(ar+i,"EXEMPT",6)) {
-				strcat(str,"$X");
-                i+=5; }
-			else if(!strncmp(ar+i,"RANDOM",6)) {
-				strcat(str,"$Q");
-                i+=5; }
-			else if(!strncmp(ar+i,"LASTON",6)) {
-				strcat(str,"$Y");
-                i+=5; }
-			else if(!strncmp(ar+i,"LOGONS",6)) {
-				strcat(str,"$V");
-                i+=5; }
-			else if(!strncmp(ar+i,":00",3)) {
-				i+=2; }
-			else
-				strncat(str,ar+i,1); }
-		strcpy(ar,str);
-		len=strlen(ar); }
-	if(len>=30) {				  /* Remove all spaces and &s */
-		str[0]=0;
-		n=strlen(ar);
-		for(i=0;i<n;i++)
-			if(ar[i]!=SP && ar[i]!='&')
-				strncat(str,ar+i,1);
-		strcpy(ar,str);
-		len=strlen(ar); }
-	i=0;
-	sprintf(opt[i++],"Requirement String (%s)",ar);
-	strcpy(opt[i++],"Clear Requirements");
-	strcpy(opt[i++],"Set Required Level");
-	strcpy(opt[i++],"Set Required Flag");
-	strcpy(opt[i++],"Set Required Age");
-	strcpy(opt[i++],"Set Required Sex");
-	strcpy(opt[i++],"Set Required Connect Rate");
-	strcpy(opt[i++],"Set Required Post/Call Ratio");
-	strcpy(opt[i++],"Set Required Number of Credits");
-	strcpy(opt[i++],"Set Required Upload/Download Ratio");
-	strcpy(opt[i++],"Set Required Upload/Download File Ratio");
-	strcpy(opt[i++],"Set Required Time of Day");
-	strcpy(opt[i++],"Set Required Day of Week");
-	strcpy(opt[i++],"Set Required Node Number");
-	strcpy(opt[i++],"Set Required User Number");
-	strcpy(opt[i++],"Set Required Time Remaining");
-	strcpy(opt[i++],"Set Required Days Till Expiration");
-	opt[i][0]=0;
-	SETHELP(WHERE);
-/*
-Access Requirements:
-
-This menu allows you to edit the access requirement string for the
-selected feature/section of your BBS. You can edit the string
-directly (see documentation for details) or use the Set Required...
-options from this menu to automatically fill in the string for you.
-*/
-	sprintf(str,"%s Requirements",desc);
-	switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&curar,0,str,opt)) {
-		case -1:
-			done=1;
-			break;
-		case 0:
-			SETHELP(WHERE);
-/*
-Key word	Symbol		Description
-������������������������������������������������������������������������
-AND 		  & 		More than one requirement (optional)
-NOT 		  ! 		Logical negation (i.e. NOT EQUAL)
-EQUAL		  = 		Equality required
-OR			  | 		Either of two or more parameters is required
-AGE 		  $A		User's age (years since birthdate, 0-255)
-BPS 		  $B		User's current connect rate (bps)
-FLAG		  $F		User's flag (A-Z)
-LEVEL		  $L		User's level (0-99)
-NODE		  $N		Current node (1-250)
-PCR 		  $P		User's post/call ratio (0-100)
-SEX 		  $S		User's sex/gender (M or F)
-TIME		  $T		Time of day (HH:MM, 00:00-23:59)
-TLEFT		  $R		User's time left online (minutes, 0-255)
-TUSED		  $O		User's time online this call (minutes, 0-255)
-USER		  $U		User's number (1-xxxx)
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Requirement String",ar,LEN_ARSTR
-                ,K_EDIT|K_UPPER);
-			break;
-		case 1:
-			i=1;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			if(savdepth)
-				savnum++;
-			SETHELP(WHERE);
-/*
-Clear Requirements:
-
-If you wish to clear the current requirement string, select Yes.
-Otherwise, select No.
-*/
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Are You Sure",opt);
-			if(savdepth)
-                savnum--;
-			if(!i) {
-				ar[0]=0;
-				changes=1; }
-			break;
-		case 2:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Level:
-
-You are being prompted to enter the security level to be used in this
-requirement evaluation. The valid range is 0 (zero) through 99.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Level",str,2,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-					strcat(ar," OR "); }
-			strcat(ar,"LEVEL ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-			break;
-		case 3:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-
-			for(i=0;i<4;i++)
-				sprintf(opt[i],"Flag Set #%d",i+1);
-			opt[i][0]=0;
-			i=0;
-			if(savdepth)
-				savnum++;
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Select Flag Set",opt);
-			if(savdepth)
-				savnum--;
-			if(i==-1)
-                break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Flag:
-
-You are being prompted to enter the security flag to be used in this
-requirement evaluation. The valid range is A through Z.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Flag (A-Z)",str,1
-				,K_UPPER|K_ALPHA);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"FLAG ");
-			if(i)
-				strcat(ar,itoa(i+1,tmp,10));
-			strcat(ar,str);
-			break;
-		case 4:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Age:
-
-You are being prompted to enter the user's age to be used in this
-requirement evaluation. The valid range is 0 through 255.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Age",str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"AGE ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 5:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Sex:
-
-You are being prompted to enter the user's gender to be used in this
-requirement evaluation. The valid values are M or F (for male or
-female).
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Sex (M or F)",str,1
-				,K_UPPER|K_ALPHA);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-					strcat(ar," OR "); }
-			strcat(ar,"SEX ");
-			strcat(ar,str);
-			break;
-		case 6:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Connect Rate (BPS):
-
-You are being prompted to enter the connect rate to be used in this
-requirement evaluation. The valid range is 300 through 57600.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Connect Rate (BPS)",str,5,K_NUMBER);
-			if(!str[0])
-				break;
-			j=atoi(str);
-			if(j>=300 && j<30000) {
-				j/=100;
-				sprintf(str,"%d",j); }
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"BPS ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 7:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Post/Call Ratio:
-
-You are being prompted to enter the post/call ratio to be used in this
-requirement evaluation (percentage). The valid range is 0 through 100.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Post/Call Ratio (Percentage)"
-				,str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"PCR ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 8:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Number of Credits:
-
-You are being prompted to enter the number of credits (in kilobytes) to
-be used in this requirement evaluation. The valid range is 0 through
-65535.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Required Credits",str,5,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"CREDIT ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 9:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Upload/Download Ratio:
-
-You are being prompted to enter the upload/download ratio to be used in
-this requirement evaluation (percentage). The valid range is 0 through
-100. This ratio is based on the number of bytes uploaded by the user
-divided by the number of bytes downloaded.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Upload/Download Ratio (Percentage)"
-				,str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"UDR ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 10:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Upload/Download File Ratio:
-
-You are being prompted to enter the upload/download ratio to be used in
-this requirement evaluation (percentage). The valid range is 0 through
-100. This ratio is based on the number of files uploaded by the user
-divided by the number of files downloaded.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0
-				,"Upload/Download File Ratio (Percentage)"
-				,str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"UDFR ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 11:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=0;
-			strcpy(opt[0],"Before");
-			strcpy(opt[1],"After");
-			opt[2][0]=0;
-			if(savdepth)
-				savnum++;
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Time Relationship",opt);
-			if(savdepth)
-				savnum--;
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Time of Day:
-
-You are being prompted to enter the time of day to be used in this
-requirement evaluation (24 hour HH:MM format). The valid range is 0
-through 23:59.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Time of Day (HH:MM)",str,5,K_UPPER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"TIME ");
-			if(!i)
-				strcat(ar,"NOT ");
-			strcat(ar,str);
-			break;
-		case 12:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			SETHELP(WHERE);
-/*
-Required Day of Week:
-
-You are being prompted to select a day of the week as an access
-requirement value.
-*/
-			for(n=0;n<7;n++)
-				strcpy(opt[n],wday[n]);
-			opt[n][0]=0;
-			n=0;
-			if(savdepth)
-				savnum++;
-			n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0,"Select Day of Week",opt);
-			if(savdepth)
-				savnum--;
-			if(n==-1)
-                break;
-			strcpy(str,wday[n]);
-			strupr(str);
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"DAY ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 13:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Node:
-
-You are being prompted to enter the number of a node to be used in this
-requirement evaluation. The valid range is 1 through 250.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Node Number",str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"NODE ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-		case 14:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required User Number:
-
-You are being prompted to enter the user's number to be used in this
-requirement evaluation.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"User Number",str,5,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"USER ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-
-		case 15:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Time Remaining:
-
-You are being prompted to enter the time remaining to be used in this
-requirement evaluation (in minutes). The valid range is 0 through 255.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Time Remaining (minutes)"
-				,str,3,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"TLEFT ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-			break;
-
-		case 16:
-			if(strlen(ar)>=30) {
-				umsg("Maximum string length reached");
-                break; }
-			i=whichlogic();
-			if(i==-1)
-				break;
-			str[0]=0;
-			SETHELP(WHERE);
-/*
-Required Days Till User Account Expiration:
-
-You are being prompted to enter the required number of days till the
-user's account will expire.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Days Till Expiration"
-				,str,5,K_NUMBER);
-			if(!str[0])
-				break;
-			if(ar[0]) {
-				j=whichcond();
-				if(j==-1)
-					break;
-				if(!j)
-					strcat(ar," AND ");
-				else
-                    strcat(ar," OR "); }
-			strcat(ar,"EXPIRE ");
-			switch(i) {
-				case 1:
-					strcat(ar,"= ");
-					break;
-				case 2:
-					strcat(ar,"NOT = ");
-					break;
-				case 3:
-					strcat(ar,"NOT ");
-					break; }
-			strcat(ar,str);
-            break;
-			} }
-sprintf(inar,"%.*s",LEN_ARSTR,ar);
-}
-
-char code_ok(char *str)
-{
-
-if(!strlen(str))
-    return(0);
-if(strcspn(str," \\/.|<>*?+[]:=\";,")!=strlen(str))
-    return(0);
-return(1);
-}
-
-/****************************************************************************/
-/*                          Functions from MISC.C                           */
-/****************************************************************************/
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.   All files are opened in BINARY mode.            */
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-    int file,share,count=0;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-    else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-    && errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	cputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an unsigned long                       */
-/****************************************************************************/
-unsigned long ahtoul(char *str)
-{
-    unsigned long l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-    val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Returns in 'string' a character representation of the number in l with   */
-/* commas. Maximum value of l is 4 gigabytes.                               */
-/****************************************************************************/
-char *ultoac(ulong l, char *string)
-{
-    char str[81];
-    char i,j;
-
-ultoa(l,str,10);
-if(!(strlen(str)%3)) i=(strlen(str)/3)-1;
-    else i=strlen(str)/3;
-j=strlen(str)+i;
-string[j--]=0;
-i=strlen(str)-1;
-while(i!=-1) {
-    if(!((strlen(str)-i)%3)) {
-        string[j--]=str[i--];
-        string[j--]=','; }
-    else string[j--]=str[i--]; }
-return(string);
-}
-
-/****************************************************************************/
-/* If the directory 'path' doesn't exist, create it.                      	*/
-/****************************************************************************/
-void md(char *inpath)
-{
-	char path[256],str[128];
-	struct ffblk ff;
-	int curdisk,disk;
-
-if(!inpath[0] || no_dirchk)
-	return;
-if(!strcmp(inpath+1,":\\")) {
-	curdisk=getdisk();
-	disk=toupper(inpath[0])-'A';
-	setdisk(disk);
-	if(getdisk()!=disk) {
-		sprintf(str,"Invalid drive %c:",toupper(inpath[0]));
-		umsg(str); }
-	setdisk(curdisk);
-	return; }
-strcpy(path,inpath);
-if(path[strlen(path)-1]=='\\')
-	path[strlen(path)-1]=0;
-if(!strcmp(path,"."))               /* Don't try to make '.' */
-	return;
-if(findfirst(path,&ff,FA_DIREC))
-	if(mkdir(path)) {
-		sprintf(str,"Failed to create %s",path);
-		umsg(str); }
-}
-
-
-void bail(int code)
-{
-	char		str[256];
-	int 		i,x;
-	smbstatus_t status;
-
-if(code) {
-	cputs("\r\nHit a key...");
-	getch(); }
-else if(forcesave) {
-	upop("Loading Configs...");
-	read_main_cfg(txt);
-	read_msgs_cfg(txt);
-	read_file_cfg(txt);
-	read_chat_cfg(txt);
-	read_xtrn_cfg(txt);
-	upop(0);
-	write_main_cfg();
-	write_msgs_cfg();
-	write_file_cfg();
-	write_chat_cfg();
-	write_xtrn_cfg(); }
-
-uifcbail();
-
-exit(code);
-}
-
-/****************************************************************************/
-/* Error handling routine. Prints to local and remote screens the error     */
-/* information, function, action, object and access and then attempts to    */
-/* write the error information into the file ERROR.LOG in the text dir.     */
-/****************************************************************************/
-void errormsg(int line, char *source,  char action, char *object, ulong access)
-{
-	char scrn_buf[8000];
-    char actstr[256];
-
-gettext(1,1,80,scrn_len,scrn_buf);
-clrscr();
-switch(action) {
-    case ERR_OPEN:
-        strcpy(actstr,"opening");
-        break;
-    case ERR_CLOSE:
-        strcpy(actstr,"closeing");
-        break;
-    case ERR_FDOPEN:
-        strcpy(actstr,"fdopen");
-        break;
-    case ERR_READ:
-        strcpy(actstr,"reading");
-        break;
-    case ERR_WRITE:
-        strcpy(actstr,"writing");
-        break;
-    case ERR_REMOVE:
-        strcpy(actstr,"removing");
-        break;
-    case ERR_ALLOC:
-        strcpy(actstr,"allocating memory");
-        break;
-    case ERR_CHK:
-        strcpy(actstr,"checking");
-        break;
-    case ERR_LEN:
-        strcpy(actstr,"checking length");
-        break;
-    case ERR_EXEC:
-        strcpy(actstr,"executing");
-        break;
-    default:
-        strcpy(actstr,"UNKNOWN"); }
-cprintf("ERROR -     line: %d\r\n",line);
-cprintf("            file: %s\r\n",source);
-cprintf("          action: %s\r\n",actstr);
-cprintf("          object: %s\r\n",object);
-cprintf("          access: %ld (%lx)\r\n",access,access);
-cputs("\r\n<Hit any key>");
-getch();
-puttext(1,1,80,scrn_len,scrn_buf);
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-/* End of SCFG.C */
diff --git a/src/sbbs2/scfg/scfg.h b/src/sbbs2/scfg/scfg.h
deleted file mode 100644
index 2ea311e2f1c3164745fd247174a94f7688d1b346..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfg.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SCFG.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "uifc.h"
-#include <dos.h>
-#include <dir.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(__DPMI32__) || defined(__OS2__)
-    #define far
-	#define huge
-#endif
-
-#include "sbbs.h"
-#include "scfglib.h"
-
-/**********/
-/* Macros */
-/**********/
-
-/*************/
-/* Constants */
-/*************/
-
-#define SUB_HDRMOD	(1L<<31)		/* Modified sub-board header info */
-
-/************/
-/* Typedefs */
-/************/
-
-/********************/
-/* Global Variables */
-/********************/
-extern long freedosmem;
-extern char item;
-extern char **opt;
-extern char tmp[256];
-extern char *nulstr;
-extern char **mdm_type;
-extern char **mdm_file;
-extern int	mdm_types;
-extern char *invalid_code,*num_flags;
-extern int	backup_level;
-
-extern read_cfg_text_t txt;
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-
-int  save_changes(int mode);
-void node_menu();
-void node_cfg();
-void results(int i);
-void sys_cfg();
-void net_cfg();
-void msgs_cfg();
-void sub_cfg(uint grpnum);
-void xfer_cfg();
-void libs_cfg();
-void dir_cfg(uint libnum);
-void xprogs_cfg();
-void fevents_cfg();
-void tevents_cfg();
-void xtrn_cfg();
-void swap_cfg();
-void xtrnsec_cfg();
-void page_cfg();
-void xedit_cfg();
-void txt_cfg();
-void shell_cfg();
-void read_node_cfg(read_cfg_text_t txt);
-void write_node_cfg();
-void write_main_cfg();
-void write_msgs_cfg();
-void write_file_cfg();
-void write_xtrn_cfg();
-void write_chat_cfg();
-void init_mdms();
-void mdm_cfg(int mdmnum);
-int export_mdm(char *fname);
-char code_ok(char *str);
-int  bits(long l);
-char oneflag(long l);
-void getar(char *desc, char *ar);
-char *ultoac(ulong l,char *str);
-FILE *fnopen(int *file, char *str, int access);
diff --git a/src/sbbs2/scfg/scfgchat.c b/src/sbbs2/scfg/scfgchat.c
deleted file mode 100644
index 842d1e24c1342f299d71f9099b68d4aae061e24c..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgchat.c
+++ /dev/null
@@ -1,819 +0,0 @@
-#line 2 "SCFGCHAT.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-void page_cfg()
-{
-	static int dflt,bar;
-	char str[81],done=0;
-	int j,k;
-	uint i;
-	static page_t savpage;
-
-while(1) {
-	for(i=0;i<total_pages && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-40.40s %.-20s",page[i]->cmd,page[i]->ar);
-	opt[i][0]=0;
-	savnum=0;
-	j=WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT;
-	if(total_pages)
-		j|=WIN_DEL|WIN_GET;
-	if(total_pages<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savpage.cmd[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-External Sysop Chat Pagers:
-
-This is a list of the configured external sysop chat pagers.
-
-To add a pager, select the desired location and hit  INS .
-
-To delete a pager, select it and hit  DEL .
-
-To configure a pager, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&dflt,&bar,"External Sysop Chat Pagers",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		sprintf(str,"%%!tone +chatpage.ton");
-		SETHELP(WHERE);
-/*
-External Chat Pager Command Line:
-
-This is the command line to execute for this external chat pager.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Command Line",str,50
-			,K_EDIT)<1)
-            continue;
-		if((page=(page_t **)REALLOC(page,sizeof(page_t *)*(total_pages+1)))
-            ==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_pages+1);
-			total_pages=0;
-			bail(1);
-            continue; }
-		if(total_pages)
-			for(j=total_pages;j>i;j--)
-				page[j]=page[j-1];
-		if((page[i]=(page_t *)MALLOC(sizeof(page_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(page_t));
-			continue; }
-		memset((page_t *)page[i],0,sizeof(page_t));
-		strcpy(page[i]->cmd,str);
-		total_pages++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(page[i]);
-		total_pages--;
-		for(j=i;j<total_pages;j++)
-			page[j]=page[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savpage=*page[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*page[i]=savpage;
-		changes=1;
-        continue; }
-	j=0;
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%.40s","Command Line",page[i]->cmd);
-		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",page[i]->ar);
-		sprintf(opt[k++],"%-27.27s%s","Intercept I/O Interrupts"
-			,page[i]->misc&IO_INTS ? "Yes":"No");
-		opt[k][0]=0;
-		sprintf(str,"Sysop Chat Pager #%d",i+1);
-		savnum=1;
-		switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&j,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-External Chat Pager Command Line:
-
-This is the command line to execute for this external chat pager.
-*/
-				strcpy(str,page[i]->cmd);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Command Line"
-					,page[i]->cmd,50,K_EDIT))
-					strcpy(page[i]->cmd,str);
-				break;
-			case 1:
-				savnum=2;
-				getar(str,page[i]->ar);
-				break;
-			case 2:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Intercept I/O Interrupts:
-
-If you wish the DOS screen output and keyboard input to be intercepted
-when running this chat pager, set this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept I/O Interrupts"
-					,opt);
-				if(!k && !(page[i]->misc&IO_INTS)) {
-					page[i]->misc|=IO_INTS;
-					changes=1; }
-				else if(k==1 && page[i]->misc&IO_INTS) {
-					page[i]->misc&=~IO_INTS;
-					changes=1; }
-                break;
-
-				} } }
-}
-
-void chan_cfg()
-{
-	static int chan_dflt,chan_bar,opt_dflt;
-	char str[81],code[9],done=0,*p;
-	int j,k;
-	uint i;
-	static chan_t savchan;
-
-while(1) {
-	for(i=0;i<total_chans && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",chan[i]->name);
-	opt[i][0]=0;
-	j=WIN_ACT|WIN_SAV|WIN_BOT|WIN_RHT;
-	savnum=0;
-	if(total_chans)
-		j|=WIN_DEL|WIN_GET;
-	if(total_chans<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savchan.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Multinode Chat Channels:
-
-This is a list of the configured multinode chat channels.
-
-To add a channel, select the desired location with the arrow keys and
-hit  INS .
-
-To delete a channel, select it with the arrow keys and hit  DEL .
-
-To configure a channel, select it with the arrow keys and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&chan_dflt,&chan_bar,"Multinode Chat Channels",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"Open");
-		SETHELP(WHERE);
-/*
-Channel Name:
-
-This is the name or description of the chat channel.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Chat Channel Name",str,25
-			,K_EDIT)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Chat Channel Internal Code:
-
-Every chat channel must have its own unique code for Synchronet to refer
-to it internally. This code is usually an abreviation of the chat
-channel name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Internal Code"
-			,code,8,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((chan=(chan_t **)REALLOC(chan,sizeof(chan_t *)*(total_chans+1)))
-            ==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_chans+1);
-			total_chans=0;
-			bail(1);
-            continue; }
-		if(total_chans)
-			for(j=total_chans;j>i;j--)
-				chan[j]=chan[j-1];
-		if((chan[i]=(chan_t *)MALLOC(sizeof(chan_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(chan_t));
-			continue; }
-		memset((chan_t *)chan[i],0,sizeof(chan_t));
-		strcpy(chan[i]->name,str);
-		strcpy(chan[i]->code,code);
-		total_chans++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(chan[i]);
-		total_chans--;
-		for(j=i;j<total_chans;j++)
-			chan[j]=chan[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savchan=*chan[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*chan[i]=savchan;
-		changes=1;
-        continue; }
-    j=0;
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Name",chan[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Internal Code",chan[i]->code);
-		sprintf(opt[k++],"%-27.27s%lu","Cost in Credits",chan[i]->cost);
-		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements"
-			,chan[i]->ar);
-		sprintf(opt[k++],"%-27.27s%s","Password Protection"
-			,chan[i]->misc&CHAN_PW ? "Yes" : "No");
-		sprintf(opt[k++],"%-27.27s%s","Guru Joins When Empty"
-			,chan[i]->misc&CHAN_GURU ? "Yes" : "No");
-		sprintf(opt[k++],"%-27.27s%s","Channel Guru"
-			,chan[i]->guru<total_gurus ? guru[chan[i]->guru]->name : "");
-        sprintf(opt[k++],"%-27.27s%s","Channel Action Set"
-            ,actset[chan[i]->actset]->name);
-		opt[k][0]=0;
-		SETHELP(WHERE);
-/*
-Chat Channel Configuration:
-
-This menu is for configuring the selected chat channel.
-*/
-		savnum=1;
-		sprintf(str,"%s Chat Channel",chan[i]->name);
-		switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Chat Channel Name:
-
-This is the name or description of the chat channel.
-*/
-				strcpy(str,chan[i]->name);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Chat Channel Name"
-					,chan[i]->name,25,K_EDIT))
-					strcpy(chan[i]->name,str);
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Chat Channel Internal Code:
-
-Every chat channel must have its own unique code for Synchronet to refer
-to it internally. This code is usually an abreviation of the chat
-channel name.
-*/
-				strcpy(str,chan[i]->code);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Internal Code"
-					,str,8,K_UPPER|K_EDIT))
-					break;
-				if(code_ok(str))
-					strcpy(chan[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-                    helpbuf=0; }
-                break;
-			case 2:
-				ultoa(chan[i]->cost,str,10);
-                SETHELP(WHERE);
-/*
-Chat Channel Cost to Join:
-
-If you want users to be charged credits to join this chat channel, set
-this value to the number of credits to charge. If you want this channel
-to be free, set this value to 0.
-*/
-				uinput(WIN_MID|WIN_SAV,0,0,"Cost to Join (in Credits)"
-                    ,str,10,K_EDIT|K_NUMBER);
-				chan[i]->cost=atol(str);
-                break;
-			case 3:
-				savnum=2;
-				sprintf(str,"%s Chat Channel",chan[i]->name);
-				getar(str,chan[i]->ar);
-				break;
-			case 4:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Allow Channel to be Password Protected:
-
-If you want to allow the first user to join this channel to password
-protect it, set this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Allow Channel to be Password Protected"
-					,opt);
-				if(!k && !(chan[i]->misc&CHAN_PW)) {
-					chan[i]->misc|=CHAN_PW;
-					changes=1; }
-				else if(k==1 && chan[i]->misc&CHAN_PW) {
-					chan[i]->misc&=~CHAN_PW;
-					changes=1; }
-				break;
-			case 5:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Guru Joins This Channel When Empty:
-
-If you want the system guru to join this chat channel when there is
-only one user, set this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Guru Joins This Channel When Empty"
-					,opt);
-				if(!k && !(chan[i]->misc&CHAN_GURU)) {
-					chan[i]->misc|=CHAN_GURU;
-					changes=1; }
-				else if(k==1 && chan[i]->misc&CHAN_GURU) {
-					chan[i]->misc&=~CHAN_GURU;
-					changes=1; }
-				break;
-			case 6:
-SETHELP(WHERE);
-/*
-Channel Guru:
-
-This is a list of available chat Gurus.  Select the one that you wish
-to have available in this channel.
-*/
-				k=0;
-				for(j=0;j<total_gurus && j<MAX_OPTS;j++)
-					sprintf(opt[j],"%-25s",guru[j]->name);
-				opt[j][0]=0;
-				savnum=2;
-				k=ulist(WIN_SAV|WIN_RHT,0,0,25,&j,0
-					,"Available Chat Gurus",opt);
-				if(k==-1)
-					break;
-				chan[i]->guru=k;
-				break;
-			case 7:
-SETHELP(WHERE);
-/*
-Channel Action Set:
-
-This is a list of available chat action sets.  Select the one that you wish
-to have available in this channel.
-*/
-				k=0;
-				for(j=0;j<total_actsets && j<MAX_OPTS;j++)
-					sprintf(opt[j],"%-25s",actset[j]->name);
-				opt[j][0]=0;
-				savnum=2;
-				k=ulist(WIN_SAV|WIN_RHT,0,0,25,&j,0
-					,"Available Chat Action Sets",opt);
-				if(k==-1)
-					break;
-				changes=1;
-				chan[i]->actset=k;
-				break; } } }
-}
-
-void chatact_cfg(uint setnum)
-{
-	static int chatact_dflt,chatact_bar;
-	char str[128],cmd[128],out[128];
-	int j,k;
-	uint i,n,chatnum[MAX_OPTS+1];
-	static chatact_t savchatact;
-
-while(1) {
-	for(i=0,j=0;i<total_chatacts && j<MAX_OPTS;i++)
-		if(chatact[i]->actset==setnum) {
-			sprintf(opt[j],"%-*.*s %s",LEN_CHATACTCMD,LEN_CHATACTCMD
-				,chatact[i]->cmd,chatact[i]->out);
-			chatnum[j++]=i; }
-	chatnum[j]=total_chatacts;
-	opt[j][0]=0;
-	savnum=2;
-	i=WIN_ACT|WIN_SAV;
-	if(j)
-		i|=WIN_DEL|WIN_GET;
-	if(j<MAX_OPTS)
-		i|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savchatact.cmd[0])
-		i|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Multinode Chat Actions:
-
-This is a list of the configured multinode chat actions.  The users can
-use these actions in multinode chat by turning on action commands with
-the /A command in multinode chat.  Then if a line is typed which
-begins with a valid action command and has a user name, chat handle,
-or node number following, the output string will be displayed replacing
-the %s symbols with the sending user's name and the receiving user's
-name (in that order).
-
-To add an action, select the desired location with the arrow keys and
-hit  INS .
-
-To delete an action, select it with the arrow keys and hit  DEL .
-
-To configure an action, select it with the arrow keys and hit  ENTER .
-*/
-	sprintf(str,"%s Chat Actions",actset[setnum]->name);
-	i=ulist(i,0,0,70,&chatact_dflt,&chatact_bar,str,opt);
-	savnum=3;
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Chat Action Command:
-
-This is the command word (normally a verb) to trigger the action output.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Action Command",cmd,LEN_CHATACTCMD
-			,K_UPPER)<1)
-            continue;
-		SETHELP(WHERE);
-/*
-Chat Action Output String:
-
-This is the output string displayed with this action output.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"",out,LEN_CHATACTOUT
-			,K_MSG)<1)
-            continue;
-		if((chatact=(chatact_t **)REALLOC(chatact
-            ,sizeof(chatact_t *)*(total_chatacts+1)))==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_chatacts+1);
-			total_chatacts=0;
-			bail(1);
-            continue; }
-		if(j)
-			for(n=total_chatacts;n>chatnum[i];n--)
-				chatact[n]=chatact[n-1];
-		if((chatact[chatnum[i]]=(chatact_t *)MALLOC(sizeof(chatact_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(chatact_t));
-			continue; }
-		memset((chatact_t *)chatact[chatnum[i]],0,sizeof(chatact_t));
-		strcpy(chatact[chatnum[i]]->cmd,cmd);
-		strcpy(chatact[chatnum[i]]->out,out);
-		chatact[chatnum[i]]->actset=setnum;
-		total_chatacts++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(chatact[chatnum[i]]);
-		total_chatacts--;
-		for(j=chatnum[i];j<total_chatacts && j<MAX_OPTS;j++)
-			chatact[j]=chatact[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savchatact=*chatact[chatnum[i]];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*chatact[chatnum[i]]=savchatact;
-		chatact[chatnum[i]]->actset=setnum;
-		changes=1;
-        continue; }
-	SETHELP(WHERE);
-/*
-Chat Action Command:
-
-This is the command that triggers this chat action.
-*/
-	strcpy(str,chatact[chatnum[i]]->cmd);
-	if(!uinput(WIN_MID|WIN_SAV,0,10,"Chat Action Command"
-		,chatact[chatnum[i]]->cmd,LEN_CHATACTCMD,K_EDIT|K_UPPER)) {
-		strcpy(chatact[chatnum[i]]->cmd,str);
-		continue; }
-	SETHELP(WHERE);
-/*
-Chat Action Output String:
-
-This is the output string that results from this chat action.
-*/
-	strcpy(str,chatact[chatnum[i]]->out);
-	if(!uinput(WIN_MID|WIN_SAV,0,10,""
-		,chatact[chatnum[i]]->out,LEN_CHATACTOUT,K_EDIT|K_MSG))
-		strcpy(chatact[chatnum[i]]->out,str); }
-}
-
-void guru_cfg()
-{
-	static int guru_dflt,guru_bar,opt_dflt;
-	char str[81],code[9],done=0,*p;
-	int j,k;
-	uint i;
-	static guru_t savguru;
-
-while(1) {
-	for(i=0;i<total_gurus && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",guru[i]->name);
-	opt[i][0]=0;
-	savnum=0;
-	j=WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT;
-	if(total_gurus)
-		j|=WIN_DEL|WIN_GET;
-	if(total_gurus<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savguru.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Gurus:
-
-This is a list of the configured Gurus.
-
-To add a Guru, select the desired location with the arrow keys and
-hit  INS .
-
-To delete a Guru, select it with the arrow keys and hit  DEL .
-
-To configure a Guru, select it with the arrow keys and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&guru_dflt,&guru_bar,"Artificial Gurus",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Guru Name:
-
-This is the name of the selected Guru.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Guru Name",str,25
-			,0)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Guru Internal Code:
-
-Every Guru must have its own unique code for Synchronet to refer to
-it internally. This code is usually an abreviation of the Guru name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Internal Code"
-			,code,8,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((guru=(guru_t **)REALLOC(guru,sizeof(guru_t *)*(total_gurus+1)))
-            ==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_gurus+1);
-			total_gurus=0;
-			bail(1);
-            continue; }
-		if(total_gurus)
-			for(j=total_gurus;j>i;j--)
-				guru[j]=guru[j-1];
-		if((guru[i]=(guru_t *)MALLOC(sizeof(guru_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(guru_t));
-			continue; }
-		memset((guru_t *)guru[i],0,sizeof(guru_t));
-		strcpy(guru[i]->name,str);
-		strcpy(guru[i]->code,code);
-		total_gurus++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(guru[i]);
-		total_gurus--;
-		for(j=i;j<total_gurus;j++)
-			guru[j]=guru[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savguru=*guru[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*guru[i]=savguru;
-		changes=1;
-        continue; }
-    j=0;
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Guru Name",guru[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Guru Internal Code",guru[i]->code);
-		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",guru[i]->ar);
-		opt[k][0]=0;
-		savnum=1;
-		SETHELP(WHERE);
-/*
-Guru Configuration:
-
-This menu is for configuring the selected Guru.
-*/
-		switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,guru[i]->name
-			,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Guru Name:
-
-This is the name of the selected Guru.
-*/
-				strcpy(str,guru[i]->name);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Guru Name"
-					,guru[i]->name,25,K_EDIT))
-					strcpy(guru[i]->name,str);
-				break;
-			case 1:
-SETHELP(WHERE);
-/*
-Guru Internal Code:
-
-Every Guru must have its own unique code for Synchronet to refer to
-it internally. This code is usually an abreviation of the Guru name.
-*/
-				strcpy(str,guru[i]->code);
-				if(!uinput(WIN_MID|WIN_SAV,0,0,"Guru Internal Code"
-					,str,8,K_EDIT|K_UPPER))
-					break;
-				if(code_ok(str))
-					strcpy(guru[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-                    helpbuf=0; }
-				break;
-			case 2:
-				savnum=2;
-				getar(guru[i]->name,guru[i]->ar);
-				break; } } }
-}
-
-void actsets_cfg()
-{
-    static int actset_dflt,actset_bar,opt_dflt;
-    char str[81];
-    int j,k,done;
-    uint i;
-    static actset_t savactset;
-
-while(1) {
-	for(i=0;i<total_actsets && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",actset[i]->name);
-	opt[i][0]=0;
-	j=WIN_ACT|WIN_RHT|WIN_BOT|WIN_SAV;
-	savnum=0;
-    if(total_actsets)
-        j|=WIN_DEL|WIN_GET;
-	if(total_actsets<MAX_OPTS)
-        j|=WIN_INS|WIN_INSACT|WIN_XTR;
-    if(savactset.name[0])
-        j|=WIN_PUT;
-    SETHELP(WHERE);
-/*
-Chat Action Sets:
-
-This is a list of the configured action sets.
-
-To add an action set, select the desired location with the arrow keys and
-hit  INS .
-
-To delete an action set, select it with the arrow keys and hit  DEL .
-
-To configure an action set, select it with the arrow keys and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&actset_dflt,&actset_bar,"Chat Action Sets",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-        SETHELP(WHERE);
-/*
-Chat Action Set Name:
-
-This is the name of the selected chat action set.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Chat Action Set Name",str,25
-			,0)<1)
-            continue;
-        if((actset=(actset_t **)REALLOC(actset,sizeof(actset_t *)*(total_actsets+1)))
-            ==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_actsets+1);
-			total_actsets=0;
-			bail(1);
-            continue; }
-        if(total_actsets)
-            for(j=total_actsets;j>i;j--)
-                actset[j]=actset[j-1];
-        if((actset[i]=(actset_t *)MALLOC(sizeof(actset_t)))==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(actset_t));
-            continue; }
-		memset((actset_t *)actset[i],0,sizeof(actset_t));
-        strcpy(actset[i]->name,str);
-        total_actsets++;
-        changes=1;
-        continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-        FREE(actset[i]);
-        total_actsets--;
-        for(j=i;j<total_actsets;j++)
-            actset[j]=actset[j+1];
-        changes=1;
-        continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-        savactset=*actset[i];
-        continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-        *actset[i]=savactset;
-        changes=1;
-        continue; }
-    j=0;
-    done=0;
-    while(!done) {
-        k=0;
-        sprintf(opt[k++],"%-27.27s%s","Action Set Name",actset[i]->name);
-        sprintf(opt[k++],"%-27.27s","Configure Chat Actions...");
-		opt[k][0]=0;
-        SETHELP(WHERE);
-/*
-Chat Action Set Configuration:
-
-This menu is for configuring the selected chat action set.
-*/
-		sprintf(str,"%s Chat Action Set",actset[i]->name);
-		savnum=1;
-		switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&opt_dflt,0,str
-            ,opt)) {
-            case -1:
-                done=1;
-                break;
-            case 0:
-                SETHELP(WHERE);
-/*
-Chat Action Set Name:
-
-This is the name of the selected action set.
-*/
-                strcpy(str,actset[i]->name);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Action Set Name"
-                    ,actset[i]->name,25,K_EDIT))
-                    strcpy(actset[i]->name,str);
-                break;
-            case 1:
-                chatact_cfg(i);
-                break; } } }
-}
-
diff --git a/src/sbbs2/scfg/scfgmdm.c b/src/sbbs2/scfg/scfgmdm.c
deleted file mode 100644
index 08a91e08bc244c76476ebe2df2e68cab80499a01..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgmdm.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/* SCFGMDM.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-int exec_mdm(char *fname);
-
-void mdm_cfg(int mdmnum)
-{
-
-FREE(mdm_result);
-mdm_result=NULL;
-
-/*
-strcpy(mdm_answ,"ATA");
-strcpy(mdm_hang,"ATH");
-strcpy(mdm_dial,"ATDT");
-strcpy(mdm_offh,"ATM0H1");
-strcpy(mdm_term,"ATE1V1");
-strcpy(mdm_init,"AT&FS0=0S2=128E0V0X4&C1&D2");
-*/
-mdm_answ[0]=0;
-mdm_hang[0]=0;
-mdm_dial[0]=0;
-mdm_offh[0]=0;
-mdm_term[0]=0;
-mdm_init[0]=0;
-mdm_spec[0]=0;
-mdm_results=0;
-mdm_misc=(MDM_RTS|MDM_CTS);
-
-exec_mdm(mdm_file[mdmnum]);
-
-}
-
-void cvttab(char *str)
-{
-	int i;
-
-for(i=0;str[i];i++)
-	if(str[i]==TAB)
-		str[i]=SP;
-}
-
-int export_mdm(char *fname)
-{
-	char str[256];
-	int file,i;
-	time_t now;
-	FILE *stream;
-
-sprintf(str,"%s%s.MDM",ctrl_dir,fname);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1)
-	return(0);
-if((stream=fdopen(file,"wb"))==NULL) {
-    close(file);
-	return(0); }
-
-now=time(NULL);
-fprintf(stream,"# Exported from %s Node %u on %.24s\r\n\r\n"
-	,sys_name,node_num,ctime(&now));
-fprintf(stream,"COM_RATE\t%ld\r\n",com_rate);
-fprintf(stream,"INIT_STR\t%s\r\n",mdm_init);
-fprintf(stream,"DIAL_STR\t%s\r\n",mdm_dial);
-fprintf(stream,"HANGUP_STR\t%s\r\n",mdm_hang);
-fprintf(stream,"ANSWER_STR\t%s\r\n",mdm_answ);
-fprintf(stream,"OFFHOOK_STR\t%s\r\n",mdm_offh);
-fprintf(stream,"SPEC_INIT\t%s\r\n",mdm_spec);
-fprintf(stream,"TERM_INIT\t%s\r\n",mdm_term);
-fprintf(stream,"LOCKED_RATE\t%s\r\n",(mdm_misc&MDM_STAYHIGH) ? "YES":"NO");
-fprintf(stream,"CALLER_ID\t%s\r\n",(mdm_misc&MDM_CALLERID) ? "YES":"NO");
-fprintf(stream,"DROP_DTR\t%s\r\n",(mdm_misc&MDM_NODTR) ? "NO":"YES");
-fprintf(stream,"FLOW_CONTROL\t%s\r\n"
-	,(mdm_misc&(MDM_RTS|MDM_CTS)==(MDM_RTS|MDM_CTS)) ? "BOTH":
-	(mdm_misc&MDM_CTS) ? "TRANSMIT" : (mdm_misc&MDM_RTS) ? "RECEIVE" : "NONE");
-for(i=0;i<mdm_results;i++)
-	fprintf(stream,"RESULT\t\t%u\t%u\t%u\t%s\r\n",mdm_result[i].code
-		,mdm_result[i].cps,mdm_result[i].rate,mdm_result[i].str);
-
-fclose(stream);
-
-return(1);
-}
-
-int exec_mdm(char *fname)
-{
-	char str[256],msg[128],*p;
-	int file,i,j;
-	FILE *stream;
-
-sprintf(str,"%s%s.MDM",ctrl_dir,fname);
-
-if((file=open(str,O_RDONLY|O_BINARY|O_DENYALL))==-1)
-	return(0);
-if((stream=fdopen(file,"rb"))==NULL) {
-    close(file);
-    return(0); }
-
-while(!feof(stream)) {
-	if(!fgets(str,255,stream))
-		break;
-	cvttab(str);
-    truncsp(str);
-	p=str;
-	while(*p && *p<=SP)   /* look for beginning of command */
-		p++;
-	if(!*p)
-		continue;
-	if(*p=='#')             /* remarks start with # */
-        continue;
-
-	if(!strnicmp(p,"COM_RATE",8)) {
-		p+=8;
-		while(*p==SP) p++;
-		com_rate=atol(p);
-		continue; }
-
-	if(!strnicmp(p,"INIT_STR",8)) {
-		p+=8;
-		while(*p==SP) p++;
-		sprintf(mdm_init,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"DIAL_STR",8)) {
-		p+=8;
-		while(*p==SP) p++;
-		sprintf(mdm_dial,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"HANGUP_STR",10)) {
-		p+=10;
-		while(*p==SP) p++;
-		sprintf(mdm_hang,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"ANSWER_STR",10)) {
-		p+=10;
-		while(*p==SP) p++;
-		sprintf(mdm_answ,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"OFFHOOK_STR",11)) {
-		p+=11;
-		while(*p==SP) p++;
-		sprintf(mdm_offh,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"SPEC_INIT",9)) {
-		p+=9;
-		while(*p==SP) p++;
-		sprintf(mdm_spec,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"TERM_INIT",9)) {
-		p+=9;
-		while(*p==SP) p++;
-		sprintf(mdm_term,"%.63s",p);
-        continue; }
-
-	if(!strnicmp(p,"LOCKED_RATE",11)) {
-		p+=11;
-		while(*p==SP) p++;
-		if(!stricmp(p,"OFF") || !stricmp(p,"NO"))
-			mdm_misc&=~MDM_STAYHIGH;
-		else
-			mdm_misc|=MDM_STAYHIGH;
-        continue; }
-
-	if(!strnicmp(p,"CALLER_ID",9)) {
-		p+=9;
-		while(*p==SP) p++;
-		if(!stricmp(p,"YES") || !stricmp(p,"ON"))
-			mdm_misc|=MDM_CALLERID;
-		else
-			mdm_misc&=~MDM_CALLERID;
-        continue; }
-
-	if(!strnicmp(p,"VERBAL_RESULTS",14)) {
-		p+=14;
-		while(*p==SP) p++;
-		if(!stricmp(p,"YES") || !stricmp(p,"ON"))
-			mdm_misc|=MDM_VERBAL;
-		else
-			mdm_misc&=~MDM_VERBAL;
-        continue; }
-
-	if(!strnicmp(p,"DROP_DTR",8)) {
-		p+=8;
-		while(*p==SP) p++;
-		if(!stricmp(p,"OFF") || !stricmp(p,"NO"))
-			mdm_misc|=MDM_NODTR;
-		else
-			mdm_misc&=~MDM_NODTR;
-        continue; }
-
-	if(!strnicmp(p,"FLOW_CONTROL",12)) {
-		p+=12;
-		while(*p==SP) p++;
-		mdm_misc&=~(MDM_RTS|MDM_CTS);
-		strupr(p);
-		if(strstr(p,"RTS") || strstr(p,"RECEIVE") || strstr(p,"RECV")
-			|| strstr(p,"BOTH"))
-			mdm_misc|=MDM_RTS;
-		if(strstr(p,"CTS") || strstr(p,"TRANSMIT") || strstr(p,"SEND")
-			|| strstr(p,"BOTH"))
-			mdm_misc|=MDM_CTS;
-        continue; }
-
-	if(!strnicmp(p,"RESULT ",7)) {
-		p+=7;
-		while(*p==SP) p++;
-		i=atoi(p);
-		for(j=0;j<mdm_results;j++)
-			if(mdm_result[j].code==i)
-				break;
-		if(j>=mdm_results) {
-			if((mdm_result=(mdm_result_t *)REALLOC(
-				mdm_result,sizeof(mdm_result_t)
-				*(mdm_results+1)))==NULL) {
-				errormsg(WHERE,ERR_ALLOC,p,mdm_results+1);
-				mdm_results=0;
-				bail(1);
-				continue; }
-			mdm_results++; }
-		mdm_result[j].code=i;
-		while(*p!=SP) p++;
-		while(*p==SP) p++;
-		mdm_result[j].cps=atoi(p);
-		while(*p!=SP) p++;
-        while(*p==SP) p++;
-		mdm_result[j].rate=atoi(p);
-		while(*p!=SP) p++;
-        while(*p==SP) p++;
-		sprintf(mdm_result[j].str,"%.*s",LEN_MODEM,p);
-		continue; }
-
-	if(!strnicmp(p,"INCLUDE ",8)) {
-		p+=8;
-		while(*p==SP) p++;
-		exec_mdm(p);
-		continue; }
-
-	sprintf(msg,"ERROR: '%.15s' in %.8s.MDM",p,fname);
-	savnum--;
-	umsg(msg);
-	savnum++; }
-
-fclose(stream);
-return(1);
-}
-
-
-void init_mdms()
-{
-	char str[128],fname[128];
-	int file;
-	FILE *stream;
-
-mdm_types=0;
-mdm_type=NULL;
-mdm_file=NULL;
-sprintf(str,"%sMDMS.IXT",ctrl_dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-if((stream=fdopen(file,"rb"))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_FDOPEN,str,O_RDONLY);
-	return; }
-
-while(!feof(stream)) {
-	if(!fgets(str,120,stream))
-        break;
-	truncsp(str);
-	if(!fgets(fname,120,stream))
-		break;
-	truncsp(fname);
-	if((mdm_type=REALLOC(mdm_type,sizeof(char *)*(mdm_types+1)))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,"Modem Type",sizeof(char *)*(mdm_types+1));
-		break; }
-	if((mdm_file=REALLOC(mdm_file,sizeof(char *)*(mdm_types+1)))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,"Modem File",sizeof(char *)*(mdm_types+1));
-        break; }
-	if((mdm_type[mdm_types]=MALLOC(strlen(str)+1))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,"Modem Typename",sizeof(char *)*(mdm_types+1));
-        break; }
-	if((mdm_file[mdm_types]=MALLOC(9))==NULL) {
-		errormsg(WHERE,ERR_ALLOC,"Modem Filename",sizeof(char *)*(mdm_types+1));
-        break; }
-	strcpy(mdm_type[mdm_types],str);
-	sprintf(mdm_file[mdm_types],"%.8s",fname);
-	mdm_types++; }
-fclose(stream);
-}
diff --git a/src/sbbs2/scfg/scfgmsg.c b/src/sbbs2/scfg/scfgmsg.c
deleted file mode 100644
index f090fc70cd136d724f220c82880dfb76fb446b0c..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgmsg.c
+++ /dev/null
@@ -1,1337 +0,0 @@
-#line 2 "SCFGMSG.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-/****************************************************************************/
-/* Converts when_t.zone into ASCII format									*/
-/****************************************************************************/
-char *zonestr(short zone)
-{
-	static char str[32];
-
-switch((ushort)zone) {
-	case 0: 	return("UT");
-	case AST:	return("AST");
-	case EST:	return("EST");
-	case CST:	return("CST");
-	case MST:	return("MST");
-	case PST:	return("PST");
-	case YST:	return("YST");
-	case HST:	return("HST");
-	case BST:	return("BST");
-	case ADT:	return("ADT");
-	case EDT:	return("EDT");
-	case CDT:	return("CDT");
-	case MDT:	return("MDT");
-	case PDT:	return("PDT");
-	case YDT:	return("YDT");
-	case HDT:	return("HDT");
-	case BDT:	return("BDT");
-	case MID:	return("MID");
-	case VAN:	return("VAN");
-	case EDM:	return("EDM");
-	case WIN:	return("WIN");
-	case BOG:	return("BOG");
-	case CAR:	return("CAR");
-	case RIO:	return("RIO");
-	case FER:	return("FER");
-	case AZO:	return("AZO");
-	case LON:	return("LON");
-	case BER:	return("BER");
-	case ATH:	return("ATH");
-	case MOS:	return("MOS");
-	case DUB:	return("DUB");
-	case KAB:	return("KAB");
-	case KAR:	return("KAR");
-	case BOM:	return("BOM");
-	case KAT:	return("KAT");
-	case DHA:	return("DHA");
-	case BAN:	return("BAN");
-	case HON:	return("HON");
-	case TOK:	return("TOK");
-	case SYD:	return("SYD");
-	case NOU:	return("NOU");
-	case WEL:	return("WEL");
-	}
-
-sprintf(str,"%02hd:%02hu",zone/60,zone<0 ? (-zone)%60 : zone%60);
-return(str);
-}
-
-char *utos(char *str)
-{
-	static char out[128];
-	int i;
-
-for(i=0;str[i];i++)
-	if(str[i]=='_')
-		out[i]=SP;
-	else
-		out[i]=str[i];
-out[i]=0;
-return(out);
-}
-
-char *stou(char *str)
-{
-	static char out[128];
-	int i;
-
-for(i=0;str[i];i++)
-	if(str[i]==SP)
-		out[i]='_';
-	else
-		out[i]=str[i];
-out[i]=0;
-return(out);
-}
-
-
-
-void clearptrs(int subnum)
-{
-	char str[256];
-	ushort idx,ch;
-	int last,file,i;
-	long l=0L;
-	struct ffblk ff;
-
-upop("Clearing Pointers...");
-sprintf(str,"%sUSER\\PTRS\\*.IXB",data_dir);
-last=findfirst(str,&ff,0);
-while(!last) {
-	if(ff.ff_fsize>=((long)sub[subnum]->ptridx+1L)*10L) {
-		sprintf(str,"%sUSER\\PTRS\\%s",data_dir,ff.ff_name);
-		if((file=nopen(str,O_WRONLY))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY);
-			bail(1); }
-		while(filelength(file)<(long)(sub[subnum]->ptridx)*10) {
-			lseek(file,0L,SEEK_END);
-			idx=tell(file)/10;
-			for(i=0;i<total_subs;i++)
-				if(sub[i]->ptridx==idx)
-					break;
-			write(file,&l,4);
-			write(file,&l,4);
-			ch=0xff;			/* default to scan ON for unknown sub */
-			if(i<total_subs) {
-				if(!(sub[i]->misc&SUB_NSDEF))
-					ch&=~5;
-				if(!(sub[i]->misc&SUB_SSDEF))
-					ch&=~2; }
-			write(file,&ch,2); }
-		lseek(file,((long)sub[subnum]->ptridx)*10L,SEEK_SET);
-		write(file,&l,4);	/* date set to null */
-		write(file,&l,4);	/* date set to null */
-		ch=0xff;
-		if(!(sub[subnum]->misc&SUB_NSDEF))
-			ch&=~5;
-		if(!(sub[subnum]->misc&SUB_SSDEF))
-			ch&=~2;
-		write(file,&ch,2);
-		close(file); }
-	last=findnext(&ff); }
-upop(0);
-}
-
-void msgs_cfg()
-{
-	static int dflt,msgs_dflt,bar;
-	char str[256],str2[256],done=0,*p;
-	int j,k,q,s;
-	int i,file,ptridx,n;
-	long ported;
-	sub_t tmpsub;
-	static grp_t savgrp;
-	FILE *stream;
-
-while(1) {
-	for(i=0;i<total_grps && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",grp[i]->lname);
-	opt[i][0]=0;
-	j=WIN_ORG|WIN_ACT|WIN_CHE;
-	if(total_grps)
-		j|=WIN_DEL|WIN_DELACT|WIN_GET;
-	if(total_grps<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savgrp.sname[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Message Groups:
-
-This is a listing of message groups for your BBS. Message groups are
-used to logically separate your message sub-boards into groups. Every
-sub-board belongs to a message group. You must have at least one message
-group and one sub-board configured.
-
-One popular use for message groups is to separate local sub-boards and
-networked sub-boards. One might have a Local message group that contains
-non-networked sub-boards of various topics and also have a FidoNet
-message group that contains sub-boards that are echoed across FidoNet.
-Some sysops separate sub-boards into more specific areas such as Main,
-Technical, or Adult. If you have many sub-boards that have a common
-subject denominator, you may want to have a separate message group for
-those sub-boards for a more organized message structure.
-*/
-	i=ulist(j,0,0,45,&msgs_dflt,&bar,"Message Groups",opt);
-	savnum=0;
-	if(i==-1) {
-		j=save_changes(WIN_MID);
-		if(j==-1)
-		   continue;
-		if(!j)
-			write_msgs_cfg();
-		return; }
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Group Long Name:
-
-This is a description of the message group which is displayed when a
-user of the system uses the /* command from the main menu.
-*/*/
-		strcpy(str,"Main");
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Group Long Name",str,LEN_GLNAME
-			,K_EDIT)<1)
-			continue;
-		SETHELP(WHERE);
-/*
-Group Short Name:
-
-This is a short description of the message group which is used for the
-main menu and reading message prompts.
-*/
-		sprintf(str2,"%.*s",LEN_GSNAME,str);
-		if(uinput(WIN_MID,0,0,"Group Short Name",str2,LEN_GSNAME,K_EDIT)<1)
-			continue;
-		if((grp=(grp_t **)REALLOC(grp,sizeof(grp_t *)*(total_grps+1)))==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_grps+1);
-			total_grps=0;
-			bail(1);
-            continue; }
-
-		if(total_grps) {	/* was total_subs (?) */
-            for(j=total_grps;j>i;j--)   /* insert above */
-                grp[j]=grp[j-1];
-            for(j=0;j<total_subs;j++)   /* move sub group numbers */
-                if(sub[j]->grp>=i)
-                    sub[j]->grp++; }
-
-		if((grp[i]=(grp_t *)MALLOC(sizeof(grp_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(grp_t));
-			continue; }
-		memset((grp_t *)grp[i],0,sizeof(grp_t));
-		strcpy(grp[i]->lname,str);
-		strcpy(grp[i]->sname,str2);
-		total_grps++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Delete All Data in Group:
-
-If you wish to delete the messages in all the sub-boards in this group,
-select Yes.
-*/
-		j=1;
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0,"Delete All Data in Group",opt);
-		if(j==-1)
-			continue;
-		if(j==0)
-			for(j=0;j<total_subs;j++)
-				if(sub[j]->grp==i) {
-					sprintf(str,"%s.s*",sub[j]->code);
-					if(!sub[j]->data_dir[0])
-						sprintf(tmp,"%sSUBS\\",data_dir);
-					else
-						strcpy(tmp,sub[j]->data_dir);
-					delfiles(tmp,str);
-					clearptrs(j); }
-		FREE(grp[i]);
-		for(j=0;j<total_subs;) {
-			if(sub[j]->grp==i) {	/* delete subs of this group */
-				FREE(sub[j]);
-				total_subs--;
-				k=j;
-				while(k<total_subs) {	/* move all subs down */
-					sub[k]=sub[k+1];
-					for(q=0;q<total_qhubs;q++)
-						for(s=0;s<qhub[q]->subs;s++)
-							if(qhub[q]->sub[s]==k)
-								qhub[q]->sub[s]--;
-					k++; } }
-			else j++; }
-		for(j=0;j<total_subs;j++)	/* move sub group numbers down */
-			if(sub[j]->grp>i)
-				sub[j]->grp--;
-		total_grps--;
-		while(i<total_grps) {
-			grp[i]=grp[i+1];
-			i++; }
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savgrp=*grp[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*grp[i]=savgrp;
-		changes=1;
-		continue; }
-	done=0;
-	while(!done) {
-		j=0;
-		sprintf(opt[j++],"%-27.27s%s","Long Name",grp[i]->lname);
-		sprintf(opt[j++],"%-27.27s%s","Short Name",grp[i]->sname);
-		sprintf(opt[j++],"%-27.27s%.40s","Access Requirements"
-			,grp[i]->ar);
-		strcpy(opt[j++],"Clone Options");
-		strcpy(opt[j++],"Export Areas...");
-		strcpy(opt[j++],"Import Areas...");
-		strcpy(opt[j++],"Message Sub-boards...");
-		opt[j][0]=0;
-		sprintf(str,"%s Group",grp[i]->sname);
-		savnum=0;
-		SETHELP(WHERE);
-/*
-Message Group Configuration:
-
-This menu allows you to configure the security requirements for access
-to this message group. You can also add, delete, and configure the
-sub-boards of this group by selecting the Messages Sub-boards... option.
-*/
-		switch(ulist(WIN_ACT,6,4,60,&dflt,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Group Long Name:
-
-This is a description of the message group which is displayed when a
-user of the system uses the /* command from the main menu.
-*/*/
-				strcpy(str,grp[i]->lname);	/* save incase setting to null */
-				if(!uinput(WIN_MID|WIN_SAV,0,17,"Name to use for Listings"
-					,grp[i]->lname,LEN_GLNAME,K_EDIT))
-					strcpy(grp[i]->lname,str);
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Group Short Name:
-
-This is a short description of the message group which is used for
-main menu and reading messages prompts.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Name to use for Prompts"
-					,grp[i]->sname,LEN_GSNAME,K_EDIT);
-				break;
-			case 2:
-				sprintf(str,"%s Group",grp[i]->sname);
-				getar(str,grp[i]->ar);
-				break;
-			case 3: 	/* Clone Options */
-				j=0;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Clone Sub-board Options:
-
-If you want to clone the options of the first sub-board of this group
-into all sub-boards of this group, select Yes.
-
-The options cloned are posting requirements, reading requirements,
-operator requirments, moderated user requirments, toggle options,
-network options (including EchoMail origin line, EchoMail address,
-and QWK Network tagline), maximum number of messages, maximum number
-of CRCs, maximum age of messages, storage method, and data directory.
-*/
-				j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-					,"Clone Options of First Sub-board into All of Group",opt);
-				if(j==0) {
-					k=-1;
-					for(j=0;j<total_subs;j++)
-						if(sub[j]->grp==i) {
-							if(k==-1)
-								k=j;
-							else {
-								changes=1;
-								sub[j]->misc=(sub[k]->misc|SUB_HDRMOD);
-								strcpy(sub[j]->post_ar,sub[k]->post_ar);
-								strcpy(sub[j]->read_ar,sub[k]->read_ar);
-								strcpy(sub[j]->op_ar,sub[k]->op_ar);
-								strcpy(sub[j]->mod_ar,sub[k]->mod_ar);
-								strcpy(sub[j]->origline,sub[k]->origline);
-								strcpy(sub[j]->tagline,sub[k]->tagline);
-								strcpy(sub[j]->data_dir,sub[k]->data_dir);
-								strcpy(sub[j]->echomail_sem
-									,sub[k]->echomail_sem);
-								sub[j]->maxmsgs=sub[k]->maxmsgs;
-								sub[j]->maxcrcs=sub[k]->maxcrcs;
-								sub[j]->maxage=sub[k]->maxage;
-
-								sub[j]->faddr=sub[k]->faddr; } } }
-				break;
-			case 4:
-				k=0;
-				ported=0;
-				q=changes;
-				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
-				strcpy(opt[k++],"AREAS.BBS   (MSG)");
-				strcpy(opt[k++],"AREAS.BBS   (SMB)");
-				strcpy(opt[k++],"AREAS.BBS   (SBBSECHO)");
-				strcpy(opt[k++],"FIDONET.NA  (Fido)");
-				opt[k][0]=0;
-				SETHELP(WHERE);
-/*
-Export Area File Format:
-
-This menu allows you to choose the format of the area file you wish to
-export the current message group into.
-*/
-				k=0;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Export Area File Format",opt);
-				if(k==-1)
-					break;
-				if(k==0)
-					sprintf(str,"%sSUBS.TXT",ctrl_dir);
-				else if(k==1 || k==2)
-					sprintf(str,"AREAS.BBS");
-				else if(k==3)
-					sprintf(str,"%sAREAS.BBS",data_dir);
-				else if(k==4)
-					sprintf(str,"FIDONET.NA");
-				strupr(str);
-				if(k && k<4)
-					if(uinput(WIN_MID|WIN_SAV,0,0,"Uplinks"
-						,str2,40,K_UPPER)<=0) {
-						changes=q;
-						break; }
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Filename"
-					,str,40,K_UPPER|K_EDIT)<=0) {
-					changes=q;
-					break; }
-				if(fexist(str)) {
-					strcpy(opt[0],"Overwrite");
-					strcpy(opt[1],"Append");
-					opt[2][0]=0;
-					j=0;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"File Exists",opt);
-					if(j==-1)
-						break;
-					if(j==0) j=O_WRONLY|O_TRUNC;
-					else	 j=O_WRONLY|O_APPEND; }
-				else
-					j=O_WRONLY|O_CREAT;
-				if((stream=fnopen(&file,str,j))==NULL) {
-					umsg("Open Failure");
-					break; }
-				upop("Exporting Areas...");
-				for(j=0;j<total_subs;j++) {
-					if(sub[j]->grp!=i)
-						continue;
-					ported++;
-					if(k==1) {		/* AREAS.BBS *.MSG */
-						if(!sub[j]->echopath[0])
-							sprintf(str,"%s%s\\",echomail_dir,sub[j]->code);
-						else
-							strcpy(str,sub[j]->echopath);
-						fprintf(stream,"%-30s %-20s %s\r\n"
-							,str,stou(sub[j]->sname),str2);
-						continue; }
-					if(k==2) {		/* AREAS.BBS SMB */
-						if(!sub[j]->data_dir[0])
-							sprintf(str,"%sSUBS\\%s",data_dir,sub[j]->code);
-						else
-							sprintf(str,"%s%s",sub[j]->data_dir,sub[j]->code);
-						fprintf(stream,"%-30s %-20s %s\r\n"
-							,str,stou(sub[j]->sname),str2);
-                        continue; }
-					if(k==3) {		/* AREAS.BBS SBBSECHO */
-						fprintf(stream,"%-30s %-20s %s\r\n"
-							,sub[j]->code,stou(sub[j]->sname),str2);
-						continue; }
-					if(k==4) {		/* FIDONET.NA */
-						fprintf(stream,"%-20s %s\r\n"
-							,stou(sub[j]->sname),sub[j]->lname);
-						continue; }
-					fprintf(stream,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-							"%s\r\n%s\r\n%s\r\n"
-						,sub[j]->lname
-						,sub[j]->sname
-						,sub[j]->qwkname
-						,sub[j]->code
-						,sub[j]->data_dir
-						,sub[j]->ar
-						,sub[j]->read_ar
-						,sub[j]->post_ar
-						,sub[j]->op_ar
-						);
-					fprintf(stream,"%lX\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-						,sub[j]->misc
-						,sub[j]->tagline
-						,sub[j]->origline
-						,sub[j]->echomail_sem
-						,sub[j]->echopath
-						,faddrtoa(sub[j]->faddr)
-						);
-					fprintf(stream,"%lu\r\n%lu\r\n%u\r\n%u\r\n%s\r\n"
-						,sub[j]->maxmsgs
-						,sub[j]->maxcrcs
-						,sub[j]->maxage
-						,sub[j]->ptridx
-						,sub[j]->mod_ar
-						);
-					fprintf(stream,"***END-OF-SUB***\r\n\r\n"); }
-				fclose(stream);
-				upop(0);
-				sprintf(str,"%lu Message Areas Exported Successfully",ported);
-				umsg(str);
-				changes=q;
-				break;
-			case 5:
-				ported=0;
-				k=0;
-				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
-				strcpy(opt[k++],"AREAS.BBS   (MSG)");
-				strcpy(opt[k++],"AREAS.BBS   (SMB)");
-				strcpy(opt[k++],"AREAS.BBS   (SBBSECHO)");
-				strcpy(opt[k++],"FIDONET.NA  (Fido)");
-				opt[k][0]=0;
-				SETHELP(WHERE);
-/*
-Import Area File Format:
-
-This menu allows you to choose the format of the area file you wish to
-import into the current message group.
-*/
-				k=0;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Import Area File Format",opt);
-				if(k==-1)
-					break;
-				if(k==0)
-					sprintf(str,"%sSUBS.TXT",ctrl_dir);
-				else if(k==1 || k==2)
-					sprintf(str,"AREAS.BBS");
-				else if(k==3)
-					sprintf(str,"%sAREAS.BBS",data_dir);
-				else if(k==4)
-					sprintf(str,"FIDONET.NA");
-				strupr(str);
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Filename"
-					,str,40,K_UPPER|K_EDIT)<=0)
-                    break;
-				if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-					umsg("Open Failure");
-                    break; }
-				upop("Importing Areas...");
-				while(!feof(stream)) {
-					if(!fgets(str,128,stream)) break;
-					truncsp(str);
-					if(!str[0])
-						continue;
-					if(k) {
-						p=str;
-						while(*p && *p<=SP) p++;
-						if(!*p || *p==';')
-							continue;
-						memset(&tmpsub,0,sizeof(sub_t));
-						tmpsub.misc|=
-							(SUB_FIDO|SUB_NAME|SUB_TOUSER|SUB_QUOTE|SUB_HYPER);
-						if(k==1) {		/* AREAS.BBS *.MSG */
-							p=strrchr(str,'\\');
-                            if(p) *p=0;
-                            else p=str;
-							sprintf(tmpsub.echopath,"%.*s",LEN_DIR,str);
-							p++;
-							sprintf(tmpsub.code,"%.8s",p);
-							while(*p && *p<=SP) p++;
-							sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,p);
-							p=strchr(tmpsub.sname,SP);
-							if(p) *p=0;
-							strcpy(tmpsub.sname,utos(tmpsub.sname));
-							sprintf(tmpsub.lname,"%.*s",LEN_SLNAME
-								,tmpsub.sname);
-							sprintf(tmpsub.qwkname,"%.*s",10
-                                ,tmpsub.sname);
-							}
-						if(k==2) {		/* AREAS.BBS SMB */
-							p=strrchr(str,'\\');
-                            if(p) *p=0;
-                            else p=str;
-							sprintf(tmpsub.data_dir,"%.*s",LEN_DIR,str);
-							p++;
-							sprintf(tmpsub.code,"%.8s",p);
-							while(*p && *p<=SP) p++;
-							sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,p);
-							p=strchr(tmpsub.sname,SP);
-							if(p) *p=0;
-							strcpy(tmpsub.sname,utos(tmpsub.sname));
-							sprintf(tmpsub.lname,"%.*s",LEN_SLNAME
-								,tmpsub.sname);
-							sprintf(tmpsub.qwkname,"%.*s",10
-                                ,tmpsub.sname);
-                            }
-						else if(k==3) { /* AREAS.BBS SBBSECHO */
-							p=str;
-							while(*p && *p>SP) p++;
-							*p=0;
-							sprintf(tmpsub.code,"%.8s",str);
-							p++;
-							while(*p && *p<=SP) p++;
-							sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,p);
-							p=strchr(tmpsub.sname,SP);
-							if(p) *p=0;
-							strcpy(tmpsub.sname,utos(tmpsub.sname));
-							sprintf(tmpsub.lname,"%.*s",LEN_SLNAME
-								,tmpsub.sname);
-							sprintf(tmpsub.qwkname,"%.*s",10
-                                ,tmpsub.sname);
-							}
-						else if(k==4) { /* FIDONET.NA */
-                            p=str;
-							while(*p && *p>SP) p++;
-							*p=0;
-							sprintf(tmpsub.code,"%.8s",str);
-							sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,utos(str));
-							sprintf(tmpsub.qwkname,"%.10s",tmpsub.sname);
-							p++;
-							while(*p && *p<=SP) p++;
-							sprintf(tmpsub.lname,"%.*s",LEN_SLNAME,p);
-							}
-						ported++; }
-					else {
-						memset(&tmpsub,0,sizeof(sub_t));
-						tmpsub.grp=i;
-						sprintf(tmpsub.lname,"%.*s",LEN_SLNAME,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.qwkname,"%.*s",10,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.code,"%.*s",8,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.data_dir,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.read_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.post_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.op_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.misc=ahtoul(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.tagline,"%.*s",80,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.origline,"%.*s",50,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.echomail_sem,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.echopath,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.faddr=atofaddr(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.maxmsgs=atol(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.maxcrcs=atol(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.maxage=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpsub.ptridx=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpsub.mod_ar,"%.*s",LEN_ARSTR,str);
-
-						ported++;
-						while(!feof(stream)
-							&& strcmp(str,"***END-OF-SUB***")) {
-							if(!fgets(str,128,stream)) break;
-							truncsp(str); } }
-
-					truncsp(tmpsub.code);
-					truncsp(tmpsub.sname);
-					truncsp(tmpsub.lname);
-					truncsp(tmpsub.qwkname);
-					for(j=0;j<total_subs;j++) {
-						if(sub[j]->grp!=i)
-							continue;
-						if(!stricmp(sub[j]->code,tmpsub.code))
-							break; }
-					if(j==total_subs) {
-
-						if((sub=(sub_t **)REALLOC(sub
-							,sizeof(sub_t *)*(total_subs+1)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,total_subs+1);
-							total_subs=0;
-							bail(1);
-							break; }
-
-						for(ptridx=0;ptridx>-1;ptridx++) {
-							for(n=0;n<total_subs;n++)
-								if(sub[n]->ptridx==ptridx)
-									break;
-							if(n==total_subs)
-								break; }
-
-						if((sub[j]=(sub_t *)MALLOC(sizeof(sub_t)))
-							==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(sub_t));
-							break; }
-						memset(sub[j],0,sizeof(sub_t)); }
-					if(!k)
-						memcpy(sub[j],&tmpsub,sizeof(sub_t));
-					else {
-                        sub[j]->grp=i;
-						if(total_faddrs)
-							sub[j]->faddr=faddr[0];
-						strcpy(sub[j]->code,tmpsub.code);
-						strcpy(sub[j]->sname,tmpsub.sname);
-						strcpy(sub[j]->lname,tmpsub.lname);
-						strcpy(sub[j]->qwkname,tmpsub.qwkname);
-						strcpy(sub[j]->echopath,tmpsub.echopath);
-						strcpy(sub[j]->data_dir,tmpsub.data_dir);
-						if(j==total_subs)
-							sub[j]->maxmsgs=1000;
-						}
-					if(j==total_subs) {
-						sub[j]->ptridx=ptridx;
-						sub[j]->misc=tmpsub.misc;
-						total_subs++; }
-					changes=1; }
-				fclose(stream);
-				upop(0);
-				sprintf(str,"%lu Message Areas Imported Successfully",ported);
-                umsg(str);
-				break;
-
-			case 6:
-                sub_cfg(i);
-				break; } } }
-
-}
-
-void msg_opts()
-{
-	char str[128],*p;
-	static int msg_dflt;
-	int i,j;
-
-	while(1) {
-		i=0;
-		sprintf(opt[i++],"%-33.33s%s"
-			,"BBS ID for QWK Packets",sys_id);
-		sprintf(opt[i++],"%-33.33s%s"
-			,"Local Time Zone",zonestr(sys_timezone));
-		sprintf(opt[i++],"%-33.33s%u seconds"
-			,"Maximum Retry Time",smb_retry_time);
-		if(max_qwkmsgs)
-			sprintf(str,"%lu",max_qwkmsgs);
-		else
-			sprintf(str,"Unlimited");
-		sprintf(opt[i++],"%-33.33s%s"
-			,"Maximum QWK Messages",str);
-		sprintf(opt[i++],"%-33.33s%s","Pre-pack QWK Requirements",preqwk_ar);
-		if(mail_maxage)
-			sprintf(str,"Enabled (%u days old)",mail_maxage);
-        else
-            strcpy(str,"Disabled");
-		sprintf(opt[i++],"%-33.33s%s","Purge E-mail by Age",str);
-		if(sys_misc&SM_DELEMAIL)
-			strcpy(str,"Immediately");
-		else
-			strcpy(str,"Daily");
-		sprintf(opt[i++],"%-33.33s%s","Purge Deleted E-mail",str);
-		if(mail_maxcrcs)
-			sprintf(str,"Enabled (%lu mail CRCs)",mail_maxcrcs);
-		else
-			strcpy(str,"Disabled");
-		sprintf(opt[i++],"%-33.33s%s","Duplicate E-mail Checking",str);
-		sprintf(opt[i++],"%-33.33s%s","Allow Anonymous E-mail"
-			,sys_misc&SM_ANON_EM ? "Yes" : "No");
-		sprintf(opt[i++],"%-33.33s%s","Allow Quoting in E-mail"
-			,sys_misc&SM_QUOTE_EM ? "Yes" : "No");
-		sprintf(opt[i++],"%-33.33s%s","Allow Uploads in E-mail"
-			,sys_misc&SM_FILE_EM ? "Yes" : "No");
-		sprintf(opt[i++],"%-33.33s%s","Allow Forwarding to NetMail"
-			,sys_misc&SM_FWDTONET ? "Yes" : "No");
-		sprintf(opt[i++],"%-33.33s%s","Kill Read E-mail"
-			,sys_misc&SM_DELREADM ? "Yes" : "No");
-		sprintf(opt[i++],"%-33.33s%s","Users Can View Deleted Messages"
-			,sys_misc&SM_USRVDELM ? "Yes" : sys_misc&SM_SYSVDELM
-				? "Sysops Only":"No");
-		strcpy(opt[i++],"Extra Attribute Codes...");
-		opt[i][0]=0;
-		savnum=0;
-		SETHELP(WHERE);
-/*
-Message Options:
-
-This is a menu of system-wide message related options. Messages include
-E-mail and public posts (on sub-boards).
-*/
-
-		switch(ulist(WIN_ORG|WIN_ACT|WIN_MID|WIN_CHE,0,0,72,&msg_dflt,0
-			,"Message Options",opt)) {
-			case -1:
-				i=save_changes(WIN_MID);
-				if(i==-1)
-				   continue;
-				if(!i) {
-					write_msgs_cfg();
-					write_main_cfg(); }
-				return;
-			case 0:
-				strcpy(str,sys_id);
-				SETHELP(WHERE);
-/*
-BBS ID for QWK Packets:
-
-This is a short system ID for your BBS that is used for QWK packets.
-It should be an abbreviation of your BBS name or other related string.
-This ID will be used for your outgoing and incoming QWK packets. If
-you plan on networking via QWK packets with another Synchronet BBS,
-this ID should not begin with a number. The maximum length of the ID
-is eight characters and cannot contain spaces or other invalid DOS
-filename characters. In a QWK packet network, each system must have
-a unique QWK system ID.
-*/
-
-				uinput(WIN_MID|WIN_SAV,0,0,"BBS ID for QWK Packets"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(sys_id,str);
-				else
-					umsg("Invalid ID");
-				break;
-			case 1:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-United States Time Zone:
-
-If your local time zone is the United States, select Yes.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"United States Time Zone",opt);
-				if(i==-1)
-					break;
-				if(i==0) {
-					strcpy(opt[i++],"Atlantic");
-					strcpy(opt[i++],"Eastern");
-					strcpy(opt[i++],"Central");
-					strcpy(opt[i++],"Mountain");
-					strcpy(opt[i++],"Pacific");
-					strcpy(opt[i++],"Yukon");
-					strcpy(opt[i++],"Hawaii/Alaska");
-					strcpy(opt[i++],"Bering");
-					opt[i][0]=0;
-					i=0;
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Time Zone",opt);
-					if(i==-1)
-						break;
-					changes=1;
-					switch(i) {
-						case 0:
-							sys_timezone=AST;
-							break;
-						case 1:
-							sys_timezone=EST;
-							break;
-						case 2:
-							sys_timezone=CST;
-                            break;
-						case 3:
-							sys_timezone=MST;
-                            break;
-						case 4:
-							sys_timezone=PST;
-                            break;
-						case 5:
-							sys_timezone=YST;
-                            break;
-						case 6:
-							sys_timezone=HST;
-                            break;
-						case 7:
-							sys_timezone=BST;
-							break; }
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					i=1;
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Daylight Savings",opt);
-					if(i==-1)
-                        break;
-					if(!i)
-						sys_timezone|=DAYLIGHT;
-					break; }
-				i=0;
-				strcpy(opt[i++],"Midway");
-				strcpy(opt[i++],"Vancouver");
-				strcpy(opt[i++],"Edmonton");
-				strcpy(opt[i++],"Winnipeg");
-				strcpy(opt[i++],"Bogota");
-				strcpy(opt[i++],"Caracas");
-				strcpy(opt[i++],"Rio de Janeiro");
-				strcpy(opt[i++],"Fernando de Noronha");
-				strcpy(opt[i++],"Azores");
-				strcpy(opt[i++],"London");
-				strcpy(opt[i++],"Berlin");
-				strcpy(opt[i++],"Athens");
-				strcpy(opt[i++],"Moscow");
-				strcpy(opt[i++],"Dubai");
-				strcpy(opt[i++],"Kabul");
-				strcpy(opt[i++],"Karachi");
-				strcpy(opt[i++],"Bombay");
-				strcpy(opt[i++],"Kathmandu");
-				strcpy(opt[i++],"Dhaka");
-				strcpy(opt[i++],"Bangkok");
-				strcpy(opt[i++],"Hong Kong");
-				strcpy(opt[i++],"Tokyo");
-				strcpy(opt[i++],"Sydney");
-				strcpy(opt[i++],"Noumea");
-				strcpy(opt[i++],"Wellington");
-				strcpy(opt[i++],"Other...");
-				opt[i][0]=0;
-				i=0;
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Time Zone",opt);
-				if(i==-1)
-					break;
-				changes=1;
-				switch(i) {
-					case 0:
-						sys_timezone=MID;
-						break;
-					case 1:
-						sys_timezone=VAN;
-						break;
-					case 2:
-						sys_timezone=EDM;
-						break;
-					case 3:
-						sys_timezone=WIN;
-						break;
-					case 4:
-						sys_timezone=BOG;
-						break;
-					case 5:
-						sys_timezone=CAR;
-						break;
-					case 6:
-						sys_timezone=RIO;
-						break;
-					case 7:
-						sys_timezone=FER;
-						break;
-					case 8:
-						sys_timezone=AZO;
-                        break;
-					case 9:
-						sys_timezone=LON;
-                        break;
-					case 10:
-						sys_timezone=BER;
-                        break;
-					case 11:
-						sys_timezone=ATH;
-                        break;
-					case 12:
-						sys_timezone=MOS;
-                        break;
-					case 13:
-						sys_timezone=DUB;
-                        break;
-					case 14:
-						sys_timezone=KAB;
-                        break;
-					case 15:
-						sys_timezone=KAR;
-                        break;
-					case 16:
-						sys_timezone=BOM;
-                        break;
-					case 17:
-						sys_timezone=KAT;
-                        break;
-					case 18:
-						sys_timezone=DHA;
-                        break;
-					case 19:
-						sys_timezone=BAN;
-                        break;
-					case 20:
-						sys_timezone=HON;
-                        break;
-					case 21:
-						sys_timezone=TOK;
-                        break;
-					case 22:
-						sys_timezone=SYD;
-                        break;
-					case 23:
-						sys_timezone=NOU;
-                        break;
-					case 24:
-						sys_timezone=WEL;
-                        break;
-					default:
-						if(sys_timezone>720 || sys_timezone<-720)
-							sys_timezone=0;
-						sprintf(str,"%02d:%02d"
-							,sys_timezone/60,sys_timezone<0
-							? (-sys_timezone)%60 : sys_timezone%60);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Time (HH:MM) East (+) or West (-) of Universal "
-								"Time"
-							,str,6,K_EDIT|K_UPPER);
-						sys_timezone=atoi(str)*60;
-						p=strchr(str,':');
-						if(p) {
-							if(sys_timezone<0)
-								sys_timezone-=atoi(p+1);
-							else
-								sys_timezone+=atoi(p+1); }
-                        break;
-						}
-                break;
-			case 2:
-				SETHELP(WHERE);
-/*
-Maximum Message Base Retry Time:
-
-This is the maximum number of seconds to allow while attempting to open
-or lock a message base (a value in the range of 10 to 45 seconds should
-be fine).
-*/
-				itoa(smb_retry_time,str,10);
-				uinput(WIN_MID|WIN_SAV,0,0
-					,"Maximum Message Base Retry Time (in seconds)"
-					,str,2,K_NUMBER|K_EDIT);
-				smb_retry_time=atoi(str);
-				break;
-			case 3:
-				SETHELP(WHERE);
-/*
-Maximum Messages Per QWK Packet:
-
-This is the maximum number of messages (excluding E-mail), that a user
-can have in one QWK packet for download. This limit does not effect
-QWK network nodes (Q restriction). If set to 0, no limit is imposed.
-*/
-
-				ultoa(max_qwkmsgs,str,10);
-				uinput(WIN_MID|WIN_SAV,0,0
-					,"Maximum Messages Per QWK Packet (0=No Limit)"
-					,str,6,K_NUMBER|K_EDIT);
-				max_qwkmsgs=atol(str);
-                break;
-			case 4:
-				SETHELP(WHERE);
-/*
-Pre-pack QWK Requirements:
-
-ALL user accounts on the BBS meeting this requirmenet will have a QWK
-packet automatically created for them every day after midnight
-(during the internal daily event).
-
-This is mainly intended for QWK network nodes that wish to save connect
-time by having their packets pre-packed. If a large number of users meet
-this requirement, it can take up a large amount of disk space on your
-system (in the DATA\FILE directory).
-*/
-				getar("Pre-pack QWK (Use with caution!)",preqwk_ar);
-				break;
-			case 5:
-				sprintf(str,"%u",mail_maxage);
-                SETHELP(WHERE);
-/*
-Maximum Age of Mail:
-
-This value is the maximum number of days that mail will be kept.
-*/
-                uinput(WIN_MID|WIN_SAV,0,17,"Maximum Age of Mail "
-                    "(in days)",str,5,K_EDIT|K_NUMBER);
-                mail_maxage=atoi(str);
-                break;
-			case 6:
-				strcpy(opt[0],"Daily");
-				strcpy(opt[1],"Immediately");
-				opt[2][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Purge Deleted E-mail:
-
-If you wish to have deleted e-mail physically (and permanently) removed
-from your e-mail database immediately after a users exits the reading
-e-mail prompt, set this option to Immediately.
-
-For the best system performance and to avoid delays when deleting e-mail
-from a large e-mail database, set this option to Daily (the default).
-Your system maintenance will automatically purge deleted e-mail once a
-day.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Purge Deleted E-mail",opt);
-				if(!i && sys_misc&SM_DELEMAIL) {
-					sys_misc&=~SM_DELEMAIL;
-					changes=1; }
-				else if(i==1 && !(sys_misc&SM_DELEMAIL)) {
-					sys_misc|=SM_DELEMAIL;
-					changes=1; }
-                break;
-			case 7:
-				sprintf(str,"%lu",mail_maxcrcs);
-                SETHELP(WHERE);
-/*
-Maximum Number of Mail CRCs:
-
-This value is the maximum number of CRCs that will be kept for duplicate
-mail checking. Once this maximum number of CRCs is reached, the oldest
-CRCs will be automatically purged.
-*/
-                uinput(WIN_MID|WIN_SAV,0,17,"Maximum Number of Mail "
-                    "CRCs",str,5,K_EDIT|K_NUMBER);
-                mail_maxcrcs=atol(str);
-                break;
-			case 8:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=1;
-				SETHELP(WHERE);
-/*
-Allow Anonymous E-mail:
-
-If you want users with the A exemption to be able to send E-mail
-anonymously, set this option to Yes.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Allow Anonymous E-mail",opt);
-				if(!i && !(sys_misc&SM_ANON_EM)) {
-					sys_misc|=SM_ANON_EM;
-					changes=1; }
-				else if(i==1 && sys_misc&SM_ANON_EM) {
-					sys_misc&=~SM_ANON_EM;
-					changes=1; }
-				break;
-			case 9:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Allow Quoting in E-mail:
-
-If you want your users to be allowed to use message quoting when
-responding in E-mail, set this option to Yes.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Allow Quoting in E-mail",opt);
-				if(!i && !(sys_misc&SM_QUOTE_EM)) {
-					sys_misc|=SM_QUOTE_EM;
-					changes=1; }
-				else if(i==1 && sys_misc&SM_QUOTE_EM) {
-					sys_misc&=~SM_QUOTE_EM;
-					changes=1; }
-				break;
-			case 10:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Allow File Attachment Uploads in E-mail:
-
-If you want your users to be allowed to attach an uploaded file to
-an E-mail message, set this option to Yes.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Allow File Attachment Uploads in E-mail",opt);
-				if(!i && !(sys_misc&SM_FILE_EM)) {
-					sys_misc|=SM_FILE_EM;
-					changes=1; }
-				else if(i==1 && sys_misc&SM_FILE_EM) {
-					sys_misc&=~SM_FILE_EM;
-					changes=1; }
-				break;
-			case 11:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Allow Users to Have Their E-mail Forwarded to NetMail:
-
-If you want your users to be able to have any e-mail sent to them
-optionally (at the sender's discretion) forwarded to a NetMail address,
-set this option to Yes.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Allow Forwarding of E-mail to NetMail",opt);
-				if(!i && !(sys_misc&SM_FWDTONET)) {
-					sys_misc|=SM_FWDTONET;
-					changes=1; }
-				else if(i==1 && sys_misc&SM_FWDTONET) {
-					sys_misc&=~SM_FWDTONET;
-					changes=1; }
-                break;
-			case 12:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				i=1;
-				SETHELP(WHERE);
-/*
-Kill Read E-mail Automatically:
-
-If this option is set to Yes, e-mail that has been read will be
-automatically deleted when message base maintenance is run.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Kill Read E-mail Automatically",opt);
-				if(!i && !(sys_misc&SM_DELREADM)) {
-					sys_misc|=SM_DELREADM;
-					changes=1; }
-				else if(i==1 && sys_misc&SM_DELREADM) {
-					sys_misc&=~SM_DELREADM;
-					changes=1; }
-                break;
-			case 13:
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				strcpy(opt[2],"Sysops Only");
-				opt[3][0]=0;
-				i=1;
-				SETHELP(WHERE);
-/*
-Users Can View Deleted Messages:
-
-If this option is set to Yes, then users will be able to view messages
-they've sent and deleted or messages sent to them and they've deleted
-with the option of un-deleting the message before the message is
-physically purged from the e-mail database.
-
-If this option is set to No, then when a message is deleted, it is no
-longer viewable (with SBBS) by anyone.
-
-If this option is set to Sysops Only, then only sysops and sub-ops (when
-appropriate) can view deleted messages.
-*/
-
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-					,"Users Can View Deleted Messages",opt);
-				if(!i && (sys_misc&(SM_USRVDELM|SM_SYSVDELM))
-					!=(SM_USRVDELM|SM_SYSVDELM)) {
-					sys_misc|=(SM_USRVDELM|SM_SYSVDELM);
-					changes=1; }
-				else if(i==1 && sys_misc&(SM_USRVDELM|SM_SYSVDELM)) {
-					sys_misc&=~(SM_USRVDELM|SM_SYSVDELM);
-					changes=1; }
-				else if(i==2 && (sys_misc&(SM_USRVDELM|SM_SYSVDELM))
-					!=SM_SYSVDELM) {
-					sys_misc|=SM_SYSVDELM;
-					sys_misc&=~SM_USRVDELM;
-					changes=1; }
-                break;
-			case 14:
-				SETHELP(WHERE);
-/*
-Extra Attribute Codes...
-
-Synchronet can suppport the native text attribute codes of other BBS
-programs in messages (menus, posts, e-mail, etc.) To enable the extra
-attribute codes for another BBS program, set the corresponding option
-to Yes.
-*/
-
-				j=0;
-				while(1) {
-					i=0;
-					sprintf(opt[i++],"%-15.15s %-3.3s","WWIV"
-						,sys_misc&SM_WWIV ? "Yes":"No");
-					sprintf(opt[i++],"%-15.15s %-3.3s","PCBoard"
-						,sys_misc&SM_PCBOARD ? "Yes":"No");
-					sprintf(opt[i++],"%-15.15s %-3.3s","Wildcat"
-						,sys_misc&SM_WILDCAT ? "Yes":"No");
-					sprintf(opt[i++],"%-15.15s %-3.3s","Celerity"
-						,sys_misc&SM_CELERITY ? "Yes":"No");
-					sprintf(opt[i++],"%-15.15s %-3.3s","Renegade"
-						,sys_misc&SM_RENEGADE ? "Yes":"No");
-					opt[i][0]=0;
-					j=ulist(WIN_BOT|WIN_RHT|WIN_SAV,2,2,0,&j,0
-						,"Extra Attribute Codes",opt);
-					if(j==-1)
-						break;
-
-					changes=1;
-					switch(j) {
-						case 0:
-							sys_misc^=SM_WWIV;
-							break;
-						case 1:
-							sys_misc^=SM_PCBOARD;
-							break;
-						case 2:
-							sys_misc^=SM_WILDCAT;
-							break;
-						case 3:
-							sys_misc^=SM_CELERITY;
-							break;
-						case 4:
-							sys_misc^=SM_RENEGADE;
-							break; } } } }
-}
diff --git a/src/sbbs2/scfg/scfgnet.c b/src/sbbs2/scfg/scfgnet.c
deleted file mode 100644
index d645ab7c9f90d4e893a0652d2964f5e9e14a3d04..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgnet.c
+++ /dev/null
@@ -1,1457 +0,0 @@
-#line 2 "SCFGNET.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-
-char *daystr(char days);
-
-
-void qhub_edit(int num);
-void phub_edit(int num);
-char *daystr(char days);
-void qhub_sub_edit(uint num);
-
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-faddr_t atofaddr(char *str)
-{
-    char *p;
-    faddr_t addr;
-
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-    addr.zone=atoi(str);
-    addr.net=atoi(p+1); }
-else {
-    if(total_faddrs)
-		addr.zone=faddr[0].zone;
-    else
-        addr.zone=1;
-    addr.net=atoi(str); }
-if(!addr.zone)              /* no such thing as zone 0 */
-    addr.zone=1;
-if((p=strchr(str,'/'))!=NULL)
-    addr.node=atoi(p+1);
-else {
-    if(total_faddrs)
-		addr.net=faddr[0].net;
-    else
-        addr.net=1;
-    addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL)
-    addr.point=atoi(p+1);
-return(addr);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(faddr_t addr)
-{
-    static char str[25];
-    char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-    sprintf(point,".%u",addr.point);
-    strcat(str,point); }
-return(str);
-}
-
-
-uint getsub()
-{
-	static int grp_dflt,sub_dflt,grp_bar,sub_bar;
-	char str[81];
-	int i,j,k;
-	uint subnum[MAX_OPTS+1];
-
-while(1) {
-	for(i=0;i<total_grps && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",grp[i]->lname);
-	opt[i][0]=0;
-	i=ulist(WIN_SAV|WIN_RHT|WIN_BOT,0,0,45,&grp_dflt,&grp_bar
-		,"Message Groups"
-		,opt);
-	if(i==-1)
-		return(-1);
-	for(j=k=0;j<total_subs && k<MAX_OPTS;j++)
-		if(sub[j]->grp==i) {
-			sprintf(opt[k],"%-25s",sub[j]->lname);
-			subnum[k++]=j; }
-	opt[k][0]=0;
-	sprintf(str,"%s Sub-boards",grp[i]->sname);
-	j=ulist(WIN_RHT|WIN_BOT|WIN_SAV,0,0,45,&sub_dflt,&sub_bar,str,opt);
-	if(j==-1)
-		continue;
-	return(subnum[j]); }
-
-}
-
-void net_cfg()
-{
-	static	int net_dflt,qnet_dflt,pnet_dflt,fnet_dflt,inet_dflt
-			,qhub_dflt,phub_dflt;
-	char	str[81],done,*p;
-	int 	i,j,k,l,m,n;
-
-while(1) {
-	i=0;
-	strcpy(opt[i++],"QWK Packet Networks");
-	strcpy(opt[i++],"FidoNet EchoMail and NetMail");
-	strcpy(opt[i++],"PostLink Networks");
-	strcpy(opt[i++],"Internet NetMail");
-	opt[i][0]=0;
-	SETHELP(WHERE);
-/*
-Configure Networks:
-
-This is the network configuration menu. Select the type of network
-technology that you want to configure.
-*/
-	i=ulist(WIN_ORG|WIN_ACT|WIN_CHE,0,0,0,&net_dflt,0,"Networks",opt);
-	if(i==0) {	/* QWK net stuff */
-		done=0;
-		while(!done) {
-			i=0;
-			strcpy(opt[i++],"Network Hubs...");
-			strcpy(opt[i++],"Default Tagline");
-			opt[i][0]=0;
-			SETHELP(WHERE);
-/*
-QWK Packet Networks:
-
-From this menu you can configure the default tagline to use for
-outgoing messages on QWK networked sub-boards, or you can select
-Network Hubs... to add, delete, or configure QWK hubs that your system
-calls to exchange packets with.
-*/
-			i=ulist(WIN_ACT|WIN_RHT|WIN_BOT|WIN_CHE,0,0,0,&qnet_dflt,0
-				,"QWK Packet Networks",opt);
-			savnum=0;
-			switch(i) {
-				case -1:	/* ESC */
-					done=1;
-					break;
-				case 1:
-					SETHELP(WHERE);
-/*
-QWK Network Default Tagline:
-
-This is the default tagline to use for outgoing messages on QWK
-networked sub-boards. This default can be overridden on a per sub-board
-basis with the sub-board configuration Network Options....
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,nulstr
-						,qnet_tagline,63,K_MSG|K_EDIT);
-					break;
-				case 0:
-					while(1) {
-						for(i=0;i<total_qhubs && i<MAX_OPTS;i++)
-							sprintf(opt[i],"%-8.8s",qhub[i]->id);
-						opt[i][0]=0;
-						i=WIN_ACT|WIN_RHT|WIN_SAV;
-						if(total_qhubs<MAX_OPTS)
-							i|=WIN_INS|WIN_INSACT|WIN_XTR;
-						if(total_qhubs)
-							i|=WIN_DEL;
-						savnum=0;
-						SETHELP(WHERE);
-/*
-QWK Network Hubs:
-
-This is a list of QWK network hubs that your system calls to exchange
-packets with.
-
-To add a hub, select the desired location with the arrow keys and hit
- INS .
-
-To delete a hub, select it and hit  DEL .
-
-To configure a hub, select it and hit  ENTER .
-*/
-						i=ulist(i,0,0,0,&qhub_dflt,0
-							,"QWK Network Hubs",opt);
-						if(i==-1)
-							break;
-						if((i&MSK_ON)==MSK_INS) {
-							i&=MSK_OFF;
-							if((qhub=(qhub_t **)REALLOC(qhub
-                                ,sizeof(qhub_t *)*(total_qhubs+1)))==NULL) {
-                                errormsg(WHERE,ERR_ALLOC,nulstr
-                                    ,sizeof(qhub_t *)*(total_qhubs+1));
-								total_qhubs=0;
-								bail(1);
-                                continue; }
-
-							savnum=1;
-							SETHELP(WHERE);
-/*
-QWK Network Hub System ID:
-
-This is the QWK System ID of this hub. It is used for incoming and
-outgoing network packets and must be accurate.
-*/
-							if(uinput(WIN_MID|WIN_SAV,0,0
-								,"System ID",str,8,K_UPPER)<1)
-								continue;
-
-							for(j=total_qhubs;j>i;j--)
-                                qhub[j]=qhub[j-1];
-							if((qhub[i]=(qhub_t *)MALLOC(sizeof(qhub_t)))
-								==NULL) {
-								errormsg(WHERE,ERR_ALLOC,nulstr
-									,sizeof(qhub_t));
-								continue; }
-							memset(qhub[i],0,sizeof(qhub_t));
-							strcpy(qhub[i]->id,str);
-							strcpy(qhub[i]->pack,"%!pkzip %f %s");
-							strcpy(qhub[i]->unpack,"%!pkunzip -o %f %g %s");
-							strcpy(qhub[i]->call,"%!qnet");
-							qhub[i]->node=1;
-							qhub[i]->days=0xff; /* all days */
-							total_qhubs++;
-							changes=1;
-							continue; }
-						if((i&MSK_ON)==MSK_DEL) {
-							i&=MSK_OFF;
-							FREE(qhub[i]->mode);
-							FREE(qhub[i]->conf);
-							FREE(qhub[i]->sub);
-							FREE(qhub[i]);
-							total_qhubs--;
-							while(i<total_qhubs) {
-								qhub[i]=qhub[i+1];
-								i++; }
-							changes=1;
-							continue; }
-						qhub_edit(i); }
-					break; } } }
-
-	else if(i==1) { 	/* FidoNet Stuff */
-		done=0;
-		while(!done) {
-			i=0;
-			sprintf(opt[i++],"%-27.27s%s"
-				,"System Addresses",total_faddrs ? faddrtoa(faddr[0])
-					: nulstr);
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Default Outbound Address"
-				,dflt_faddr.zone ? faddrtoa(dflt_faddr) : "No");
-			sprintf(opt[i++],"%-27.27s"
-				,"Default Origin Line");
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"NetMail Semaphore",netmail_sem);
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"EchoMail Semaphore",echomail_sem);
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"Inbound File Directory",fidofile_dir);
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"EchoMail Base Directory",echomail_dir);
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"NetMail Directory",netmail_dir);
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Allow Sending of NetMail"
-				,netmail_misc&NMAIL_ALLOW ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Allow File Attachments"
-				,netmail_misc&NMAIL_FILE ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Send NetMail Using Alias"
-				,netmail_misc&NMAIL_ALIAS ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"NetMail Defaults to Crash"
-				,netmail_misc&NMAIL_CRASH ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"NetMail Defaults to Direct"
-				,netmail_misc&NMAIL_DIRECT ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"NetMail Defaults to Hold"
-				,netmail_misc&NMAIL_HOLD ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Kill NetMail After Sent"
-				,netmail_misc&NMAIL_KILL ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%lu"
-				,"Cost to Send NetMail",netmail_cost);
-			opt[i][0]=0;
-			SETHELP(WHERE);
-/*
-FidoNet EchoMail and NetMail:
-
-This menu contains configuration options that pertain specifically to
-networking E-mail (NetMail) and sub-boards (EchoMail) through networks
-using FidoNet technology.
-*/
-			i=ulist(WIN_ACT|WIN_MID|WIN_CHE,0,0,60,&fnet_dflt,0
-				,"FidoNet EchoMail and NetMail",opt);
-			savnum=0;
-			switch(i) {
-				case -1:	/* ESC */
-					done=1;
-					break;
-				case 0:
-					SETHELP(WHERE);
-/*
-System FidoNet Addresses:
-
-This is the FidoNet address of this system used to receive NetMail.
-The Main address is also used as the default address for sub-boards.
-Format: Zone:Net/Node[.Point]
-*/
-					k=l=0;
-					while(1) {
-						for(i=0;i<total_faddrs && i<MAX_OPTS;i++) {
-							if(i==0)
-								strcpy(str,"Main");
-							else
-								sprintf(str,"AKA %u",i);
-							sprintf(opt[i],"%-8.8s %-16s"
-								,str,faddrtoa(faddr[i])); }
-						opt[i][0]=0;
-						j=WIN_RHT|WIN_SAV|WIN_ACT|WIN_INSACT;
-						if(total_faddrs<MAX_OPTS)
-							j|=WIN_INS|WIN_XTR;
-						if(total_faddrs)
-							j|=WIN_DEL;
-						i=ulist(j,0,0,0,&k,&l
-							,"System Addresses",opt);
-						if(i==-1)
-							break;
-						if((i&MSK_ON)==MSK_INS) {
-							i&=MSK_OFF;
-
-							if(!total_faddrs)
-								strcpy(str,"1:1/0");
-							else
-								strcpy(str,faddrtoa(faddr[0]));
-							if(!uinput(WIN_MID|WIN_SAV,0,0,"Address"
-								,str,25,K_EDIT|K_UPPER))
-								continue;
-
-							if((faddr=(faddr_t *)REALLOC(faddr
-                                ,sizeof(faddr_t)*(total_faddrs+1)))==NULL) {
-                                errormsg(WHERE,ERR_ALLOC,nulstr
-                                    ,sizeof(faddr_t)*total_faddrs+1);
-								total_faddrs=0;
-								bail(1);
-                                continue; }
-
-							for(j=total_faddrs;j>i;j--)
-                                faddr[j]=faddr[j-1];
-
-							faddr[i]=atofaddr(str);
-							total_faddrs++;
-							changes=1;
-							continue; }
-						if((i&MSK_ON)==MSK_DEL) {
-							i&=MSK_OFF;
-							total_faddrs--;
-							while(i<total_faddrs) {
-								faddr[i]=faddr[i+1];
-								i++; }
-							changes=1;
-							continue; }
-						strcpy(str,faddrtoa(faddr[i]));
-						uinput(WIN_MID|WIN_SAV,0,0,"Address"
-							,str,25,K_EDIT);
-						faddr[i]=atofaddr(str); }
-                    break;
-				case 1:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Use Default Outbound NetMail Address:
-
-If you would like to have a default FidoNet address adding to outbound
-NetMail mail messages that do not have an address specified, select
-Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Use Default Outbound NetMail Address",opt);
-					if(i==1) {
-						if(dflt_faddr.zone)
-							changes=1;
-						dflt_faddr.zone=0;
-						break; }
-					if(i==-1)
-						break;
-					if(!dflt_faddr.zone) {
-						dflt_faddr.zone=1;
-						changes=1; }
-					strcpy(str,faddrtoa(dflt_faddr));
-					SETHELP(WHERE);
-/*
-Default Outbound FidoNet NetMail Address:
-
-If you would like to automatically add a FidoNet address to outbound
-NetMail that does not have an address specified, set this option
-to that address. This is useful for Fido/UUCP gateway mail.
-Format: Zone:Net/Node[.Point]
-*/
-					if(uinput(WIN_MID|WIN_SAV,0,0,"Outbound Address"
-						,str,25,K_EDIT)) {
-						dflt_faddr=atofaddr(str);
-						changes=1; }
-                    break;
-				case 2:
-					SETHELP(WHERE);
-/*
-Default Origin Line:
-
-This is the default origin line used for sub-boards networked via
-EchoMail. This origin line can be overridden on a per sub-board basis
-with the sub-board configuration Network Options....
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"* Origin"
-						,origline,50,K_EDIT);
-                    break;
-				case 3:
-					SETHELP(WHERE);
-/*
-NetMail Semaphore File:
-
-This is a filename that will be used as a semaphore (signal) to your
-FidoNet front-end that new NetMail has been created and the messages
-should be re-scanned.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"NetMail Semaphore"
-						,netmail_sem,50,K_EDIT|K_UPPER);
-                    break;
-				case 4:
-					SETHELP(WHERE);
-/*
-EchoMail Semaphore File:
-
-This is a filename that will be used as a semaphore (signal) to your
-FidoNet front-end that new EchoMail has been created and the messages
-should be re-scanned.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"EchoMail Semaphore"
-						,echomail_sem,50,K_EDIT|K_UPPER);
-                    break;
-				case 5:
-					SETHELP(WHERE);
-/*
-Inbound File Directory:
-
-This directory is where inbound files are placed. This directory is
-only used when an incoming message has a file attached.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"Inbound Files"
-						,fidofile_dir,50,K_EDIT|K_UPPER);
-                    break;
-				case 6:
-					SETHELP(WHERE);
-/*
-EchoMail Base Directory:
-
-This is an optional field used as a base directory for the location
-of EchoMail messages for sub-boards that do not have a specified
-EchoMail Storage Directory. If a sub-board does not have a specified
-storage directory for EchoMail, its messages will be imported from and
-exported to a sub-directory off of this base directory. The name of the
-sub-directory is the same as the internal code for the sub-directory.
-
-If all EchoMail sub-boards have specified EchoMail storage directories,
-this option is not used at all.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"EchoMail Base"
-						,echomail_dir,50,K_EDIT|K_UPPER);
-                    break;
-				case 7:
-					SETHELP(WHERE);
-/*
-NetMail Directory:
-
-This is the directory where NetMail will be imported from and exported
-to.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"NetMail"
-						,netmail_dir,50,K_EDIT|K_UPPER);
-                    break;
-				case 8:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Allow Users to Send NetMail:
-
-If you are on a FidoNet style network and want your users to be allowed
-to send NetMail, set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Allow Users to Send NetMail",opt);
-					if(!i && !(netmail_misc&NMAIL_ALLOW)) {
-						changes=1;
-						netmail_misc|=NMAIL_ALLOW; }
-					else if(i==1 && netmail_misc&NMAIL_ALLOW) {
-						changes=1;
-						netmail_misc&=~NMAIL_ALLOW; }
-					break;
-				case 9:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Allow Users to Send NetMail File Attachments:
-
-If you are on a FidoNet style network and want your users to be allowed
-to send NetMail file attachments, set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Allow Users to Send NetMail File Attachments",opt);
-					if(!i && !(netmail_misc&NMAIL_FILE)) {
-						changes=1;
-						netmail_misc|=NMAIL_FILE; }
-					else if(i==1 && netmail_misc&NMAIL_FILE) {
-						changes=1;
-						netmail_misc&=~NMAIL_FILE; }
-                    break;
-				case 10:
-					i=1;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Use Aliases in NetMail:
-
-If you allow aliases on your system and wish users to have their NetMail
-contain their alias as the From User, set this option to Yes. If you
-want all NetMail to be sent using users' real names, set this option to
-No.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Use Aliases in NetMail",opt);
-					if(!i && !(netmail_misc&NMAIL_ALIAS)) {
-						changes=1;
-						netmail_misc|=NMAIL_ALIAS; }
-					else if(i==1 && netmail_misc&NMAIL_ALIAS) {
-						changes=1;
-						netmail_misc&=~NMAIL_ALIAS; }
-                    break;
-				case 11:
-					i=1;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-NetMail Defaults to Crash Status:
-
-If you want all NetMail to default to crash (send immediately) status,
-set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"NetMail Defaults to Crash Status",opt);
-					if(!i && !(netmail_misc&NMAIL_CRASH)) {
-						changes=1;
-						netmail_misc|=NMAIL_CRASH; }
-					else if(i==1 && netmail_misc&NMAIL_CRASH) {
-						changes=1;
-						netmail_misc&=~NMAIL_CRASH; }
-                    break;
-				case 12:
-					i=1;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-NetMail Defaults to Direct Status:
-
-If you want all NetMail to default to direct (send directly) status,
-set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"NetMail Defaults to Direct Status",opt);
-					if(!i && !(netmail_misc&NMAIL_DIRECT)) {
-						changes=1;
-						netmail_misc|=NMAIL_DIRECT; }
-					else if(i==1 && netmail_misc&NMAIL_DIRECT) {
-						changes=1;
-						netmail_misc&=~NMAIL_DIRECT; }
-                    break;
-				case 13:
-					i=1;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-NetMail Defaults to Hold Status:
-
-If you want all NetMail to default to hold status, set this option to
-Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"NetMail Defaults to Hold Status",opt);
-					if(!i && !(netmail_misc&NMAIL_HOLD)) {
-						changes=1;
-						netmail_misc|=NMAIL_HOLD; }
-					else if(i==1 && netmail_misc&NMAIL_HOLD) {
-						changes=1;
-						netmail_misc&=~NMAIL_HOLD; }
-                    break;
-				case 14:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Kill NetMail After it is Sent:
-
-If you want NetMail messages to be deleted after they are successfully
-sent, set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Kill NetMail After it is Sent",opt);
-					if(!i && !(netmail_misc&NMAIL_KILL)) {
-						changes=1;
-						netmail_misc|=NMAIL_KILL; }
-					else if(i==1 && netmail_misc&NMAIL_KILL) {
-						changes=1;
-						netmail_misc&=~NMAIL_KILL; }
-                    break;
-				case 15:
-					ultoa(netmail_cost,str,10);
-					SETHELP(WHERE);
-/*
-Cost in Credits to Send NetMail:
-
-This is the number of credits it will cost your users to send NetMail.
-If you want the sending of NetMail to be free, set this value to 0.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0
-						,"Cost in Credits to Send NetMail"
-						,str,10,K_EDIT|K_NUMBER);
-					netmail_cost=atol(str);
-					break; } } }
-	else if(i==2) {
-		done=0;
-		while(!done) {
-			i=0;
-			strcpy(opt[i++],"Network Hubs...");
-			sprintf(opt[i++],"%-20.20s%-12s","Site Name",sys_psname);
-			sprintf(opt[i++],"%-20.20s%-lu","Site Number",sys_psnum);
-			opt[i][0]=0;
-			SETHELP(WHERE);
-/*
-PostLink Networks:
-
-From this menu you can configure the default tagline to use for
-outgoing messages on QWK networked sub-boards, or you can select
-Network Hubs... to add, delete, or configure QWK hubs that your system
-calls to exchange packets with.
-*/
-			i=ulist(WIN_ACT|WIN_RHT|WIN_BOT|WIN_CHE,0,0,0,&pnet_dflt,0
-				,"PostLink Networks",opt);
-			savnum=0;
-			switch(i) {
-				case -1:	/* ESC */
-					done=1;
-					break;
-				case 1:
-					SETHELP(WHERE);
-/*
-PostLink Site Name:
-
-If your system is networked via PostLink or PCRelay, this should be the
-Site Name for your BBS.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"Site Name"
-						,sys_psname,12,K_UPPER|K_EDIT);
-					break;
-				case 2:
-					SETHELP(WHERE);
-/*
-PostLink Site Number:
-
-If your system is networked via PostLink or PCRelay, this should be the
-Site Number for your BBS.
-*/
-					ultoa(sys_psnum,str,10);
-					uinput(WIN_MID|WIN_SAV,0,0,"Site Number"
-						,str,10,K_NUMBER|K_EDIT);
-					sys_psnum=atol(str);
-                    break;
-				case 0:
-					while(1) {
-						for(i=0;i<total_phubs && i<MAX_OPTS;i++)
-							sprintf(opt[i],"%-10.10s",phub[i]->name);
-						opt[i][0]=0;
-						i=WIN_ACT|WIN_RHT|WIN_SAV;
-						if(total_phubs<MAX_OPTS)
-							i|=WIN_INS|WIN_INSACT|WIN_XTR;
-						if(total_phubs)
-							i|=WIN_DEL;
-						savnum=0;
-						SETHELP(WHERE);
-/*
-PostLink Network Hubs:
-
-This is a list of PostLink and/or PCRelay network hubs that your system
-calls to exchange packets with.
-
-To add a hub, select the desired location with the arrow keys and hit
- INS .
-
-To delete a hub, select it and hit  DEL .
-
-To configure a hub, select it and hit  ENTER .
-*/
-						i=ulist(i,0,0,0,&phub_dflt,0
-							,"PostLink Hubs",opt);
-						if(i==-1)
-							break;
-						if((i&MSK_ON)==MSK_INS) {
-							i&=MSK_OFF;
-							if((phub=(phub_t **)REALLOC(phub
-                                ,sizeof(phub_t *)*(total_phubs+1)))==NULL) {
-                                errormsg(WHERE,ERR_ALLOC,nulstr
-                                    ,sizeof(phub_t *)*(total_phubs+1));
-								total_phubs=0;
-								bail(1);
-                                continue; }
-
-							savnum=1;
-							SETHELP(WHERE);
-/*
-Network Hub Site Name:
-
-This is the Site Name of this hub. It is used for only for reference.
-*/
-							if(uinput(WIN_MID|WIN_SAV,0,0
-								,"Site Name",str,10,K_UPPER)<1)
-								continue;
-
-							for(j=total_phubs;j>i;j--)
-                                phub[j]=phub[j-1];
-
-							if((phub[i]=(phub_t *)MALLOC(sizeof(phub_t)))
-								==NULL) {
-								errormsg(WHERE,ERR_ALLOC,nulstr
-									,sizeof(phub_t));
-								continue; }
-							memset(phub[i],0,sizeof(phub_t));
-							strcpy(phub[i]->name,str);
-							strcpy(phub[i]->call,"%!pnet");
-							phub[i]->node=1;
-							phub[i]->days=0xff; /* all days */
-							total_phubs++;
-							changes=1;
-							continue; }
-						if((i&MSK_ON)==MSK_DEL) {
-							i&=MSK_OFF;
-							FREE(phub[i]);
-							total_phubs--;
-							while(i<total_phubs) {
-								phub[i]=phub[i+1];
-								i++; }
-							changes=1;
-							continue; }
-						phub_edit(i); }
-                    break; } } }
-
-	else if(i==3) { 	/* Internet */
-		done=0;
-		while(!done) {
-			i=0;
-			sprintf(opt[i++],"%-27.27s%s"
-				,"System Address",sys_inetaddr);
-			sprintf(opt[i++],"%-27.27s%.40s"
-				,"NetMail Semaphore",inetmail_sem);
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Allow Sending of NetMail"
-				,inetmail_misc&NMAIL_ALLOW ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Allow File Attachments"
-				,inetmail_misc&NMAIL_FILE ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%s"
-				,"Send NetMail Using Alias"
-				,inetmail_misc&NMAIL_ALIAS ? "Yes":"No");
-			sprintf(opt[i++],"%-27.27s%lu"
-				,"Cost to Send NetMail",inetmail_cost);
-			opt[i][0]=0;
-			SETHELP(WHERE);
-/*
-Internet NetMail:
-
-This menu contains configuration options that pertain specifically to
-Internet E-mail (NetMail). To utilize these options, you must own
-a Synchronet compatible UUCP/Internet gateway (e.g. SyncUUCP).
-*/
-			i=ulist(WIN_ACT|WIN_MID|WIN_CHE,0,0,60,&inet_dflt,0
-				,"Internet NetMail",opt);
-			savnum=0;
-			switch(i) {
-				case -1:	/* ESC */
-					done=1;
-					break;
-				case 0:
-					SETHELP(WHERE);
-/*
-Sytem Internet Address:
-
-If your system has an Internet mail feed, enter your system's Internet
-address here (e.g. joesbbs.com).
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,""
-						,sys_inetaddr,60,K_EDIT);
-                    break;
-				case 1:
-					SETHELP(WHERE);
-/*
-Internet NetMail Semaphore File:
-
-This is a filename that will be used as a semaphore (signal) to your
-Internet gateway (if supported) that new mail has been created and the
-message base should be re-scanned.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0,"Semaphore File"
-						,inetmail_sem,50,K_EDIT|K_UPPER);
-                    break;
-
-				case 2:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Allow Users to Send Internet NetMail:
-
-If your system has an Internet uplink and you want your users to be
-allowed to send Internet NetMail, set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Allow Users to Send NetMail",opt);
-					if(!i && !(inetmail_misc&NMAIL_ALLOW)) {
-						changes=1;
-						inetmail_misc|=NMAIL_ALLOW; }
-					else if(i==1 && inetmail_misc&NMAIL_ALLOW) {
-						changes=1;
-						inetmail_misc&=~NMAIL_ALLOW; }
-					break;
-
-				case 3:
-					i=0;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Allow Users to Send Internet NetMail File Attachments:
-
-If your system has an Internet uplink and you want your users to be
-allowed to send Internet NetMail file attachments, set this option to Yes.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Allow Users to Send NetMail File Attachments",opt);
-					if(!i && !(inetmail_misc&NMAIL_FILE)) {
-						changes=1;
-						inetmail_misc|=NMAIL_FILE; }
-					else if(i==1 && inetmail_misc&NMAIL_FILE) {
-						changes=1;
-						inetmail_misc&=~NMAIL_FILE; }
-                    break;
-				case 4:
-					i=1;
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					SETHELP(WHERE);
-/*
-Use Aliases in NetMail:
-
-If you allow aliases on your system and wish users to have their NetMail
-contain their alias as the From User, set this option to Yes. If you
-want all NetMail to be sent using users' real names, set this option to
-No.
-*/
-					i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-						,"Use Aliases in NetMail",opt);
-					if(!i && !(inetmail_misc&NMAIL_ALIAS)) {
-						changes=1;
-						inetmail_misc|=NMAIL_ALIAS; }
-					else if(i==1 && inetmail_misc&NMAIL_ALIAS) {
-						changes=1;
-						inetmail_misc&=~NMAIL_ALIAS; }
-					break;
-				case 5:
-					ultoa(inetmail_cost,str,10);
-					SETHELP(WHERE);
-/*
-Cost in Credits to Send NetMail:
-
-This is the number of credits it will cost your users to send NetMail.
-If you want the sending of NetMail to be free, set this value to 0.
-*/
-					uinput(WIN_MID|WIN_SAV,0,0
-						,"Cost in Credits to Send NetMail"
-						,str,10,K_EDIT|K_NUMBER);
-					inetmail_cost=atol(str);
-					break; } } }
-
-	else { /* ESC */
-		i=save_changes(WIN_MID|WIN_SAV);
-		if(i==-1)
-			continue;
-		if(!i)
-			write_msgs_cfg();
-		break; } }
-}
-
-void qhub_edit(int num)
-{
-	static int qhub_dflt;
-	char *p,done=0,str[256];
-	int i,j,k,n;
-
-while(!done) {
-	i=0;
-	sprintf(opt[i++],"%-27.27s%s","Hub System ID",qhub[num]->id);
-	sprintf(opt[i++],"%-27.27s%.40s","Pack Command Line",qhub[num]->pack);
-	sprintf(opt[i++],"%-27.27s%.40s","Unpack Command Line",qhub[num]->unpack);
-	sprintf(opt[i++],"%-27.27s%.40s","Call-out Command Line",qhub[num]->call);
-	sprintf(opt[i++],"%-27.27s%u","Call-out Node",qhub[num]->node);
-	sprintf(opt[i++],"%-27.27s%s","Call-out Days",daystr(qhub[num]->days));
-	if(qhub[num]->freq) {
-		sprintf(str,"%u times a day",1440/qhub[num]->freq);
-		sprintf(opt[i++],"%-27.27s%s","Call-out Frequency",str); }
-	else {
-		sprintf(str,"%2.2d:%2.2d",qhub[num]->time/60,qhub[num]->time%60);
-		sprintf(opt[i++],"%-27.27s%s","Call-out Time",str); }
-	strcpy(opt[i++],"Networked Sub-boards...");
-	opt[i][0]=0;
-	sprintf(str,"%s Network Hub",qhub[num]->id);
-	savnum=1;
-	SETHELP(WHERE);
-/*
-QWK Network Hub Configuration:
-
-This menu allows you to configure options specific to this QWK network
-hub.
-*/
-	switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,0,&qhub_dflt,0
-		,str,opt)) {
-		case -1:
-			done=1;
-			break;
-		case 0:
-			SETHELP(WHERE);
-/*
-QWK Network Hub System ID:
-
-This is the QWK System ID of this hub. It is used for incoming and
-outgoing network packets and must be accurate.
-*/
-			strcpy(str,qhub[num]->id);	/* save */
-			if(!uinput(WIN_MID|WIN_SAV,0,0,"QWK Network Hub System ID"
-				,qhub[num]->id,8,K_UPPER|K_EDIT))
-				strcpy(qhub[num]->id,str);
-			break;
-		case 1:
-			SETHELP(WHERE);
-/*
-REP Packet Creation Command:
-
-This is the command line to use to create (compress) REP packets for
-this QWK network hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Packet Creation"
-				,qhub[num]->pack,50,K_EDIT);
-			break;
-		case 2:
-			SETHELP(WHERE);
-/*
-QWK Packet Extraction Command:
-
-This is the command line to use to extract (decompress) QWK packets from
-this QWK network hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Packet Extraction"
-				,qhub[num]->unpack,50,K_EDIT);
-			break;
-		case 3:
-			SETHELP(WHERE);
-/*
-QWK Network Hub Call-out Command Line:
-
-This is the command line to use to initiate a call-out to this QWK
-network hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Call-out Command"
-				,qhub[num]->call,50,K_EDIT);
-			break;
-		case 4:
-			sprintf(str,"%u",qhub[num]->node);
-			SETHELP(WHERE);
-/*
-Node to Perform Call-out:
-
-This is the number of the node to perform the call-out for this QWK
-network hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0
-				,"Node to Perform Call-out",str,3,K_EDIT|K_NUMBER);
-			qhub[num]->node=atoi(str);
-			break;
-		case 5:
-			j=0;
-			while(1) {
-				for(i=0;i<7;i++)
-					sprintf(opt[i],"%s        %s"
-						,wday[i],(qhub[num]->days&(1<<i)) ? "Yes":"No");
-				opt[i][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Days to Perform Call-out:
-
-These are the days that a call-out will be performed for this QWK
-network hub.
-*/
-				i=ulist(WIN_MID,0,0,0,&j,0
-					,"Days to Perform Call-out",opt);
-				if(i==-1)
-					break;
-				qhub[num]->days^=(1<<i);
-				changes=1; }
-			break;
-		case 6:
-			i=1;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			savnum=2;
-			SETHELP(WHERE);
-/*
-Perform Call-out at a Specific Time:
-
-If you want the system call this QWK network hub at a specific time,
-set this option to Yes. If you want the system to call this network
-hub more than once a day at predetermined intervals, set this option to
-No.
-*/
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-				,"Perform Call-out at a Specific Time",opt);
-			if(i==0) {
-				sprintf(str,"%2.2d:%2.2d",qhub[num]->time/60
-					,qhub[num]->time%60);
-				SETHELP(WHERE);
-/*
-Time to Perform Call-out:
-
-This is the time (in 24 hour HH:MM format) to perform the call-out to
-this QWK network hub.
-*/
-				if(uinput(WIN_MID|WIN_SAV,0,0
-					,"Time to Perform Call-out (HH:MM)"
-					,str,5,K_UPPER|K_EDIT)>0) {
-					qhub[num]->freq=0;
-					qhub[num]->time=atoi(str)*60;
-					if((p=strchr(str,':'))!=NULL)
-						qhub[num]->time+=atoi(p+1); } }
-			else if(i==1) {
-				sprintf(str,"%u",qhub[num]->freq
-					&& qhub[num]->freq<=1440 ? 1440/qhub[num]->freq : 0);
-				SETHELP(WHERE);
-/*
-Number of Call-outs Per Day:
-
-This is the maximum number of times the system will perform a call-out
-per day to this QWK network hub. This value is actually converted by
-Synchronet into minutes between call-outs and when the BBS is idle
-and this number of minutes since the last call-out is reached, it will
-perform a call-out.
-*/
-				if(uinput(WIN_MID|WIN_SAV,0,0
-					,"Number of Call-outs Per Day"
-					,str,4,K_NUMBER|K_EDIT)>0) {
-					qhub[num]->time=0;
-					i=atoi(str);
-					if(i && i<=1440)
-						qhub[num]->freq=1440/i;
-					else
-						qhub[num]->freq=0; } }
-			break;
-		case 7:
-			qhub_sub_edit(num);
-			break; } }
-}
-
-void qhub_sub_edit(uint num)
-{
-	char str[256];
-	int i,j,k,l,m,n,bar=0;
-
-k=0;
-while(1) {
-	for(j=0;j<qhub[num]->subs;j++)
-		sprintf(opt[j],"%-*.*s %-*.*s"
-			,LEN_GSNAME,LEN_GSNAME
-			,grp[sub[qhub[num]->sub[j]]->grp]->sname
-			,LEN_SSNAME,LEN_SSNAME
-			,sub[qhub[num]->sub[j]]->sname);
-	opt[j][0]=0;
-	savnum=2;
-	j=WIN_BOT|WIN_SAV|WIN_ACT;
-	if(qhub[num]->subs<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(qhub[num]->subs)
-		j|=WIN_DEL;
-	SETHELP(WHERE);
-/*
-QWK Networked Sub-boards:
-
-This is a list of the sub-boards that are networked with this QWK
-network hub.
-
-To add a sub-board, select the desired location and hit  INS .
-
-To remove a sub-board, select it and hit  DEL .
-
-To configure a sub-board for this QWK network hub, select it and hit
- ENTER .
-*/
-	j=ulist(j,0,0,0,&k,&bar
-		,"Networked Sub-boards",opt);
-	if(j==-1)
-		break;
-	if((j&MSK_ON)==MSK_INS) {
-		j&=MSK_OFF;
-		savnum=3;
-		if((l=getsub())==-1)
-			continue;
-		savnum=3;
-		SETHELP(WHERE);
-/*
-Conference Number on Hub:
-
-This is the number of the conference on the QWK network hub, that this
-sub-board is networked with. On Synchronet systems, this number is
-derived by multiplying the group number by 10 and adding the sub-board
-number. For example, group 2, sub-board 3, is conference number 203.
-
-It is important to understand that this is NOT the conference number of
-this sub-board on your system. It is the number of the conference this
-sub-board is networked with on this QWK network hub.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0
-			,"Conference Number on Hub"
-			,str,5,K_NUMBER)<1)
-			continue;
-		strcpy(opt[0],"Strip out");
-		strcpy(opt[1],"Leave in");
-		strcpy(opt[2],"Expand to ANSI");
-		opt[3][0]=0;
-		m=0;
-		SETHELP(WHERE);
-/*
-Ctrl-A Codes:
-
-You are being prompted for the method of handling Ctrl-A attribute codes
-generated by Synchronet. If this QWK network hub is a Synchronet BBS,
-set this option to Leave in. If the QWK network hub is not a Synchronet
-BBS, but allows ANSI escape sequences in messages, set this option to
-Expand to ANSI. If the QWK network hub is not a Synchronet BBS and does
-not support ANSI escape sequences in messages (or you're not sure), set
-this option to Strip out.
-*/
-		if((m=ulist(WIN_MID|WIN_SAV,0,0,0,&m,0
-			,"Ctrl-A Codes",opt))==-1)
-			continue;
-		if((qhub[num]->sub=(ushort *)REALLOC(qhub[num]->sub
-			,sizeof(ushort *)*(qhub[num]->subs+1)))==NULL
-		|| (qhub[num]->conf=(ushort *)REALLOC(qhub[num]->conf
-            ,sizeof(ushort *)*(qhub[num]->subs+1)))==NULL
-		|| (qhub[num]->mode=(uchar *)REALLOC(qhub[num]->mode
-			,sizeof(uchar *)*(qhub[num]->subs+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,qhub[num]->subs+1);
-			continue; }
-		if(qhub[num]->subs) 			  /* insert */
-			for(n=qhub[num]->subs;n>j;n--) {
-				qhub[num]->sub[n]=qhub[num]->sub[n-1];
-				qhub[num]->conf[n]=qhub[num]->conf[n-1];
-				qhub[num]->mode[n]=qhub[num]->mode[n-1]; }
-		if(!m)
-			qhub[num]->mode[j]=A_STRIP;
-		else if(m==1)
-			qhub[num]->mode[j]=A_LEAVE;
-		else
-			qhub[num]->mode[j]=A_EXPAND;
-		qhub[num]->sub[j]=l;
-		qhub[num]->conf[j]=atoi(str);
-		qhub[num]->subs++;
-		changes=1;
-		continue; }
-	if((j&MSK_ON)==MSK_DEL) {
-		j&=MSK_OFF;
-		qhub[num]->subs--;
-		while(j<qhub[num]->subs) {
-			qhub[num]->sub[j]=qhub[num]->sub[j+1];
-			qhub[num]->mode[j]=qhub[num]->mode[j+1];
-			qhub[num]->conf[j]=qhub[num]->conf[j+1];
-			j++; }
-		changes=1;
-		continue; }
-	l=0;
-	while(1) {
-		n=0;
-		sprintf(opt[n++],"%-22.22s%.*s %.*s"
-			,"Sub-board"
-			,LEN_GSNAME
-			,grp[sub[qhub[num]->sub[j]]->grp]->sname
-			,LEN_SSNAME
-			,sub[qhub[num]->sub[j]]->sname);
-		sprintf(opt[n++],"%-22.22s%u"
-			,"Conference Number",qhub[num]->conf[j]);
-		sprintf(opt[n++],"%-22.22s%s"
-			,"Ctrl-A Codes",qhub[num]->mode[j]==A_STRIP ?
-			"Strip out" : qhub[num]->mode[j]==A_LEAVE ?
-			"Leave in" : "Expand to ANSI");
-		opt[n][0]=0;
-		savnum=3;
-		SETHELP(WHERE);
-/*
-QWK Netted Sub-board:
-
-You are configuring the options for this sub-board for this QWK network
-hub.
-*/
-		l=ulist(WIN_MID|WIN_SAV|WIN_ACT,0,0,
-			22+LEN_GSNAME+LEN_SSNAME,&l,0
-			,"Netted Sub-board",opt);
-		if(l==-1)
-			break;
-		if(!l) {
-			savnum=4;
-			m=getsub();
-			if(m!=-1) {
-				qhub[num]->sub[j]=m;
-				changes=1; } }
-		else if(l==1) {
-			savnum=4;
-			SETHELP(WHERE);
-/*
-Conference Number on Hub:
-
-This is the number of the conference on the QWK network hub, that this
-sub-board is networked with. On Synchronet systems, this number is
-derived by multiplying the group number by 10 and adding the sub-board
-number. For example, group 2, sub-board 3, is conference number 203.
-
-It is important to understand that this is NOT the conference number of
-this sub-board on your system. It is the number of the conference this
-sub-board is networked with on this QWK network hub.
-*/
-			if(uinput(WIN_MID|WIN_SAV,0,0
-				,"Conference Number on Hub"
-				,str,5,K_NUMBER)>0)
-				qhub[num]->conf[j]=atoi(str); }
-		else if(l==2) {
-			strcpy(opt[0],"Strip out");
-			strcpy(opt[1],"Leave in");
-			strcpy(opt[2],"Expand to ANSI");
-			opt[3][0]=0;
-			m=0;
-			savnum=4;
-			SETHELP(WHERE);
-/*
-Ctrl-A Codes:
-
-You are being prompted for the method of handling Ctrl-A attribute codes
-generated by Synchronet. If this QWK network hub is a Synchronet BBS,
-set this option to Leave in. If the QWK network hub is not a Synchronet
-BBS, but allows ANSI escape sequences in messages, set this option to
-Expand to ANSI. If the QWK network hub is not a Synchronet BBS and does
-not support ANSI escape sequences in messages (or you're not sure), set
-this option to Strip out.
-*/
-			m=ulist(WIN_MID|WIN_SAV,0,0,0,&m,0
-				,"Ctrl-A Codes",opt);
-			changes=1;
-			if(!m)
-				qhub[num]->mode[j]=A_STRIP;
-			else if(m==1)
-				qhub[num]->mode[j]=A_LEAVE;
-			else if(m==2)
-				qhub[num]->mode[j]=A_EXPAND; } } }
-}
-
-void phub_edit(int num)
-{
-	static int phub_dflt;
-	char *p,done=0,str[256];
-	int i,j,k,n;
-
-while(!done) {
-	i=0;
-	sprintf(opt[i++],"%-27.27s%s","Hub Site Name",phub[num]->name);
-	sprintf(opt[i++],"%-27.27s%.40s","Call-out Command Line",phub[num]->call);
-	sprintf(opt[i++],"%-27.27s%u","Call-out Node",phub[num]->node);
-	sprintf(opt[i++],"%-27.27s%s","Call-out Days",daystr(phub[num]->days));
-	if(phub[num]->freq) {
-		sprintf(str,"%u times a day",1440/phub[num]->freq);
-		sprintf(opt[i++],"%-27.27s%s","Call-out Frequency",str); }
-	else {
-		sprintf(str,"%2.2d:%2.2d",phub[num]->time/60
-			,phub[num]->time%60);
-		sprintf(opt[i++],"%-27.27s%s","Call-out Time",str); }
-	opt[i][0]=0;
-	sprintf(str,"%s Network Hub",phub[num]->name);
-	savnum=1;
-	SETHELP(WHERE);
-/*
-PostLink Network Hub Configuration:
-
-This menu allows you to configure options specific to this network hub.
-*/
-	switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,0,&phub_dflt,0
-		,str,opt)) {
-		case -1:
-			done=1;
-			break;
-		case 0:
-			SETHELP(WHERE);
-/*
-Network Hub Site Name:
-
-This is the Site Name of this hub. It is used for only for reference.
-*/
-			strcpy(str,phub[num]->name);	/* save */
-			if(!uinput(WIN_MID|WIN_SAV,0,0,"Hub Site Name"
-				,phub[num]->name,10,K_UPPER|K_EDIT))
-				strcpy(phub[num]->name,str);	/* restore */
-			break;
-		case 1:
-			SETHELP(WHERE);
-/*
-Network Hub Call-out Command Line:
-
-This is the command line to use to initiate a call-out to this network
-hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Call-out Command"
-				,phub[num]->call,50,K_EDIT);
-			break;
-		case 2:
-			sprintf(str,"%u",phub[num]->node);
-			SETHELP(WHERE);
-/*
-Node to Perform Call-out:
-
-This is the number of the node to perform the call-out for this network
-hub.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0
-				,"Node to Perform Call-out",str,3,K_EDIT|K_NUMBER);
-			phub[num]->node=atoi(str);
-			break;
-		case 3:
-			j=0;
-			while(1) {
-				for(i=0;i<7;i++)
-					sprintf(opt[i],"%s        %s"
-						,wday[i],(phub[num]->days&(1<<i)) ? "Yes":"No");
-				opt[i][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Days to Perform Call-out:
-
-These are the days that a call-out will be performed for this network
-hub.
-*/
-				i=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-					,"Days to Perform Call-out",opt);
-				if(i==-1)
-					break;
-				phub[num]->days^=(1<<i);
-				changes=1; }
-			break;
-		case 4:
-			i=1;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			savnum=2;
-			SETHELP(WHERE);
-/*
-Perform Call-out at a Specific Time:
-
-If you want the system call this network hub at a specific time, set
-this option to Yes. If you want the system to call this hub more than
-once a day at predetermined intervals, set this option to No.
-*/
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-				,"Perform Call-out at a Specific Time",opt);
-			if(i==0) {
-				sprintf(str,"%2.2d:%2.2d",phub[num]->time/60
-					,phub[num]->time%60);
-				SETHELP(WHERE);
-/*
-Time to Perform Call-out:
-
-This is the time (in 24 hour HH:MM format) to perform the call-out to
-this network hub.
-*/
-				if(uinput(WIN_MID|WIN_SAV,0,0
-					,"Time to Perform Call-out (HH:MM)"
-					,str,5,K_UPPER|K_EDIT)>0) {
-					phub[num]->freq=0;
-					phub[num]->time=atoi(str)*60;
-					if((p=strchr(str,':'))!=NULL)
-						phub[num]->time+=atoi(p+1); } }
-			else if(i==1) {
-				sprintf(str,"%u",phub[num]->freq
-					&& phub[num]->freq<=1440 ? 1440/phub[num]->freq : 0);
-				SETHELP(WHERE);
-/*
-Number of Call-outs Per Day:
-
-This is the maximum number of times the system will perform a call-out
-per day to this network hub. This value is actually converted by
-Synchronet into minutes between call-outs and when the BBS is idle
-and this number of minutes since the last call-out is reached, it will
-perform a call-out.
-*/
-				if(uinput(WIN_MID|WIN_SAV,0,0
-					,"Number of Call-outs Per Day"
-					,str,4,K_NUMBER|K_EDIT)>0) {
-					phub[num]->time=0;
-					i=atoi(str);
-					if(i && i<=1440)
-						phub[num]->freq=1440/i;
-					else
-						phub[num]->freq=0; } }
-			break; } }
-}
-
-char *daystr(char days)
-{
-	static char str[256];
-	int i;
-
-str[0]=0;
-for(i=0;i<7;i++) {
-	if(days&(1<<i))
-		strcat(str,wday[i]);
-	else
-		strcat(str,"   ");
-	strcat(str," "); }
-return(str);
-}
diff --git a/src/sbbs2/scfg/scfgnode.c b/src/sbbs2/scfg/scfgnode.c
deleted file mode 100644
index ddb9155e8578a727cd5beccd08f72cab4fef4ad3..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgnode.c
+++ /dev/null
@@ -1,2163 +0,0 @@
-#line 2 "SCFGNODE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************************************/
-/* Synchronet configuration utility 										*/
-/****************************************************************************/
-
-#include "scfg.h"
-#include "spawno.h"
-
-int com_type()
-{
-	int i;
-
-i=0;
-strcpy(opt[0],"UART");
-strcpy(opt[1],"FOSSIL Int 14h");
-strcpy(opt[2],"PC BIOS Int 14h");
-strcpy(opt[3],"PS/2 BIOS Int 14h");
-strcpy(opt[4],"DigiBoard Int 14h");
-opt[5][0]=0;
-SETHELP(WHERE);
-/*
-COM Port Type:
-
-Select the type of serial COM port for this node. If you are unsure,
-select UART. If you have a FOSSIL driver installed, you do not have to
-select FOSSIL unless you specifically want to override Synchronet's
-internal COM functions.
-*/
-i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-	,"COM Port Type",opt);
-if(i==-1)
-	return(0);
-changes=1;
-if(i) {
-	com_irq=com_port-1;
-	if(i==1) {
-		savnum=0;
-		umsg("WARNING: This is not a recommended setting for most systems");
-		umsg("The default DSZ command lines will not work with this setting");
-		com_base=0xf; }
-	else if(i==2)
-		com_base=0xb;
-	else if(i==3)
-		com_base=0xe;
-	else if(i==4)
-		com_base=0xd; }
-
-else {	/* UART */
-	if(com_port && com_port<5) {
-		i=0;
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		SETHELP(WHERE);
-/*
-Use Default UART IRQ and I/O Address:
-
-If your COM Port's UART is using the normal IRQ and Base I/O Address
-for the configured COM Port number, select Yes. If your COM Port
-is using a non-standard IRQ or I/O Address, select No and be sure
-to set the UART IRQ and UART I/O Address options. If you are not
-sure what IRQ and I/O Address your COM Port is using, select Yes.
-*/
-		i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-			,"Use Default UART IRQ and I/O Address"
-			,opt);
-		if(i==0) {
-			switch(com_port) {
-				case 1:
-					com_irq=4;
-					com_base=0x3f8;
-					break;
-				case 2:
-					com_irq=3;
-					com_base=0x2f8;
-					break;
-				case 3:
-					com_irq=4;
-					com_base=0x3e8;
-					break;
-				case 4:
-					com_irq=3;
-					com_base=0x2e8;
-					break; }
-			changes=1;
-			return(1); } }
-	else {
-		if(com_base<0x100)
-			com_base=0x100;
-		if(com_irq<2 || com_irq>15)
-			com_irq=5; } }
-return(0);
-}
-
-void node_menu()
-{
-	char	done,str[81],savnode=0;
-	int 	i,j;
-	static int node_menu_dflt,node_bar;
-
-while(1) {
-	for(i=0;i<sys_nodes;i++)
-		sprintf(opt[i],"Node %d",i+1);
-	opt[i][0]=0;
-	j=WIN_ORG|WIN_ACT|WIN_INSACT|WIN_DELACT;
-	if(sys_nodes>1)
-		j|=WIN_DEL|WIN_GET;
-	if(sys_nodes<MAX_NODES && sys_nodes<MAX_OPTS)
-		j|=WIN_INS;
-	if(savnode)
-		j|=WIN_PUT;
-SETHELP(WHERE);
-/*
-Node List:
-
-This is the list of configured nodes in your system.
-
-To add a node, hit  INS .
-
-To delete a node, hit  DEL .
-
-To configure a node, select it using the arrow keys and hit  ENTER .
-
-To copy a node's configuration to another node, first select the source
-node with the arrow keys and hit  F5 . Then select the destination
-node and hit  F6 .
-*/
-
-	i=ulist(j,0,0,13,&node_menu_dflt,&node_bar,"Nodes",opt);
-	if(i==-1) {
-		if(savnode) {
-			free_node_cfg();
-			savnode=0; }
-		return; }
-
-	if((i&MSK_ON)==MSK_DEL) {
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		sprintf(str,"Delete Node %d",sys_nodes);
-		i=1;
-SETHELP(WHERE);
-/*
-Delete Node:
-
-If you are positive you want to delete this node, select Yes. Otherwise,
-select No or hit  ESC .
-*/
-		i=ulist(WIN_MID,0,0,0,&i,0,str,opt);
-		if(!i) {
-			--sys_nodes;
-			FREE(node_path[sys_nodes]);
-			write_main_cfg(); }
-		continue; }
-	if((i&MSK_ON)==MSK_INS) {
-		strcpy(node_dir,node_path[sys_nodes-1]);
-		i=sys_nodes+1;
-		upop("Reading NODE.CNF...");
-		read_node_cfg(txt);
-		upop(0);
-		sprintf(str,"..\\NODE%d\\",i);
-		sprintf(tmp,"Node %d Path",i);
-SETHELP(WHERE);
-/*
-Node Path:
-
-This is the path to this node's private directory where its separate
-configuration and data files are stored.
-
-The drive and directory of this path can be set to any valid DOS
-directory that can be accessed by ALL nodes and MUST NOT be on a RAM disk
-or other volatile media.
-
-If you want to abort the creation of this new node, hit  ESC .
-*/
-		j=uinput(WIN_MID,0,0,tmp,str,50,K_EDIT|K_UPPER);
-		changes=0;
-		if(j<2)
-			continue;
-		truncsp(str);
-		if((node_path=(char **)REALLOC(node_path,sizeof(char *)*(sys_nodes+1)))
-			==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sys_nodes+1);
-			continue; }
-		if((node_path[i-1]=MALLOC(strlen(str)+2))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,str,strlen(str)+2);
-			continue; }
-		strcpy(node_path[i-1],str);
-		if(str[strlen(str)-1]=='\\')
-			str[strlen(str)-1]=0;
-		mkdir(str);
-		node_num=++sys_nodes;
-		sprintf(node_name,"Node %u",node_num);
-		write_node_cfg();
-		write_main_cfg();
-		free_node_cfg();
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		if(savnode)
-			free_node_cfg();
-		i&=MSK_OFF;
-		strcpy(node_dir,node_path[i]);
-		upop("Reading NODE.CNF...");
-		read_node_cfg(txt);
-		upop(0);
-		savnode=1;
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		strcpy(node_dir,node_path[i]);
-		node_num=i+1;
-		write_node_cfg();
-		changes=1;
-		continue; }
-
-	if(savnode) {
-		free_node_cfg();
-		savnode=0; }
-	strcpy(node_dir,node_path[i]);
-	upop("Reading NODE.CNF...");
-	read_node_cfg(txt);
-	upop(0);
-	if(node_num!=i+1) { 	/* Node number isn't right? */
-		node_num=i+1;		/* so fix it */
-		write_node_cfg(); } /* and write it back */
-	node_cfg();
-
-	free_node_cfg(); }
-}
-
-void node_cfg()
-{
-	static	int node_dflt;
-	char	done,str[81];
-	static	int mdm_dflt,adv_dflt,tog_dflt,tog_bar;
-	int 	i,j,dflt=0,bar=0;
-
-while(1) {
-	i=0;
-	sprintf(opt[i++],"%-27.27s%s","Name",node_name);
-	sprintf(opt[i++],"%-27.27s%s","Phone Number",node_phone);
-	sprintf(opt[i++],"%-27.27s%ubps","Minimum Connect Rate",node_minbps);
-	sprintf(opt[i++],"%-27.27s%.40s","Logon Requirements",node_ar);
-	sprintf(opt[i++],"%-27.27s%.40s","Local Text Editor",node_editor);
-	sprintf(opt[i++],"%-27.27s%.40s","Local Text Viewer",node_viewer);
-	sprintf(opt[i++],"%-27.27s%.40s","Configuration Command",scfg_cmd);
-	sprintf(opt[i++],"%-27.27s%.40s","DOS Command Interpreter"
-		,node_comspec[0] ? node_comspec : "%COMSPEC%");
-	strcpy(opt[i++],"Toggle Options...");
-	strcpy(opt[i++],"Advanced Options...");
-	strcpy(opt[i++],"Modem Configuration...");
-	strcpy(opt[i++],"Wait for Call Number Keys...");
-	strcpy(opt[i++],"Wait for Call Function Keys...");
-	opt[i][0]=0;
-	sprintf(str,"Node %d Configuration",node_num);
-SETHELP(WHERE);
-/*
-Node Configuration Menu:
-
-This is the node configuration menu. The options available from this
-menu will only affect the selected node's configuration.
-
-Options with a trailing ... will produce a sub-menu of more options.
-*/
-	switch(ulist(WIN_ACT|WIN_CHE|WIN_BOT|WIN_RHT,0,0,60,&node_dflt,0
-		,str,opt)) {
-		case -1:
-			i=save_changes(WIN_MID);
-			if(!i)
-				write_node_cfg();
-			if(i!=-1)
-				return;
-			break;
-		case 0:
-SETHELP(WHERE);
-/*
-Node Name:
-
-This is the name of the selected node. It is used for documentary
-purposes only.
-*/
-			uinput(WIN_MID|WIN_SAV,0,10,"Name",node_name,40,K_EDIT);
-			break;
-		case 1:
-SETHELP(WHERE);
-/*
-Node Phone Number:
-
-This is the phone number to access the selected node. It is used for
-documentary purposes only.
-*/
-			uinput(WIN_MID|WIN_SAV,0,10,"Phone Number",node_phone,12,K_EDIT);
-			break;
-		case 2:
-SETHELP(WHERE);
-/*
-Minimum Connect Rate:
-
-This is the lowest modem connection speed allowed for the selected node.
-The speed is a decimal number representing bits per second (bps) or more
-inaccurately referred to as baud.
-
-If a user attempts to logon this node at a speed lower than the minimum
-connect rate, a message is displayed explaining the minimum connect
-rate and the user is disconnected.
-
-If the file TEXT\TOOSLOW.MSG exists, it will be displayed to the user
-before the user is disconnected.
-
-Users with the M exemption can log onto any node at any speed.
-*/
-			sprintf(str,"%u",node_minbps);
-			uinput(WIN_MID|WIN_SAV,0,10,"Minimum Connect Rate",str,5
-				,K_NUMBER|K_EDIT);
-			node_minbps=atoi(str);
-			break;
-		case 3:
-			sprintf(str,"Node %u Logon",node_num);
-			getar(str,node_ar);
-			break;
-		case 4:
-SETHELP(WHERE);
-/*
-Local Text Editor:
-
-This is the command line to execute to edit text files locally in
-Synchronet. If this command line is blank, the default editor of the
-sysop (user #1) will be used.
-
-This command line can be used to create posts and e-mail locally, if the
-toggle option Use Editor for Messages is set to Yes.
-
-The %f command line specifier is used for the filename to edit.
-*/
-			uinput(WIN_MID|WIN_SAV,0,13,"Editor",node_editor
-				,50,K_EDIT);
-			break;
-		case 5:
-SETHELP(WHERE);
-/*
-Local Text Viewer:
-
-This is the command line used to view log files from the wait for call
-screen.
-
-The %f command line specifier is used for the filename to view.
-*/
-			uinput(WIN_MID|WIN_SAV,0,14,"Viewer",node_viewer
-				,50,K_EDIT);
-			break;
-		case 6:
-SETHELP(WHERE);
-/*
-Configuration Command Line:
-
-This is the command line used to launch the Synchronet configuration
-program (SCFG) from this node's Waiting for Call (WFC) screen.
-*/
-			uinput(WIN_MID|WIN_SAV,0,14,"Configuration Command",scfg_cmd
-				,40,K_EDIT);
-            break;
-		case 7:
-SETHELP(WHERE);
-/*
-DOS Command Interpreter:
-
-This is the complete path to your DOS command interpreter (normally
-COMMAND.COM). Leaving this option blank (designated by %COMSPEC%)
-specifies that the path contained in the COMSPEC environment variable
-should be used.
-
-When running Synchronet for OS/2, this option should be set to:
-C:\OS2\MDOS\COMMAND.COM.
-*/
-			uinput(WIN_MID|WIN_SAV,0,14,"DOS Command Interpreter"
-				,node_comspec,40,K_EDIT);
-            break;
-		case 8:
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%s","Alarm When Answering"
-					,node_misc&NM_ANSALARM ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Status Screen While WFC"
-					,node_misc&NM_WFCSCRN ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Total Msgs/Files on WFC"
-					,node_misc&NM_WFCMSGS ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Use Editor for Messages"
-					,node_misc&NM_LCL_EDIT ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Use EMS for Overlays"
-					,node_misc&NM_EMSOVL ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Allow Swapping"
-                    ,node_swap&SWAP_NONE ? "No":"Yes");
-                sprintf(opt[i++],"%-27.27s%s","Swap to EMS Memory"
-					,node_swap&SWAP_EMS ? "Yes":"No");
-                sprintf(opt[i++],"%-27.27s%s","Swap to XMS Memory"
-					,node_swap&SWAP_XMS ? "Yes":"No");
-                sprintf(opt[i++],"%-27.27s%s","Swap to Extended Memory"
-					,node_swap&SWAP_EXT ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Windows/OS2 Time Slice API"
-					,node_misc&NM_WINOS2 ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","DESQview Time Slice API"
-					,node_misc&NM_NODV ? "No":"Yes");
-				sprintf(opt[i++],"%-27.27s%s","DOS Idle Interrupts"
-					,node_misc&NM_INT28 ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Low Priority String Input"
-					,node_misc&NM_LOWPRIO ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Allow Logon by Number"
-					,node_misc&NM_NO_NUM ? "No":"Yes");
-				sprintf(opt[i++],"%-27.27s%s","Allow Logon by Real Name"
-					,node_misc&NM_LOGON_R ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Always Prompt for Password"
-					,node_misc&NM_LOGON_P ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Disable Local Inactivity"
-					,node_misc&NM_NO_INACT ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Disable Local Keyboard"
-                    ,node_misc&NM_NO_LKBRD ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Local System Protection"
-					,node_misc&NM_SYSPW ? "Yes":"No");
-				sprintf(opt[i++],"%-27.27s%s","Beep Locally"
-					,node_misc&NM_NOBEEP ? "No":"Yes");
-				sprintf(opt[i++],"%-27.27s%s","Allow 8-bit Remote Logons"
-					,node_misc&NM_7BITONLY ? "No":"Yes");
-				sprintf(opt[i++],"%-27.27s%s","Reset Video Between Calls"
-					,node_misc&NM_RESETVID ? "Yes":"No");
-
-				opt[i][0]=0;
-				savnum=0;
-SETHELP(WHERE);
-/*
-Node Toggle Options:
-
-This is the toggle options menu for the selected node's configuration.
-
-The available options from this menu can all be toggled between two or
-more states, such as Yes and No.
-*/
-				switch(ulist(WIN_BOT|WIN_RHT|WIN_ACT|WIN_SAV,3,2,35,&tog_dflt
-					,&tog_bar,"Toggle Options",opt)) {
-					case -1:
-						done=1;
-						break;
-					case 0:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-SETHELP(WHERE);
-/*
-Alarm When Answering:
-
-Set this option to Yes if want this node to make an alarm sound each
-time it answers an incoming call. Usually, the modem's speaker is a
-sufficient alarm if one is desired.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,15,0,&i,0
-							,"Sound Alarm When Answering",opt);
-						if(i==0 && !(node_misc&NM_ANSALARM)) {
-							node_misc|=NM_ANSALARM;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_ANSALARM)) {
-							node_misc&=~NM_ANSALARM;
-							changes=1; }
-						break;
-					case 1:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-SETHELP(WHERE);
-/*
-Status Screen While WFC:
-
-If you want the current system statistics and current status of all
-active nodes to be displayed while this node is waiting for a caller,
-set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Display Status Screen While Waiting for Call",opt);
-						if(i==0 && !(node_misc&NM_WFCSCRN)) {
-							node_misc|=NM_WFCSCRN;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_WFCSCRN)) {
-							node_misc&=~NM_WFCSCRN;
-							changes=1; }
-						break;
-					case 2:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-SETHELP(WHERE);
-/*
-Total Messages and Files on WFC Status Screen:
-
-If you want the total number of messages and files to be retrieved
-and displayed on the WFC status screen, set this option to Yes.
-
-Setting this option to No will significantly reduce the amount of
-time required to retrieve the system statistics on systems with large
-numbers of message and file areas.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Display Total Messages and Files while WFC",opt);
-						if(i==0 && !(node_misc&NM_WFCMSGS)) {
-							node_misc|=(NM_WFCMSGS|NM_WFCSCRN);
-							changes=1; }
-						else if(i==1 && (node_misc&NM_WFCMSGS)) {
-							node_misc&=~NM_WFCMSGS;
-							changes=1; }
-                        break;
-					case 3:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-SETHELP(WHERE);
-/*
-Use Local Text Editor for Messages:
-
-If a local text editor command has been specified, it can be used to
-create messages (posts and e-mail) locally by setting this option to
-Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Use Local Text Editor to Create Messages",opt);
-						if(i==0 && !(node_misc&NM_LCL_EDIT)) {
-							node_misc|=NM_LCL_EDIT;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_LCL_EDIT)) {
-							node_misc&=~NM_LCL_EDIT;
-							changes=1; }
-						break;
-					case 4:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-SETHELP(WHERE);
-/*
-Use Available Expanded Memory (EMS) for Swapping Overlays:
-
-If you wish to use any available expanded memory (EMS) for swapping
-overlays, set this option to Yes. Swapping overlays to memory is much
-faster than swapping to disk.
-
-If this option is set to Yes, Synchronet will attempt to allocation 360K
-of EMS for swapping overlays into.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Use Available EMS for Overlays",opt);
-						if(i==0 && !(node_misc&NM_EMSOVL)) {
-							node_misc|=NM_EMSOVL;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_EMSOVL)) {
-							node_misc&=~NM_EMSOVL;
-							changes=1; }
-						break;
-					case 5:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-                        SETHELP(WHERE);
-/*
-Allow Swapping:
-
-If this option is set to Yes, Synchronet will use one of the available
-Swap to options when swapping out of memory.	If you have no Extended,
-EMS, or XMS memory available, and this option is set to Yes, Synchronet
-will swap to disk.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Allow Swapping",opt);
-						if(i==0 && node_swap&SWAP_NONE) {
-							node_swap&=~SWAP_NONE;
-							changes=1; }
-						else if(i==1 && !(node_swap&SWAP_NONE)) {
-							node_swap|=SWAP_NONE;
-							changes=1; }
-                        break;
-					case 6:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-                        SETHELP(WHERE);
-/*
-Swap to EMS Memory:
-
-If this option is set to Yes, and the Allow Swapping option is set to
-Yes Synchronet will use EMS memory (when available) for swapping out
-of memory.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Swap to EMS Memory",opt);
-						if(i==1 && node_swap&SWAP_EMS) {
-							node_swap&=~SWAP_EMS;
-							changes=1; }
-						else if(i==0 && !(node_swap&SWAP_EMS)) {
-							node_swap|=SWAP_EMS;
-							changes=1; }
-                        break;
-					case 7:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-                        SETHELP(WHERE);
-/*
-Swap to XMS Memory:
-
-If this option is set to Yes, and the Allow Swapping option is set to
-Yes Synchronet will use XMS memory (when available) for swapping out
-of memory.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Swap to XMS Memory",opt);
-						if(i==1 && node_swap&SWAP_XMS) {
-							node_swap&=~SWAP_XMS;
-							changes=1; }
-						else if(i==0 && !(node_swap&SWAP_XMS)) {
-							node_swap|=SWAP_XMS;
-							changes=1; }
-                        break;
-					case 8:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-                        SETHELP(WHERE);
-/*
-Swap to Extended Memory:
-
-If this option is set to Yes, and the Allow Swapping option is set to
-Yes Synchronet will use non-XMS Extended memory (when available) for
-swapping out of memory.
-
-If you are running under a DOS multitasker (e.g. Windows, DESQview, or
-OS/2) set this option to No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Swap to Extended Memory",opt);
-						if(i==1 && node_swap&SWAP_EXT) {
-							node_swap&=~SWAP_EXT;
-							changes=1; }
-						else if(i==0 && !(node_swap&SWAP_EXT)) {
-							node_swap|=SWAP_EXT;
-							changes=1; }
-                        break;
-					case 9:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Windows/OS2 Time Slice API:
-
-If you wish to have Synchronet specifically use the Windows and OS/2
-API call to surrender time slices when in a low priority task, set this
-option to Yes. If setting this option to Yes causes erratic pauses
-or performance problems, leave the option on No. This type of behavior
-has been witnessed under Windows 3.1 when using this API call.
-
-If running in an OS/2 DOS session, you will most likely want this
-option set to Yes for the best aggregate performance for your system.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Use Windows/OS2 Time Slice API",opt);
-						if(i==0 && !(node_misc&NM_WINOS2)) {
-							node_misc|=NM_WINOS2;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_WINOS2)) {
-							node_misc&=~NM_WINOS2;
-							changes=1; }
-                        break;
-					case 10:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-DESQview Time Slice API:
-
-If this option is set to Yes, and this node is run under DESQview,
-Synchronet will use the DESQview Time Slice API calls for intelligent
-variable time slicing.
-
-Since Synchronet automatically detects DESQview, there is no harm in
-having this option set to Yes if you are not running DESQview. Only set
-this option to No, if you wish to disable the DESQview API for some
-reason.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"DESQview Time Slice API",opt);
-						if(i==0 && node_misc&NM_NODV) {
-							node_misc&=~NM_NODV;
-							changes=1; }
-						else if(i==1 && !(node_misc&NM_NODV)) {
-							node_misc|=NM_NODV;
-							changes=1; }
-                        break;
-					case 11:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-DOS Idle Interrupts:
-
-If you want Synchronet to make DOS Idle Interrupts when waiting for user
-input or in other low priority loops, set this option to Yes.
-
-For best aggregate multinode performance under multitaskers, you should
-set this option to Yes.
-
-For best single node performance under multitaskers, you should set this
-option to No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"DOS Idle Interrupts",opt);
-						if(i==0 && !(node_misc&NM_INT28)) {
-							node_misc|=NM_INT28;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_INT28)) {
-							node_misc&=~NM_INT28;
-							changes=1; }
-                        break;
-					case 12:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Low Priority String Input:
-
-Normally, Synchronet will not give up time slices (under a multitasker)
-when users are prompted for a string of characters. This is considered
-a high priority task.
-
-Setting this option to Yes will force Synchronet to give up time slices
-during string input, possibly causing jerky keyboard input from the
-user, but improving aggregate system performance under multitaskers.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Low Priority String Input",opt);
-						if(i==0 && !(node_misc&NM_LOWPRIO)) {
-							node_misc|=NM_LOWPRIO;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_LOWPRIO)) {
-							node_misc&=~NM_LOWPRIO;
-							changes=1; }
-                        break;
-					case 13:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Allow Logon by Number:
-
-If you want users to be able logon using their user number at the NN:
-set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Allow Logon by Number",opt);
-						if(i==0 && node_misc&NM_NO_NUM) {
-							node_misc&=~NM_NO_NUM;
-							changes=1; }
-						else if(i==1 && !(node_misc&NM_NO_NUM)) {
-							node_misc|=NM_NO_NUM;
-							changes=1; }
-                        break;
-					case 14:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Allow Logon by Real Name:
-
-If you want users to be able logon using their real name as well as
-their alias, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Allow Logon by Real Name",opt);
-						if(i==0 && !(node_misc&NM_LOGON_R)) {
-							node_misc|=NM_LOGON_R;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_LOGON_R)) {
-							node_misc&=~NM_LOGON_R;
-							changes=1; }
-                        break;
-					case 15:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Always Prompt for Password:
-
-If you want to have attempted logons using an unknown user name still
-prompt for a password, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Always Prompt for Password",opt);
-						if(i==0 && !(node_misc&NM_LOGON_P)) {
-							node_misc|=NM_LOGON_P;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_LOGON_P)) {
-							node_misc&=~NM_LOGON_P;
-							changes=1; }
-                        break;
-					case 16:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Disable Local Inactivity Warning/Logoff:
-
-Setting this option to Yes will disable the user inactivity warning
-and automatic logoff for local logons.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Disable Local Inactivity",opt);
-						if(i==0 && !(node_misc&NM_NO_INACT)) {
-							node_misc|=NM_NO_INACT;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_NO_INACT)) {
-							node_misc&=~NM_NO_INACT;
-							changes=1; }
-                        break;
-					case 17:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Disable Local Keyboard (Entirely):
-
-Setting this option to Yes will disable the local keyboard when the
-BBS is running. Use this option only for the absolute highest degree
-of local system security. If this option is set to Yes, the BBS cannot
-be exited until the node is downed from another process or the machine
-is rebooted.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Disable Local Keyboard (Entirely)",opt);
-						if(i==0 && !(node_misc&NM_NO_LKBRD)) {
-							node_misc|=NM_NO_LKBRD;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_NO_LKBRD)) {
-							node_misc&=~NM_NO_LKBRD;
-							changes=1; }
-                        break;
-					case 18:
-						i=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Local System Protection:
-
-When this option is set to Yes, all local system functions from the
-Waiting for Call screen and Alt-Key combinations will require the user
-to enter the system password.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Local System Protection (Password)",opt);
-						if(i==0 && !(node_misc&NM_SYSPW)) {
-							node_misc|=NM_SYSPW;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_SYSPW)) {
-							node_misc&=~NM_SYSPW;
-							changes=1; }
-                        break;
-					case 19:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Beep Locally:
-
-If you want the local speaker to be disabled for online beeps, set this
-option to No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Beep Locally",opt);
-						if(i==1 && !(node_misc&NM_NOBEEP)) {
-							node_misc|=NM_NOBEEP;
-							changes=1; }
-						else if(i==0 && (node_misc&NM_NOBEEP)) {
-							node_misc&=~NM_NOBEEP;
-							changes=1; }
-                        break;
-					case 20:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Allow 8-bit Remote Input During Logon:
-
-If you wish to allow E-7-1 terminals to use this node, you must set this
-option to No. This will also eliminate the ability of 8-bit remote users
-to send IBM extended ASCII characters during the logon sequence.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Allow 8-bit Remote Input During Logon",opt);
-						if(i==1 && !(node_misc&NM_7BITONLY)) {
-							node_misc|=NM_7BITONLY;
-							changes=1; }
-						else if(i==0 && (node_misc&NM_7BITONLY)) {
-							node_misc&=~NM_7BITONLY;
-							changes=1; }
-                        break;
-					case 21:
-						i=0;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						savnum=1;
-						SETHELP(WHERE);
-/*
-Reset Video Mode Between Calls:
-
-If you wish to have SBBS reset the video mode between calls, set this
-option to Yes. This is to reverse the effects of some external programs
-that change the video mode without permission.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,10,0,&i,0
-							,"Reset Video Mode Beteween Calls",opt);
-						if(i==0 && !(node_misc&NM_RESETVID)) {
-							node_misc|=NM_RESETVID;
-							changes=1; }
-						else if(i==1 && (node_misc&NM_RESETVID)) {
-							node_misc&=~NM_RESETVID;
-							changes=1; }
-                        break;
-						} }
-			break;
-		case 9:
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%s","Validation User"
-					,node_valuser ? itoa(node_valuser,tmp,10) : "Nobody");
-				sprintf(opt[i++],"%-27.27s%s","Screen Length"
-					,node_scrnlen ? itoa(node_scrnlen,tmp,10)
-					: "Auto-Detect");
-				sprintf(opt[i++],"%-27.27s%s","Screen Blanker"
-					,node_scrnblank ? itoa(node_scrnblank,tmp,10)
-					: "Disabled");
-				sprintf(opt[i++],"%-27.27s%u seconds","Semaphore Frequency"
-					,node_sem_check);
-				sprintf(opt[i++],"%-27.27s%u seconds","Statistics Frequency"
-					,node_stat_check);
-				sprintf(opt[i++],"%-27.27s%u seconds","Inactivity Warning"
-					,sec_warn);
-				sprintf(opt[i++],"%-27.27s%u seconds","Inactivity Disconnection"
-					,sec_hangup);
-				sprintf(tmp,"$%d.00",node_dollars_per_call);
-				sprintf(opt[i++],"%-27.27s%s","Cost Per Call",tmp);
-				sprintf(opt[i++],"%-27.27s%.40s","Daily Event",node_daily);
-				sprintf(opt[i++],"%-27.27s%.40s","Control Directory",ctrl_dir);
-				sprintf(opt[i++],"%-27.27s%.40s","Text Directory",text_dir);
-				sprintf(opt[i++],"%-27.27s%.40s","Temporary Directory"
-					,temp_dir);
-				sprintf(opt[i++],"%-27.27s%.40s","Swap Directory"
-					,node_swapdir);
-				opt[i][0]=0;
-				savnum=0;
-SETHELP(WHERE);
-/*
-Node Advanced Options:
-
-This is the advanced options menu for the selected node. The available
-options are of an advanced nature and should not be modified unless you
-are sure of the consequences and necessary preparation.
-*/
-				switch(ulist(WIN_T2B|WIN_RHT|WIN_ACT|WIN_SAV,2,0,60,&adv_dflt,0
-					,"Advanced Options",opt)) {
-                    case -1:
-						done=1;
-                        break;
-					case 0:
-						itoa(node_valuser,str,10);
-SETHELP(WHERE);
-/*
-Validation User Number:
-
-When a caller logs onto the system as New, he or she must send
-validation feedback to the sysop. This feature can be disabled by
-setting this value to 0, allowing new users to logon without sending
-validation feedback. If you want new users on this node to be forced to
-send validation feedback, set this value to the number of the user to
-whom the feedback is sent. The normal value of this option is 1 for
-user number one.
-*/
-						uinput(WIN_MID,0,13,"Validation User Number (0=Nobody)"
-							,str,4,K_NUMBER|K_EDIT);
-						node_valuser=atoi(str);
-						break;
-					case 1:
-						itoa(node_scrnlen,str,10);
-SETHELP(WHERE);
-/*
-Screen Length:
-
-Synchronet automatically senses the number of lines on your display and
-uses all of them. If for some reason you want to override the detected
-screen length, set this value to the number of lines (rows) you want
-Synchronet to use.
-*/
-						uinput(WIN_MID,0,14,"Screen Length (0=Auto-Detect)"
-							,str,2,K_NUMBER|K_EDIT);
-						node_scrnlen=atoi(str);
-						break;
-					case 2:
-						itoa(node_scrnblank,str,10);
-SETHELP(WHERE);
-/*
-Screen Blanker:
-
-This option allows you to have this node blank its Waiting for Call
-screen after this number of minutes of inactivity. Setting this option
-to 0 disables the screen blanker.
-*/
-						uinput(WIN_MID|WIN_SAV,0,14
-							,"Minutes Inactive Before Blanking Screen "
-							"(0=Disabled)"
-							,str,2,K_NUMBER|K_EDIT);
-						node_scrnblank=atoi(str);
-                        break;
-					case 3:
-						itoa(node_sem_check,str,10);
-SETHELP(WHERE);
-/*
-Semaphore Check Frequency While Waiting for Call (in seconds):
-
-This is the number of seconds between semaphore checks while this node
-is waiting for a caller. Default is 60 seconds.
-*/
-						uinput(WIN_MID|WIN_SAV,0,14
-							,"Seconds Between Semaphore Checks"
-							,str,3,K_NUMBER|K_EDIT);
-						node_sem_check=atoi(str);
-                        break;
-					case 4:
-						itoa(node_stat_check,str,10);
-SETHELP(WHERE);
-/*
-Statistics Check Frequency While Waiting for Call (in seconds):
-
-This is the number of seconds between static checks while this node
-is waiting for a caller. Default is 10 seconds.
-*/
-						uinput(WIN_MID|WIN_SAV,0,14
-							,"Seconds Between Statistic Checks"
-							,str,3,K_NUMBER|K_EDIT);
-						node_stat_check=atoi(str);
-                        break;
-					case 5:
-						itoa(sec_warn,str,10);
-SETHELP(WHERE);
-/*
-Seconds Before Inactivity Warning:
-
-This is the number of seconds the user must be inactive before a
-warning will be given. Default is 180 seconds.
-*/
-						uinput(WIN_MID|WIN_SAV,0,14
-							,"Seconds Before Inactivity Warning"
-							,str,4,K_NUMBER|K_EDIT);
-						sec_warn=atoi(str);
-                        break;
-					case 6:
-						itoa(sec_hangup,str,10);
-SETHELP(WHERE);
-/*
-Seconds Before Inactivity Disconnection:
-
-This is the number of seconds the user must be inactive before they
-will be automatically disconnected. Default is 300 seconds.
-*/
-						uinput(WIN_MID|WIN_SAV,0,14
-							,"Seconds Before Inactivity Disconnection"
-							,str,4,K_NUMBER|K_EDIT);
-						sec_hangup=atoi(str);
-                        break;
-					case 7:
-						itoa(node_dollars_per_call,str,10);
-SETHELP(WHERE);
-/*
-Billing Node Cost Per Call:
-
-If you have an automated billing phone number (usually area code 900
-or prefix 976) and you wish to use this node as an automated billing
-node, set this value to the dollar amount that is billed for the first
-minute. Subsequent minutes should be charged the minimum amount as the
-maximum connect time for a billing node is 90 seconds.
-
-If this feature is used, when a caller connects to the node, he or she
-will be notified of the eminent charge amount if they do not drop
-carrier within the allotted free period. If the caller is still
-connected after 30 seconds, he or she will be prompted to enter a valid
-user name or number. After a valid user name or number has been entered,
-the caller is disconnected and the entered user is immediately given the
-purchased credits based on this dollar amount multiplied by the
-Credits per Dollar system option.
-*/
-						uinput(WIN_MID,0,0,"Billing Node Cost Per Call "
-							"(in dollars)",str,2,K_NUMBER|K_EDIT);
-						node_dollars_per_call=atoi(str);
-						break;
-					case 8:
-SETHELP(WHERE);
-/*
-Daily Event:
-
-If you have an event that this node should run every day, enter the
-command line for that event here.
-
-An event can be any valid DOS command line. If multiple programs or
-commands are required, use a batch file.
-
-Remember: The %! command line specifier is an abreviation for your
-		  configured EXEC directory path.
-*/
-						uinput(WIN_MID|WIN_SAV,0,10,"Daily Event"
-							,node_daily,50,K_EDIT);
-						break;
-					case 9:
-						strcpy(str,ctrl_dir);
-						if(strstr(str,"\\CTRL\\")!=NULL)
-							*strstr(str,"\\CTRL\\")=0;
-SETHELP(WHERE);
-/*
-Control Directory Parent:
-
-Your control directory contains important configuration and data files
-that ALL nodes share. This directory MUST NOT be located on a RAM disk
-or other volatile media.
-
-This option allows you to change the parent of your control directory.
-The \CTRL\ suffix (sub-directory) cannot be changed or removed.
-*/
-						if(uinput(WIN_MID|WIN_SAV,0,9,"Control Dir Parent"
-							,str,50,K_EDIT|K_UPPER)>0) {
-							if(str[strlen(str)-1]!='\\')
-								strcat(str,"\\");
-							strcat(str,"CTRL\\");
-							strcpy(ctrl_dir,str); }
-						break;
-					case 10:
-						strcpy(str,text_dir);
-						if(strstr(str,"\\TEXT\\")!=NULL)
-							*strstr(str,"\\TEXT\\")=0;
-SETHELP(WHERE);
-/*
-Text Directory Parent:
-
-Your text directory contains read-only text files. Synchronet never
-writes to any files in this directory so it CAN be placed on a RAM
-disk or other volatile media. This directory contains the system's menus
-and other important text files, so be sure the files and directories are
-moved to this directory if you decide to change it.
-
-This option allows you to change the parent of your control directory.
-The \TEXT\ suffix (sub-directory) cannot be changed or removed.
-*/
-						if(uinput(WIN_MID|WIN_SAV,0,10,"Text Dir Parent"
-							,str,50,K_EDIT|K_UPPER)>0) {
-							if(str[strlen(str)-1]!='\\')
-								strcat(str,"\\");
-							strcat(str,"TEXT\\");
-							strcpy(text_dir,str); }
-						break;
-					case 11:
-						strcpy(str,temp_dir);
-SETHELP(WHERE);
-/*
-Temp Directory:
-
-Your temp directory is where Synchronet stores files of a temporary
-nature for this node. Each node MUST have its own unique temp directory.
-This directory can exist on a RAM disk or other volatile media. For
-the best batch upload performance, it should be located on the same
-drive as the majority of your upload directories.
-*/
-						uinput(WIN_MID|WIN_SAV,0,10,"Temp Directory"
-							,str,50,K_EDIT|K_UPPER);
-						if(!strlen(str))
-							umsg("Temp directory cannot be blank");
-						else
-							strcpy(temp_dir,str);
-						break;
-					case 12:
-						strcpy(str,node_swapdir);
-SETHELP(WHERE);
-/*
-Swap Directory:
-
-Your swap directory is where Synchronet will swap out to if you have
-swapping enabled, and it is necessary to swap to disk. The default is
-the node directory. If you do specify a swap directory, it must not
-be a relative path (i.e. "..\etc"). Specify the entire path and include
-the drive letter specification (i.e. "D:\SBBS\SWAP").
-*/
-						uinput(WIN_MID|WIN_SAV,0,10,"Swap Directory"
-							,str,50,K_EDIT|K_UPPER);
-						if(str[0] && strcmp(str,".") && strcmp(str,".\\")
-							&& (strstr(str,"..") || str[1]!=':'
-							|| str[2]!='\\'))
-							umsg("Must specify full path");
-						else
-							strcpy(node_swapdir,str);
-						break; } }
-			break;
-		case 11:
-SETHELP(WHERE);
-/*
-Wait for Call Number Key Commands:
-
-Each of the number keys (0 through 9) can be assigned a command to
-execute when entered at the wait for call screen. This is a list of
-those keys and the assigned commands. Since Synchronet is still in
-memory when these command are executed, the number keys should be used
-for small program execution or command lines with small memory
-requirements.
-
-If you have a program or command line with large memory requirements,
-use a Wait for Call Function Key Command.
-*/
-			j=0;
-			while(1) {
-				for(i=0;i<10;i++)
-					sprintf(opt[i],"%d  %s",i,wfc_cmd[i]);
-				opt[i][0]=0;
-				savnum=0;
-
-				i=ulist(WIN_T2B|WIN_RHT|WIN_ACT|WIN_SAV,2,0,50,&j,0
-					,"Number Key Commands",opt);
-				if(i==-1)
-					break;
-				sprintf(str,"%d Key Command Line",i);
-				uinput(WIN_MID|WIN_SAV,0,0,str,wfc_cmd[i],50,K_EDIT); }
-			break;
-		case 12:
-SETHELP(WHERE);
-/*
-Wait for Call Function Key Commands:
-
-Each of the function keys (F1 through F12) can be assigned a command to
-execute when entered at the wait for call screen. This is a list of
-those keys and the currently assigned commands. Synchronet will shrink
-to 16K of RAM before executing one of these command lines.
-
-If you have a command line with small memory requirements, you should
-probably use a Wait for Call Number Key Command for faster execution.
-*/
-			j=0;
-			while(1) {
-				for(i=0;i<12;i++)
-					sprintf(opt[i],"F%-2d  %s",i+1,wfc_scmd[i]);
-				opt[i][0]=0;
-				savnum=0;
-				i=ulist(WIN_T2B|WIN_RHT|WIN_ACT|WIN_SAV,2,0,50,&j,0
-					,"Function Key (Shrinking) Commands",opt);
-				if(i==-1)
-					break;
-				sprintf(str,"F%d Key Command Line",i+1);
-				uinput(WIN_MID|WIN_SAV,0,0,str,wfc_scmd[i],50,K_EDIT); }
-            break;
-		case 10:
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%s","COM Port"
-					,com_port ? itoa(com_port,tmp,10) : "Disabled");
-				sprintf(opt[i++],"%-27.27s%u"
-					,com_base && com_base<0x100 ? "COM Channel"
-						:"UART IRQ Line"
-					,com_irq);
-				if(com_base==0xd)
-					strcpy(str,"DigiBoard");
-				else if(com_base==0xf)
-					strcpy(str,"FOSSIL");
-				else if(com_base==0xb)
-					strcpy(str,"PC BIOS");
-				else if(com_base==0xe)
-					strcpy(str,"PS/2 BIOS");
-				else
-					sprintf(str,"%Xh",com_base);
-				sprintf(opt[i++],"%-27.27s%s"
-					,com_base<0x100 ? "COM Type":"UART I/O Address",str);
-				sprintf(opt[i++],"%-27.27s%lu","DTE Rate",com_rate);
-				sprintf(opt[i++],"%-27.27s%s","Fixed DTE Rate"
-					,mdm_misc&MDM_STAYHIGH ? "Yes" : "No");
-				if(!(mdm_misc&(MDM_RTS|MDM_CTS)))
-					strcpy(str,"None");
-				else {
-					if(mdm_misc&MDM_CTS) {
-						strcpy(str,"CTS");
-						if(mdm_misc&MDM_RTS)
-							strcat(str,"/"); }
-					else str[0]=0;
-					if(mdm_misc&MDM_RTS)
-						strcat(str,"RTS"); }
-				sprintf(opt[i++],"%-27.27s%s","Hardware Flow Control",str);
-				sprintf(opt[i++],"%-27.27s%u ring%c","Answer After"
-					,mdm_rings,mdm_rings>1 ? 's':' ');
-				sprintf(opt[i++],"%-27.27s%u second%c","Answer Delay"
-					,mdm_ansdelay,mdm_ansdelay>1 ? 's':' ');
-				sprintf(opt[i++],"%-27.27s%s","Reinitialization Timer"
-					,mdm_reinit ? itoa(mdm_reinit,tmp,10) : "Disabled");
-				strcpy(opt[i++],"Result Codes...");
-				strcpy(opt[i++],"Toggle Options...");
-				strcpy(opt[i++],"Control Strings...");
-				strcpy(opt[i++],"Auto-Configuration...");
-				strcpy(opt[i++],"Import Configuration...");
-				strcpy(opt[i++],"Export Configuration...");
-				opt[i][0]=0;
-				savnum=0;
-SETHELP(WHERE);
-/*
-Modem Configuration Menu:
-
-This menu contains the configuration options for this node's modem.
-If you do not have a modem attached to this node or do not want to use
-an attached modem, you can disable the Synchronet modem communications
-by setting the COM Port to 0.
-
-If your modem is listed in the Auto-Configuration, you should probably
-just set the COM Port and run the auto-configuration for your modem
-type.
-*/
-				switch(ulist(WIN_T2B|WIN_RHT|WIN_ACT|WIN_SAV,2,0,44,&mdm_dflt,0
-					,"Modem Configuration",opt)) {
-                    case -1:
-						done=1;
-						break;
-					case 0:
-						itoa(com_port,str,10);
-SETHELP(WHERE);
-/*
-COM Port:
-
-This is the serial communications port that the modem for this node is
-connected to. If you do not have a modem connected to this node, or
-do not wish to use a connected modem, you can disable the Synchronet
-modem communications by setting this value to 0.
-*/
-						if(uinput(WIN_MID|WIN_SAV,0,10,"COM Port (0=Disabled)"
-							,str,2,K_EDIT|K_NUMBER)==-1)
-							break;
-						com_port=atoi(str);
-						if(!com_port)
-							break;
-						savnum=1;
-						com_type();
-						break;
-					case 1:
-						itoa(com_irq,str,10);
-SETHELP(WHERE);
-/*
-UART IRQ Line or Channel Number:
-
-If you are using a standard UART serial interface for this COM port,
-this is the IRQ line that your COM Port's UART is using. If you have
-configured your COM Port and selected the default IRQ and I/O address,
-you should not need to change the value of this option.
-
-If this COM port is accessed via Int 14h, this is the channel number
-for this COM port (normally, the COM port number minus one).
-*/
-						uinput(WIN_MID|WIN_SAV,0,10
-							,com_base && com_base<0x100 ? "Channel"
-							: "UART IRQ Line"
-							,str,2,K_EDIT|K_NUMBER);
-						com_irq=atoi(str);
-						break;
-					case 2:
-						savnum=1;
-						if(com_type() || com_base<0x100)
-							break;
-SETHELP(WHERE);
-/*
-UART I/O Address in Hex:
-
-This is the base I/O address of your COM Port's UART. If you have
-configured your COM Port and selected the default IRQ and I/O address,
-you should not need to change the value of this option. If this node's
-COM Port's UART is using a non-standard I/O address, enter that address
-(in hexadecimal) using this option.
-*/
-						itoa(com_base,str,16);
-						strupr(str);
-						uinput(WIN_MID|WIN_SAV,0,10
-							,"UART I/O Address in Hex"
-							,str,4,K_EDIT|K_UPPER);
-						com_base=ahtoul(str);
-                        break;
-					case 3:
-						savnum=1;
-SETHELP(WHERE);
-/*
-UART (DTE) Rate:
-
-This is the data transfer rate between your COM Port's UART (Data
-Terminal Equipment) and your modem. This is NOT the connect rate of
-your modem (Data Communications Equipment). Most high-speed (9600bps+)
-modems use a fixed DTE rate that is higher than the highest DCE rate to
-allow for data compression and error correction. This value should be
-set to the highest DTE rate your modem supports. If you have a 1200 or
-2400bps modem without data compression capabilities, this value should
-be set to 1200 or 2400 respectively. If you have a high-speed modem,
-refer to the modem's manual to find the highest supported DTE rate.
-*/
-						i=0;
-						strcpy(opt[i++],"300");
-						strcpy(opt[i++],"1200");
-						strcpy(opt[i++],"2400");
-						strcpy(opt[i++],"4800");
-						strcpy(opt[i++],"9600");
-						strcpy(opt[i++],"19200");
-						strcpy(opt[i++],"38400");
-						strcpy(opt[i++],"57600");
-						strcpy(opt[i++],"115200");
-						opt[i][0]=0;
-						switch(com_rate) {
-							default:
-								i=0;
-								break;
-							case 1200:
-								i=1;
-								break;
-							case 2400:
-								i=2;
-								break;
-							case 4800:
-								i=3;
-								break;
-							case 9600:
-								i=4;
-								break;
-							case 19200:
-								i=5;
-								break;
-							case 38400:
-								i=6;
-								break;
-							case 57600:
-								i=7;
-								break;
-							case 115200L:
-								i=8;
-								break; }
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"UART (DTE) Rate"
-							,opt);
-						if(i==-1)
-							break;
-						changes=1;
-						switch(i) {
-							default:
-								com_rate=300;
-								break;
-							case 1:
-								com_rate=1200;
-								break;
-							case 2:
-								com_rate=2400;
-								break;
-							case 3:
-								com_rate=4800;
-								break;
-							case 4:
-								com_rate=9600;
-								break;
-							case 5:
-								com_rate=19200;
-								break;
-							case 6:
-								com_rate=38400;
-								break;
-							case 7:
-								com_rate=57600;
-								break;
-							case 8:
-								com_rate=115200L;
-								break; }
-						break;
-					case 4:
-						i=1;
-						savnum=1;
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Use Fixed DTE Rate:
-
-If this node is using a modem with error correction or data compression
-capabilities, set this option to Yes. If you are using a 2400bps or
-slower modem, it is most likely this value should be set to No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Use Fixed "
-							"DTE Rate",opt);
-						if(i==0 && !(mdm_misc&MDM_STAYHIGH)) {
-							mdm_misc|=MDM_STAYHIGH;
-							changes=1; }
-						else if(i==1 && mdm_misc&MDM_STAYHIGH) {
-							mdm_misc&=~MDM_STAYHIGH;
-							changes=1; }
-						break;
-					case 5:
-						i=1;
-						savnum=1;
-						strcpy(opt[0],"Both");
-						strcpy(opt[1],"CTS Only");
-						strcpy(opt[2],"RTS Only");
-						strcpy(opt[3],"None");
-						opt[4][0]=0;
-						i=0;
-SETHELP(WHERE);
-/*
-Hardware Flow Control (CTS/RTS):
-
-If your modem supports the use of hardware flow control via CTS/RTS
-(Clear to Send/Request to Send), set this option to Both. If are using
-a high-speed modem or a modem with data compression or error correction
-capabilities, it is most likely this option should be set to Both. If
-you are using a 2400bps or slower modem without data compression or
-error correction capabilities, set this option to None.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Hardware "
-							"Flow Control (CTS/RTS)",opt);
-						if(i==0
-							&& (mdm_misc&(MDM_CTS|MDM_RTS))
-									   !=(MDM_CTS|MDM_RTS)) {
-							mdm_misc|=(MDM_CTS|MDM_RTS);
-							changes=1; }
-						else if(i==1
-							&& (mdm_misc&(MDM_CTS|MDM_RTS))!=MDM_CTS) {
-							mdm_misc|=MDM_CTS;
-							mdm_misc&=~MDM_RTS;
-							changes=1; }
-						else if(i==2
-							&& (mdm_misc&(MDM_CTS|MDM_RTS))!=MDM_RTS) {
-							mdm_misc|=MDM_RTS;
-							mdm_misc&=~MDM_CTS;
-                            changes=1; }
-						else if(i==3
-							&& mdm_misc&(MDM_CTS|MDM_RTS)) {
-							mdm_misc&=~(MDM_RTS|MDM_CTS);
-                            changes=1; }
-						break;
-
-					case 6:
-SETHELP(WHERE);
-/*
-Number of Rings to Answer After:
-
-This is the number of rings to let pass before answering the phone.
-*/
-                        itoa(mdm_rings,str,10);
-                        uinput(WIN_MID|WIN_SAV,0,0
-                            ,"Number of Rings to Answer After"
-                            ,str,2,K_EDIT|K_NUMBER);
-                        mdm_rings=atoi(str);
-                        if(!mdm_rings)
-                            mdm_rings=1;
-                        break;
-
-					case 7:
-SETHELP(WHERE);
-/*
-Seconds to Delay after Answer:
-
-This is the length of time (in seconds) to delay after connection and
-before the terminal detection sequence is trasmitted to the remote user
-and the logon prompt is displayed.
-*/
-						itoa(mdm_ansdelay,str,10);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Answer Delay (in seconds)"
-							,str,4,K_EDIT|K_NUMBER);
-						mdm_ansdelay=atoi(str);
-						break;
-
-					case 8:
-SETHELP(WHERE);
-/*
-Minutes Between Reinitialization:
-
-If you want your modem to be periodically reinitialized while waiting
-for a caller, set this option to the maximum number of minutes between
-initializations. Setting this value to 0 disables this feature.
-*/
-						itoa(mdm_reinit,str,10);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Minutes Between Reinitialization (0=Disabled)"
-							,str,4,K_EDIT|K_NUMBER);
-						mdm_reinit=atoi(str);
-						break;
-					case 9:
-						dflt=bar=0;
-						while(1) {
-							for(i=0;i<mdm_results;i++) {
-								sprintf(opt[i],"%3u %5ubps %4ucps %s"
-									,mdm_result[i].code,mdm_result[i].rate
-									,mdm_result[i].cps,mdm_result[i].str); }
-							opt[i][0]=0;
-							i=WIN_ACT|WIN_SAV|WIN_RHT;
-							if(mdm_results<MAX_OPTS)
-								i|=WIN_INS;
-							if(mdm_results>1)
-								i|=WIN_DEL;
-							savnum=1;
-SETHELP(WHERE);
-/*
-Modem Result Codes:
-
-This is the list of configured numeric connection result codes that this
-node's modem supports. If this node is getting Invalid Result Code
-errors when answer incoming calls, those result codes should be added
-to this list. Refer to your modem's manual for a list of supported
-result codes. Using the Auto-Configuration option automatically
-configures this list for you.
-To add a result code, hit  INS .
-
-To delete a result code, select it using the arrow keys and hit  DEL .
-*/
-							i=ulist(i,0,0,34,&dflt,&bar
-								,"Modem Result Codes",opt);
-							if(i==-1)
-								break;
-							if((i&MSK_ON)==MSK_DEL) {
-								i&=MSK_OFF;
-								mdm_results--;
-								while(i<mdm_results) {
-									mdm_result[i]=mdm_result[i+1];
-									i++; }
-								changes=1;
-								continue; }
-							if((i&MSK_ON)==MSK_INS) {
-								i&=MSK_OFF;
-								if((mdm_result=(mdm_result_t *)REALLOC(
-									mdm_result,sizeof(mdm_result_t)
-									*(mdm_results+1)))==NULL) {
-									errormsg(WHERE,ERR_ALLOC,nulstr
-										,mdm_results+1);
-									mdm_results=0;
-									bail(1);
-									continue; }
-								for(j=mdm_results;j>i;j--)
-									mdm_result[j]=mdm_result[j-1];
-								mdm_result[i]=mdm_result[i+1];
-								mdm_results++;
-								changes=1;
-								continue; }
-							results(dflt); }
-						break;
-					case 10:	/* Toggle Options */
-						dflt=0;
-						while(1) {
-							savnum=1;
-							i=0;
-							sprintf(opt[i++],"%-27.27s%s"
-								,"Caller Identification"
-								,mdm_misc&MDM_CALLERID ? "Yes" : "No");
-							sprintf(opt[i++],"%-27.27s%s"
-								,"Dumb Modem Connection"
-								,mdm_misc&MDM_DUMB ? "Yes" : "No");
-							sprintf(opt[i++],"%-27.27s%s"
-								,"Drop DTR to Hang Up"
-								,mdm_misc&MDM_NODTR ? "No" : "Yes");
-							sprintf(opt[i++],"%-27.27s%s"
-								,"Use Verbal Result Codes"
-								,mdm_misc&MDM_VERBAL ? "Yes" : "No");
-							sprintf(opt[i++],"%-27.27s%s"
-								,"Allow Unknown Result Codes"
-                                ,mdm_misc&MDM_KNOWNRES ? "No" : "Yes");
-							opt[i][0]=0;
-							i=ulist(WIN_SAV|WIN_ACT,0,0,0,&dflt,0
-								,"Modem Toggle Options",opt);
-							savnum=2;
-							if(i==-1)
-								break;
-							if(i==0) {
-								i=1;
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No");
-								opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Caller Identification:
-
-If your modem supports Caller ID and is configured to return caller
-number delivery messages, set this option to Yes.
-
-If this option is set to Yes, Synchronet will log caller number delivery
-messages. If a caller attempts to connect with a number listed in the
-file TEXT\CID.CAN, they will be displayed TEXT\BADCID.MSG (if it exists)
-and disconnected. Each user will have their most recent caller ID number
-stored in their note field.
-*/
-								i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-									,"Caller ID",opt);
-								if(i==0 && !(mdm_misc&MDM_CALLERID)) {
-									mdm_misc|=MDM_CALLERID;
-									changes=1; }
-								else if(i==1 && mdm_misc&MDM_CALLERID) {
-									mdm_misc&=~MDM_CALLERID;
-									changes=1; } }
-							else if(i==1) {
-								i=1;
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No");
-								opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Dumb Modem Connection:
-
-If this node is connected to a serial line through a dumb modem, set
-this option to Yes to disable all modem commands and answer calls when
-DCD is raised.
-*/
-								i=ulist(WIN_SAV|WIN_MID,0,0,0,&i,0
-									,"Dumb Modem",opt);
-								if(i==0 && !(mdm_misc&MDM_DUMB)) {
-									mdm_misc|=MDM_DUMB;
-									changes=1; }
-								else if(i==1 && mdm_misc&MDM_DUMB) {
-									mdm_misc&=~MDM_DUMB;
-									changes=1; } }
-							else if(i==2) {
-								i=0;
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No");
-								opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Drop DTR to Hang Up:
-
-If you wish to have the BBS drop DTR to hang up the modem, set this
-option to Yes. If this option is set to No, the Hang Up String is sent
-to modem instead.
-*/
-								i=ulist(WIN_SAV|WIN_MID,0,0,0,&i,0
-									,"Drop DTR to Hang Up",opt);
-								if(i==0 && mdm_misc&MDM_NODTR) {
-									mdm_misc&=~MDM_NODTR;
-									changes=1; }
-								else if(i==1 && !(mdm_misc&MDM_NODTR)) {
-									mdm_misc|=MDM_NODTR;
-                                    changes=1; } }
-							else if(i==3) {
-								i=1;
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No");
-								opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Use Verbal Result Codes:
-
-If you wish to have the BBS expect verbal (or verbose) result codes
-from the modem instead of numeric (non-verbose) result codes, set this
-option to Yes.
-
-This option can be useful for modems that insist on returning multiple
-result codes upon connection (CARRIER, PROTOCOL, etc) or modems that
-do not report numeric result codes correctly. While this option is more
-flexible than numeric result codes, it may not be as accurate in
-describing the connection or estimating the CPS rate of the connection.
-
-If this option is set to Yes, the configured result code list will not
-be used (you may remove all entries from the list if you wish). The
-connection rate, description, and estimated CPS will be automatically
-generated by the BBS.
-*/
-								i=ulist(WIN_SAV|WIN_MID,0,0,0,&i,0
-									,"Use Verbal Result Codes",opt);
-								if(i==0 && !(mdm_misc&MDM_VERBAL)) {
-									mdm_misc|=MDM_VERBAL;
-									changes=1; }
-								else if(i==1 && mdm_misc&MDM_VERBAL) {
-									mdm_misc&=~MDM_VERBAL;
-                                    changes=1; } }
-							else if(i==4) {
-								i=0;
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No");
-								opt[2][0]=0;
-SETHELP(WHERE);
-/*
-Allow Unknown Result Codes:
-
-If you wish to have the BBS allow modem connections with an unknown
-(un-configured) numeric result code by using the last known (configured)
-result code information by default, set this option to Yes.
-
-This option has no effect if Verbal Result Codes are used.
-*/
-								i=ulist(WIN_SAV|WIN_MID,0,0,0,&i,0
-									,"Allow Unknown Result Codes",opt);
-								if(i==0 && mdm_misc&MDM_KNOWNRES) {
-									mdm_misc&=~MDM_KNOWNRES;
-									changes=1; }
-								else if(i==1 && !(mdm_misc&MDM_KNOWNRES)) {
-									mdm_misc|=MDM_KNOWNRES;
-                                    changes=1; } }
-									}
-						break;
-					case 11:
-SETHELP(WHERE);
-/*
-Modem Control Strings:
-
-This menu contains a list of available modem control strings. It is usually
-not necessary to modify these except under special circumstances.
-*/
-                        j=0;
-                        while(1) {
-                            i=0;
-                            savnum=1;
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Initialization String",mdm_init);
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Special Init String",mdm_spec);
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Terminal Init String",mdm_term);
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Dial String",mdm_dial);
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Off Hook String",mdm_offh);
-							sprintf(opt[i++],"%-27.27s%.40s"
-                                ,"Answer String",mdm_answ);
-							sprintf(opt[i++],"%-27.27s%.40s"
-								,"Hang Up String",mdm_hang);
-							opt[i][0]=0;
-                            j=ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&j,0
-                                ,"Modem Control Strings",opt);
-                            if(j==-1)
-                                break;
-                            switch(j) {
-                                case 0:
-SETHELP(WHERE);
-/*
-Initialization String:
-
-This is one of the strings of characters sent to your modem upon
-modem initialization. If you find it necessary to send additional
-commands to the modem during initialization, use the Special Init String
-for that purpose.
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-                                        ,"Initialization"
-                                        ,mdm_init,50,K_EDIT|K_UPPER);
-                                    break;
-                                case 1:
-SETHELP(WHERE);
-/*
-Special Init String:
-
-This is an additional optional string of characters to be sent to your
-modem during initialization. Many of the Auto-Configuration options
-automatically set this string. It is used for sending commands that are
-particular to this modem type. If you find it necessary to send
-additional commands to your modem during initialization, use this option
-for that purpose.
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-                                        ,"Special Init"
-                                        ,mdm_spec,50,K_EDIT|K_UPPER);
-                                    break;
-                                case 2:
-SETHELP(WHERE);
-/*
-Terminal Init String:
-
-This is the string of characters sent to your modem when terminal mode
-is entered from the Synchronet wait for call screen.
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-                                        ,"Terminal Init"
-                                        ,mdm_term,50,K_EDIT|K_UPPER);
-                                    break;
-                                case 3:
-SETHELP(WHERE);
-/*
-Dial String:
-
-This is the string used to dial the modem in Synchronet Callback
-(an optional callback verification module).
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-										,"Dial String",mdm_dial,40
-                                        ,K_EDIT|K_UPPER);
-                                    break;
-                                case 4:
-SETHELP(WHERE);
-/*
-Off Hook String:
-
-This is the string of characters sent to your modem to take it off hook
-(make busy).
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-                                        ,"Off Hook String",mdm_offh
-                                        ,40,K_EDIT|K_UPPER);
-                                    break;
-                                case 5:
-SETHELP(WHERE);
-/*
-Answer String:
-
-This is the string of characters sent to your modem to answer an
-incoming call.
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-                                        ,"Answer String",mdm_answ,40
-                                        ,K_EDIT|K_UPPER);
-									break;
-								case 6:
-SETHELP(WHERE);
-/*
-Hang Up String:
-
-This is the string of characters sent to your modem to hang up the
-phone line (go on-hook).
-*/
-                                    uinput(WIN_MID|WIN_SAV,0,0
-										,"Hang Up String",mdm_hang,40
-                                        ,K_EDIT|K_UPPER);
-                                    break;
-									} }
-						break;
-					case 12:
-						dflt=bar=0;
-						while(1) {
-							for(i=0;i<mdm_types;i++)
-								strcpy(opt[i],mdm_type[i]);
-							opt[i][0]=0;
-							savnum=1;
-SETHELP(WHERE);
-/*
-Auto-Configuration Modem Type:
-
-This is the list of modem types currently supported by Synchronet's
-automatic modem configuration feature. If your modem is listed, select
-it using the arrow keys and hit  ENTER . If your modem is not listed,
-you may want to try using the auto-configuration of a compatible modem
-or one from the same manufacturer. If you have a 2400bps modem, select
-Hayes SmartModem 2400. If you have a high-speed modem that is not
-listed, you may want to try Generic 9600 or Generic 14400 and add
-the additional high-speed result codes by hand. Refer to your modem's
-manual for a list of result codes supported by your modem.
-*/
-							i=ulist(WIN_ACT|WIN_SAV|WIN_RHT,0,0,0
-								,&dflt,&bar,"Modem Type",opt);
-							if(i==-1)
-								break;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							j=1;
-							savnum=2;
-
-							j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-								,"Continue with Modem Auto-Configuration",opt);
-							if(!j) {
-								mdm_cfg(i);
-								changes=1;
-								sprintf(str
-									,"Modem configured as %s",mdm_type[i]);
-								savnum=1;
-								umsg(str); } }
-						break;
-					case 13:
-SETHELP(WHERE);
-/*
-Import Modem Configuration File
-
-Using this option, you can import modem settings from an MDM file in
-your CTRL directory (i.e. To import from CTRL\MYMODEM.MDM, type MYMODEM
-now).
-*/
-						i=changes;
-						str[0]=0;
-						uinput(WIN_MID|WIN_SAV,0,0,"MDM Filename",str
-							,8,K_UPPER);
-						if(str[0]) {
-							FREE(mdm_result);
-							mdm_result=NULL;
-
-							mdm_answ[0]=0;
-							mdm_hang[0]=0;
-							mdm_dial[0]=0;
-							mdm_offh[0]=0;
-							mdm_term[0]=0;
-							mdm_init[0]=0;
-							mdm_spec[0]=0;
-							mdm_results=0;
-
-							if(exec_mdm(str))
-								umsg("Imported");
-							else {
-								umsg("File Not Found");
-								changes=i; } }
-						else
-							changes=i;
-                        break;
-
-					case 14:
-SETHELP(WHERE);
-/*
-Export Current Modem Configuration to a File
-
-Using this option, you can save the current modem settings to a file.
-The file will be placed into the CTRL directory and will be given an
-extension of MDM (i.e. To create CTRL\MYMODEM.MDM, type MYMODEM now).
-*/
-						i=changes;
-						str[0]=0;
-						uinput(WIN_MID|WIN_SAV,0,0,"MDM Filename",str
-							,8,K_UPPER);
-						if(str[0]) {
-							if(export_mdm(str))
-								umsg("Exported");
-							else
-								umsg("Error Exporting"); }
-						changes=i;
-						break;
-						} } } }
-}
-
-void results(int i)
-{
-	char str[81];
-	int n,dflt=0;
-
-while(1) {
-	n=0;
-	sprintf(opt[n++],"%-22.22s%u","Numeric Code",mdm_result[i].code);
-	sprintf(opt[n++],"%-22.22s%ubps","Modem Connect Rate",mdm_result[i].rate);
-	sprintf(opt[n++],"%-22.22s%ucps","Modem Average CPS",mdm_result[i].cps);
-	sprintf(opt[n++],"%-22.22s%s","Description",mdm_result[i].str);
-	opt[n][0]=0;
-	savnum=2;
-SETHELP(WHERE);
-/*
-Result Code:
-
-This is one of the configured connect result codes for your modem. The
-available options are:
-
-    Numeric Code       :  Numeric result code
-    Modem Connect Rate :  Connect speed (in bps) for this result code
-	Modem Average CPS  :  Average file transfer throughput in cps
-    Description        :  Description of this connection type
-*/
-	switch(ulist(WIN_SAV|WIN_MID|WIN_ACT,0,0,35,&dflt,0,"Result Code",opt)) {
-		case -1:
-			return;
-		case 0:
-			sprintf(str,"%u",mdm_result[i].code);
-SETHELP(WHERE);
-/*
-Numeric Result Code:
-
-This is the numeric (as opposed to verbal) result code your modem will
-send to your computer when it establishes a connection with another
-modem with this connect type. Your modem must have the V0 setting
-enabled to return numeric result codes.
-*/
-			uinput(WIN_L2R|WIN_SAV,0,15,"Numeric Result Code",str,3
-				,K_EDIT|K_NUMBER);
-			mdm_result[i].code=atoi(str);
-			break;
-		case 1:
-SETHELP(WHERE);
-/*
-Connection (DCE) Rate:
-
-This is the modem (DCE) rate established with this connect type. This is
-NOT the DTE rate of your modem. As an example, a 14,400bps modem may
-have a DTE rate of 38,400bps but a maximum DCE rate of 14,400bps.
-*/
-			sprintf(str,"%u",mdm_result[i].rate);
-			uinput(WIN_L2R|WIN_SAV,0,15,"Connection (DCE) Rate",str,5
-				,K_EDIT|K_NUMBER);
-			mdm_result[i].rate=atoi(str);
-			break;
-		case 2:
-SETHELP(WHERE);
-/*
-Average File Transfer CPS:
-
-This is the average file transfer through-put (characters per second)
-of connections with this result code. If you don't know the average
-through-put, just divide the DCE Rate by ten for an approximation.
-As an example, a 9600bps DCE Rate would have an approximate file
-transfer through-put of 960cps.
-*/
-			sprintf(str,"%u",mdm_result[i].cps);
-			uinput(WIN_L2R|WIN_SAV,0,15,"Average File Transfer CPS",str,5
-				,K_EDIT|K_NUMBER);
-			mdm_result[i].cps=atoi(str);
-			break;
-		case 3:
-SETHELP(WHERE);
-/*
-Modem Description:
-
-This is a description of the modem type used for a connection with
-this result code. It can be up to eight characters long. This
-description usually just contains the DCE rate and possibly the
-protocol type. Such as 2400 for a 2400bps connection, 9600/V32
-for a 9600bps V.32 connection or 9600/HST for a 9600bps HST connection.
-*/
-			uinput(WIN_L2R|WIN_SAV,0,15,"Modem Description"
-				,mdm_result[i].str,LEN_MODEM,K_EDIT);
-			break; } }
-}
diff --git a/src/sbbs2/scfg/scfgsub.c b/src/sbbs2/scfg/scfgsub.c
deleted file mode 100644
index a318e8b4be287900b4903b26674932b5d4742668..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgsub.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-#line 2 "SCFGSUB.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-void sub_cfg(uint grpnum)
-{
-	static int dflt,tog_dflt,opt_dflt,net_dflt,adv_dflt,bar;
-	char str[81],str2[81],str3[11],done=0,code[9],*p;
-	int j,m,n,ptridx,q,s;
-	uint i,subnum[MAX_OPTS+1];
-	static sub_t savsub;
-
-while(1) {
-	for(i=0,j=0;i<total_subs && j<MAX_OPTS;i++)
-        if(sub[i]->grp==grpnum) {
-			subnum[j]=i;
-			if(sub[subnum[0]]->qwkconf)
-				sprintf(opt[j],"%-5u %s"
-					,sub[i]->qwkconf,sub[i]->lname);
-			else
-				sprintf(opt[j],"%s"
-					,sub[i]->lname);
-			j++; }
-	subnum[j]=total_subs;
-	opt[j][0]=0;
-	sprintf(str,"%s Sub-boards",grp[grpnum]->sname);
-	savnum=0;
-	i=WIN_SAV|WIN_ACT;
-	if(j)
-		i|=WIN_DEL|WIN_GET|WIN_DELACT;
-	if(j<MAX_OPTS)
-		i|=WIN_INS|WIN_XTR|WIN_INSACT;
-	if(savsub.sname[0])
-		i|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Message Sub-boards:
-
-This is a list of message sub-boards that have been configured for the
-selected message group.
-
-To add a sub-board, select the desired position with the arrow keys and
-hit  INS .
-
-To delete a sub-board, select it with the arrow keys and hit  DEL .
-
-To configure a sub-board, select it with the arrow keys and hit  ENTER .
-*/
-	i=ulist(i,24,1,LEN_SLNAME+5,&dflt,&bar,str,opt);
-	savnum=1;
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"General");
-		SETHELP(WHERE);
-/*
-Sub-board Long Name:
-
-This is a description of the message sub-board which is displayed in all
-sub-board listings.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Sub-board Long Name",str,LEN_SLNAME
-			,K_EDIT)<1)
-			continue;
-		sprintf(str2,"%.*s",LEN_SSNAME,str);
-		SETHELP(WHERE);
-/*
-Sub-board Short Name:
-
-This is a short description of the message sub-board which is displayed
-at the main and reading messages prompts.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Sub-board Short Name",str2,LEN_SSNAME
-			,K_EDIT)<1)
-			continue;
-		sprintf(str3,"%.10s",str2);
-		SETHELP(WHERE);
-/*
-Sub-board QWK Name:
-
-This is the name of the sub-board used for QWK off-line readers.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Sub-board QWK Name",str3,10
-            ,K_EDIT)<1)
-            continue;
-		sprintf(code,"%.8s",str3);
-		p=strchr(code,SP);
-		if(p) *p=0;
-		strupr(code);
-		SETHELP(WHERE);
-/*
-Sub-board Internal Code:
-
-Every sub-board must have its own unique code for Synchronet to refer to
-it internally. This code should be descriptive of the sub-board's topic,
-usually an abreviation of the sub-board's name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Sub-board Internal Code",code,8
-			,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			savnum=0;
-			umsg("Invalid Code");
-			helpbuf=0;
-			continue; }
-
-		if((sub=(sub_t **)REALLOC(sub,sizeof(sub_t *)*(total_subs+1)))==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_subs+1);
-			total_subs=0;
-			bail(1);
-            continue; }
-
-		for(ptridx=0;ptridx>-1;ptridx++) { /* Search for unused pointer indx */
-            for(n=0;n<total_subs;n++)
-				if(sub[n]->ptridx==ptridx)
-                    break;
-            if(n==total_subs)
-                break; }
-
-		if(j) {
-			for(n=total_subs;n>subnum[i];n--)
-                sub[n]=sub[n-1];
-			for(q=0;q<total_qhubs;q++)
-				for(s=0;s<qhub[q]->subs;s++)
-					if(qhub[q]->sub[s]>=subnum[i])
-						qhub[q]->sub[s]++; }
-
-		if((sub[subnum[i]]=(sub_t *)MALLOC(sizeof(sub_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(sub_t));
-			continue; }
-		memset((sub_t *)sub[subnum[i]],0,sizeof(sub_t));
-		sub[subnum[i]]->grp=grpnum;
-		if(total_faddrs)
-			sub[subnum[i]]->faddr=faddr[0];
-		else
-			memset(&sub[subnum[i]]->faddr,0,sizeof(faddr_t));
-		sub[subnum[i]]->maxmsgs=500;
-		strcpy(sub[subnum[i]]->code,code);
-		strcpy(sub[subnum[i]]->lname,str);
-		strcpy(sub[subnum[i]]->sname,str2);
-		strcpy(sub[subnum[i]]->qwkname,str3);
-		sub[subnum[i]]->misc=(SUB_NSDEF|SUB_SSDEF|SUB_QUOTE|SUB_TOUSER
-			|SUB_HDRMOD|SUB_FAST);
-		sub[subnum[i]]->ptridx=ptridx;
-		total_subs++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Delete Data in Sub-board:
-
-If you want to delete all the messages for this sub-board, select Yes.
-*/
-		j=1;
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-			,"Delete Data in Sub-board",opt);
-		if(j==-1)
-			continue;
-		if(j==0) {
-				sprintf(str,"%s.s*",sub[subnum[i]]->code);
-				if(!sub[subnum[i]]->data_dir[0])
-					sprintf(tmp,"%sSUBS\\",data_dir);
-				else
-					strcpy(tmp,sub[subnum[i]]->data_dir);
-				delfiles(tmp,str);
-				clearptrs(subnum[i]); }
-		FREE(sub[subnum[i]]);
-		total_subs--;
-		for(j=subnum[i];j<total_subs;j++)
-			sub[j]=sub[j+1];
-		for(q=0;q<total_qhubs;q++)
-			for(s=0;s<qhub[q]->subs;s++) {
-				if(qhub[q]->sub[s]==subnum[i])
-					qhub[q]->sub[s]=INVALID_SUB;
-				else if(qhub[q]->sub[s]>subnum[i])
-					qhub[q]->sub[s]--; }
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savsub=*sub[subnum[i]];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		ptridx=sub[subnum[i]]->ptridx;
-		*sub[subnum[i]]=savsub;
-		sub[subnum[i]]->ptridx=ptridx;
-		sub[subnum[i]]->grp=grpnum;
-		changes=1;
-        continue; }
-	i=subnum[i];
-	j=0;
-	done=0;
-	while(!done) {
-		n=0;
-		sprintf(opt[n++],"%-27.27s%s","Long Name",sub[i]->lname);
-		sprintf(opt[n++],"%-27.27s%s","Short Name",sub[i]->sname);
-		sprintf(opt[n++],"%-27.27s%s","QWK Name",sub[i]->qwkname);
-		sprintf(opt[n++],"%-27.27s%s","Internal Code",sub[i]->code);
-		sprintf(opt[n++],"%-27.27s%.40s","Access Requirements"
-			,sub[i]->ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Reading Requirements"
-            ,sub[i]->read_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Posting Requirements"
-			,sub[i]->post_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Operator Requirements"
-			,sub[i]->op_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Moderated Posting User"
-			,sub[i]->mod_ar);
-		sprintf(opt[n++],"%-27.27s%u","Maximum Messages"
-            ,sub[i]->maxmsgs);
-		if(sub[i]->maxage)
-            sprintf(str,"Enabled (%u days old)",sub[i]->maxage);
-        else
-            strcpy(str,"Disabled");
-		sprintf(opt[n++],"%-27.27s%s","Purge by Age",str);
-		if(sub[i]->maxcrcs)
-			sprintf(str,"Enabled (%lu message CRCs)",sub[i]->maxcrcs);
-		else
-			strcpy(str,"Disabled");
-		sprintf(opt[n++],"%-27.27s%s","Duplicate Checking",str);
-
-		strcpy(opt[n++],"Toggle Options...");
-		strcpy(opt[n++],"Network Options...");
-		strcpy(opt[n++],"Advanced Options...");
-		opt[n][0]=0;
-		sprintf(str,"%s Sub-board",sub[i]->sname);
-		savnum=1;
-		SETHELP(WHERE);
-/*
-Sub-board Configuration:
-
-This menu allows you to configure the individual selected sub-board.
-Options with a trailing ... provide a sub-menu of more options.
-*/
-		switch(ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT
-			,0,0,60,&opt_dflt,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Sub-board Long Name:
-
-This is a description of the message sub-board which is displayed in all
-sub-board listings.
-*/
-				strcpy(str,sub[i]->lname);	/* save */
-				if(!uinput(WIN_MID|WIN_SAV,0,17,"Name to use for Listings"
-					,sub[i]->lname,LEN_SLNAME,K_EDIT))
-					strcpy(sub[i]->lname,str);	/* restore */
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Sub-board Short Name:
-
-This is a short description of the message sub-board which is displayed
-at the main and reading messages prompts.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Name to use for Prompts"
-					,sub[i]->sname,LEN_SSNAME,K_EDIT);
-				break;
-			case 2:
-				SETHELP(WHERE);
-/*
-Sub-board QWK Name:
-
-This is the name of the sub-board used for QWK off-line readers.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Name to use for QWK Packets"
-					,sub[i]->qwkname,10,K_EDIT);
-                break;
-			case 3:
-                SETHELP(WHERE);
-/*
-Sub-board Internal Code:
-
-Every sub-board must have its own unique code for Synchronet to refer
-to it internally. This code should be descriptive of the sub-board's
-topic, usually an abreviation of the sub-board's name.
-*/
-                strcpy(str,sub[i]->code);
-                uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-                    ,str,8,K_EDIT|K_UPPER);
-                if(code_ok(str))
-                    strcpy(sub[i]->code,str);
-                else {
-                    helpbuf=invalid_code;
-                    umsg("Invalid Code");
-                    helpbuf=0; }
-                break;
-			case 4:
-				savnum=2;
-				sprintf(str,"%s Access",sub[i]->sname);
-				getar(str,sub[i]->ar);
-				break;
-			case 5:
-				savnum=2;
-				sprintf(str,"%s Reading",sub[i]->sname);
-				getar(str,sub[i]->read_ar);
-                break;
-			case 6:
-				savnum=2;
-				sprintf(str,"%s Posting",sub[i]->sname);
-				getar(str,sub[i]->post_ar);
-                break;
-			case 7:
-				savnum=2;
-				sprintf(str,"%s Operator",sub[i]->sname);
-				getar(str,sub[i]->op_ar);
-                break;
-			case 8:
-				savnum=2;
-				sprintf(str,"%s Moderated Posting User",sub[i]->sname);
-				getar(str,sub[i]->mod_ar);
-                break;
-			case 9:
-				sprintf(str,"%u",sub[i]->maxmsgs);
-                SETHELP(WHERE);
-/*
-Maximum Number of Messages:
-
-This value is the maximum number of messages that will be kept in the
-sub-board. Once this maximum number of messages is reached, the oldest
-messages will be automatically purged. Usually, 100 messages is a
-sufficient maximum.
-*/
-                uinput(WIN_MID|WIN_SAV,0,17,"Maximum Number of Messages"
-                    ,str,5,K_EDIT|K_NUMBER);
-                sub[i]->maxmsgs=atoi(str);
-                sub[i]->misc|=SUB_HDRMOD;
-				break;
-			case 10:
-				sprintf(str,"%u",sub[i]->maxage);
-                SETHELP(WHERE);
-/*
-Maximum Age of Messages:
-
-This value is the maximum number of days that messages will be kept in
-the sub-board.
-*/
-                uinput(WIN_MID|WIN_SAV,0,17,"Maximum Age of Messages (in days)"
-                    ,str,5,K_EDIT|K_NUMBER);
-                sub[i]->maxage=atoi(str);
-                sub[i]->misc|=SUB_HDRMOD;
-				break;
-			case 11:
-				sprintf(str,"%u",sub[i]->maxcrcs);
-				SETHELP(WHERE);
-/*
-Maximum Number of CRCs:
-
-This value is the maximum number of CRCs that will be kept in the
-sub-board for duplicate message checking. Once this maximum number of
-CRCs is reached, the oldest CRCs will be automatically purged.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Maximum Number of CRCs"
-					,str,5,K_EDIT|K_NUMBER);
-				sub[i]->maxcrcs=atol(str);
-				sub[i]->misc|=SUB_HDRMOD;
-                break;
-			case 12:
-				while(1) {
-					n=0;
-					sprintf(opt[n++],"%-27.27s%s","Allow Private Posts"
-						,sub[i]->misc&SUB_PRIV ? sub[i]->misc&SUB_PONLY
-						? "Only":"Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Allow Anonymous Posts"
-						,sub[i]->misc&SUB_ANON ? sub[i]->misc&SUB_AONLY
-						? "Only":"Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Post Using Real Names"
-						,sub[i]->misc&SUB_NAME ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Users Can Delete Posts"
-						,sub[i]->misc&SUB_DEL ? sub[i]->misc&SUB_DELLAST
-						? "Last":"Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Default On for New Scan"
-						,sub[i]->misc&SUB_NSDEF ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Forced On for New Scan"
-						,sub[i]->misc&SUB_FORCED ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Default On for Your Scan"
-						,sub[i]->misc&SUB_SSDEF ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Public 'To' User"
-						,sub[i]->misc&SUB_TOUSER ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Allow Message Quoting"
-						,sub[i]->misc&SUB_QUOTE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Permanent Operator Msgs"
-						,sub[i]->misc&SUB_SYSPERM ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Kill Read Messages"
-						,sub[i]->misc&SUB_KILL ? "Yes"
-						: (sub[i]->misc&SUB_KILLP ? "Pvt" : "No"));
-#if 1
-					sprintf(opt[n++],"%-27.27s%s","Compress Messages (LZH)"
-						,sub[i]->misc&SUB_LZH ? "Yes" : "No");
-#endif
-					opt[n][0]=0;
-					savnum=2;
-					SETHELP(WHERE);
-/*
-Sub-board Toggle Options:
-
-This menu allows you to toggle certain options for the selected
-sub-board between two or more settings, such as Yes and No.
-*/
-					n=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,3,2,36,&tog_dflt,0
-						,"Toggle Options",opt);
-					if(n==-1)
-						break;
-					savnum=3;
-					switch(n) {
-						case 0:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							strcpy(opt[2],"Only");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Allow Private Posts on Sub-board:
-
-If you want users to be able to post private messages to other users
-on this sub-board, set this value to Yes. Usually, E-mail is the
-preferred method of private communication. If you want users to be able
-to post private messages only on this sub-board, select Only.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Allow Private Posts",opt);
-							if(n==-1)
-								break;
-							if(!n && (sub[i]->misc&(SUB_PRIV|SUB_PONLY))
-								!=SUB_PRIV) {
-								changes=1;
-								sub[i]->misc&=~SUB_PONLY;
-								sub[i]->misc|=SUB_PRIV;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_PRIV) {
-								changes=1;
-								sub[i]->misc&=~SUB_PRIV;
-								break; }
-							if(n==2 && (sub[i]->misc&(SUB_PRIV|SUB_PONLY))
-								!=(SUB_PRIV|SUB_PONLY)) {
-								changes=1;
-								sub[i]->misc|=(SUB_PRIV|SUB_PONLY); }
-							break;
-						case 1:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							strcpy(opt[2],"Only");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Allow Anonymous Posts on Sub-board:
-
-If you want users with the A exemption to be able to post anonymously on
-this sub-board, select Yes. If you want all posts on this sub-board to be
-forced anonymous, select Only. If you do not want anonymous posts allowed
-on this sub-board at all, select No.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Allow Anonymous Posts",opt);
-							if(n==-1)
-								break;
-							if(!n && (sub[i]->misc&(SUB_ANON|SUB_AONLY))
-								!=SUB_ANON) {
-								changes=1;
-								sub[i]->misc&=~SUB_AONLY;
-								sub[i]->misc|=SUB_ANON;
-								break; }
-							if(n==1 && sub[i]->misc&(SUB_ANON|SUB_AONLY)) {
-								changes=1;
-								sub[i]->misc&=~(SUB_ANON|SUB_AONLY);
-								break; }
-							if(n==2 && (sub[i]->misc&(SUB_ANON|SUB_AONLY))
-								!=(SUB_ANON|SUB_AONLY)) {
-								changes=1;
-								sub[i]->misc|=(SUB_ANON|SUB_AONLY); }
-                            break;
-						case 2:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-User Real Names in Posts on Sub-board:
-
-If you allow aliases on your system, you can have messages on this
-sub-board automatically use the real name of the posting user by setting
-this option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Use Real Names in Posts",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_NAME)) {
-								changes=1;
-								sub[i]->misc|=SUB_NAME;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_NAME) {
-								changes=1;
-								sub[i]->misc&=~SUB_NAME; }
-							break;
-						case 3:
-							n=2;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							strcpy(opt[2],"Last Post Only");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Users Can Delete Posts on Sub-board:
-
-If you want users to be able to delete any of their own posts on this
-sub-board, set this option to Yes. If you want to allow users the
-ability to delete their message only if it is the last message on the
-sub-board, select Last Post Only. If you want to disallow users from
-deleting any of their posts, set this option to No.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Users Can Delete Posts",opt);
-							if(n==-1)
-								break;
-							if(!n && (sub[i]->misc&(SUB_DEL|SUB_DELLAST))
-								!=SUB_DEL) {
-								changes=1;
-								sub[i]->misc&=~SUB_DELLAST;
-								sub[i]->misc|=SUB_DEL;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_DEL) {
-								changes=1;
-								sub[i]->misc&=~SUB_DEL;
-								break; }
-							if(n==2 && (sub[i]->misc&(SUB_DEL|SUB_DELLAST))
-								!=(SUB_DEL|SUB_DELLAST)) {
-								changes=1;
-								sub[i]->misc|=(SUB_DEL|SUB_DELLAST); }
-                            break;
-						case 4:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Default On for New Scan:
-
-If you want this sub-board to be included in all user new message scans
-by default, set this option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Default On for New Scan",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_NSDEF)) {
-								changes=1;
-								sub[i]->misc|=SUB_NSDEF;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_NSDEF) {
-								changes=1;
-								sub[i]->misc&=~SUB_NSDEF; }
-                            break;
-						case 5:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Forced On for New Scan:
-
-If you want this sub-board to be included in all user new message scans
-even if the user has removed it from their new scan configuration, set
-this option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Forced New Scan",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_FORCED)) {
-								changes=1;
-								sub[i]->misc|=SUB_FORCED;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_FORCED) {
-								changes=1;
-								sub[i]->misc&=~SUB_FORCED; }
-                            break;
-						case 6:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Default On for Your Scan:
-
-If you want this sub-board to be included in all user personal message
-scans by default, set this option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Default On for Your Scan",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_SSDEF)) {
-								changes=1;
-								sub[i]->misc|=SUB_SSDEF;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_SSDEF) {
-								changes=1;
-								sub[i]->misc&=~SUB_SSDEF; }
-                            break;
-						case 7:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Prompt for 'To' User on Public Posts:
-
-If you want all posts on this sub-board to be prompted for a 'To' user,
-set this option to Yes. This is a useful option for sub-boards that
-are on a network that does not allow private posts.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Prompt for 'To' User on Public Posts",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_TOUSER)) {
-								changes=1;
-								sub[i]->misc|=SUB_TOUSER;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_TOUSER) {
-								changes=1;
-								sub[i]->misc&=~SUB_TOUSER; }
-							break;
-						case 8:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Allow Message Quoting:
-
-If you want users to be allowed to quote messages on this sub-board, set
-this option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Allow Message Quoting",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_QUOTE)) {
-								changes=1;
-								sub[i]->misc|=SUB_QUOTE;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_QUOTE) {
-								changes=1;
-								sub[i]->misc&=~SUB_QUOTE; }
-                            break;
-						case 9:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Operator Messages Automatically Permanent:
-
-If you want messages posted by System and Sub-board Operators to be
-automatically permanent (non-purgable) for this sub-board, set this
-option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Permanent Operator Messages",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_SYSPERM)) {
-								changes=1;
-								sub[i]->misc|=SUB_SYSPERM;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_SYSPERM) {
-								changes=1;
-								sub[i]->misc&=~SUB_SYSPERM; }
-                            break;
-						case 10:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							strcpy(opt[2],"Private");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Kill Read Messages Automatically:
-
-If you want messages that have been read by the intended recipient to
-be automatically deleted by SMBUTIL, set this option to Yes or
-Private if you want only private messages to be automatically deleted.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Kill Read Messages",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_KILL)) {
-								changes=1;
-								sub[i]->misc|=SUB_KILL;
-								sub[i]->misc&=~SUB_KILLP;
-								break; }
-							if(n==1 && sub[i]->misc&(SUB_KILL|SUB_KILLP)) {
-								changes=1;
-								sub[i]->misc&=~(SUB_KILL|SUB_KILLP); }
-							if(n==2 && !(sub[i]->misc&SUB_KILLP)) {
-								changes=1;
-								sub[i]->misc|=SUB_KILLP;
-								sub[i]->misc&=~SUB_KILL;
-                                break; }
-                            break;
-#if 1
-						case 11:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Compress Messages with LZH Encoding:
-
-If you want all messages in this sub-board to be automatically
-compressed via LZH (Lempel/Ziv/Huffman algorithm used in LHarc, LHA,
-and other popular compression and archive programs), this option to Yes.
-
-Compression will slow down the reading and writing of messages slightly,
-but the storage space saved can be as much as 50 percent.
-
-Before setting this option to Yes, make sure that all of the SMB
-compatible mail programs you use support the LZH translation.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Compress Messages (LZH)",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_LZH)) {
-								changes=1;
-								sub[i]->misc|=SUB_LZH;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_LZH) {
-								changes=1;
-								sub[i]->misc&=~SUB_LZH; }
-                            break;
-#endif
-							} }
-				break;
-			case 13:
-				while(1) {
-					n=0;
-					sprintf(opt[n++],"%-27.27s%s","Append Tag/Origin Line"
-						,sub[i]->misc&SUB_NOTAG ? "No":"Yes");
-					sprintf(opt[n++],"%-27.27s%s","Export ASCII Only"
-						,sub[i]->misc&SUB_ASCII ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Gate Between Net Types"
-						,sub[i]->misc&SUB_GATE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","QWK Networked"
-						,sub[i]->misc&SUB_QNET ? "Yes":"No");
-					sprintf(opt[n++],"QWK Tagline");
-					sprintf(opt[n++],"%-27.27s%s","Internet"
-						,sub[i]->misc&SUB_INET ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","PostLink or PCRelay"
-                        ,sub[i]->misc&SUB_PNET ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","FidoNet EchoMail"
-						,sub[i]->misc&SUB_FIDO ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","FidoNet Address"
-                        ,faddrtoa(sub[i]->faddr));
-					sprintf(opt[n++],"EchoMail Origin Line");
-					if(!sub[i]->echopath[0])
-						sprintf(str,"%s%s\\",echomail_dir,sub[i]->code);
-					else
-						strcpy(str,sub[i]->echopath);
-					sprintf(opt[n++],"%-27.27s%.40s","EchoMail Directory"
-						,str);
-					if(!sub[i]->echomail_sem[0])
-						strcpy(str,echomail_sem);
-					else
-						strcpy(str,sub[i]->echomail_sem);
-					sprintf(opt[n++],"%-27.27s%.40s","EchoMail Semaphore File"
-						,str);
-					opt[n][0]=0;
-					savnum=2;
-					SETHELP(WHERE);
-/*
-Sub-board Network Options:
-
-This menu contains options for the selected sub-board that pertain
-specifically to message networking.
-*/
-					n=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,3,2,60,&net_dflt,0
-						,"Network Options",opt);
-					if(n==-1)
-						break;
-					savnum=3;
-                    switch(n) {
-						case 0:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Append Tag/Origin Line to Posts:
-
-If you want to disable the automatic addition of a network tagline or
-origin line to the bottom of outgoing networked posts from this
-sub-board, set this option to No.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Append Tag/Origin Line to Posts",opt);
-							if(n==-1)
-                                break;
-							if(!n && sub[i]->misc&SUB_NOTAG) {
-								changes=1;
-								sub[i]->misc&=~SUB_NOTAG;
-								break; }
-							if(n==1 && !(sub[i]->misc&SUB_NOTAG)) {
-								changes=1;
-								sub[i]->misc|=SUB_NOTAG; }
-                            break;
-						case 1:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Export ASCII Characters Only:
-
-If the network that this sub-board is echoed on does not allow extended
-ASCII (>127) or control codes (<20, not including CR), set this option
-to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Export ASCII Characters Only",opt);
-							if(n==-1)
-                                break;
-							if(n && sub[i]->misc&SUB_ASCII) {
-								changes=1;
-								sub[i]->misc&=~SUB_ASCII;
-								break; }
-							if(!n && !(sub[i]->misc&SUB_ASCII)) {
-								changes=1;
-								sub[i]->misc|=SUB_ASCII; }
-                            break;
-						case 2:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Gate Between Net Types:
-
-If this sub-board is networked using more than one network technology,
-and you want messages to be gated between the networks, set this
-option to Yes.
-
-If this option is set to No, messages imported from one network type
-will not be exported to another network type. This is the default and
-should be used unless you have specific permission from both networks
-to gate this sub-board. Incorrectly gated sub-boards can cause duplicate
-messages loops and cross-posted messages.
-
-This option does not affect the exporting of messages created on your
-BBS.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Gate Between Net Types",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_GATE)) {
-								changes=1;
-								sub[i]->misc|=SUB_GATE;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_GATE) {
-								changes=1;
-								sub[i]->misc&=~SUB_GATE; }
-                            break;
-						case 3:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Sub-board Networked via QWK Packets:
-
-If this sub-board is networked with other BBSs via QWK packets, this
-option should be set to Yes. With this option set to Yes, titles of
-posts on this sub-board will be limited to the QWK packet limitation of
-25 characters. It also allows the Network restriction to function
-properly.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Networked via QWK Packets",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_QNET)) {
-								changes=1;
-								sub[i]->misc|=SUB_QNET;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_QNET) {
-								changes=1;
-								sub[i]->misc&=~SUB_QNET; }
-                            break;
-						case 4:
-							SETHELP(WHERE);
-/*
-Sub-board QWK Network Tagline:
-
-If you want to use a different QWK tagline than the configured default
-tagline in the Networks configuration, you should enter that tagline
-here. If this option is left blank, the default tagline is used.
-*/
-							uinput(WIN_MID|WIN_SAV,0,0,nulstr,sub[i]->tagline
-								,63,K_MSG|K_EDIT);
-							break;
-						case 5:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Sub-board Networked via Internet:
-
-If this sub-board is networked to the Internet via UUCP, this option
-should be set to Yes.
-
-It will allow the Network restriction to function properly.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Networked via Internet",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_INET)) {
-								changes=1;
-								sub[i]->misc|=SUB_INET;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_INET) {
-								changes=1;
-								sub[i]->misc&=~SUB_INET; }
-                            break;
-						case 6:
-                            n=1;
-                            strcpy(opt[0],"Yes");
-                            strcpy(opt[1],"No");
-                            opt[2][0]=0;
-                            SETHELP(WHERE);
-/*
-Sub-board Networked via PostLink or PCRelay:
-
-If this sub-board is networked with other BBSs via PostLink or PCRelay,
-this option should be set to Yes. With this option set to Yes,
-titles of posts on this sub-board will be limited to the UTI
-specification limitation of 25 characters. It also allows the Network
-restriction to function properly.
-*/
-                            n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-                                ,"Networked via PostLink or PCRelay",opt);
-                            if(n==-1)
-                                break;
-                            if(!n && !(sub[i]->misc&SUB_PNET)) {
-                                changes=1;
-                                sub[i]->misc|=SUB_PNET;
-                                break; }
-                            if(n==1 && sub[i]->misc&SUB_PNET) {
-                                changes=1;
-                                sub[i]->misc&=~SUB_PNET; }
-                            break;
-						case 7:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Sub-board Networked via FidoNet EchoMail:
-
-If this sub-board is part of a FidoNet EchoMail conference, set this
-option to Yes.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Networked via FidoNet EchoMail",opt);
-							if(n==-1)
-                                break;
-							if(!n && !(sub[i]->misc&SUB_FIDO)) {
-								changes=1;
-								sub[i]->misc|=SUB_FIDO;
-								break; }
-							if(n==1 && sub[i]->misc&SUB_FIDO) {
-								changes=1;
-								sub[i]->misc&=~SUB_FIDO; }
-                            break;
-						case 8:
-							strcpy(str,faddrtoa(sub[i]->faddr));
-							SETHELP(WHERE);
-/*
-Sub-board FidoNet Address:
-
-If this sub-board is part of a FidoNet EchoMail conference, this is
-the address used for this sub-board. Format: Zone:Net/Node[.Point]
-*/
-							uinput(WIN_MID|WIN_SAV,0,0,"FidoNet Address"
-								,str,20,K_EDIT);
-							sub[i]->faddr=atofaddr(str);
-							break;
-						case 9:
-							SETHELP(WHERE);
-/*
-Sub-board FidoNet Origin Line:
-
-If this sub-board is part of a FidoNet EchoMail conference and you
-want to use an origin line other than the default origin line in the
-Networks configuration, set this value to the desired origin line.
-
-If this option is blank, the default origin line is used.
-*/
-							uinput(WIN_MID|WIN_SAV,0,0,nulstr,sub[i]->origline
-								,50,K_EDIT);
-                            break;
-						case 10:
-							SETHELP(WHERE);
-/*
-Sub-board EchoMail Storage Directory:
-
-This is the storage directory where FidoNet style (FTS-0001 stored
-message format) messages are imported from and exported to for this
-sub-board. If this option is blank, then the EchoMail Base Directory is
-used with the internal code of this sub-board as the sub-directory where
-the FidoNet messages are stored.
-*/
-
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"EchoMail Directory"
-								,sub[i]->echopath,50,K_UPPER|K_EDIT);
-							break;
-						case 11:
-SETHELP(WHERE);
-/*
-EchoMail Semaphore File:
-
-This is a filename that will be used as a semaphore (signal) to your
-FidoNet front-end that new EchoMail has been created and the messages
-should be re-scanned.
-*/
-							uinput(WIN_MID|WIN_SAV,0,17,"EchoMail Semaphore"
-								,sub[i]->echomail_sem,50,K_EDIT|K_UPPER);
-							break; } }
-				break;
-			case 14:
-				while(1) {
-					n=0;
-					if(sub[i]->qwkconf)
-						sprintf(str,"Static (%u)",sub[i]->qwkconf);
-					else
-						strcpy(str,"Dynamic");
-					sprintf(opt[n++],"%-27.27s%s","QWK Conference Number"
-						,str);
-					sprintf(opt[n++],"%-27.27s%s","Storage Method"
-						,sub[i]->misc&SUB_HYPER ? "Hyper Allocation"
-						: sub[i]->misc&SUB_FAST ? "Fast Allocation"
-						: "Self-packing");
-					if(!sub[i]->data_dir[0])
-						sprintf(str,"%sSUBS\\",data_dir);
-					else
-						strcpy(str,sub[i]->data_dir);
-					sprintf(opt[n++],"%-27.27s%.40s","Storage Directory",str);
-					opt[n][0]=0;
-					savnum=2;
-					SETHELP(WHERE);
-/*
-Sub-board Advanced Options:
-
-This menu contains options for the selected sub-board that are advanced
-in nature.
-*/
-					n=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,3,2,60,&adv_dflt,0
-						,"Advanced Options",opt);
-					if(n==-1)
-						break;
-					savnum=3;
-                    switch(n) {
-                        case 0:
-							SETHELP(WHERE);
-/*
-Sub-board QWK Conference Number:
-
-If you wish to have the QWK conference number for this sub-board
-automatically generated by Synchronet (based on the group number
-and sub-board number for the user), set this option to Dynamic.
-
-If you wish to have the same QWK conference number for this sub-board
-regardless of which user access it, set this option to Static
-by entering the conference number you want to use.
-*/
-							if(sub[i]->qwkconf)
-								sprintf(str,"%u",sub[i]->qwkconf);
-							else
-								str[0]=0;
-							if(uinput(WIN_MID|WIN_SAV,0,17
-								,"QWK Conference Number (0=Dynamic)"
-								,str,5,K_EDIT|K_NUMBER)>=0)
-								sub[i]->qwkconf=atoi(str);
-							break;
-						case 1:
-							n=0;
-							strcpy(opt[0],"Hyper Allocation");
-							strcpy(opt[1],"Fast Allocation");
-							strcpy(opt[2],"Self-packing");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Self-Packing is the slowest storage method because it conserves disk
-  space as it imports messages by using deleted message header and data
-  blocks for new messages automatically. If you use this storage method,
-  you will not need to run SMBUTIL P on this message base unless you
-  accumilate a large number of deleted message blocks and wish to free
-  that disk space. You can switch from self-packing to fast allocation
-  storage method and back again as you wish.
-Fast Allocation is faster than self-packing because it does not search
-  for deleted message blocks for new messages. It automatically places
-  all new message blocks at the end of the header and data files. If you
-  use this storage method, you will need to run SMBUTIL P on this
-  message base periodically or it will continually use up disk space.
-Hyper Allocation is the fastest storage method because it does not
-  maintain allocation files at all. Once a message base is setup to use
-  this storage method, it should not be changed without first deleting
-  the message base data files in your DATA\DIRS\SUBS directory for this
-  sub-board. You must use SMBUTIL P as with the fast allocation method.
-*/
-							n=ulist(WIN_SAV|WIN_MID,0,0,0,&n,0
-								,"Storage Method",opt);
-							if(n==-1)
-								break;
-							if(!n && !(sub[i]->misc&SUB_HYPER)) {
-								changes=1;
-								sub[i]->misc|=SUB_HYPER;
-								sub[i]->misc&=~SUB_FAST;
-								sub[i]->misc|=SUB_HDRMOD;
-								break; }
-							if(!n)
-								break;
-							if(sub[i]->misc&SUB_HYPER) {	/* Switching from hyper */
-								strcpy(opt[0],"Yes");
-								strcpy(opt[1],"No, I want to use Hyper Allocation");
-								opt[2][0]=0;
-								m=0;
-								if(ulist(WIN_SAV|WIN_MID,0,0,0,&m,0
-									,"Delete all messages in this sub-board?",opt)!=0)
-									break;
-								if(sub[i]->data_dir[0])
-									sprintf(str,"%s",sub[i]->data_dir);
-								else
-									sprintf(str,"%sSUBS\\",data_dir);
-								sprintf(str2,"%s.*",sub[i]->code);
-								delfiles(str,str2); }
-
-							if(sub[i]->misc&SUB_HYPER)
-								sub[i]->misc|=SUB_HDRMOD;
-							if(n==1 && !(sub[i]->misc&SUB_FAST)) {
-								changes=1;
-								sub[i]->misc|=SUB_FAST;
-								sub[i]->misc&=~SUB_HYPER;
-								break; }
-							if(n==2 && sub[i]->misc&(SUB_FAST|SUB_HYPER)) {
-								changes=1;
-								sub[i]->misc&=~(SUB_FAST|SUB_HYPER);
-								break; }
-							break;
-						case 2:
-							SETHELP(WHERE);
-/*
-Sub-board Storage Directory:
-
-Use this if you wish to place the data directory for this sub-board on
-another drive or in another directory besides the default setting.
-*/
-							uinput(WIN_MID|WIN_SAV,0,17,"Directory"
-								,sub[i]->data_dir,50,K_EDIT|K_UPPER);
-							break; } }
-				break;
-				} } }
-}
diff --git a/src/sbbs2/scfg/scfgsys.c b/src/sbbs2/scfg/scfgsys.c
deleted file mode 100644
index 4f6a595e3998ceffc603edf14a1c3bd8cf32d653..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgsys.c
+++ /dev/null
@@ -1,1790 +0,0 @@
-#line 2 "SCFGSYS.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-void sys_cfg(void)
-{
-	static int sys_dflt,adv_dflt,tog_dflt,new_dflt;
-	char str[81],str2[81],done=0,*dupehelp;
-	int i,j,k,dflt,bar,savchanges;
-
-while(1) {
-	i=0;
-	sprintf(opt[i++],"%-33.33s%s","BBS Name",sys_name);
-	sprintf(opt[i++],"%-33.33s%s","Location",sys_location);
-	sprintf(opt[i++],"%-33.33s%s","Operator",sys_op);
-	sprintf(opt[i++],"%-33.33s%s","Password",sys_pass);
-
-	sprintf(str,"%s Password"
-		,sys_misc&SM_PWEDIT && sys_pwdays ? "Users Must Change"
-		: sys_pwdays ? "Users Get New Random" : "Users Can Change");
-	if(sys_pwdays)
-		sprintf(tmp,"Every %u Days",sys_pwdays);
-	else if(sys_misc&SM_PWEDIT)
-		strcpy(tmp,"Yes");
-	else
-		strcpy(tmp,"No");
-	sprintf(opt[i++],"%-33.33s%s",str,tmp);
-
-	sprintf(opt[i++],"%-33.33s%u","Days to Preserve Deleted Users"
-		,sys_deldays);
-	sprintf(opt[i++],"%-33.33s%s","Maximum Days of Inactivity"
-		,sys_autodel ? itoa(sys_autodel,tmp,10) : "Unlimited");
-    sprintf(opt[i++],"%-33.33s%s","New User Password",new_pass);
-
-	strcpy(opt[i++],"Toggle Options...");
-	strcpy(opt[i++],"New User Values...");
-	strcpy(opt[i++],"Advanced Options...");
-	strcpy(opt[i++],"Loadable Modules...");
-	strcpy(opt[i++],"Security Level Values...");
-	strcpy(opt[i++],"Expired Account Values...");
-	strcpy(opt[i++],"Quick-Validation Values...");
-	opt[i][0]=0;
-	SETHELP(WHERE);
-/*
-System Configuration:
-
-This menu contains options and sub-menus of options that affect the
-entire system.
-*/
-	switch(ulist(WIN_ORG|WIN_ACT|WIN_CHE,0,0,72,&sys_dflt,0
-		,"System Configuration",opt)) {
-		case -1:
-			i=save_changes(WIN_MID);
-			if(i==-1)
-				break;
-			if(!i)
-				write_main_cfg();
-			return;
-		case 0:
-			SETHELP(WHERE);
-/*
-BBS Name:
-
-This is the name of the BBS.
-*/
-			uinput(WIN_MID,0,0,"BBS Name",sys_name,40,K_EDIT);
-			break;
-		case 1:
-			SETHELP(WHERE);
-/*
-System Location:
-
-This is the location of the BBS. The format is flexible, but it is
-suggested you use the City, State format for clarity.
-*/
-			uinput(WIN_MID,0,0,"Location",sys_location,40,K_EDIT);
-            break;
-		case 2:
-			SETHELP(WHERE);
-/*
-System Operator:
-
-This is the name or alias of the system operator. This does not have to
-be the same as user #1. This field is used for documentary purposes
-only.
-*/
-			uinput(WIN_MID,0,0,"System Operator",sys_op,40,K_EDIT);
-			break;
-		case 3:
-			SETHELP(WHERE);
-/*
-System Password:
-
-This is an extra security password required for sysop logon and certain
-sysop functions. This password should be something not easily guessed
-and should be kept absolutely confidential. This password must be
-entered at the SY: prompt.
-*/
-			uinput(WIN_MID,0,0,"System Password",sys_pass,40,K_EDIT|K_UPPER);
-			break;
-		case 4:
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			i=1;
-			SETHELP(WHERE);
-/*
-Allow Users to Change Their Password:
-
-If you want the users of your system to have the option of changing
-their password to a string of their choice, set this option to Yes.
-For the highest level of security, set this option to No.
-*/
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-				,"Allow Users to Change Their Password",opt);
-			if(!i && !(sys_misc&SM_PWEDIT)) {
-				sys_misc|=SM_PWEDIT;
-				changes=1; }
-			else if(i==1 && sys_misc&SM_PWEDIT) {
-                sys_misc&=~SM_PWEDIT;
-                changes=1; }
-			i=0;
-			SETHELP(WHERE);
-/*
-Force Periodic Password Changes:
-
-If you want your users to be forced to change their passwords
-periodically, select Yes.
-*/
-			i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-				,"Force Periodic Password Changes",opt);
-			if(!i) {
-				itoa(sys_pwdays,str,10);
-			SETHELP(WHERE);
-/*
-Maximum Days Between Password Changes:
-
-Enter the maximum number of days allowed between password changes.
-If a user has not voluntarily changed his or her password in this
-many days, he or she will be forced to change their password upon
-logon.
-*/
-				uinput(WIN_MID,0,0,"Maximum Days Between Password Changes"
-					,str,5,K_NUMBER|K_EDIT);
-				sys_pwdays=atoi(str); }
-			else if(i==1 && sys_pwdays) {
-				sys_pwdays=0;
-				changes=1; }
-			
-			break;
-		case 5:
-			sprintf(str,"%u",sys_deldays);
-			SETHELP(WHERE);
-/*
-Days Since Last Logon to Preserve Deleted Users:
-
-Deleted user slots can be undeleted until the slot is written over
-by a new user. If you want deleted user slots to be preserved for period
-of time since their last logon, set this value to the number of days to
-keep new users from taking over a deleted user's slot.
-*/
-			uinput(WIN_MID,0,0,"Days Since Last Logon to Preserve Deleted Users"
-				,str,5,K_EDIT|K_NUMBER);
-			sys_deldays=atoi(str);
-			break;
-		case 6:
-			sprintf(str,"%u",sys_autodel);
-			SETHELP(WHERE);
-/*
-Maximum Days of Inactivity Before Auto-Deletion:
-
-If you want users that haven't logged on in certain period of time to
-be automatically deleted, set this value to the maximum number of days
-of inactivity before the user is deleted. Setting this value to 0
-disables this feature.
-
-Users with the P exemption will not be deleted due to inactivity.
-*/
-			uinput(WIN_MID,0,0,"Maximum Days of Inactivity Before Auto-Deletion"
-				,str,5,K_EDIT|K_NUMBER);
-			sys_autodel=atoi(str);
-            break;
-		case 7:
-			SETHELP(WHERE);
-/*
-New User Password:
-
-If you want callers to only be able to logon as New if they know a
-certain password, enter that password here. If you want any caller to
-be able to logon as New, leave this option blank.
-*/
-			uinput(WIN_MID,0,0,"New User Password",new_pass,40
-				,K_EDIT|K_UPPER);
-			break;
-		case 8:    /* Toggle Options */
-            done=0;
-            while(!done) {
-                i=0;
-				sprintf(opt[i++],"%-33.33s%s","Allow Aliases"
-					,uq&UQ_ALIASES ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Allow Time Banking"
-					,sys_misc&SM_TIMEBANK ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Allow Credit Conversions"
-					,sys_misc&SM_NOCDTCVT ? "No" : "Yes");
-				sprintf(opt[i++],"%-33.33s%s","Allow Local Sysop Access"
-					,sys_misc&SM_L_SYSOP ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Allow Remote Sysop Access"
-					,sys_misc&SM_R_SYSOP ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Echo Passwords Locally"
-					,sys_misc&SM_ECHO_PW ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Require Passwords Locally"
-					,sys_misc&SM_REQ_PW ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Short Sysop Page"
-					,sys_misc&SM_SHRTPAGE ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Sound Alarm on Error"
-					,sys_misc&SM_ERRALARM ? "Yes" : "No");
-                sprintf(opt[i++],"%-33.33s%s","Include Sysop in Statistics"
-                    ,sys_misc&SM_SYSSTAT ? "Yes" : "No");
-                sprintf(opt[i++],"%-33.33s%s","Closed to New Users"
-                    ,sys_misc&SM_CLOSED ? "Yes" : "No");
-                sprintf(opt[i++],"%-33.33s%s","Use Location in User Lists"
-					,sys_misc&SM_LISTLOC ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Military (24 hour) Time Format"
-					,sys_misc&SM_MILITARY ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","European Date Format (DD/MM/YY)"
-					,sys_misc&SM_EURODATE ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","User Expires When Out-of-time"
-					,sys_misc&SM_TIME_EXP ? "Yes" : "No");
-				sprintf(opt[i++],"%-33.33s%s","Quick Validation Hot-Keys"
-					,sys_misc&SM_QVALKEYS ? "Yes" : "No");
-				opt[i][0]=0;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-System Toggle Options:
-
-This is a menu of system related options that can be toggled between
-two or more states, such as Yes and No.
-*/
-				switch(ulist(WIN_ACT|WIN_BOT|WIN_RHT,0,0,41,&tog_dflt,0
-                    ,"Toggle Options",opt)) {
-                    case -1:
-                        done=1;
-                        break;
-					case 0:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Allow Users to Use Aliases:
-
-If you want the users of your system to be allowed to be known by a
-false name, handle, or alias, set this option to Yes. If you want all
-users on your system to be known only by their real names, select No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Allow Users to Use Aliases",opt);
-						if(!i && !(uq&UQ_ALIASES)) {
-							uq|=UQ_ALIASES;
-							changes=1; }
-						else if(i==1 && uq&UQ_ALIASES) {
-							uq&=~UQ_ALIASES;
-							changes=1; }
-						break;
-					case 1:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Allow Time Banking:
-
-If you want the users of your system to be allowed to be deposit
-any extra time they may have left during a call into their minute bank,
-set this option to Yes. If this option is set to No, then the only
-way a user may get minutes in their minute bank is to purchase them
-with credits.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Allow Users to Depost Time in Minute Bank",opt);
-						if(!i && !(sys_misc&SM_TIMEBANK)) {
-							sys_misc|=SM_TIMEBANK;
-							changes=1; }
-						else if(i==1 && sys_misc&SM_TIMEBANK) {
-							sys_misc&=~SM_TIMEBANK;
-							changes=1; }
-                        break;
-					case 2:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Allow Credits to be Converted into Minutes:
-
-If you want the users of your system to be allowed to be convert
-any credits they may have into minutes for their minute bank,
-set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Allow Users to Convert Credits into Minutes"
-							,opt);
-						if(!i && sys_misc&SM_NOCDTCVT) {
-							sys_misc&=~SM_NOCDTCVT;
-							changes=1; }
-						else if(i==1 && !(sys_misc&SM_NOCDTCVT)) {
-							sys_misc|=SM_NOCDTCVT;
-							changes=1; }
-                        break;
-					case 3:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Allow Local Sysop Access:
-
-If you want to be able to logon locally with sysop access, set this
-option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Allow Local Sysop Access",opt);
-						if(!i && !(sys_misc&SM_L_SYSOP)) {
-							sys_misc|=SM_L_SYSOP;
-							changes=1; }
-						else if(i==1 && sys_misc&SM_L_SYSOP) {
-							sys_misc&=~SM_L_SYSOP;
-							changes=1; }
-                        break;
-					case 4:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Allow Remote Sysop Access:
-
-If you want to be able to logon remotely with sysop access, set this
-option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Allow Remote Sysop Access",opt);
-						if(!i && !(sys_misc&SM_R_SYSOP)) {
-							sys_misc|=SM_R_SYSOP;
-							changes=1; }
-						else if(i==1 && sys_misc&SM_R_SYSOP) {
-							sys_misc&=~SM_R_SYSOP;
-							changes=1; }
-                        break;
-					case 5:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Echo Passwords Locally:
-
-If you want to passwords to be displayed locally, set this option to
-Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Echo Passwords Locally",opt);
-						if(!i && !(sys_misc&SM_ECHO_PW)) {
-							sys_misc|=SM_ECHO_PW;
-							changes=1; }
-						else if(i==1 && sys_misc&SM_ECHO_PW) {
-							sys_misc&=~SM_ECHO_PW;
-							changes=1; }
-                        break;
-					case 6:
-						strcpy(opt[0],"Yes");
-						strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=0;
-						SETHELP(WHERE);
-/*
-Require Passwords Locally:
-
-If you want to passwords to be required when logged on locally, set this
-option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Require Passwords Locally",opt);
-						if(!i && !(sys_misc&SM_REQ_PW)) {
-							sys_misc|=SM_REQ_PW;
-							changes=1; }
-						else if(i==1 && sys_misc&SM_REQ_PW) {
-							sys_misc&=~SM_REQ_PW;
-							changes=1; }
-                        break;
-					case 7:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-                        i=0;
-						SETHELP(WHERE);
-/*
-Short Sysop Page:
-
-If you would like the sysop page to be a short series of beeps rather
-than continuous random tones, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Short Sysop Page"
-							,opt);
-						if(i==1 && sys_misc&SM_SHRTPAGE) {
-							sys_misc&=~SM_SHRTPAGE;
-                            changes=1; }
-						else if(!i && !(sys_misc&SM_SHRTPAGE)) {
-							sys_misc|=SM_SHRTPAGE;
-                            changes=1; }
-						break;
-					case 8:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-                        i=0;
-						SETHELP(WHERE);
-/*
-Sound Alarm on Error:
-
-If you would like to have an alarm sounded locally when a critical
-system error has occured, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Sound Alarm on Error",opt);
-						if(i==1 && sys_misc&SM_ERRALARM) {
-							sys_misc&=~SM_ERRALARM;
-                            changes=1; }
-						else if(!i && !(sys_misc&SM_ERRALARM)) {
-							sys_misc|=SM_ERRALARM;
-                            changes=1; }
-                        break;
-					case 9:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-                        i=1;
-						SETHELP(WHERE);
-/*
-Include Sysop Activity in System Statistics:
-
-If you want sysops to be included in the statistical data of the BBS,
-set this option to Yes. The suggested setting for this option is
-No so that statistical data will only reflect user usage and not
-include sysop maintenance activity.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Include Sysop Activity in System Statistics"
-							,opt);
-                        if(!i && !(sys_misc&SM_SYSSTAT)) {
-                            sys_misc|=SM_SYSSTAT;
-                            changes=1; }
-                        else if(i==1 && sys_misc&SM_SYSSTAT) {
-                            sys_misc&=~SM_SYSSTAT;
-                            changes=1; }
-                        break;
-					case 10:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-                        i=1;
-						SETHELP(WHERE);
-/*
-Closed to New Users:
-
-If you want callers to be able to logon as New, set this option to No.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Closed to New Users",opt);
-                        if(!i && !(sys_misc&SM_CLOSED)) {
-                            sys_misc|=SM_CLOSED;
-                            changes=1; }
-                        else if(i==1 && sys_misc&SM_CLOSED) {
-                            sys_misc&=~SM_CLOSED;
-                            changes=1; }
-                        break;
-					case 11:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-                        i=0;
-						SETHELP(WHERE);
-/*
-User Location in User Lists:
-
-If you want user locations (city, state) displayed in the user lists,
-set this option to Yes. If this option is set to No, the user notes
-(if they exist) are displayed in the user lists.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-                            ,"User Location (Instead of Note) in User Lists"
-                            ,opt);
-						if(!i && !(sys_misc&SM_LISTLOC)) {
-							sys_misc|=SM_LISTLOC;
-                            changes=1; }
-						else if(i==1 && sys_misc&SM_LISTLOC) {
-							sys_misc&=~SM_LISTLOC;
-                            changes=1; }
-                        break;
-					case 12:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=1;
-						SETHELP(WHERE);
-/*
-Military:
-
-If you would like the time-of-day to be displayed and entered in 24 hour
-format always, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Use Military Time Format",opt);
-						if(!i && !(sys_misc&SM_MILITARY)) {
-							sys_misc|=SM_MILITARY;
-                            changes=1; }
-						else if(i==1 && sys_misc&SM_MILITARY) {
-							sys_misc&=~SM_MILITARY;
-                            changes=1; }
-                        break;
-					case 13:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=1;
-						SETHELP(WHERE);
-/*
-European Date Format:
-
-If you would like dates to be displayed and entered in DD/MM/YY format
-instead of MM/DD/YY format, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"European Date Format",opt);
-						if(!i && !(sys_misc&SM_EURODATE)) {
-							sys_misc|=SM_EURODATE;
-                            changes=1; }
-						else if(i==1 && sys_misc&SM_EURODATE) {
-							sys_misc&=~SM_EURODATE;
-                            changes=1; }
-                        break;
-
-					case 14:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=1;
-						SETHELP(WHERE);
-/*
-User Expires When Out-of-time:
-
-If you want users to be set to Expired User Values if they run out of
-time online, then set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"User Expires When Out-of-time",opt);
-						if(!i && !(sys_misc&SM_TIME_EXP)) {
-							sys_misc|=SM_TIME_EXP;
-                            changes=1; }
-						else if(i==1 && sys_misc&SM_TIME_EXP) {
-							sys_misc&=~SM_TIME_EXP;
-                            changes=1; }
-                        break;
-
-					case 15:
-                        strcpy(opt[0],"Yes");
-                        strcpy(opt[1],"No");
-						opt[2][0]=0;
-						i=1;
-						SETHELP(WHERE);
-/*
-Quick Validation Hot-Keys:
-
-If you would like to enable the Alt-# hot-keys for quick user
-validation, set this option to Yes.
-*/
-						i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0
-							,"Quick Validation Hot-Keys",opt);
-						if(!i && !(sys_misc&SM_QVALKEYS)) {
-							sys_misc|=SM_QVALKEYS;
-                            changes=1; }
-						else if(i==1 && sys_misc&SM_QVALKEYS) {
-							sys_misc&=~SM_QVALKEYS;
-                            changes=1; }
-                        break;
-
-						} }
-            break;
-		case 9:    /* New User Values */
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%u","Level",new_level);
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #1"
-					,ltoaf(new_flags1,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #2"
-					,ltoaf(new_flags2,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #3"
-					,ltoaf(new_flags3,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #4"
-					,ltoaf(new_flags4,str));
-				sprintf(opt[i++],"%-27.27s%s","Exemptions"
-					,ltoaf(new_exempt,str));
-				sprintf(opt[i++],"%-27.27s%s","Restrictions"
-					,ltoaf(new_rest,str));
-				sprintf(opt[i++],"%-27.27s%s","Expiration Days"
-					,itoa(new_expire,str,10));
-
-				ultoac(new_cdt,str);
-				sprintf(opt[i++],"%-27.27s%s","Credits",str);
-				ultoac(new_min,str);
-				sprintf(opt[i++],"%-27.27s%s","Minutes",str);
-				sprintf(opt[i++],"%-27.27s%s","Editor"
-					,new_xedit);
-				sprintf(opt[i++],"%-27.27s%s","Command Shell"
-					,shell[new_shell]->code);
-				if(new_prot!=SP)
-                    sprintf(str,"%c",new_prot);
-                else
-                    strcpy(str,"None");
-				sprintf(opt[i++],"%-27.27s%s","Download Protocol",str);
-				strcpy(opt[i++],"Default Toggles...");
-				strcpy(opt[i++],"Question Toggles...");
-				opt[i][0]=0;
-				SETHELP(WHERE);
-/*
-New User Values:
-
-This menu allows you to determine the default settings for new users.
-*/
-				switch(ulist(WIN_ACT|WIN_BOT|WIN_RHT,0,0,60,&new_dflt,0
-					,"New User Values",opt)) {
-					case -1:
-						done=1;
-						break;
-					case 0:
-						itoa(new_level,str,10);
-						SETHELP(WHERE);
-/*
-New User Security Level:
-
-This is the security level automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Security Level"
-							,str,2,K_EDIT|K_NUMBER);
-						new_level=atoi(str);
-						break;
-					case 1:
-						ltoaf(new_flags1,str);
-						SETHELP(WHERE);
-/*
-New User Security Flags:
-
-These are the security flags automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flag Set #1"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						new_flags1=aftol(str);
-						break;
-					case 2:
-						ltoaf(new_flags2,str);
-						SETHELP(WHERE);
-/*
-New User Security Flags:
-
-These are the security flags automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flag Set #2"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						new_flags2=aftol(str);
-                        break;
-					case 3:
-						ltoaf(new_flags3,str);
-						SETHELP(WHERE);
-/*
-New User Security Flags:
-
-These are the security flags automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flag Set #3"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						new_flags3=aftol(str);
-                        break;
-					case 4:
-						ltoaf(new_flags4,str);
-						SETHELP(WHERE);
-/*
-New User Security Flags:
-
-These are the security flags automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flag Set #4"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						new_flags4=aftol(str);
-                        break;
-					case 5:
-						ltoaf(new_exempt,str);
-						SETHELP(WHERE);
-/*
-New User Exemption Flags:
-
-These are the exemptions that are automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Exemption Flags",str,26
-							,K_EDIT|K_UPPER|K_ALPHA);
-						new_exempt=aftol(str);
-						break;
-					case 6:
-						ltoaf(new_rest,str);
-						SETHELP(WHERE);
-/*
-New User Restriction Flags:
-
-These are the restrictions that are automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Restriction Flags",str,26
-							,K_EDIT|K_UPPER|K_ALPHA);
-						new_rest=aftol(str);
-						break;
-					case 7:
-						itoa(new_expire,str,10);
-						SETHELP(WHERE);
-/*
-New User Expiration Days:
-
-If you wish new users to have an automatic expiration date, set this
-value to the number of days before the user will expire. To disable
-New User expiration, set this value to 0.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Expiration Days",str,4
-							,K_EDIT|K_NUMBER);
-						new_expire=atoi(str);
-						break;
-					case 8:
-						ultoa(new_cdt,str,10);
-						SETHELP(WHERE);
-/*
-New User Credits:
-
-This is the amount of credits that are automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Credits",str,10
-							,K_EDIT|K_NUMBER);
-						new_cdt=atol(str);
-                        break;
-					case 9:
-						ultoa(new_min,str,10);
-						SETHELP(WHERE);
-/*
-New User Minutes:
-
-This is the number of extra minutes automatically given to new users.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Minutes (Time Credit)"
-							,str,10,K_EDIT|K_NUMBER);
-						new_min=atol(str);
-						break;
-					case 10:
-						if(!total_xedits) {
-							umsg("No External Editors Configured");
-							break; }
-						strcpy(opt[0],"Internal");
-						for(i=1;i<=total_xedits;i++)
-							strcpy(opt[i],xedit[i-1]->code);
-						opt[i][0]=0;
-						i=0;
-						savnum=0;
-						SETHELP(WHERE);
-/*
-New User Editor:
-
-You can use this option to select the default editor for new users.
-*/
-						i=ulist(WIN_SAV|WIN_RHT,2,1,13,&i,0,"Editors",opt);
-						if(i==-1)
-							break;
-						changes=1;
-						if(i && i<=total_xedits)
-							sprintf(new_xedit,"%-.8s",xedit[i-1]->code);
-						else
-							new_xedit[0]=0;
-						break;
-					case 11:
-						for(i=0;i<total_shells && i<MAX_OPTS;i++)
-							sprintf(opt[i],"%-.8s",shell[i]->code);
-						opt[i][0]=0;
-						i=0;
-						savnum=0;
-						SETHELP(WHERE);
-/*
-New User Command Shell:
-
-You can use this option to select the default command shell for new
-users.
-*/
-						i=ulist(WIN_SAV|WIN_RHT,2,1,13,&i,0
-							,"Command Shells",opt);
-						if(i==-1)
-							break;
-						new_shell=i;
-						changes=1;
-						break;
-					case 12:
-						SETHELP(WHERE);
-/*
-New User Default Download Protocol:
-
-This option allows you to set the default download protocol of new users
-(protocol command key or BLANK for no default).
-*/
-						sprintf(str,"%c",new_prot);
-						uinput(WIN_SAV|WIN_MID,0,0
-							,"Default Download Protocol (SPACE=Disabled)"
-							,str,1,K_EDIT|K_UPPER);
-						new_prot=str[0];
-						if(new_prot<SP)
-							new_prot=SP;
-                        break;
-					case 13:
-						SETHELP(WHERE);
-/*
-New User Default Toggle Options:
-
-This menu contains the default state of new user toggle options. All new
-users on your system will have their defaults set according to the
-settings on this menu. The user can then change them to his or her
-liking.
-
-See the Synchronet User Manual for more information on the individual
-options available.
-*/
-						j=0;
-                        while(1) {
-                            i=0;
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Expert Menu Mode"
-								,new_misc&EXPERT ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Screen Pause"
-								,new_misc&UPAUSE ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Spinning Cursor"
-								,new_misc&SPIN ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Clear Screen"
-								,new_misc&CLRSCRN ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Ask For New Scan"
-								,new_misc&ASK_NSCAN ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Ask For Your Msg Scan"
-								,new_misc&ASK_SSCAN ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Automatic New File Scan"
-								,new_misc&ANFSCAN ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Remember Current Sub-board"
-								,new_misc&CURSUB ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Batch Download File Flag"
-								,new_misc&BATCHFLAG ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Extended File Descriptions"
-								,new_misc&EXTDESC ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Hot Keys"
-								,new_misc&COLDKEYS ? "No":"Yes");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Auto Hang-up After Xfer"
-								,new_misc&AUTOHANG ? "Yes":"No");
-							opt[i][0]=0;
-							j=ulist(WIN_BOT|WIN_RHT,2,1,0,&j,0
-								,"Default Toggle Options",opt);
-                            if(j==-1)
-                                break;
-                            changes=1;
-                            switch(j) {
-                                case 0:
-									new_misc^=EXPERT;
-                                    break;
-								case 1:
-									new_misc^=UPAUSE;
-									break;
-								case 2:
-									new_misc^=SPIN;
-									break;
-								case 3:
-									new_misc^=CLRSCRN;
-									break;
-								case 4:
-									new_misc^=ASK_NSCAN;
-									break;
-								case 5:
-									new_misc^=ASK_SSCAN;
-                                    break;
-								case 6:
-									new_misc^=ANFSCAN;
-									break;
-								case 7:
-									new_misc^=CURSUB;
-									break;
-								case 8:
-									new_misc^=BATCHFLAG;
-									break;
-								case 9:
-									new_misc^=EXTDESC;
-                                    break;
-								case 10:
-									new_misc^=COLDKEYS;
-                                    break;
-								case 11:
-									new_misc^=AUTOHANG;
-                                    break;
-									} }
-						break;
-					case 14:
-						SETHELP(WHERE);
-/*
-New User Question Toggle Options:
-
-This menu allows you to decide which questions will be asked of a new
-user.
-*/
-						j=0;
-                        while(1) {
-                            i=0;
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Real Name"
-								,uq&UQ_REALNAME ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Force Unique Real Name"
-								,uq&UQ_DUPREAL ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Company Name"
-								,uq&UQ_COMPANY ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Multinode Chat Handle"
-								,uq&UQ_HANDLE ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Force Unique Chat Handle"
-								,uq&UQ_DUPHAND ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Sex (Gender)"
-								,uq&UQ_SEX ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Birthday"
-								,uq&UQ_BIRTH ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Address and Zip Code"
-								,uq&UQ_ADDRESS ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Location"
-								,uq&UQ_LOCATION ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Require Comma in Location"
-								,uq&UQ_NOCOMMAS ? "No":"Yes");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Phone Number"
-								,uq&UQ_PHONE ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Computer Type"
-								,uq&UQ_COMP ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Multiple Choice Computer"
-								,uq&UQ_MC_COMP ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Allow EX-ASCII in Answers"
-								,uq&UQ_NOEXASC ? "No":"Yes");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"External Editor"
-								,uq&UQ_XEDIT ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Command Shell"
-								,uq&UQ_CMDSHELL ? "Yes":"No");
-							sprintf(opt[i++],"%-27.27s %-3.3s"
-								,"Default Settings"
-								,uq&UQ_NODEF ? "No":"Yes");
-							opt[i][0]=0;
-							j=ulist(WIN_BOT|WIN_RHT|WIN_SAV,2,1,0,&j,0
-								,"New User Questions",opt);
-                            if(j==-1)
-                                break;
-                            changes=1;
-                            switch(j) {
-                                case 0:
-									uq^=UQ_REALNAME;
-                                    break;
-								case 1:
-									uq^=UQ_DUPREAL;
-									break;
-								case 2:
-									uq^=UQ_COMPANY;
-                                    break;
-								case 3:
-									uq^=UQ_HANDLE;
-                                    break;
-								case 4:
-									uq^=UQ_DUPHAND;
-									break;
-								case 5:
-									uq^=UQ_SEX;
-									break;
-								case 6:
-									uq^=UQ_BIRTH;
-									break;
-								case 7:
-									uq^=UQ_ADDRESS;
-									break;
-								case 8:
-									uq^=UQ_LOCATION;
-									break;
-								case 9:
-									uq^=UQ_NOCOMMAS;
-									break;
-								case 10:
-									uq^=UQ_PHONE;
-									break;
-								case 11:
-									uq^=UQ_COMP;
-									break;
-								case 12:
-									uq^=UQ_MC_COMP;
-									break;
-								case 13:
-									uq^=UQ_NOEXASC;
-									break;
-								case 14:
-									uq^=UQ_XEDIT;
-                                    break;
-								case 15:
-									uq^=UQ_CMDSHELL;
-                                    break;
-								case 16:
-									uq^=UQ_NODEF;
-                                    break;
-									} }
-						break; } }
-			break;
-		case 10:	/* Advanced Options */
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%s","New User Magic Word",new_magic);
-				sprintf(opt[i++],"%-27.27s%.40s","Data Directory",data_dir);
-				sprintf(opt[i++],"%-27.27s%.40s","Executables Directory"
-					,exec_dir);
-				sprintf(opt[i++],"%-27.27s%s","Input SIF Questionnaire"
-					,new_sif);
-				sprintf(opt[i++],"%-27.27s%s","Output SIF Questionnaire"
-					,new_sof);
-				ultoac(cdt_per_dollar,str);
-				sprintf(opt[i++],"%-27.27s%s","Credits Per Dollar",str);
-				sprintf(opt[i++],"%-27.27s%u","Minutes Per 100k Credits"
-					,cdt_min_value);
-				sprintf(opt[i++],"%-27.27s%s","Maximum Number of Minutes"
-					,max_minutes ? ltoa(max_minutes,tmp,10) : "Unlimited");
-				sprintf(opt[i++],"%-27.27s%u","Warning Days Till Expire"
-					,sys_exp_warn);
-				sprintf(opt[i++],"%-27.27s%u","Default Status Line"
-					,sys_def_stat);
-				sprintf(opt[i++],"%-27.27s%u","Last Displayable Node"
-					,sys_lastnode);
-				sprintf(opt[i++],"%-27.27s%u","First Local Auto-Node"
-					,sys_autonode);
-				sprintf(opt[i++],"%-27.27s%s","Phone Number Format"
-					,sys_phonefmt);
-				sprintf(opt[i++],"%-27.27s%.40s","Sysop Chat Requirements"
-					,sys_chat_ar);
-				opt[i][0]=0;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-System Advanced Options:
-
-Care should be taken when modifying any of the options listed here.
-*/
-				switch(ulist(WIN_ACT|WIN_BOT|WIN_RHT,0,0,60,&adv_dflt,0
-					,"Advanced Options",opt)) {
-					case -1:
-						done=1;
-                        break;
-
-					case 0:
-						SETHELP(WHERE);
-/*
-New User Magic Word:
-
-If this field has a value, it is assumed the sysop has placed some
-reference to this magic word in TEXT\NEWUSER.MSG and new users
-will be prompted for the magic word after they enter their password.
-If they do not enter it correctly, it is assumed they didn't read the
-new user information displayed to them and they are disconnected.
-
-Think of it as a password to guarantee that new users read the text
-displayed to them.
-*/
-						uinput(WIN_MID,0,0,"New User Magic Word",new_magic,20
-							,K_EDIT|K_UPPER);
-						break;
-					case 1:
-						SETHELP(WHERE);
-/*
-Data Directory Parent:
-
-The Synchronet data directory contains almost all the data for your BBS.
-This directory must be located where ALL nodes can access it and
-MUST NOT be placed on a RAM disk or other volatile media.
-
-This option allows you to change the parent of your data directory.
-The \DATA\ suffix (sub-directory) cannot be changed or removed.
-*/
-						strcpy(str,data_dir);
-						if(strstr(str,"\\DATA\\")!=NULL)
-							*strstr(str,"\\DATA\\")=0;
-						if(uinput(WIN_MID|WIN_SAV,0,9,"Data Dir Parent"
-							,str,50,K_EDIT|K_UPPER)>0) {
-							if(str[strlen(str)-1]!='\\')
-								strcat(str,"\\");
-							strcat(str,"DATA\\");
-							strcpy(data_dir,str); }
-                        break;
-					case 2:
-						SETHELP(WHERE);
-/*
-Exec Directory Parent:
-
-The Synchronet exec directory contains executable files that your BBS
-executes. This directory does not need to be in your DOS search path.
-If you place programs in this directory for the BBS to execute, you
-should place the %! abreviation for this exec directory at the
-beginning of the command line.
-
-This option allows you to change the parent of your exec directory.
-The \EXEC\ suffix (sub-directory) cannot be changed or removed.
-*/
-						strcpy(str,exec_dir);
-						if(strstr(str,"\\EXEC\\")!=NULL)
-							*strstr(str,"\\EXEC\\")=0;
-						if(uinput(WIN_MID|WIN_SAV,0,9,"Exec Dir Parent"
-							,str,50,K_EDIT|K_UPPER)>0) {
-							if(str[strlen(str)-1]!='\\')
-								strcat(str,"\\");
-							strcat(str,"EXEC\\");
-							strcpy(exec_dir,str); }
-                        break;
-					case 3:
-						strcpy(str,new_sif);
-						SETHELP(WHERE);
-/*
-SIF Questionnaire for User Input:
-
-This is the name of a SIF questionnaire file that resides your text
-directory that all users will be prompted to answer.
-*/
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"SIF Questionnaire for User Input"
-							,str,8,K_UPPER|K_EDIT);
-						if(!str[0] || code_ok(str))
-							strcpy(new_sif,str);
-						else
-							umsg("Invalid SIF Name");
-						break;
-					case 4:
-						strcpy(str,new_sof);
-						SETHELP(WHERE);
-/*
-SIF Questionnaire for Reviewing User Input:
-
-This is the SIF file used to review the input of users from the user
-edit function.
-*/
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"SIF Questionnaire for Reviewing User Input"
-							,str,8,K_UPPER|K_EDIT);
-						if(!str[0] || code_ok(str))
-							strcpy(new_sof,str);
-						else
-							umsg("Invalid SIF Name");
-						break;
-					case 5:
-						SETHELP(WHERE);
-/*
-Credits Per Dollar:
-
-This is the monetary value of a credit (How many credits per dollar).
-This value should be a power of 2 (1, 2, 4, 8, 16, 32, 64, 128, etc.)
-since credits are usually converted by 100 kilobyte (102400) blocks.
-To make a dollar worth two megabytes of credits, set this value to
-2,097,152 (a megabyte is 1024*1024 or 1048576).
-*/
-						ultoa(cdt_per_dollar,str,10);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Credits Per Dollar",str,10,K_NUMBER|K_EDIT);
-						cdt_per_dollar=atol(str);
-						break;
-					case 6:
-						SETHELP(WHERE);
-/*
-Minutes Per 100K Credits:
-
-This is the value of a minute of time online. This field is the number
-of minutes to give the user in exchange for each 100K credit block.
-*/
-						sprintf(str,"%u",cdt_min_value);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Minutes Per 100K Credits",str,5,K_NUMBER|K_EDIT);
-						cdt_min_value=atoi(str);
-						break;
-					case 7:
-						SETHELP(WHERE);
-/*
-Maximum Number of Minutes User Can Have:
-
-This value is the maximum total number of minutes a user can have. If a
-user has this number of minutes or more, they will not be allowed to
-convert credits into minutes. A sysop can add minutes to a user's
-account regardless of this maximum. If this value is set to 0, users
-will have no limit on the total number of minutes they can have.
-*/
-						sprintf(str,"%lu",max_minutes);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Maximum Number of Minutes a User Can Have "
-							"(0=No Limit)"
-							,str,10,K_NUMBER|K_EDIT);
-						max_minutes=atol(str);
-						break;
-					case 8:
-						SETHELP(WHERE);
-/*
-Warning Days Till Expire:
-
-If a user's account will expire in this many days or less, the user will
-be notified at logon. Setting this value to 0 disables the warning
-completely.
-*/
-						sprintf(str,"%u",sys_exp_warn);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Warning Days Till Expire",str,5,K_NUMBER|K_EDIT);
-						sys_exp_warn=atoi(str);
-                        break;
-					case 9:
-						SETHELP(WHERE);
-/*
-Default Status Line:
-
-This is the number of the status line format that will be the default
-display on the bottom line of the screen. For explanation of the
-available status lines, see the sysop documentation.
-*/
-						sprintf(str,"%u",sys_def_stat);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Default Status Line",str,5,K_NUMBER|K_EDIT);
-						sys_def_stat=atoi(str);
-						break;
-					case 10:
-						SETHELP(WHERE);
-/*
-Last Displayed Node:
-
-This is the number of the last node to display to users in node lists.
-This allows the sysop to define the higher numbered nodes as invisible
-to users.
-*/
-						sprintf(str,"%u",sys_lastnode);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Last Displayed Node",str,5,K_NUMBER|K_EDIT);
-						sys_lastnode=atoi(str);
-                        break;
-					case 11:
-						SETHELP(WHERE);
-/*
-First Local Auto-Node:
-
-This is the number of the first node in the search for an available
-node for local login using the AUTONODE utility.
-*/
-						sprintf(str,"%u",sys_autonode);
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"First Local Auto-Node",str,5,K_NUMBER|K_EDIT);
-						sys_autonode=atoi(str);
-                        break;
-					case 12:
-						SETHELP(WHERE);
-/*
-Phone Number Format:
-
-This is the format used for phone numbers in your local calling
-area. Use N for number positions, A for alphabetic, or ! for any
-character. All other characters will be static in the phone number
-format. An example for North American phone numbers is NNN-NNN-NNNN.
-*/
-						uinput(WIN_MID|WIN_SAV,0,0
-							,"Phone Number Format",sys_phonefmt
-							,LEN_PHONE,K_UPPER|K_EDIT);
-                        break;
-					case 13:
-						getar("Sysop Chat",sys_chat_ar);
-						break;
-						} }
-				break;
-		case 11: /* Loadable Modules */
-			done=0;
-			k=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-16.16s%s","Login",login_mod);
-				sprintf(opt[i++],"%-16.16s%s","Logon Event",logon_mod);
-				sprintf(opt[i++],"%-16.16s%s","Sync Event",sync_mod);
-				sprintf(opt[i++],"%-16.16s%s","Logoff Event",logoff_mod);
-				sprintf(opt[i++],"%-16.16s%s","Logout Event",logout_mod);
-				sprintf(opt[i++],"%-16.16s%s","New User Event",newuser_mod);
-				sprintf(opt[i++],"%-16.16s%s","Expired User",expire_mod);
-				opt[i][0]=0;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Loadable Modules:
-
-Baja modules (.BIN files) can be automatically loaded and executed
-during certain system functions. The name of the module can be specified
-for each of the available triggers listed here.
-
-Login 		Required module for remote and local logins (online)
-Logon 		Executed as an event during logon procedure (online)
-Sync			Executed when nodes are periodically synchronized (online)
-Logoff		Executed during logoff procedure (online)
-Logout		Executed during logout procedure (offline)
-New User		Executed at end of new user procedure (online)
-Expired User	Executed during daily event when user expires (offline)
-*/
-				switch(ulist(WIN_ACT|WIN_T2B|WIN_RHT,0,0,32,&k,0
-					,"Loadable Modules",opt)) {
-
-					case -1:
-						done=1;
-                        break;
-
-					case 0:
-						uinput(WIN_MID|WIN_SAV,0,0,"Login Module",login_mod,8
-							,K_EDIT|K_UPPER);
-                        break;
-					case 1:
-						uinput(WIN_MID|WIN_SAV,0,0,"Logon Module",logon_mod,8
-							,K_EDIT|K_UPPER);
-                        break;
-					case 2:
-						uinput(WIN_MID|WIN_SAV,0,0,"Synchronize Module"
-							,sync_mod,8,K_EDIT|K_UPPER);
-                        break;
-					case 3:
-						uinput(WIN_MID|WIN_SAV,0,0,"Logoff Module",logoff_mod,8
-							,K_EDIT|K_UPPER);
-                        break;
-					case 4:
-						uinput(WIN_MID|WIN_SAV,0,0,"Logout Module",logout_mod,8
-							,K_EDIT|K_UPPER);
-                        break;
-					case 5:
-						uinput(WIN_MID|WIN_SAV,0,0,"New User Module"
-							,newuser_mod,8,K_EDIT|K_UPPER);
-                        break;
-					case 6:
-						uinput(WIN_MID|WIN_SAV,0,0,"Expired User Module"
-							,expire_mod,8,K_EDIT|K_UPPER);
-                        break;
-
-					} }
-			break;
-
-		case 12: /* Security Levels */
-			dflt=bar=0;
-			k=0;
-			while(1) {
-				for(i=0;i<100;i++) {
-					sprintf(tmp,"%luk",level_freecdtperday[i]/1024L);
-					sprintf(opt[i],"%-2d    %5d %5d "
-						"%5d %5d %5d %5d %6s %7s %2u",i
-						,level_timeperday[i],level_timepercall[i]
-						,level_callsperday[i],level_emailperday[i]
-						,level_postsperday[i],level_linespermsg[i]
-						,tmp
-						,level_misc[i]&LEVEL_EXPTOVAL ? "Val Set" : "Level"
-						,level_misc[i]&(LEVEL_EXPTOVAL|LEVEL_EXPTOLVL) ?
-							level_expireto[i] : expired_level); }
-				opt[i][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Security Level Values:
-
-This menu allows you to change the security options for every possible
-security level from 0 to 99. The available options for each level are:
-
-	Time Per Day		 :	Maximum online time per day
-	Time Per Call		 :	Maximum online time per call
-	Calls Per Day		 :	Maximum number of calls per day
-	Email Per Day		 :	Maximum number of email per day
-	Posts Per Day		 :	Maximum number of posts per day
-	Lines Per Message	 :	Maximum number of lines per message
-	Free Credits Per Day :	Number of free credits per day
-	Expire To			 :	Level or validation set to Expire to
-*/
-				i=ulist(WIN_RHT|WIN_ACT,0,3,0,&dflt,&bar
-					,"Level   T/D   T/C   C/D   E/D   P/D   L/M   F/D   "
-						"Expire To",opt);
-				if(i==-1)
-					break;
-				while(1) {
-					sprintf(str,"Security Level %d Values",i);
-					j=0;
-					sprintf(opt[j++],"%-22.22s%-5u","Time Per Day"
-						,level_timeperday[i]);
-					sprintf(opt[j++],"%-22.22s%-5u","Time Per Call"
-						,level_timepercall[i]);
-					sprintf(opt[j++],"%-22.22s%-5u","Calls Per Day"
-						,level_callsperday[i]);
-					sprintf(opt[j++],"%-22.22s%-5u","Email Per Day"
-						,level_emailperday[i]);
-					sprintf(opt[j++],"%-22.22s%-5u","Posts Per Day"
-                        ,level_postsperday[i]);
-					sprintf(opt[j++],"%-22.22s%-5u","Lines Per Message"
-						,level_linespermsg[i]);
-					sprintf(tmp,"%luk",level_freecdtperday[i]/1024L);
-					sprintf(opt[j++],"%-22.22s%-6s","Free Credits Per Day"
-						,tmp);
-					sprintf(opt[j++],"%-22.22s%s %u","Expire To"
-						,level_misc[i]&LEVEL_EXPTOVAL ? "Validation Set"
-							: "Level"
-						,level_misc[i]&(LEVEL_EXPTOVAL|LEVEL_EXPTOLVL) ?
-							level_expireto[i] : expired_level);
-					opt[j][0]=0;
-					savnum=0;
-					j=ulist(WIN_RHT|WIN_SAV|WIN_ACT,2,1,0,&k,0
-						,str,opt);
-					if(j==-1)
-						break;
-					switch(j) {
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Total Time Allowed Per Day"
-								,itoa(level_timeperday[i],tmp,10),3
-								,K_NUMBER|K_EDIT);
-							level_timeperday[i]=atoi(tmp);
-							if(level_timeperday[i]>500)
-								level_timeperday[i]=500;
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Time Allowed Per Call"
-								,itoa(level_timepercall[i],tmp,10),3
-								,K_NUMBER|K_EDIT);
-							level_timepercall[i]=atoi(tmp);
-							if(level_timepercall[i]>500)
-								level_timepercall[i]=500;
-                            break;
-						case 2:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Calls Allowed Per Day"
-								,itoa(level_callsperday[i],tmp,10),4
-								,K_NUMBER|K_EDIT);
-							level_callsperday[i]=atoi(tmp);
-                            break;
-						case 3:
-                            uinput(WIN_MID|WIN_SAV,0,0
-                                ,"Email Allowed Per Day"
-								,itoa(level_emailperday[i],tmp,10),4
-                                ,K_NUMBER|K_EDIT);
-                            level_emailperday[i]=atoi(tmp);
-                            break;
-						case 4:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Posts Allowed Per Day"
-								,itoa(level_postsperday[i],tmp,10),4
-								,K_NUMBER|K_EDIT);
-							level_postsperday[i]=atoi(tmp);
-                            break;
-						case 5:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Lines Allowed Per Message (Post/E-mail)"
-								,itoa(level_linespermsg[i],tmp,10),4
-								,K_NUMBER|K_EDIT);
-							level_linespermsg[i]=atoi(tmp);
-							break;
-						case 6:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Free Credits Per Day (in Kilobytes)"
-								,ultoa(level_freecdtperday[i]/1024L,tmp,10),8
-								,K_EDIT|K_UPPER);
-							level_freecdtperday[i]=atol(tmp)*1024L;
-							break;
-						case 7:
-							j=0;
-							sprintf(opt[j++],"Default Expired Level "
-								"(Currently %u)",expired_level);
-							sprintf(opt[j++],"Specific Level");
-							sprintf(opt[j++],"Quick-Validation Set");
-							opt[j][0]=0;
-							j=0;
-							sprintf(str,"Level %u Expires To",i);
-							savnum=1;
-							j=ulist(WIN_SAV,2,1,0,&j,0
-								,str,opt);
-							if(j==-1)
-								break;
-							if(j==0) {
-								level_misc[i]&=
-									~(LEVEL_EXPTOLVL|LEVEL_EXPTOVAL);
-								changes=1;
-								break; }
-							if(j==1) {
-								level_misc[i]&=~LEVEL_EXPTOVAL;
-								level_misc[i]|=LEVEL_EXPTOLVL;
-								changes=1;
-								uinput(WIN_MID|WIN_SAV,0,0
-									,"Expired Level"
-									,itoa(level_expireto[i],tmp,10),2
-									,K_EDIT|K_NUMBER);
-								level_expireto[i]=atoi(tmp);
-								break; }
-							level_misc[i]&=~LEVEL_EXPTOLVL;
-							level_misc[i]|=LEVEL_EXPTOVAL;
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Quick-Validation Set to Expire To"
-								,itoa(level_expireto[i],tmp,10),1
-								,K_EDIT|K_NUMBER);
-							level_expireto[i]=atoi(tmp);
-							break;
-							} } }
-			break;
-		case 13:	/* Expired Acccount Values */
-			dflt=0;
-			done=0;
-			while(!done) {
-				i=0;
-				sprintf(opt[i++],"%-27.27s%u","Level",expired_level);
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #1 to Remove"
-					,ltoaf(expired_flags1,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #2 to Remove"
-					,ltoaf(expired_flags2,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #3 to Remove"
-					,ltoaf(expired_flags3,str));
-				sprintf(opt[i++],"%-27.27s%s","Flag Set #4 to Remove"
-					,ltoaf(expired_flags4,str));
-				sprintf(opt[i++],"%-27.27s%s","Exemptions to Remove"
-					,ltoaf(expired_exempt,str));
-				sprintf(opt[i++],"%-27.27s%s","Restrictions to Add"
-					,ltoaf(expired_rest,str));
-				opt[i][0]=0;
-				SETHELP(WHERE);
-/*
-Expired Account Values:
-
-If a user's account expires, the security levels for that account will
-be modified according to the settings of this menu. The Main Level and
-Transfer Level will be set to the values listed on this menu. The Main
-Flags, Transfer Flags, and Exemptions listed on this menu will be
-removed from the account if they are set. The Restrictions listed will
-be added to the account.
-*/
-				switch(ulist(WIN_ACT|WIN_BOT|WIN_RHT,0,0,60,&dflt,0
-					,"Expired Account Values",opt)) {
-					case -1:
-						done=1;
-						break;
-					case 0:
-						itoa(expired_level,str,10);
-						SETHELP(WHERE);
-/*
-Expired Account Security Level:
-
-This is the security level automatically given to expired user accounts.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Security Level"
-							,str,2,K_EDIT|K_NUMBER);
-						expired_level=atoi(str);
-						break;
-					case 1:
-						ltoaf(expired_flags1,str);
-						SETHELP(WHERE);
-/*
-Expired Security Flags to Remove:
-
-These are the security flags automatically removed when a user account
-has expired.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flags Set #1"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						expired_flags1=aftol(str);
-						break;
-					case 2:
-						ltoaf(expired_flags2,str);
-						SETHELP(WHERE);
-/*
-Expired Security Flags to Remove:
-
-These are the security flags automatically removed when a user account
-has expired.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flags Set #2"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						expired_flags2=aftol(str);
-                        break;
-					case 3:
-						ltoaf(expired_flags3,str);
-						SETHELP(WHERE);
-/*
-Expired Security Flags to Remove:
-
-These are the security flags automatically removed when a user account
-has expired.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flags Set #3"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						expired_flags3=aftol(str);
-                        break;
-					case 4:
-						ltoaf(expired_flags4,str);
-						SETHELP(WHERE);
-/*
-Expired Security Flags to Remove:
-
-These are the security flags automatically removed when a user account
-has expired.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Flags Set #4"
-							,str,26,K_EDIT|K_UPPER|K_ALPHA);
-						expired_flags4=aftol(str);
-                        break;
-					case 5:
-						ltoaf(expired_exempt,str);
-						SETHELP(WHERE);
-/*
-Expired Exemption Flags to Remove:
-
-These are the exemptions that are automatically removed from a user
-account if it expires.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Exemption Flags",str,26
-							,K_EDIT|K_UPPER|K_ALPHA);
-						expired_exempt=aftol(str);
-						break;
-					case 6:
-						ltoaf(expired_rest,str);
-						SETHELP(WHERE);
-/*
-Expired Restriction Flags to Add:
-
-These are the restrictions that are automatically added to a user
-account if it expires.
-*/
-						uinput(WIN_SAV|WIN_MID,0,0,"Restriction Flags",str,26
-							,K_EDIT|K_UPPER|K_ALPHA);
-						expired_rest=aftol(str);
-						break; } }
-			break;
-		case 14:	/* Quick-Validation Values */
-			dflt=0;
-			k=0;
-			while(1) {
-				for(i=0;i<10;i++)
-					sprintf(opt[i],"%d  SL: %-2d  F1: %s"
-						,i,val_level[i],ltoaf(val_flags1[i],str));
-				opt[i][0]=0;
-				i=0;
-				SETHELP(WHERE);
-/*
-Quick-Validation Values:
-
-This is a list of the ten quick-validation sets. These sets are used to
-quickly set a user's security values (Level, Flags, Exemptions,
-Restrictions, Expiration Date, and Credits) with one key stroke. The
-user's expiration date may be extended and additional credits may also
-be added using quick-validation sets.
-
-Holding down  ALT  and one of the number keys (1-9) while a user
-is online, automatically sets his or user security values to the
-quick-validation set for that number key.
-
-From within the User Edit function, a sysop can use the Validate
-User command and select from this quick-validation list to change a
-user's security values with very few key-strokes.
-*/
-				savnum=0;
-				i=ulist(WIN_RHT|WIN_BOT|WIN_ACT|WIN_SAV,0,0,0,&dflt,0
-					,"Quick-Validation Values",opt);
-				if(i==-1)
-                    break;
-				sprintf(str,"Quick-Validation Set %d",i);
-				savnum=0;
-				while(1) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%u","Level",val_level[i]);
-					sprintf(opt[j++],"%-22.22s%s","Flag Set #1"
-						,ltoaf(val_flags1[i],tmp));
-					sprintf(opt[j++],"%-22.22s%s","Flag Set #2"
-						,ltoaf(val_flags2[i],tmp));
-					sprintf(opt[j++],"%-22.22s%s","Flag Set #3"
-						,ltoaf(val_flags3[i],tmp));
-					sprintf(opt[j++],"%-22.22s%s","Flag Set #4"
-						,ltoaf(val_flags4[i],tmp));
-					sprintf(opt[j++],"%-22.22s%s","Exemptions"
-						,ltoaf(val_exempt[i],tmp));
-					sprintf(opt[j++],"%-22.22s%s","Restrictions"
-						,ltoaf(val_rest[i],tmp));
-					sprintf(opt[j++],"%-22.22s%u days","Extend Expiration"
-						,val_expire[i]);
-					sprintf(opt[j++],"%-22.22s%lu","Additional Credits"
-						,val_cdt[i]);
-					opt[j][0]=0;
-					savnum=1;
-					j=ulist(WIN_RHT|WIN_SAV|WIN_ACT,2,1,0,&k,0
-						,str,opt);
-					if(j==-1)
-						break;
-					switch(j) {
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Level"
-								,itoa(val_level[i],tmp,10),2
-								,K_NUMBER|K_EDIT);
-							val_level[i]=atoi(tmp);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Flag Set #1"
-								,ltoaf(val_flags1[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_flags1[i]=aftol(tmp);
-                            break;
-						case 2:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Flag Set #2"
-								,ltoaf(val_flags2[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_flags2[i]=aftol(tmp);
-                            break;
-						case 3:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Flag Set #3"
-								,ltoaf(val_flags3[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_flags3[i]=aftol(tmp);
-                            break;
-						case 4:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Flag Set #4"
-								,ltoaf(val_flags4[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_flags4[i]=aftol(tmp);
-                            break;
-						case 5:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Exemption Flags"
-								,ltoaf(val_exempt[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_exempt[i]=aftol(tmp);
-                            break;
-						case 6:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Restriction Flags"
-								,ltoaf(val_rest[i],tmp),26
-								,K_UPPER|K_ALPHA|K_EDIT);
-							val_rest[i]=aftol(tmp);
-							break;
-						case 7:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Days to Extend Expiration"
-								,itoa(val_expire[i],tmp,10),4
-								,K_NUMBER|K_EDIT);
-							val_expire[i]=atoi(tmp);
-                            break;
-						case 8:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Additional Credits"
-								,ultoa(val_cdt[i],tmp,10),10
-								,K_NUMBER|K_EDIT);
-							val_cdt[i]=atol(tmp);
-							break; } } }
-			break; } }
-
-}
diff --git a/src/sbbs2/scfg/scfgxfr1.c b/src/sbbs2/scfg/scfgxfr1.c
deleted file mode 100644
index 8fcb4e5ebb96ace982039f2968b5f5bed65dabc1..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgxfr1.c
+++ /dev/null
@@ -1,976 +0,0 @@
-#line 2 "SCFGXFR1.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-void xfer_opts()
-{
-	static int xfr_dflt;
-	char str[81],done;
-	int i,j,k,l,dflt,bar;
-	static fextr_t savfextr;
-	static fview_t savfview;
-	static ftest_t savftest;
-	static fcomp_t savfcomp;
-	static prot_t savprot;
-	static dlevent_t savdlevent;
-	static char savaltpath[LEN_DIR+1];
-
-while(1) {
-	i=0;
-	sprintf(opt[i++],"%-33.33s%uk","Min Bytes Free Disk Space",min_dspace);
-	sprintf(opt[i++],"%-33.33s%u","Max Files in Batch UL Queue"
-		,max_batup);
-	sprintf(opt[i++],"%-33.33s%u","Max Files in Batch DL Queue"
-		,max_batdn);
-	sprintf(opt[i++],"%-33.33s%u","Max Users in User Transfers",max_userxfer);
-	sprintf(opt[i++],"%-33.33s%u%%","Default Credit on Upload"
-		,cdt_up_pct);
-	sprintf(opt[i++],"%-33.33s%u%%","Default Credit on Download"
-		,cdt_dn_pct);
-	if(leech_pct)
-		sprintf(str,"%u%% after %u seconds",leech_pct,leech_sec);
-	else
-		strcpy(str,"Disabled");
-	sprintf(opt[i++],"%-33.33s%s","Leech Protocol Detection",str);
-	strcpy(opt[i++],"Viewable Files...");
-	strcpy(opt[i++],"Testable Files...");
-	strcpy(opt[i++],"Download Events...");
-	strcpy(opt[i++],"Extractable Files...");
-	strcpy(opt[i++],"Compressable Files...");
-	strcpy(opt[i++],"Transfer Protocols...");
-	strcpy(opt[i++],"Alternate File Paths...");
-	opt[i][0]=0;
-	SETHELP(WHERE);
-/*
-File Transfer Configuration:
-
-This menu has options and sub-menus that pertain specifically to the
-file transfer section of the BBS.
-*/
-	switch(ulist(WIN_ORG|WIN_ACT|WIN_CHE,0,0,72,&xfr_dflt,0
-		,"File Transfer Configuration",opt)) {
-		case -1:
-			i=save_changes(WIN_MID);
-			if(i==-1)
-				break;
-			if(!i)
-				write_file_cfg();
-            return;
-		case 0:
-			SETHELP(WHERE);
-/*
-Minimum Kilobytes Free Disk Space to Allow Uploads:
-
-This is the minimum free space in a file directory to allow user
-uploads.
-*/
-			uinput(WIN_MID,0,0
-				,"Minimum Kilobytes Free Disk Space to Allow Uploads"
-				,itoa(min_dspace,tmp,10),5,K_EDIT|K_NUMBER);
-			min_dspace=atoi(tmp);
-			break;
-		case 1:
-			SETHELP(WHERE);
-/*
-Maximum Files in Batch Upload Queue:
-
-This is the maximum number of files that can be placed in the batch
-upload queue.
-*/
-			uinput(WIN_MID,0,0,"Maximum Files in Batch Upload Queue"
-				,itoa(max_batup,tmp,10),5,K_EDIT|K_NUMBER);
-			max_batup=atoi(tmp);
-            break;
-		case 2:
-			SETHELP(WHERE);
-/*
-Maximum Files in Batch Download Queue:
-
-This is the maximum number of files that can be placed in the batch
-download queue.
-*/
-			uinput(WIN_MID,0,0,"Maximum Files in Batch Download Queue"
-				,itoa(max_batdn,tmp,10),5,K_EDIT|K_NUMBER);
-			max_batdn=atoi(tmp);
-            break;
-		case 3:
-			SETHELP(WHERE);
-/*
-Maximum Destination Users in User to User Transfer:
-
-This is the maximum number of users allowed in the destination user list
-of a user to user upload.
-*/
-			uinput(WIN_MID,0,0
-				,"Maximum Destination Users in User to User Transfers"
-				,itoa(max_userxfer,tmp,10),5,K_EDIT|K_NUMBER);
-			max_userxfer=atoi(tmp);
-			break;
-		case 4:
-SETHELP(WHERE);
-/*
-Default Percentage of Credits to Credit Uploader on Upload:
-
-This is the default setting that will be used when new file
-directories are created.
-*/
-			uinput(WIN_MID,0,0
-				,"Default Percentage of Credits to Credit Uploader on Upload"
-				,itoa(cdt_up_pct,tmp,10),4,K_EDIT|K_NUMBER);
-			cdt_up_pct=atoi(tmp);
-			break;
-		case 5:
-SETHELP(WHERE);
-/*
-Default Percentage of Credits to Credit Uploader on Download:
-
-This is the default setting that will be used when new file
-directories are created.
-*/
-			uinput(WIN_MID,0,0
-				,"Default Percentage of Credits to Credit Uploader on Download"
-				,itoa(cdt_dn_pct,tmp,10),4,K_EDIT|K_NUMBER);
-			cdt_dn_pct=atoi(tmp);
-			break;
-		case 6:
-			SETHELP(WHERE);
-/*
-Leech Protocol Detection Percentage:
-
-This value is the sensitivity of the leech protocol detection feature of
-Synchronet. If the transfer is apparently unsuccessful, but the transfer
-time was at least this percentage of the estimated transfer time (based
-on the estimated CPS of the connection result code), then a leech
-protocol error is issued and the user's leech download counter is
-incremented. Setting this value to 0 disables leech protocol detection.
-*/
-			savnum=0;
-			uinput(WIN_MID|WIN_SAV,0,0
-				,"Leech Protocol Detection Percentage (0=Disabled)"
-				,itoa(leech_pct,tmp,10),3,K_EDIT|K_NUMBER);
-			leech_pct=atoi(tmp);
-			if(!leech_pct)
-				break;
-			SETHELP(WHERE);
-/*
-Leech Protocol Minimum Time (in Seconds):
-
-This option allows you to adjust the sensitivity of the leech protocol
-detection feature. This value is the minimum length of transfer time
-(in seconds) that must elapse before an aborted tranfser will be
-considered a possible leech attempt.
-*/
-			uinput(WIN_MID,0,0
-				,"Leech Protocol Minimum Time (in Seconds)"
-				,itoa(leech_sec,tmp,10),3,K_EDIT|K_NUMBER);
-			leech_sec=atoi(tmp);
-			break;
-		case 7: 	/* Viewable file types */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<total_fviews && i<MAX_OPTS;i++)
-					sprintf(opt[i],"%-3.3s  %-40s",fview[i]->ext,fview[i]->cmd);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if(total_fviews<MAX_OPTS)
-					i|=WIN_INS;
-				if(total_fviews)
-					i|=WIN_DEL|WIN_GET;
-				if(savfview.cmd[0])
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Viewable File Types:
-
-This is a list of file types that have content information that can be
-viewed through the execution of an external program. Here are a couple of
-command line examples for a few file types.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Viewable File Types",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(fview[i]);
-					total_fviews--;
-					while(i<total_fviews) {
-						fview[i]=fview[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((fview=(fview_t **)REALLOC(fview
-						,sizeof(fview_t *)*(total_fviews+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_fviews+1);
-						total_fviews=0;
-						bail(1);
-						continue; }
-					if(!total_fviews) {
-						if((fview[0]=(fview_t *)MALLOC(
-							sizeof(fview_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fview_t));
-							continue; }
-						memset(fview[0],0,sizeof(fview_t));
-						strcpy(fview[0]->ext,"ZIP");
-						strcpy(fview[0]->cmd,"%!pkunzip -v %f"); }
-					else {
-						for(j=total_fviews;j>i;j--)
-							fview[j]=fview[j-1];
-						if((fview[i]=(fview_t *)MALLOC(
-							sizeof(fview_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fview_t));
-							continue; }
-						*fview[i]=*fview[i+1]; }
-					total_fviews++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					savfview=*fview[i];
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					*fview[i]=savfview;
-					changes=1;
-					continue; }
-				k=0;
-				done=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%s","File Extension"
-						,fview[i]->ext);
-					sprintf(opt[j++],"%-22.22s%-40s","Command Line"
-						,fview[i]->cmd);
-					sprintf(opt[j++],"%-22.22s%s","Access Requirements"
-						,fview[i]->ar);
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"Viewable File Type",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Viewable File Type Extension"
-								,fview[i]->ext,3,K_UPPER|K_EDIT);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Command Line"
-								,fview[i]->cmd,50,K_EDIT);
-							break;
-						case 2:
-							savnum=2;
-							sprintf(str,"Viewable File Type %s"
-								,fview[i]->ext);
-							getar(str,fview[i]->ar);
-                            break; } } }
-            break;
-		case 8:    /* Testable file types */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<total_ftests && i<MAX_OPTS;i++)
-					sprintf(opt[i],"%-3.3s  %-40s",ftest[i]->ext,ftest[i]->cmd);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if(total_ftests<MAX_OPTS)
-					i|=WIN_INS;
-				if(total_ftests)
-					i|=WIN_DEL|WIN_GET;
-				if(savftest.cmd[0])
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Testable File Types:
-
-This is a list of file types that will have a command line executed to
-test the file integrity upon their upload. The file types are specified
-by extension and if one file extension is listed more than once, each
-command line will be executed. The command lines must return a DOS error
-code of 0 (no error) in order for the file to pass the test. This method
-of file testing upon upload is also known as an upload event. This test
-or event, can do more than just test the file, it can perform any
-function that the sysop wishes. Such as adding comments to an archived
-file, or extracting an archive and performing a virus scan. While the
-external program is executing, a text string is displayed to the user.
-This working string can be set for each file type and command line
-listed.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Testable File Types",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(ftest[i]);
-					total_ftests--;
-					while(i<total_ftests) {
-						ftest[i]=ftest[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((ftest=(ftest_t **)REALLOC(ftest
-						,sizeof(ftest_t *)*(total_ftests+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_ftests+1);
-						total_ftests=0;
-						bail(1);
-						continue; }
-					if(!total_ftests) {
-						if((ftest[0]=(ftest_t *)MALLOC(
-							sizeof(ftest_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(ftest_t));
-							continue; }
-						memset(ftest[0],0,sizeof(ftest_t));
-						strcpy(ftest[0]->ext,"ZIP");
-						strcpy(ftest[0]->cmd,"%!pkunzip -t %f");
-						strcpy(ftest[0]->workstr,"Testing ZIP Integrity..."); }
-					else {
-
-						for(j=total_ftests;j>i;j--)
-							ftest[j]=ftest[j-1];
-						if((ftest[i]=(ftest_t *)MALLOC(
-							sizeof(ftest_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(ftest_t));
-							continue; }
-						*ftest[i]=*ftest[i+1]; }
-					total_ftests++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					savftest=*ftest[i];
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					*ftest[i]=savftest;
-					changes=1;
-					continue; }
-				done=0;
-				k=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%s","File Extension"
-						,ftest[i]->ext);
-					sprintf(opt[j++],"%-22.22s%-40s","Command Line"
-						,ftest[i]->cmd);
-					sprintf(opt[j++],"%-22.22s%s","Working String"
-						,ftest[i]->workstr);
-					sprintf(opt[j++],"%-22.22s%s","Access Requirements"
-						,ftest[i]->ar);
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"Testable File Type",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Testable File Type Extension"
-								,ftest[i]->ext,3,K_UPPER|K_EDIT);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Command Line"
-								,ftest[i]->cmd,50,K_EDIT);
-							break;
-						case 2:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Working String"
-								,ftest[i]->workstr,40,K_EDIT|K_MSG);
-							break;
-						case 3:
-							savnum=2;
-							sprintf(str,"Testable File Type %s",ftest[i]->ext);
-							getar(str,ftest[i]->ar);
-							break; } } }
-			break;
-		case 9:    /* Download Events */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<total_dlevents && i<MAX_OPTS;i++)
-					sprintf(opt[i],"%-3.3s  %-40s",dlevent[i]->ext,dlevent[i]->cmd);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if(total_dlevents<MAX_OPTS)
-					i|=WIN_INS;
-				if(total_dlevents)
-					i|=WIN_DEL|WIN_GET;
-				if(savdlevent.cmd[0])
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Download Events:
-
-This is a list of file types that will have a command line executed to
-perform an event upon their download (e.g. trigger a download event).
-The file types are specified by extension and if one file extension
-is listed more than once, each command line will be executed. The
-command lines must return a DOS error code of 0 (no error) in order
-for the file to pass the test. This test or event, can do more than
-just test the file, it can perform any function that the sysop wishes.
-Such as adding comments to an archived file, or extracting an archive
-and performing a virus scan. While the external program is executing,
-a text string is displayed to the user. This working string can be set
-for each file type and command line listed.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Download Events",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(dlevent[i]);
-					total_dlevents--;
-					while(i<total_dlevents) {
-						dlevent[i]=dlevent[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((dlevent=(dlevent_t **)REALLOC(dlevent
-						,sizeof(dlevent_t *)*(total_dlevents+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_dlevents+1);
-						total_dlevents=0;
-						bail(1);
-						continue; }
-					if(!total_dlevents) {
-						if((dlevent[0]=(dlevent_t *)MALLOC(
-							sizeof(dlevent_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(dlevent_t));
-							continue; }
-						memset(dlevent[0],0,sizeof(dlevent_t));
-						strcpy(dlevent[0]->ext,"ZIP");
-						strcpy(dlevent[0]->cmd,"%!pkzip -z %f "
-							"< ..\\text\\zipmsg.txt");
-						strcpy(dlevent[0]->workstr,"Adding ZIP Comment..."); }
-					else {
-
-						for(j=total_dlevents;j>i;j--)
-							dlevent[j]=dlevent[j-1];
-						if((dlevent[i]=(dlevent_t *)MALLOC(
-							sizeof(dlevent_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(dlevent_t));
-							continue; }
-						*dlevent[i]=*dlevent[i+1]; }
-					total_dlevents++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					savdlevent=*dlevent[i];
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					*dlevent[i]=savdlevent;
-					changes=1;
-					continue; }
-				done=0;
-				k=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%s","File Extension"
-						,dlevent[i]->ext);
-					sprintf(opt[j++],"%-22.22s%-40s","Command Line"
-						,dlevent[i]->cmd);
-					sprintf(opt[j++],"%-22.22s%s","Working String"
-						,dlevent[i]->workstr);
-					sprintf(opt[j++],"%-22.22s%s","Access Requirements"
-						,dlevent[i]->ar);
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"Download Event",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Download Event Extension"
-								,dlevent[i]->ext,3,K_UPPER|K_EDIT);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Command Line"
-								,dlevent[i]->cmd,50,K_EDIT);
-							break;
-						case 2:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Working String"
-								,dlevent[i]->workstr,40,K_EDIT|K_MSG);
-							break;
-						case 3:
-							savnum=2;
-							sprintf(str,"Download Event %s",dlevent[i]->ext);
-							getar(str,dlevent[i]->ar);
-							break; } } }
-            break;
-		case 10:	 /* Extractable file types */
-			dflt=bar=0;
-            while(1) {
-				for(i=0;i<total_fextrs && i<MAX_OPTS;i++)
-                    sprintf(opt[i],"%-3.3s  %-40s"
-                        ,fextr[i]->ext,fextr[i]->cmd);
-				opt[i][0]=0;
-                i=WIN_ACT|WIN_SAV;  /* save cause size can change */
-				if(total_fextrs<MAX_OPTS)
-                    i|=WIN_INS;
-                if(total_fextrs)
-                    i|=WIN_DEL|WIN_GET;
-				if(savfextr.cmd[0])
-                    i|=WIN_PUT;
-                savnum=0;
-                SETHELP(WHERE);
-/*
-Extractable File Types:
-
-This is a list of archive file types that can be extracted to the temp
-directory by an external program. The file types are specified by their
-extension. For each file type you must specify the command line used to
-extract the file(s).
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Extractable File Types",opt);
-                if(i==-1)
-                    break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-                    FREE(fextr[i]);
-                    total_fextrs--;
-                    while(i<total_fextrs) {
-                        fextr[i]=fextr[i+1];
-                        i++; }
-                    changes=1;
-                    continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((fextr=(fextr_t **)REALLOC(fextr
-						,sizeof(fextr_t *)*(total_fextrs+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_fextrs+1);
-						total_fextrs=0;
-						bail(1);
-						continue; }
-                    if(!total_fextrs) {
-                        if((fextr[0]=(fextr_t *)MALLOC(
-                            sizeof(fextr_t)))==NULL) {
-                            errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fextr_t));
-                            continue; }
-						memset(fextr[0],0,sizeof(fextr_t));
-                        strcpy(fextr[0]->ext,"ZIP");
-                        strcpy(fextr[0]->cmd,"%!pkunzip -o %f %g %s"); }
-                    else {
-
-                        for(j=total_fextrs;j>i;j--)
-                            fextr[j]=fextr[j-1];
-                        if((fextr[i]=(fextr_t *)MALLOC(
-                            sizeof(fextr_t)))==NULL) {
-                            errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fextr_t));
-                            continue; }
-                        *fextr[i]=*fextr[i+1]; }
-                    total_fextrs++;
-                    changes=1;
-                    continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-                    savfextr=*fextr[i];
-                    continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-                    *fextr[i]=savfextr;
-                    changes=1;
-                    continue; }
-				k=0;
-				done=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%s","File Extension"
-						,fextr[i]->ext);
-					sprintf(opt[j++],"%-22.22s%-40s","Command Line"
-						,fextr[i]->cmd);
-					sprintf(opt[j++],"%-22.22s%s","Access Requirements"
-						,fextr[i]->ar);
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"Extractable File Type",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Extractable File Type Extension"
-								,fextr[i]->ext,3,K_UPPER|K_EDIT);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Command Line"
-								,fextr[i]->cmd,50,K_EDIT);
-							break;
-						case 2:
-							savnum=2;
-							sprintf(str,"Extractable File Type %s"
-								,fextr[i]->ext);
-							getar(str,fextr[i]->ar);
-                            break; } } }
-            break;
-		case 11:	 /* Compressable file types */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<total_fcomps && i<MAX_OPTS;i++)
-					sprintf(opt[i],"%-3.3s  %-40s",fcomp[i]->ext,fcomp[i]->cmd);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if(total_fcomps<MAX_OPTS)
-					i|=WIN_INS;
-				if(total_fcomps)
-					i|=WIN_DEL|WIN_GET;
-				if(savfcomp.cmd[0])
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Compressable File Types:
-
-This is a list of compression methods available for different file types.
-These will be used for items such as creating QWK packets, temporary
-files from the transfer section, and more.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Compressable File Types",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(fcomp[i]);
-					total_fcomps--;
-					while(i<total_fcomps) {
-						fcomp[i]=fcomp[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((fcomp=(fcomp_t **)REALLOC(fcomp
-						,sizeof(fcomp_t *)*(total_fcomps+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_fcomps+1);
-						total_fcomps=0;
-						bail(1);
-						continue; }
-					if(!total_fcomps) {
-						if((fcomp[0]=(fcomp_t *)MALLOC(
-							sizeof(fcomp_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fcomp_t));
-							continue; }
-						memset(fcomp[0],0,sizeof(fcomp_t));
-						strcpy(fcomp[0]->ext,"ZIP");
-						strcpy(fcomp[0]->cmd,"%!pkzip %f %s"); }
-					else {
-						for(j=total_fcomps;j>i;j--)
-							fcomp[j]=fcomp[j-1];
-						if((fcomp[i]=(fcomp_t *)MALLOC(
-							sizeof(fcomp_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(fcomp_t));
-							continue; }
-						*fcomp[i]=*fcomp[i+1]; }
-					total_fcomps++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					savfcomp=*fcomp[i];
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					*fcomp[i]=savfcomp;
-					changes=1;
-					continue; }
-				k=0;
-				done=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-22.22s%s","File Extension"
-						,fcomp[i]->ext);
-					sprintf(opt[j++],"%-22.22s%-40s","Command Line"
-						,fcomp[i]->cmd);
-					sprintf(opt[j++],"%-22.22s%s","Access Requirements"
-						,fcomp[i]->ar);
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"Compressable File Type",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Compressable File Type Extension"
-								,fcomp[i]->ext,3,K_UPPER|K_EDIT);
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Command Line"
-								,fcomp[i]->cmd,50,K_EDIT);
-							break;
-						case 2:
-							savnum=2;
-							sprintf(str,"Compressable File Type %s"
-								,fcomp[i]->ext);
-							getar(str,fcomp[i]->ar);
-                            break; } } }
-            break;
-		case 12:	/* Transfer protocols */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<total_prots && i<MAX_OPTS;i++)
-					sprintf(opt[i],"%c  %-40s"
-						,prot[i]->mnemonic,prot[i]->ulcmd);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if(total_prots<MAX_OPTS)
-					i|=WIN_INS;
-				if(total_prots)
-					i|=WIN_DEL|WIN_GET;
-				if(savprot.mnemonic)
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-File Transfer Protocols:
-
-This is a list of file transfer protocols that can be used to transfer
-files either to or from a remote user. For each protocol, you can
-specify the mnemonic (hot-key) to use to specify that protocol, the
-command line to use for uploads, downloads, batch uploads, batch
-downloads, bidirectional file transfers, and the support of DSZLOG. If
-the protocol doesn't support a certain method of transfer, or you don't
-wish it to be available for a certain method of transfer, leave the
-command line for that method blank. Be advised, that if you add or
-remove any transfer protocols, you will need to edit the protocol menus
-(ULPROT, DLPROT, BATUPROT, BATDPROT, and BIPROT) in the TEXT\MENU
-directory accordingly.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"File Transfer Protocols",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(prot[i]);
-					total_prots--;
-					while(i<total_prots) {
-						prot[i]=prot[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((prot=(prot_t **)REALLOC(prot
-						,sizeof(prot_t *)*(total_prots+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,total_prots+1);
-						total_prots=0;
-						bail(1);
-						continue; }
-					if(!total_prots) {
-						if((prot[0]=(prot_t *)MALLOC(
-							sizeof(prot_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(prot_t));
-							continue; }
-						memset(prot[0],0,sizeof(prot_t));
-						prot[0]->mnemonic='Y';
-						prot[0]->misc=PROT_DSZLOG;
-						strcpy(prot[0]->ulcmd
-							,"%!dsz port %p estimate 0 %e rb %f");
-						strcpy(prot[0]->dlcmd
-							,"%!dsz port %p estimate 0 %e sb %f");
-						strcpy(prot[0]->batulcmd
-							,"%!dsz port %p estimate 0 %e rb %f");
-						strcpy(prot[0]->batdlcmd
-							,"%!dsz port %p estimate 0 %e sb @%f"); }
-					else {
-
-						for(j=total_prots;j>i;j--)
-							prot[j]=prot[j-1];
-						if((prot[i]=(prot_t *)MALLOC(
-							sizeof(prot_t)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(prot_t));
-							continue; }
-						*prot[i]=*prot[i+1]; }
-					total_prots++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					savprot=*prot[i];
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					*prot[i]=savprot;
-					changes=1;
-					continue; }
-				done=0;
-				k=0;
-				while(!done) {
-					j=0;
-					sprintf(opt[j++],"%-25.25s%c","Mnemonic (Command Key)"
-						,prot[i]->mnemonic);
-					sprintf(opt[j++],"%-25.25s%-40s","Protocol Name"
-						,prot[i]->name);
-					sprintf(opt[j++],"%-25.25s%-40s","Access Requirements"
-						,prot[i]->ar);
-					sprintf(opt[j++],"%-25.25s%-40s","Upload Command Line"
-						,prot[i]->ulcmd);
-					sprintf(opt[j++],"%-25.25s%-40s","Download Command Line"
-						,prot[i]->dlcmd);
-					sprintf(opt[j++],"%-25.25s%-40s","Batch UL Command Line"
-						,prot[i]->batulcmd);
-					sprintf(opt[j++],"%-25.25s%-40s","Batch DL Command Line"
-						,prot[i]->batdlcmd);
-					sprintf(opt[j++],"%-25.25s%-40s","Bidir Command Line"
-						,prot[i]->bicmd);
-					sprintf(opt[j++],"%-25.25s%s","Uses DSZLOG"
-						,prot[i]->misc&PROT_DSZLOG ? "Yes":"No");
-					opt[j][0]=0;
-					savnum=1;
-					switch(ulist(WIN_RHT|WIN_BOT|WIN_SAV|WIN_ACT,0,0,0,&k,0
-						,"File Transfer Protocol",opt)) {
-						case -1:
-							done=1;
-							break;
-						case 0:
-							str[0]=prot[i]->mnemonic;
-							str[1]=0;
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Mnemonic (Command Key)"
-								,str,1,K_UPPER|K_EDIT);
-							if(str[0])
-								prot[i]->mnemonic=str[0];
-							break;
-						case 1:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Protocol Name"
-								,prot[i]->name,25,K_EDIT);
-                            break;
-						case 2:
-							savnum=2;
-							sprintf(str,"Protocol %s",prot[i]->name);
-							getar(str,prot[i]->ar);
-							break;
-						case 3:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Upload Command"
-								,prot[i]->ulcmd,50,K_EDIT);
-							break;
-						case 4:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Download Command"
-								,prot[i]->dlcmd,50,K_EDIT);
-                            break;
-						case 5:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Batch UL Command"
-								,prot[i]->batulcmd,50,K_EDIT);
-                            break;
-						case 6:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Batch DL Command"
-								,prot[i]->batdlcmd,50,K_EDIT);
-                            break;
-						case 7:
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Bi-dir Command"
-								,prot[i]->bicmd,50,K_EDIT);
-                            break;
-						case 8:
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							l=0;
-							savnum=2;
-							l=ulist(WIN_MID|WIN_SAV,0,0,0,&l,0
-								,"Uses DSZLOG",opt);
-							if(!l && !(prot[i]->misc&PROT_DSZLOG)) {
-								prot[i]->misc|=PROT_DSZLOG;
-								changes=1; }
-							else if(l==1 && prot[i]->misc&PROT_DSZLOG) {
-								prot[i]->misc&=~PROT_DSZLOG;
-								changes=1; }
-							break; } } }
-			break;
-		case 13:	/* Alternate file paths */
-			dflt=bar=0;
-			while(1) {
-				for(i=0;i<altpaths;i++)
-					sprintf(opt[i],"%3d: %-40s",i+1,altpath[i]);
-				opt[i][0]=0;
-				i=WIN_ACT|WIN_SAV;	/* save cause size can change */
-				if((int)altpaths<MAX_OPTS)
-					i|=WIN_INS;
-				if(altpaths)
-					i|=WIN_DEL|WIN_GET;
-				if(savaltpath[0])
-					i|=WIN_PUT;
-				savnum=0;
-				SETHELP(WHERE);
-/*
-Alternate File Paths:
-
-This option allows the sysop to add and configure alternate file paths
-for files stored on drives and directories other than the configured
-storage path for a file directory. This command is useful for those who
-have file directories where they wish to have files listed from
-multiple CD-ROMs or hard disks.
-*/
-				i=ulist(i,0,0,50,&dflt,&bar,"Alternate File Paths",opt);
-				if(i==-1)
-					break;
-				if((i&MSK_ON)==MSK_DEL) {
-					i&=MSK_OFF;
-					FREE(altpath[i]);
-					altpaths--;
-					while(i<altpaths) {
-						altpath[i]=altpath[i+1];
-						i++; }
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_INS) {
-					i&=MSK_OFF;
-					if((altpath=(char **)REALLOC(altpath
-						,sizeof(char *)*(altpaths+1)))==NULL) {
-						errormsg(WHERE,ERR_ALLOC,nulstr,altpaths+1);
-						altpaths=0;
-						bail(1);
-                        continue; }
-					if(!altpaths) {
-						if((altpath[0]=(char *)MALLOC(LEN_DIR+1))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,LEN_DIR+1);
-							continue; }
-						memset(altpath[0],0,LEN_DIR+1); }
-					else {
-						for(j=altpaths;j>i;j--)
-							altpath[j]=altpath[j-1];
-						if((altpath[i]=(char *)MALLOC(LEN_DIR+1))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,nulstr,LEN_DIR+1);
-							continue; }
-						memcpy(altpath[i],altpath[i+1],LEN_DIR+1); }
-					altpaths++;
-					changes=1;
-					continue; }
-				if((i&MSK_ON)==MSK_GET) {
-					i&=MSK_OFF;
-					memcpy(savaltpath,altpath[i],LEN_DIR+1);
-					continue; }
-				if((i&MSK_ON)==MSK_PUT) {
-					i&=MSK_OFF;
-					memcpy(altpath[i],savaltpath,LEN_DIR+1);
-					changes=1;
-					continue; }
-				sprintf(str,"Path %d",i+1);
-				uinput(WIN_MID|WIN_SAV,0,0,str,altpath[i],50,K_UPPER|K_EDIT); }
-			break; } }
-}
-
diff --git a/src/sbbs2/scfg/scfgxfr2.c b/src/sbbs2/scfg/scfgxfr2.c
deleted file mode 100644
index 6169caf3e458d71ed0eb45b6ecc7f910321d4273..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgxfr2.c
+++ /dev/null
@@ -1,1453 +0,0 @@
-#line 2 "SCFGXFR2.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-void xfer_cfg()
-{
-	static int libs_dflt,libs_bar,dflt;
-	char str[256],str2[81],done=0,*p;
-	int file,j,k,q;
-	uint i;
-	long ported;
-	static lib_t savlib;
-	dir_t tmpdir;
-	FILE *stream;
-
-while(1) {
-	for(i=0;i<total_libs && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",lib[i]->lname);
-	opt[i][0]=0;
-	j=WIN_ACT|WIN_CHE|WIN_ORG;
-	if(total_libs)
-		j|=WIN_DEL|WIN_GET|WIN_DELACT;
-	if(total_libs<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savlib.sname[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-File Libraries:
-
-This is a listing of file libraries for your BBS. File Libraries are
-used to logically separate your file directories into groups. Every
-directory belongs to a file library.
-
-One popular use for file libraries is to separate CD-ROM and hard disk
-directories. One might have an Uploads file library that contains
-uploads to the hard disk directories and also have a PC-SIG file
-library that contains directories from a PC-SIG CD-ROM. Some sysops
-separate directories into more specific areas such as Main, Graphics,
-or Adult. If you have many directories that have a common subject
-denominator, you may want to have a separate file library for those
-directories for a more organized file structure.
-*/
-	i=ulist(j,0,0,45,&libs_dflt,&libs_bar,"File Libraries",opt);
-	if((signed)i==-1) {
-		j=save_changes(WIN_MID);
-		if(j==-1)
-			continue;
-		if(!j)
-			write_file_cfg();
-		return; }
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"Main");
-		SETHELP(WHERE);
-/*
-Library Long Name:
-
-This is a description of the file library which is displayed when a
-user of the system uses the /* command from the file transfer menu.
-*/*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Library Long Name",str,LEN_GLNAME
-			,K_EDIT)<1)
-			continue;
-		sprintf(str2,"%.*s",LEN_GSNAME,str);
-		SETHELP(WHERE);
-/*
-Library Short Name:
-
-This is a short description of the file library which is used for the
-file transfer menu prompt.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Library Short Name",str2,LEN_GSNAME
-			,K_EDIT)<1)
-			continue;
-		if((lib=(lib_t **)REALLOC(lib,sizeof(lib_t *)*(total_libs+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_libs+1);
-			total_libs=0;
-			bail(1);
-            continue; }
-
-		if(total_libs) {
-			for(j=total_libs;j>i;j--)
-                lib[j]=lib[j-1];
-			for(j=0;j<total_dirs;j++)
-				if(dir[j]->lib>=i)
-					dir[j]->lib++; }
-		if((lib[i]=(lib_t *)MALLOC(sizeof(lib_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(lib_t));
-			continue; }
-		memset((lib_t *)lib[i],0,sizeof(lib_t));
-		strcpy(lib[i]->lname,str);
-		strcpy(lib[i]->sname,str2);
-		total_libs++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Delete All Data in Library:
-
-If you wish to delete the database files for all directories in this
-library, select Yes.
-*/
-		j=1;
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-			,"Delete All Library Data Files",opt);
-		if(j==-1)
-			continue;
-		if(j==0)
-			for(j=0;j<total_dirs;j++)
-				if(dir[j]->lib==i) {
-					sprintf(str,"%s.*",dir[j]->code);
-					if(!dir[j]->data_dir[0])
-						sprintf(tmp,"%sDIRS\\",data_dir);
-					else
-						strcpy(tmp,dir[j]->data_dir);
-					delfiles(tmp,str); }
-		FREE(lib[i]);
-		for(j=0;j<total_dirs;) {
-			if(dir[j]->lib==i) {
-				FREE(dir[j]);
-				total_dirs--;
-				k=j;
-				while(k<total_dirs) {
-					dir[k]=dir[k+1];
-					k++; } }
-			else j++; }
-		for(j=0;j<total_dirs;j++)
-			if(dir[j]->lib>i)
-				dir[j]->lib--;
-		total_libs--;
-		while(i<total_libs) {
-			lib[i]=lib[i+1];
-			i++; }
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savlib=*lib[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*lib[i]=savlib;
-		changes=1;
-        continue; }
-	done=0;
-	while(!done) {
-		j=0;
-		sprintf(opt[j++],"%-27.27s%s","Long Name",lib[i]->lname);
-		sprintf(opt[j++],"%-27.27s%s","Short Name",lib[i]->sname);
-		sprintf(opt[j++],"%-27.27s%.40s","Access Requirements"
-			,lib[i]->ar);
-		strcpy(opt[j++],"Clone Options");
-		strcpy(opt[j++],"Export Areas...");
-		strcpy(opt[j++],"Import Areas...");
-		strcpy(opt[j++],"File Directories...");
-		opt[j][0]=0;
-		savnum=0;
-		sprintf(str,"%s Library",lib[i]->sname);
-		SETHELP(WHERE);
-/*
-File Library Configuration:
-
-This menu allows you to configure the security requirments for access
-to this file library. You can also add, delete, and configure the
-directories of this library by selecting the File Directories... option.
-*/
-		switch(ulist(WIN_ACT,6,4,60,&dflt,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Library Long Name:
-
-This is a description of the file library which is displayed when a
-user of the system uses the /* command from the file transfer menu.
-*/*/
-				strcpy(str,lib[i]->lname);	/* save */
-				if(!uinput(WIN_MID|WIN_SAV,0,0,"Name to use for Listings"
-					,lib[i]->lname,LEN_GLNAME,K_EDIT))
-					strcpy(lib[i]->lname,str);	/* restore */
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Library Short Name:
-
-This is a short description of the file librarly which is used for the
-file transfer menu prompt.
-*/
-				uinput(WIN_MID|WIN_SAV,0,0,"Name to use for Prompts"
-					,lib[i]->sname,LEN_GSNAME,K_EDIT);
-				break;
-			case 2:
-				sprintf(str,"%s Library",lib[i]->sname);
-				getar(str,lib[i]->ar);
-				break;
-			case 3: /* clone options */
-				j=0;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Clone Directory Options:
-
-If you want to clone the options of the first directory of this library
-into all directories of this library, select Yes.
-
-The options cloned are upload requirments, download requirments,
-operator requirements, exempted user requirements, toggle options,
-maximum number of files, allowed file extensions, default file
-extension, and sort type.
-*/
-				j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-					,"Clone Options of First Directory into All of Library"
-					,opt);
-				if(j==0) {
-					k=-1;
-					for(j=0;j<total_dirs;j++)
-						if(dir[j]->lib==i) {
-							if(k==-1)
-								k=j;
-							else {
-								changes=1;
-								dir[j]->misc=dir[k]->misc;
-								strcpy(dir[j]->ul_ar,dir[k]->ul_ar);
-								strcpy(dir[j]->dl_ar,dir[k]->dl_ar);
-								strcpy(dir[j]->op_ar,dir[k]->op_ar);
-								strcpy(dir[j]->ex_ar,dir[k]->ex_ar);
-								strcpy(dir[j]->exts,dir[k]->exts);
-								strcpy(dir[j]->data_dir,dir[k]->data_dir);
-								strcpy(dir[j]->upload_sem,dir[k]->upload_sem);
-								dir[j]->maxfiles=dir[k]->maxfiles;
-								dir[j]->maxage=dir[k]->maxage;
-								dir[j]->up_pct=dir[k]->up_pct;
-								dir[j]->dn_pct=dir[k]->dn_pct;
-								dir[j]->seqdev=dir[k]->seqdev;
-								dir[j]->sort=dir[k]->sort; } } }
-                break;
-			case 4:
-				k=0;
-				ported=0;
-				q=changes;
-				strcpy(opt[k++],"DIRS.TXT    (Synchronet)");
-				strcpy(opt[k++],"FILEBONE.NA (Fido)");
-				opt[k][0]=0;
-				SETHELP(WHERE);
-/*
-Export Area File Format:
-
-This menu allows you to choose the format of the area file you wish to
-export to.
-*/
-				k=0;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Export Area File Format",opt);
-				if(k==-1)
-					break;
-				if(k==0)
-					sprintf(str,"%sDIRS.TXT",ctrl_dir);
-				else if(k==1)
-					sprintf(str,"FILEBONE.NA");
-				strupr(str);
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Filename"
-					,str,40,K_UPPER|K_EDIT)<=0) {
-					changes=q;
-					break; }
-				if(fexist(str)) {
-					strcpy(opt[0],"Overwrite");
-					strcpy(opt[1],"Append");
-					opt[2][0]=0;
-					j=0;
-					j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"File Exists",opt);
-					if(j==-1)
-						break;
-					if(j==0) j=O_WRONLY|O_TRUNC;
-					else	 j=O_WRONLY|O_APPEND; }
-				else
-					j=O_WRONLY|O_CREAT;
-				if((stream=fnopen(&file,str,j))==NULL) {
-					umsg("Open Failure");
-					break; }
-				upop("Exporting Areas...");
-				for(j=0;j<total_dirs;j++) {
-					if(dir[j]->lib!=i)
-						continue;
-					ported++;
-					if(k==1) {
-						fprintf(stream,"Area %-8s  0     !      %s\r\n"
-							,dir[j]->code,dir[j]->lname);
-						continue; }
-					fprintf(stream,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-							"%s\r\n%s\r\n"
-						,dir[j]->lname
-						,dir[j]->sname
-						,dir[j]->code
-						,dir[j]->data_dir
-						,dir[j]->ar
-						,dir[j]->ul_ar
-						,dir[j]->dl_ar
-						,dir[j]->op_ar
-						);
-					fprintf(stream,"%s\r\n%s\r\n%u\r\n%s\r\n%lX\r\n%u\r\n"
-							"%u\r\n"
-						,dir[j]->path
-						,dir[j]->upload_sem
-						,dir[j]->maxfiles
-						,dir[j]->exts
-						,dir[j]->misc
-						,dir[j]->seqdev
-						,dir[j]->sort
-						);
-					fprintf(stream,"%s\r\n%u\r\n%u\r\n%u\r\n"
-						,dir[j]->ex_ar
-						,dir[j]->maxage
-						,dir[j]->up_pct
-						,dir[j]->dn_pct
-						);
-					fprintf(stream,"***END-OF-DIR***\r\n\r\n"); }
-				fclose(stream);
-				upop(0);
-				sprintf(str,"%lu File Areas Exported Successfully",ported);
-				umsg(str);
-				changes=q;
-				break;
-
-			case 5:
-				ported=0;
-				k=0;
-				SETHELP(WHERE);
-/*
-Import Area File Format:
-
-This menu allows you to choose the format of the area file you wish to
-import into the current file library.
-*/
-				strcpy(opt[k++],"DIRS.TXT    (Synchronet)");
-                strcpy(opt[k++],"FILEBONE.NA (Fido)");
-				opt[k][0]=0;
-				k=0;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Import Area File Format",opt);
-				if(k==-1)
-					break;
-				if(k==0)
-					sprintf(str,"%sDIRS.TXT",ctrl_dir);
-				else if(k==1)
-					sprintf(str,"FILEBONE.NA");
-				strupr(str);
-				if(uinput(WIN_MID|WIN_SAV,0,0,"Filename"
-					,str,40,K_UPPER|K_EDIT)<=0)
-                    break;
-				if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-					umsg("Open Failure");
-                    break; }
-				upop("Importing Areas...");
-				while(!feof(stream)) {
-					if(!fgets(str,128,stream)) break;
-					truncsp(str);
-					if(!str[0])
-						continue;
-					if(k) {
-						p=str;
-						while(*p && *p<=SP) p++;
-						if(strnicmp(p,"AREA ",5))
-							continue;
-						memset(&tmpdir,0,sizeof(dir_t));
-						tmpdir.misc|=
-							(DIR_FCHK|DIR_DUPES|DIR_CDTUL|DIR_CDTDL|DIR_DIZ);
-						if(k==1) {
-							p+=5;
-							while(*p && *p<=SP) p++;
-							sprintf(tmpdir.code,"%.8s",p);
-							truncsp(tmpdir.code);
-							while(*p>SP) p++;			/* Skip areaname */
-							while(*p && *p<=SP) p++;	/* Skip space */
-							while(*p>SP) p++;			/* Skip level */
-							while(*p && *p<=SP) p++;	/* Skip space */
-							while(*p>SP) p++;			/* Skip flags */
-							while(*p && *p<=SP) p++;	/* Skip space */
-							sprintf(tmpdir.lname,"%.*s",LEN_SLNAME,p); }
-						ported++; }
-					else {
-						memset(&tmpdir,0,sizeof(dir_t));
-						sprintf(tmpdir.lname,"%.*s",LEN_SLNAME,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.sname,"%.*s",LEN_SSNAME,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.code,"%.*s",8,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.data_dir,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.ul_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.dl_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.op_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-                        truncsp(str);
-                        sprintf(tmpdir.path,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-                        truncsp(str);
-                        sprintf(tmpdir.upload_sem,"%.*s",LEN_DIR,str);
-						if(!fgets(str,128,stream)) break;
-                        truncsp(str);
-						tmpdir.maxfiles=atoi(str);
-						if(!fgets(str,128,stream)) break;
-                        truncsp(str);
-						sprintf(tmpdir.exts,"%.*s",40,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.misc=ahtoul(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.seqdev=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.sort=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						sprintf(tmpdir.ex_ar,"%.*s",LEN_ARSTR,str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.maxage=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.up_pct=atoi(str);
-						if(!fgets(str,128,stream)) break;
-						truncsp(str);
-						tmpdir.dn_pct=atoi(str);
-
-						ported++;
-						while(!feof(stream)
-							&& strcmp(str,"***END-OF-DIR***")) {
-							if(!fgets(str,128,stream)) break;
-							truncsp(str); } }
-
-					for(j=0;j<total_dirs;j++) {
-						if(dir[j]->lib!=i)
-							continue;
-						if(!stricmp(dir[j]->code,tmpdir.code))
-							break; }
-					if(j==total_dirs) {
-
-						if((dir=(dir_t **)REALLOC(dir
-							,sizeof(dir_t *)*(total_dirs+1)))==NULL) {
-							errormsg(WHERE,ERR_ALLOC,"dir",total_dirs+1);
-							total_dirs=0;
-							bail(1);
-							break; }
-
-						if((dir[j]=(dir_t *)MALLOC(sizeof(dir_t)))
-							==NULL) {
-							errormsg(WHERE,ERR_ALLOC,"dir",sizeof(dir_t));
-							break; }
-						memset(dir[j],0,sizeof(dir_t)); }
-					if(!k)
-						memcpy(dir[j],&tmpdir,sizeof(dir_t));
-					else {
-						strcpy(dir[j]->code,tmpdir.code);
-						strcpy(dir[j]->sname,tmpdir.code);
-						strcpy(dir[j]->lname,tmpdir.lname);
-						if(j==total_dirs) {
-							dir[j]->maxfiles=1000;
-							dir[j]->up_pct=cdt_up_pct;
-							dir[j]->dn_pct=cdt_dn_pct; }
-						}
-					dir[j]->lib=i;
-					if(j==total_dirs) {
-						dir[j]->misc=tmpdir.misc;
-						total_dirs++; }
-					changes=1; }
-				fclose(stream);
-				upop(0);
-				sprintf(str,"%lu File Areas Imported Successfully",ported);
-                umsg(str);
-                break;
-
-			case 6:
-				dir_cfg(i);
-				break; } } }
-
-}
-
-void dir_cfg(uint libnum)
-{
-	static int dflt,bar,tog_dflt,tog_bar,adv_dflt,opt_dflt;
-	char str[81],str2[81],code[9],path[128],done=0,*p;
-	int j,n;
-	uint i,dirnum[MAX_OPTS+1];
-	static dir_t savdir;
-
-while(1) {
-	for(i=0,j=0;i<total_dirs && j<MAX_OPTS;i++)
-		if(dir[i]->lib==libnum) {
-			sprintf(opt[j],"%-25s",dir[i]->lname);
-			dirnum[j++]=i; }
-	dirnum[j]=total_dirs;
-	opt[j][0]=0;
-	sprintf(str,"%s Directories",lib[libnum]->sname);
-	savnum=0;
-	i=WIN_SAV|WIN_ACT;
-	if(j)
-		i|=WIN_DEL|WIN_GET|WIN_DELACT;
-	if(j<MAX_OPTS)
-		i|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savdir.sname[0])
-		i|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-File Directories:
-
-This is a list of file directories that have been configured for the
-selected file library.
-
-To add a directory, select the desired position with the arrow keys and
-hit  INS .
-
-To delete a directory, select it with the arrow keys and hit  DEL .
-
-To configure a directory, select it with the arrow keys and hit  ENTER .
-*/
-	i=ulist(i,24,1,45,&dflt,&bar,str,opt);
-	savnum=1;
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		strcpy(str,"Games");
-		SETHELP(WHERE);
-/*
-Directory Long Name:
-
-This is a description of the file directory which is displayed in all
-directory listings.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Directory Long Name",str,LEN_SLNAME
-			,K_EDIT)<1)
-			continue;
-		sprintf(str2,"%.*s",LEN_SSNAME,str);
-		SETHELP(WHERE);
-/*
-Directory Short Name:
-
-This is a short description of the file directory which is displayed at
-the file transfer prompt.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Directory Short Name",str2,LEN_SSNAME
-			,K_EDIT)<1)
-            continue;
-		sprintf(code,"%.8s",str2);
-		p=strchr(code,SP);
-		if(p) *p=0;
-		strupr(code);
-		SETHELP(WHERE);
-/*
-Directory Internal Code:
-
-Every directory must have its own unique code for Synchronet to refer to
-it internally. This code should be descriptive of the directory's
-contents, usually an abreviation of the directory's name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Directory Internal Code",code,8
-			,K_EDIT|K_UPPER)<1)
-            continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-			continue; }
-		sprintf(path,"%sDIRS\\%s",data_dir,code);
-		SETHELP(WHERE);
-/*
-Directory File Path:
-
-This is the drive and directory where your uploads to and downloads from
-this directory will be stored. Example: C:\XFER\GAMES
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Directory File Path",path,50
-			,K_EDIT|K_UPPER)<1)
-			continue;
-		if((dir=(dir_t **)REALLOC(dir,sizeof(dir_t *)*(total_dirs+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_dirs+1);
-			total_dirs=0;
-			bail(1);
-            continue; }
-
-		if(j)
-			for(n=total_dirs;n>dirnum[i];n--)
-                dir[n]=dir[n-1];
-		if((dir[dirnum[i]]=(dir_t *)MALLOC(sizeof(dir_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(dir_t));
-			continue; }
-		memset((dir_t *)dir[dirnum[i]],0,sizeof(dir_t));
-		dir[dirnum[i]]->lib=libnum;
-		dir[dirnum[i]]->maxfiles=MAX_FILES<500 ? MAX_FILES:500;
-		if(strcmpi(str2,"OFFLINE"))
-			dir[dirnum[i]]->misc=(DIR_FCHK|DIR_MULT|DIR_DUPES
-				|DIR_CDTUL|DIR_CDTDL|DIR_DIZ);
-		strcpy(dir[dirnum[i]]->code,code);
-		strcpy(dir[dirnum[i]]->lname,str);
-		strcpy(dir[dirnum[i]]->sname,str2);
-		strcpy(dir[dirnum[i]]->path,path);
-		dir[dirnum[i]]->up_pct=cdt_up_pct;
-		dir[dirnum[i]]->dn_pct=cdt_dn_pct;
-		total_dirs++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Delete Directory Data Files:
-
-If you want to delete all the database files for this directory,
-select Yes.
-*/
-		j=1;
-		strcpy(opt[0],"Yes");
-		strcpy(opt[1],"No");
-		opt[2][0]=0;
-		j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-			,"Delete Data in Sub-board",opt);
-		if(j==-1)
-			continue;
-		if(j==0) {
-				sprintf(str,"%s.*",dir[dirnum[i]]->code);
-				if(!dir[dirnum[i]]->data_dir[0])
-					sprintf(tmp,"%sDIRS\\",data_dir);
-				else
-					strcpy(tmp,dir[dirnum[i]]->data_dir);
-				delfiles(tmp,str); }
-		FREE(dir[dirnum[i]]);
-		total_dirs--;
-		for(j=dirnum[i];j<total_dirs;j++)
-			dir[j]=dir[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savdir=*dir[dirnum[i]];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*dir[dirnum[i]]=savdir;
-		dir[dirnum[i]]->lib=libnum;
-		changes=1;
-        continue; }
-	i=dirnum[dflt];
-	j=0;
-	done=0;
-	while(!done) {
-		n=0;
-		sprintf(opt[n++],"%-27.27s%s","Long Name",dir[i]->lname);
-		sprintf(opt[n++],"%-27.27s%s","Short Name",dir[i]->sname);
-		sprintf(opt[n++],"%-27.27s%s","Internal Code",dir[i]->code);
-		sprintf(opt[n++],"%-27.27s%.40s","Access Requirements"
-			,dir[i]->ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Upload Requirements"
-			,dir[i]->ul_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Download Requirements"
-			,dir[i]->dl_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Operator Requirements"
-            ,dir[i]->op_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Exemption Requirements"
-			,dir[i]->ex_ar);
-		sprintf(opt[n++],"%-27.27s%.40s","Transfer File Path"
-			,dir[i]->path);
-		sprintf(opt[n++],"%-27.27s%u","Maximum Number of Files"
-			,dir[i]->maxfiles);
-		if(dir[i]->maxage)
-			sprintf(str,"Enabled (%u days old)",dir[i]->maxage);
-        else
-            strcpy(str,"Disabled");
-        sprintf(opt[n++],"%-27.27s%s","Purge by Age",str);
-		sprintf(opt[n++],"%-27.27s%u%%","Credit on Upload"
-			,dir[i]->up_pct);
-		sprintf(opt[n++],"%-27.27s%u%%","Credit on Download"
-			,dir[i]->dn_pct);
-		strcpy(opt[n++],"Toggle Options...");
-		strcpy(opt[n++],"Advanced Options...");
-		opt[n][0]=0;
-		sprintf(str,"%s Directory",dir[i]->sname);
-		SETHELP(WHERE);
-/*
-Directory Configuration:
-
-This menu allows you to configure the individual selected directory.
-Options with a trailing ... provide a sub-menu of more options.
-*/
-		savnum=1;
-		switch(ulist(WIN_SAV|WIN_ACT|WIN_RHT|WIN_BOT
-			,0,0,60,&opt_dflt,0,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Directory Long Name:
-
-This is a description of the file directory which is displayed in all
-directory listings.
-*/
-				strcpy(str,dir[i]->lname);	/* save */
-				if(!uinput(WIN_L2R|WIN_SAV,0,17,"Name to use for Listings"
-					,dir[i]->lname,LEN_SLNAME,K_EDIT))
-					strcpy(dir[i]->lname,str);
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Directory Short Name:
-
-This is a short description of the file directory which is displayed at
-the file transfer prompt.
-*/
-				uinput(WIN_L2R|WIN_SAV,0,17,"Name to use for Prompts"
-					,dir[i]->sname,LEN_SSNAME,K_EDIT);
-				break;
-			case 2:
-                SETHELP(WHERE);
-/*
-Directory Internal Code:
-
-Every directory must have its own unique code for Synchronet to refer to
-it internally. This code should be descriptive of the directory's
-contents, usually an abreviation of the directory's name.
-*/
-                strcpy(str,dir[i]->code);
-                uinput(WIN_L2R|WIN_SAV,0,17,"Internal Code (unique)"
-                    ,str,8,K_EDIT|K_UPPER);
-                if(code_ok(str))
-                    strcpy(dir[i]->code,str);
-                else {
-                    helpbuf=invalid_code;
-                    umsg("Invalid Code");
-                    helpbuf=0; }
-                break;
-			case 3:
-				savnum=2;
-				sprintf(str,"%s Access",dir[i]->sname);
-				getar(str,dir[i]->ar);
-				break;
-			case 4:
-				savnum=2;
-				sprintf(str,"%s Upload",dir[i]->sname);
-				getar(str,dir[i]->ul_ar);
-				break;
-			case 5:
-				savnum=2;
-				sprintf(str,"%s Download",dir[i]->sname);
-				getar(str,dir[i]->dl_ar);
-				break;
-			case 6:
-				savnum=2;
-				sprintf(str,"%s Operator",dir[i]->sname);
-				getar(str,dir[i]->op_ar);
-                break;
-			case 7:
-				savnum=2;
-				sprintf(str,"%s Exemption",dir[i]->sname);
-				getar(str,dir[i]->ex_ar);
-                break;
-			case 8:
-				SETHELP(WHERE);
-/*
-File Path:
-
-This is the default storage path for files uploaded to this directory.
-If this path is blank, files are stored in a directory off of the
-DATA\DIRS directory using the internal code of this directory as the
-name of the dirdirectory (i.e. DATA\DIRS\<CODE>).
-
-This path can be overridden on a per file basis using Alternate File
-Paths.
-*/
-				uinput(WIN_L2R|WIN_SAV,0,17,"File Path"
-					,dir[i]->path,50,K_EDIT|K_UPPER);
-				break;
-			case 9:
-				SETHELP(WHERE);
-/*
-Maximum Number of Files:
-
-This value is the maximum number of files allowed in this directory.
-*/
-				sprintf(str,"%u",dir[i]->maxfiles);
-				uinput(WIN_L2R|WIN_SAV,0,17,"Maximum Number of Files"
-					,str,5,K_EDIT|K_NUMBER);
-				n=atoi(str);
-				if(n>MAX_FILES) {
-					sprintf(str,"Maximum Files is %u",MAX_FILES);
-					umsg(str); }
-				else
-					dir[i]->maxfiles=n;
-				break;
-			case 10:
-				sprintf(str,"%u",dir[i]->maxage);
-                SETHELP(WHERE);
-/*
-Maximum Age of Files:
-
-This value is the maximum number of days that files will be kept in
-the directory based on the date the file was uploaded or last
-downloaded (If the Purge by Last Download toggle option is used).
-
-The Synchronet file base maintenance program (DELFILES) must be used
-to automatically remove files based on age.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Maximum Age of Files (in days)"
-                    ,str,5,K_EDIT|K_NUMBER);
-				dir[i]->maxage=atoi(str);
-                break;
-			case 11:
-SETHELP(WHERE);
-/*
-Percentage of Credits to Credit Uploader on Upload:
-
-This is the percentage of a file's credit value that is given to users
-when they upload files. Most often, this value will be set to 100 to
-give full credit value (100%) for uploads.
-
-If you want uploaders to receive no credits upon upload, set this value
-to 0.
-*/
-				uinput(WIN_MID|WIN_SAV,0,0
-					,"Percentage of Credits to Credit Uploader on Upload"
-					,itoa(dir[i]->up_pct,tmp,10),4,K_EDIT|K_NUMBER);
-				dir[i]->up_pct=atoi(tmp);
-				break;
-			case 12:
-SETHELP(WHERE);
-/*
-Percentage of Credits to Credit Uploader on Download:
-
-This is the percentage of a file's credit value that is given to users
-who upload a file that is later downloaded by another user. This is an
-award type system where more popular files will generate more credits
-for the uploader.
-
-If you do not want uploaders to receive credit when files they upload
-are later downloaded, set this value to 0.
-*/
-				uinput(WIN_MID|WIN_SAV,0,0
-					,"Percentage of Credits to Credit Uploader on Download"
-					,itoa(dir[i]->dn_pct,tmp,10),4,K_EDIT|K_NUMBER);
-				dir[i]->dn_pct=atoi(tmp);
-				break;
-			case 13:
-				while(1) {
-					n=0;
-					sprintf(opt[n++],"%-27.27s%s","Check for File Existence"
-						,dir[i]->misc&DIR_FCHK ? "Yes":"No");
-					strcpy(str,"Slow Media Device");
-					if(dir[i]->seqdev) {
-						sprintf(tmp," #%u",dir[i]->seqdev);
-						strcat(str,tmp); }
-					sprintf(opt[n++],"%-27.27s%s",str
-						,dir[i]->seqdev ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Force Content Ratings"
-						,dir[i]->misc&DIR_RATE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Upload Date in Listings"
-						,dir[i]->misc&DIR_ULDATE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Multiple File Numberings"
-						,dir[i]->misc&DIR_MULT ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Search for Duplicates"
-						,dir[i]->misc&DIR_DUPES ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Search for New Files"
-						,dir[i]->misc&DIR_NOSCAN ? "No":"Yes");
-					sprintf(opt[n++],"%-27.27s%s","Search for Auto-ADDFILES"
-						,dir[i]->misc&DIR_NOAUTO ? "No":"Yes");
-					sprintf(opt[n++],"%-27.27s%s","Import FILE_ID.DIZ"
-						,dir[i]->misc&DIR_DIZ ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Free Downloads"
-						,dir[i]->misc&DIR_FREE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Free Download Time"
-						,dir[i]->misc&DIR_TFREE ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Deduct Upload Time"
-						,dir[i]->misc&DIR_ULTIME ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Credit Uploads"
-						,dir[i]->misc&DIR_CDTUL ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Credit Downloads"
-						,dir[i]->misc&DIR_CDTDL ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Credit with Minutes"
-						,dir[i]->misc&DIR_CDTMIN ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Anonymous Uploads"
-						,dir[i]->misc&DIR_ANON ? dir[i]->misc&DIR_AONLY
-						? "Only":"Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Purge by Last Download"
-						,dir[i]->misc&DIR_SINCEDL ? "Yes":"No");
-					sprintf(opt[n++],"%-27.27s%s","Mark Moved Files as New"
-						,dir[i]->misc&DIR_MOVENEW ? "Yes":"No");
-					opt[n][0]=0;
-					savnum=2;
-					SETHELP(WHERE);
-/*
-Directory Toggle Options:
-
-This is the toggle options menu for the selected file directory.
-
-The available options from this menu can all be toggled between two or
-more states, such as Yes and No.
-*/
-					n=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,3,2,36,&tog_dflt
-						,&tog_bar,"Toggle Options",opt);
-					if(n==-1)
-                        break;
-					savnum=3;
-					switch(n) {
-						case 0:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Check for File Existence When Listing:
-
-If you want the actual existence of files to be verified while listing
-directories, set this value to Yes.
-
-Directories with files located on CD-ROM or other slow media should have
-this option set to No.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Check for File Existence When Listing",opt);
-							if(n==0 && !(dir[i]->misc&DIR_FCHK)) {
-								dir[i]->misc|=DIR_FCHK;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_FCHK)) {
-								dir[i]->misc&=~DIR_FCHK;
-								changes=1; }
-							break;
-						case 1:
-                            n=0;
-                            strcpy(opt[0],"Yes");
-                            strcpy(opt[1],"No");
-                            opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Slow Media Device:
-
-If this directory contains files located on CD-ROM or other slow media
-device, you should set this option to Yes. Each slow media device on
-your system should have a unique Device Number. If you only have one
-slow media device, then this number should be set to 1.
-
-CD-ROM multidisk changers are considered one device and all the
-directories on all the CD-ROMs in each changer should be set to the same
-device number.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Slow Media Device"
-								,opt);
-							if(n==0) {
-								if(!dir[i]->seqdev) {
-									changes=1;
-									strcpy(str,"1"); }
-								else
-									sprintf(str,"%u",dir[i]->seqdev);
-								uinput(WIN_MID|WIN_SAV,0,0
-									,"Device Number"
-									,str,2,K_EDIT|K_UPPER);
-								dir[i]->seqdev=atoi(str); }
-							else if(n==1 && dir[i]->seqdev) {
-								dir[i]->seqdev=0;
-                                changes=1; }
-                            break;
-						case 2:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Force Content Ratings in Descriptions:
-
-If you would like all uploads to this directory to be prompted for
-content rating (G, R, or X), set this value to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Force Content Ratings in Descriptions",opt);
-							if(n==0 && !(dir[i]->misc&DIR_RATE)) {
-								dir[i]->misc|=DIR_RATE;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_RATE)) {
-								dir[i]->misc&=~DIR_RATE;
-								changes=1; }
-							break;
-						case 3:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Include Upload Date in File Descriptions:
-
-If you wish the upload date of each file in this directory to be
-automatically included in the file description, set this option to
-Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Include Upload Date in Descriptions",opt);
-							if(n==0 && !(dir[i]->misc&DIR_ULDATE)) {
-								dir[i]->misc|=DIR_ULDATE;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_ULDATE)) {
-								dir[i]->misc&=~DIR_ULDATE;
-								changes=1; }
-                            break;
-						case 4:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Ask for Multiple File Numberings:
-
-If you would like uploads to this directory to be prompted for multiple
-file (disk) numbers, set this value to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Ask for Multiple File Numberings",opt);
-							if(n==0 && !(dir[i]->misc&DIR_MULT)) {
-								dir[i]->misc|=DIR_MULT;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_MULT)) {
-								dir[i]->misc&=~DIR_MULT;
-								changes=1; }
-							break;
-						case 5:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Search Directory for Duplicate Filenames:
-
-If you would like to have this directory searched for duplicate
-filenames when a user attempts to upload a file, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Search for Duplicate Filenames",opt);
-							if(n==0 && !(dir[i]->misc&DIR_DUPES)) {
-								dir[i]->misc|=DIR_DUPES;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_DUPES)) {
-								dir[i]->misc&=~DIR_DUPES;
-								changes=1; }
-							break;
-						case 6:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Search Directory for New Files:
-
-If you would like to have this directory searched for newly uploaded
-files when a user scans All libraries for new files, set this option to
-Yes.
-
-If this directory is located on CD-ROM or other read only media
-(where uploads are unlikely to occur), it will improve new file scans
-if this option is set to No.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Search for New files",opt);
-							if(n==0 && dir[i]->misc&DIR_NOSCAN) {
-								dir[i]->misc&=~DIR_NOSCAN;
-								changes=1; }
-							else if(n==1 && !(dir[i]->misc&DIR_NOSCAN)) {
-								dir[i]->misc|=DIR_NOSCAN;
-								changes=1; }
-                            break;
-						case 7:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Search Directory for Auto-ADDFILES:
-
-If you would like to have this directory searched for a file list to
-import automatically when using the ADDFILES * (Auto-ADD) feature,
-set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Search for Auto-ADDFILES",opt);
-							if(n==0 && dir[i]->misc&DIR_NOAUTO) {
-								dir[i]->misc&=~DIR_NOAUTO;
-								changes=1; }
-							else if(n==1 && !(dir[i]->misc&DIR_NOAUTO)) {
-								dir[i]->misc|=DIR_NOAUTO;
-								changes=1; }
-                            break;
-						case 8:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Import FILE_ID.DIZ and DESC.SDI Descriptions:
-
-If you would like archived descriptions (FILE_ID.DIZ and DESC.SDI)
-of uploaded files to be automatically imported as the extended
-description, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Import FILE_ID.DIZ and DESC.SDI",opt);
-							if(n==0 && !(dir[i]->misc&DIR_DIZ)) {
-								dir[i]->misc|=DIR_DIZ;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_DIZ)) {
-								dir[i]->misc&=~DIR_DIZ;
-								changes=1; }
-                            break;
-						case 9:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Downloads are Free:
-
-If you would like all downloads from this directory to be free (cost
-no credits), set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Downloads are Free",opt);
-							if(n==0 && !(dir[i]->misc&DIR_FREE)) {
-								dir[i]->misc|=DIR_FREE;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_FREE)) {
-								dir[i]->misc&=~DIR_FREE;
-								changes=1; }
-                            break;
-						case 10:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Free Download Time:
-
-If you would like all downloads from this directory to not subtract
-time from the user, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Free Download Time",opt);
-							if(n==0 && !(dir[i]->misc&DIR_TFREE)) {
-								dir[i]->misc|=DIR_TFREE;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_TFREE)) {
-								dir[i]->misc&=~DIR_TFREE;
-								changes=1; }
-                            break;
-						case 11:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Deduct Upload Time:
-
-If you would like all uploads to this directory to have the time spent
-uploading subtracted from their time online, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Deduct Upload Time",opt);
-							if(n==0 && !(dir[i]->misc&DIR_ULTIME)) {
-								dir[i]->misc|=DIR_ULTIME;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_ULTIME)) {
-								dir[i]->misc&=~DIR_ULTIME;
-								changes=1; }
-                            break;
-						case 12:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Give Credit for Uploads:
-
-If you want users who upload to this directory to get credit for their
-initial upload, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Give Credit for Uploads",opt);
-							if(n==0 && !(dir[i]->misc&DIR_CDTUL)) {
-								dir[i]->misc|=DIR_CDTUL;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_CDTUL)) {
-								dir[i]->misc&=~DIR_CDTUL;
-								changes=1; }
-                            break;
-						case 13:
-							n=0;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Give Uploader Credit for Downloads:
-
-If you want users who upload to this directory to get credit when their
-files are downloaded, set this optin to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Give Uploader Credit for Downloads",opt);
-							if(n==0 && !(dir[i]->misc&DIR_CDTDL)) {
-								dir[i]->misc|=DIR_CDTDL;
-								changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_CDTDL)) {
-								dir[i]->misc&=~DIR_CDTDL;
-								changes=1; }
-                            break;
-						case 14:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Credit Uploader with Minutes instead of Credits:
-
-If you wish to give the uploader of files to this directory minutes,
-intead of credits, set this option to Yes.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Credit Uploader with Minutes",opt);
-							if(n==0 && !(dir[i]->misc&DIR_CDTMIN)) {
-								dir[i]->misc|=DIR_CDTMIN;
-								changes=1; }
-							else if(n==1 && dir[i]->misc&DIR_CDTMIN){
-								dir[i]->misc&=~DIR_CDTMIN;
-								changes=1; }
-                            break;
-
-						case 15:
-							n=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							strcpy(opt[2],"Only");
-							opt[3][0]=0;
-							SETHELP(WHERE);
-/*
-Allow Anonymous Uploads:
-
-If you want users with the A exemption to be able to upload anonymously
-to this directory, set this option to Yes. If you want all uploads to
-this directory to be forced anonymous, set this option to Only.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Allow Anonymous Uploads",opt);
-							if(n==0 && (dir[i]->misc&(DIR_ANON|DIR_AONLY))
-								!=DIR_ANON) {
-								dir[i]->misc|=DIR_ANON;
-								dir[i]->misc&=~DIR_AONLY;
-								changes=1; }
-							else if(n==1 && dir[i]->misc&(DIR_ANON|DIR_AONLY)){
-								dir[i]->misc&=~(DIR_ANON|DIR_AONLY);
-								changes=1; }
-							else if(n==2 && (dir[i]->misc&(DIR_ANON|DIR_AONLY))
-								!=(DIR_ANON|DIR_AONLY)) {
-								dir[i]->misc|=(DIR_ANON|DIR_AONLY);
-								changes=1; }
-							break;
-						case 16:
-                            n=0;
-                            strcpy(opt[0],"Yes");
-                            strcpy(opt[1],"No");
-                            opt[2][0]=0;
-                            SETHELP(WHERE);
-/*
-Purge Files Based on Date of Last Download:
-
-Using the Synchronet file base maintenance utility (DELFILES), you can
-have files removed based on the number of days since last downloaded
-rather than the number of days since the file was uploaded (default),
-by setting this option to Yes.
-*/
-                            n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Purge Files Based on Date of Last Download"
-                                ,opt);
-							if(n==0 && !(dir[i]->misc&DIR_SINCEDL)) {
-								dir[i]->misc|=DIR_SINCEDL;
-                                changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_SINCEDL)) {
-								dir[i]->misc&=~DIR_SINCEDL;
-                                changes=1; }
-                            break;
-						case 17:
-                            n=0;
-                            strcpy(opt[0],"Yes");
-                            strcpy(opt[1],"No");
-                            opt[2][0]=0;
-                            SETHELP(WHERE);
-/*
-Mark Moved Files as New:
-
-If this option is set to Yes, then all files moved from this directory
-will have their upload date changed to the current date so the file will
-appear in users' new-file scans again.
-*/
-                            n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Mark Moved Files as New"
-                                ,opt);
-							if(n==0 && !(dir[i]->misc&DIR_MOVENEW)) {
-								dir[i]->misc|=DIR_MOVENEW;
-                                changes=1; }
-							else if(n==1 && (dir[i]->misc&DIR_MOVENEW)) {
-								dir[i]->misc&=~DIR_MOVENEW;
-                                changes=1; }
-                            break;
-							} }
-				break;
-		case 14:
-			while(1) {
-				n=0;
-				sprintf(opt[n++],"%-27.27s%s","Extensions Allowed"
-					,dir[i]->exts);
-				if(!dir[i]->data_dir[0])
-					sprintf(str,"%sDIRS\\",data_dir);
-				else
-					strcpy(str,dir[i]->data_dir);
-				sprintf(opt[n++],"%-27.27s%.40s","Data Directory"
-					,str);
-				sprintf(opt[n++],"%-27.27s%.40s","Upload Semaphore File"
-                    ,dir[i]->upload_sem);
-				sprintf(opt[n++],"%-27.27s%s","Sort Value and Direction"
-					, dir[i]->sort==SORT_NAME_A ? "Name Ascending"
-					: dir[i]->sort==SORT_NAME_D ? "Name Descending"
-					: dir[i]->sort==SORT_DATE_A ? "Date Ascending"
-					: "Date Descending");
-				opt[n][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Directory Advanced Options:
-
-This is the advanced options menu for the selected file directory.
-*/
-					n=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,3,4,60,&adv_dflt,0
-						,"Advanced Options",opt);
-					if(n==-1)
-                        break;
-					savnum=3;
-                    switch(n) {
-						case 0:
-							SETHELP(WHERE);
-/*
-File Extensions Allowed:
-
-This option allows you to limit the types of files uploaded to this
-directory. This is a list of file extensions that are allowed, each
-separated by a comma (Example: ZIP,EXE). If this option is left
-blank, all file extensions will be allowed to be uploaded.
-*/
-							uinput(WIN_L2R|WIN_SAV,0,17
-								,"File Extensions Allowed"
-								,dir[i]->exts,40,K_EDIT|K_UPPER);
-							break;
-						case 1:
-SETHELP(WHERE);
-/*
-Data Directory:
-
-Use this if you wish to place the data directory for this directory
-on another drive or in another directory besides the default setting.
-*/
-							uinput(WIN_MID|WIN_SAV,0,17,"Data"
-								,dir[i]->data_dir,50,K_EDIT|K_UPPER);
-							break;
-						case 2:
-SETHELP(WHERE);
-/*
-Upload Semaphore File:
-
-This is a filename that will be used as a semaphore (signal) to your
-FidoNet front-end that new files are ready to be hatched for export.
-*/
-							uinput(WIN_MID|WIN_SAV,0,17,"Upload Semaphore"
-								,dir[i]->upload_sem,50,K_EDIT|K_UPPER);
-							break;
-						case 3:
-							n=0;
-							strcpy(opt[0],"Name Ascending");
-							strcpy(opt[1],"Name Descending");
-							strcpy(opt[2],"Date Ascending");
-							strcpy(opt[3],"Date Descending");
-							opt[4][0]=0;
-							SETHELP(WHERE);
-/*
-Sort Value and Direction:
-
-This option allows you to determine the sort value and direction. Files
-that are uploaded are automatically sorted by filename or upload date,
-ascending or descending. If you change the sort value or direction after
-a directory already has files in it, use the sysop transfer menu ;RESORT
-command to resort the directory with the new sort parameters.
-*/
-							n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0
-								,"Sort Value and Direction",opt);
-							if(n==0 && dir[i]->sort!=SORT_NAME_A) {
-								dir[i]->sort=SORT_NAME_A;
-								changes=1; }
-							else if(n==1 && dir[i]->sort!=SORT_NAME_D) {
-								dir[i]->sort=SORT_NAME_D;
-								changes=1; }
-							else if(n==2 && dir[i]->sort!=SORT_DATE_A) {
-								dir[i]->sort=SORT_DATE_A;
-								changes=1; }
-							else if(n==3 && dir[i]->sort!=SORT_DATE_D) {
-								dir[i]->sort=SORT_DATE_D;
-								changes=1; }
-							break; } }
-			break;
-			} } }
-
-}
diff --git a/src/sbbs2/scfg/scfgxtrn.c b/src/sbbs2/scfg/scfgxtrn.c
deleted file mode 100644
index 38561a964d7eac780067150bb4afb1db43405f25..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/scfgxtrn.c
+++ /dev/null
@@ -1,1798 +0,0 @@
-#line 2 "SCFGXTRN.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-extern char *wday[];
-
-char *daystr(char days);
-
-
-/****************************************************************************/
-/* Synchronet configuration utility 										*/
-/****************************************************************************/
-
-#include "scfg.h"
-
-void xprogs_cfg()
-{
-	static int xprogs_dflt;
-	int 	i;
-	char	str[81];
-
-while(1) {
-	i=0;
-	strcpy(opt[i++],"Fixed Events");
-	strcpy(opt[i++],"Timed Events");
-	strcpy(opt[i++],"Global Swap List");
-	strcpy(opt[i++],"OS/2 Program List");
-	strcpy(opt[i++],"External Editors");
-	strcpy(opt[i++],"Online Programs");
-	opt[i][0]=0;
-	SETHELP(WHERE);
-/*
-Online External Programs:
-
-From this menu, you can configure external events, external editors, or
-online external programs (doors).
-*/
-	switch(ulist(WIN_ORG|WIN_CHE|WIN_ACT,0,0,0,&xprogs_dflt,0
-		,"External Programs",opt)) {
-		case -1:
-			i=save_changes(WIN_MID);
-            if(i==-1)
-                break;
-			if(!i) {
-                write_xtrn_cfg();
-				write_main_cfg(); }
-			return;
-		case 0:
-			fevents_cfg();
-			break;
-		case 1:
-			tevents_cfg();
-			break;
-		case 2:
-			swap_cfg();
-			break;
-		case 3:
-			os2pgm_cfg();
-			break;
-		case 4:
-			xedit_cfg();
-			break;
-		case 5:
-			xtrnsec_cfg();
-			break; } }
-}
-
-void fevents_cfg()
-{
-	static int event_dflt;
-	char str[81],*p;
-	int i;
-
-while(1) {
-	i=0;
-	sprintf(opt[i++],"%-32.32s%.40s","Logon Event",sys_logon);
-	sprintf(opt[i++],"%-32.32s%.40s","Logout Event",sys_logout);
-	sprintf(opt[i++],"%-32.32s%.40s","Daily Event",sys_daily);
-	opt[i][0]=0;
-	savnum=0;
-	SETHELP(WHERE);
-/*
-External Events:
-
-From this menu, you can configure the logon and logout events, and the
-system daily event.
-*/
-	switch(ulist(WIN_ACT|WIN_SAV|WIN_CHE|WIN_BOT|WIN_RHT,0,0,60,&event_dflt,0
-		,"Fixed Events",opt)) {
-		case -1:
-			return;
-		case 0:
-			SETHELP(WHERE);
-/*
-Logon Event:
-
-This is the command line for a program that will execute during the
-logon sequence of every user. The program cannot have user interaction.
-The program will be executed after the LOGON message is displayed and
-before the logon user list is displayed. If you wish to place a program
-in the logon sequence of users that includes interaction or requires
-account information, you probably want to use an online external
-program configured to run as a logon event.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Logon Event"
-				,sys_logon,50,K_EDIT);
-			break;
-		case 1:
-			SETHELP(WHERE);
-/*
-Logout Event:
-
-This is the command line for a program that will execute during the
-logout sequence of every user. This program cannot have user
-interaction because it is executed after carrier is dropped. If you
-wish to have a program execute before carrier is dropped, you probably
-want to use an Online External Program configured to run as a logoff
-event.
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Logout Event"
-				,sys_logout,50,K_EDIT);
-			break;
-		case 2:
-			SETHELP(WHERE);
-/*
-Daily Event:
-
-This is the command line for a program that will run after the first
-user that logs on after midnight, logs off (regardless of what node).
-*/
-			uinput(WIN_MID|WIN_SAV,0,0,"Daily Event"
-				,sys_daily,50,K_EDIT);
-
-			break; } }
-}
-
-void tevents_cfg()
-{
-	static int dflt,dfltopt,bar;
-	char str[81],done=0,*p;
-	int j,k;
-	uint i;
-	static event_t savevent;
-
-while(1) {
-	for(i=0;i<total_events && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-8.8s      %.50s",event[i]->code,event[i]->cmd);
-	opt[i][0]=0;
-	j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
-	savnum=0;
-	if(total_events)
-		j|=WIN_DEL|WIN_GET;
-	if(total_events<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT;
-	if(savevent.code[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Timed Events:
-
-This is a list of the configured timed external events.
-
-To add an event hit  INS .
-
-To delete an event, select it and hit  DEL .
-
-To configure an event, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&dflt,&bar,"Timed Events",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i=total_events;
-		SETHELP(WHERE);
-/*
-Timed Event Internal Code:
-
-This is the internal code for the timed event.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Event Internal Code",str,8
-			,K_UPPER)<1)
-            continue;
-		if((event=(event_t **)REALLOC(event
-			,sizeof(event_t *)*(total_events+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_events+1);
-			total_events=0;
-			bail(1);
-            continue; }
-		if((event[i]=(event_t *)MALLOC(sizeof(event_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(event_t));
-			continue; }
-		memset((event_t *)event[i],0,sizeof(event_t));
-		strcpy(event[i]->code,str);
-		event[i]->node=1;
-		event[i]->days=0xff;
-		total_events++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(event[i]);
-		total_events--;
-		for(j=i;j<total_events;j++)
-			event[j]=event[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savevent=*event[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*event[i]=savevent;
-		changes=1;
-        continue; }
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-32.32s%s","Internal Code",event[i]->code);
-		sprintf(opt[k++],"%-32.32s%.40s","Start-up Directory",event[i]->dir);
-		sprintf(opt[k++],"%-32.32s%.40s","Command Line",event[i]->cmd);
-		sprintf(opt[k++],"%-32.32s%u","Execution Node",event[i]->node);
-		sprintf(opt[k++],"%-32.32s%s","Execution Days",daystr(event[i]->days));
-		sprintf(opt[k++],"%-32.32s%02u:%02u","Execution Time"
-			,event[i]->time/60,event[i]->time%60);
-		sprintf(opt[k++],"%-32.32s%s","Requires Exclusive Execution"
-			,event[i]->misc&EVENT_EXCL ? "Yes":"No");
-		sprintf(opt[k++],"%-32.32s%s","Force Users Off-line For Event"
-			,event[i]->misc&EVENT_FORCE ? "Yes":"No");
-		opt[k][0]=0;
-		SETHELP(WHERE);
-/*
-Timed Event:
-
-This is the configuration menu for a timed event. An event is an
-external program that performs some type of automated function on the
-system. Use this menu to configure how and when this event will be
-executed.
-
-If you need the BBS to swap out of memory for this event (to make more
-available memory), add the program name (first word of the command line)
-to Global Swap List from the External Programs menu.
-*/
-		savnum=1;
-		sprintf(str,"%s Timed Event",event[i]->code);
-		switch(ulist(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
-			,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				strcpy(str,event[i]->code);
-				SETHELP(WHERE);
-/*
-Timed Event Internal Code:
-
-Every timed event must have its own unique internal code for Synchronet
-to reference it by. It is helpful if this code is an abreviation of the
-command line.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(event[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-					helpbuf=0; }
-                break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Timed Event Start-up Directory:
-
-This is the DOS drive/directory where the event program is located.
-If a path is specified here, it will be made the current directory
-before the event's command line is executed. This eliminates the need
-for batch files that just change the current drive and directory before
-executing the event.
-
-If this option is not used, the current NODE's directory will be the
-current DOS drive/directory before the command line is executed.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Directory"
-					,event[i]->dir,50,K_EDIT|K_UPPER);
-                break;
-			case 2:
-				SETHELP(WHERE);
-/*
-Timed Event Command Line:
-
-This is the command line to execute upon this timed event.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Command"
-					,event[i]->cmd,50,K_EDIT);
-				break;
-			case 3:
-				SETHELP(WHERE);
-/*
-Timed Event Node:
-
-This is the node number to execute the timed event.
-*/
-				sprintf(str,"%u",event[i]->node);
-				uinput(WIN_MID|WIN_SAV,0,0,"Node Number"
-					,str,3,K_EDIT|K_NUMBER);
-				event[i]->node=atoi(str);
-				break;
-			case 4:
-				j=0;
-				while(1) {
-					for(k=0;k<7;k++)
-						sprintf(opt[k],"%s        %s"
-							,wday[k],(event[i]->days&(1<<k)) ? "Yes":"No");
-					opt[k][0]=0;
-					savnum=2;
-					SETHELP(WHERE);
-/*
-Days to Execute Event:
-
-These are the days of the week that this event will be executed.
-*/
-					k=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-						,"Days to Execute Event",opt);
-					if(k==-1)
-						break;
-					event[i]->days^=(1<<k);
-					changes=1; }
-				break;
-			case 5:
-				sprintf(str,"%2.2d:%2.2d",event[i]->time/60
-					,event[i]->time%60);
-				SETHELP(WHERE);
-/*
-Time to Execute Event:
-
-This is the time (in 24 hour HH:MM format) to execute the event.
-*/
-				if(uinput(WIN_MID|WIN_SAV,0,0
-					,"Time to Execute Event (HH:MM)"
-					,str,5,K_UPPER|K_EDIT)>0) {
-					event[i]->time=atoi(str)*60;
-					if((p=strchr(str,':'))!=NULL)
-						event[i]->time+=atoi(p+1); }
-				break;
-			case 6:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Exclusive Event Execution:
-
-If this event must be run exclusively (all nodes inactive), set this
-option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Exclusive Execution"
-					,opt);
-				if(!k && !(event[i]->misc&EVENT_EXCL)) {
-					event[i]->misc|=EVENT_EXCL;
-					changes=1; }
-				else if(k==1 && event[i]->misc&EVENT_EXCL) {
-					event[i]->misc&=~EVENT_EXCL;
-					changes=1; }
-                break;
-			case 7:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Force Users Off-line for Event:
-
-If you want to have your users' on-line time reduced so the event can
-execute precisely on time, set this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Force Users Off-line for Event",opt);
-				if(!k && !(event[i]->misc&EVENT_FORCE)) {
-					event[i]->misc|=EVENT_FORCE;
-					changes=1; }
-				else if(k==1 && event[i]->misc&EVENT_FORCE) {
-					event[i]->misc&=~EVENT_FORCE;
-                    changes=1; }
-                break;
-
-				} } }
-}
-
-
-void xtrn_cfg(uint section)
-{
-	static int ext_dflt,ext_bar,opt_dflt,time_dflt;
-	char str[128],code[9],done=0,*p;
-	int j,k;
-	uint i,n,xtrnnum[MAX_OPTS+1];
-	static xtrn_t savxtrn;
-
-while(1) {
-	for(i=0,j=0;i<total_xtrns && j<MAX_OPTS;i++)
-		if(xtrn[i]->sec==section) {
-			sprintf(opt[j],"%-25s",xtrn[i]->name);
-			xtrnnum[j++]=i; }
-	xtrnnum[j]=total_xtrns;
-	opt[j][0]=0;
-	savnum=2;
-	i=WIN_ACT|WIN_CHE|WIN_SAV|WIN_RHT;
-	if(j)
-		i|=WIN_DEL|WIN_GET;
-	if(total_xtrns<MAX_OPTS)
-		i|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savxtrn.name[0])
-		i|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Online External Programs:
-
-This is a list of the configured online external programs (doors).
-
-To add a program, select the desired location with the arrow keys and
-hit  INS .
-
-To delete a program, select it with the arrow keys and hit  DEL .
-
-To configure a program, select it with the arrow keys and hit  ENTER .
-*/
-	sprintf(str,"%s Online Programs",xtrnsec[section]->name);
-	i=ulist(i,0,0,45,&ext_dflt,&ext_bar,str,opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Online Program Name:
-
-This is the name or description of the online program (door).
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Online Program Name",str,25
-			,0)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Online Program Internal Code:
-
-Every online program must have its own unique code for Synchronet to
-refer to it internally. This code is usually an abreviation of the
-online program name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Internal Code"
-			,code,8,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((xtrn=(xtrn_t **)REALLOC(xtrn,sizeof(xtrn_t *)*(total_xtrns+1)))
-            ==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrns+1);
-			total_xtrns=0;
-			bail(1);
-            continue; }
-		if(j)
-			for(n=total_xtrns;n>xtrnnum[i];n--)
-				xtrn[n]=xtrn[n-1];
-		if((xtrn[xtrnnum[i]]=(xtrn_t *)MALLOC(sizeof(xtrn_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrn_t));
-			continue; }
-		memset((xtrn_t *)xtrn[xtrnnum[i]],0,sizeof(xtrn_t));
-		strcpy(xtrn[xtrnnum[i]]->name,str);
-		strcpy(xtrn[xtrnnum[i]]->code,code);
-		xtrn[xtrnnum[i]]->sec=section;
-		total_xtrns++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(xtrn[xtrnnum[i]]);
-		total_xtrns--;
-		for(j=xtrnnum[i];j<total_xtrns;j++)
-			xtrn[j]=xtrn[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savxtrn=*xtrn[xtrnnum[i]];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*xtrn[xtrnnum[i]]=savxtrn;
-		xtrn[xtrnnum[i]]->sec=section;
-		changes=1;
-        continue; }
-	done=0;
-	i=xtrnnum[i];
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Name",xtrn[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Internal Code",xtrn[i]->code);
-		sprintf(opt[k++],"%-27.27s%.40s","Start-up Directory",xtrn[i]->path);
-		sprintf(opt[k++],"%-27.27s%.40s","Command Line",xtrn[i]->cmd);
-		sprintf(opt[k++],"%-27.27s%.40s","Clean-up Command Line",xtrn[i]->clean);
-		if(xtrn[i]->cost)
-			sprintf(str,"%lu credits",xtrn[i]->cost);
-		else
-			strcpy(str,"None");
-		sprintf(opt[k++],"%-27.27s%s","Execution Cost",str);
-		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements",xtrn[i]->ar);
-		sprintf(opt[k++],"%-27.27s%.40s","Execution Requirements"
-			,xtrn[i]->run_ar);
-		sprintf(opt[k++],"%-27.27s%s","Multiple Concurrent Users"
-			,xtrn[i]->misc&MULTIUSER ? "Yes" : "No");
-		sprintf(opt[k++],"%-27.27s%s%s","Intercept I/O Interrupts"
-			,xtrn[i]->misc&IO_INTS ? "Yes" : "No"
-			,xtrn[i]->misc&WWIVCOLOR ? ", WWIV" : nulstr);
-		sprintf(opt[k++],"%-27.27s%s","Swap BBS out of Memory"
-			,xtrn[i]->misc&SWAP ? "Yes" : "No");
-		sprintf(opt[k++],"%-27.27s%s","Modify User Data"
-            ,xtrn[i]->misc&MODUSERDAT ? "Yes" : "No");
-		switch(xtrn[i]->event) {
-			case EVENT_LOGON:
-				strcpy(str,"Logon");
-				break;
-			case EVENT_LOGOFF:
-				strcpy(str,"Logoff");
-				break;
-			case EVENT_NEWUSER:
-				strcpy(str,"New User");
-				break;
-			case EVENT_BIRTHDAY:
-				strcpy(str,"Birthday");
-				break;
-			default:
-				strcpy(str,"No");
-				break; }
-		if(xtrn[i]->misc&EVENTONLY && xtrn[i]->event)
-			strcat(str,", Only");
-		sprintf(opt[k++],"%-27.27s%s","Execute on Event",str);
-		switch(xtrn[i]->type) {
-			case XTRN_SBBS:
-				sprintf(str,"%-15s %s","Synchronet","XTRN.DAT");
-				break;
-			case XTRN_WWIV:
-				sprintf(str,"%-15s %s","WWIV","CHAIN.TXT");
-				break;
-			case XTRN_GAP:
-				sprintf(str,"%-15s %s","GAP","DOOR.SYS");
-				break;
-			case XTRN_RBBS:
-				sprintf(str,"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
-				break;
-			case XTRN_RBBS1:
-				sprintf(str,"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
-                break;
-			case XTRN_WILDCAT:
-				sprintf(str,"%-15s %s","Wildcat","CALLINFO.BBS");
-				break;
-			case XTRN_PCBOARD:
-				sprintf(str,"%-15s %s","PCBoard","PCBOARD.SYS");
-				break;
-			case XTRN_SPITFIRE:
-				sprintf(str,"%-15s %s","SpitFire","SFDOORS.DAT");
-				break;
-			case XTRN_UTI:
-				sprintf(str,"%-15s %s","MegaMail","UTIDOOR.TXT");
-				break;
-			case XTRN_SR:
-				sprintf(str,"%-15s %s","Solar Realms","DOORFILE.SR");
-				break;
-			case XTRN_TRIBBS:
-				sprintf(str,"%-15s %s","TriBBS","TRIBBS.SYS");
-				break;
-			default:
-				strcpy(str,"None");
-				break; }
-		sprintf(opt[k++],"%-23.23s%-4s%s","BBS Drop File Type"
-			,xtrn[i]->misc&REALNAME ? "(R)":nulstr,str);
-		sprintf(opt[k++],"%-27.27s%s","Place Drop File In"
-			,xtrn[i]->misc&STARTUPDIR ? "Start-Up Directory":"Node Directory");
-		sprintf(opt[k++],"Time Options...");
-		opt[k][0]=0;
-		savnum=3;
-		SETHELP(WHERE);
-/*
-Online Program Configuration:
-
-This menu is for configuring the selected online program.
-*/
-		switch(ulist(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&opt_dflt,0,xtrn[i]->name
-			,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Online Program Name:
-
-This is the name or description of the online program (door).
-*/
-				strcpy(str,xtrn[i]->name);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"Online Program Name"
-					,xtrn[i]->name,25,K_EDIT))
-					strcpy(xtrn[i]->name,str);
-				break;
-			case 1:
-				SETHELP(WHERE);
-/*
-Online Program Internal Code:
-
-Every online program must have its own unique code for Synchronet to
-refer to it internally. This code is usually an abreviation of the
-online program name.
-*/
-				strcpy(str,xtrn[i]->code);
-				uinput(WIN_MID|WIN_SAV,0,10,"Internal Code"
-					,str,8,K_UPPER|K_EDIT);
-				if(code_ok(str))
-					strcpy(xtrn[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-                    helpbuf=0; }
-                break;
-			case 2:
-                SETHELP(WHERE);
-/*
-Online Program Start-up Directory:
-
-This is the DOS drive/directory where the online program is located.
-If a path is specified here, it will be made the current directory
-before the program's command line is executed. This eliminates the need
-for batch files that just change the current drive and directory before
-executing the program.
-
-If this option is not used, the current NODE's directory will be the
-current DOS drive/directory before the command line is executed.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Directory"
-					,xtrn[i]->path,50,K_EDIT|K_UPPER);
-                break;
-			case 3:
-				SETHELP(WHERE);
-/*
-Online Program Command Line:
-
-This is the command line to execute to run the online program.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Command"
-					,xtrn[i]->cmd,50,K_EDIT);
-				break;
-			case 4:
-				SETHELP(WHERE);
-/*
-Online Program Clean-up Command:
-
-This is the command line to execute after the main command line. This
-option is usually only used for multiuser online programs.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Clean-up"
-					,xtrn[i]->clean,50,K_EDIT);
-                break;
-			case 5:
-                ultoa(xtrn[i]->cost,str,10);
-                SETHELP(WHERE);
-/*
-Online Program Cost to Run:
-
-If you want users to be charged credits to run this online program,
-set this value to the number of credits to charge. If you want this
-online program to be free, set this value to 0.
-*/
-                uinput(WIN_MID|WIN_SAV,0,0,"Cost to Run (in Credits)"
-                    ,str,10,K_EDIT|K_NUMBER);
-                xtrn[i]->cost=atol(str);
-                break;
-			case 6:
-				savnum=4;
-				sprintf(str,"%s Access",xtrn[i]->name);
-				getar(str,xtrn[i]->ar);
-                break;
-			case 7:
-				savnum=4;
-				sprintf(str,"%s Execution",xtrn[i]->name);
-				getar(str,xtrn[i]->run_ar);
-                break;
-			case 8:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Supports Multiple Users:
-
-If this online program supports multiple simultaneous users (nodes),
-set this option to Yes.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Supports Multiple Users"
-					,opt);
-				if(!k && !(xtrn[i]->misc&MULTIUSER)) {
-					xtrn[i]->misc|=MULTIUSER;
-					changes=1; }
-				else if(k==1 && xtrn[i]->misc&MULTIUSER) {
-					xtrn[i]->misc&=~MULTIUSER;
-					changes=1; }
-                break;
-			case 9:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Intercept I/O Interrupts:
-
-If this online program has its own serial communication abilities, set
-this option to No.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept I/O Interrupts"
-					,opt);
-				if(!k && !(xtrn[i]->misc&IO_INTS)) {
-					xtrn[i]->misc|=IO_INTS;
-					changes=1; }
-				else if(k==1 && xtrn[i]->misc&IO_INTS) {
-					xtrn[i]->misc&=~(IO_INTS|WWIVCOLOR);
-					changes=1; }
-				if(!(xtrn[i]->misc&IO_INTS))
-					break;
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Program Uses WWIV Color Codes:
-
-If this program was written for use exclusively under WWIV, set this
-option to Yes.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Program Uses WWIV Color Codes"
-					,opt);
-				if(!k && !(xtrn[i]->misc&WWIVCOLOR)) {
-					xtrn[i]->misc|=WWIVCOLOR;
-					changes=1; }
-				else if(k==1 && xtrn[i]->misc&WWIVCOLOR) {
-					xtrn[i]->misc&=~WWIVCOLOR;
-                    changes=1; }
-                break;
-			case 10:
-				k=0;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Swap BBS out of Memory to Run Executable:
-
-If this online programs requires a large amount of free memory,
-set this option to Yes to have the BBS swapped out of memory.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Swap BBS out of Memory",opt);
-				if(!k && !(xtrn[i]->misc&SWAP)) {
-					xtrn[i]->misc|=SWAP;
-					changes=1; }
-				else if(k==1 && xtrn[i]->misc&SWAP) {
-					xtrn[i]->misc&=~SWAP;
-					changes=1; }
-				break;
-			case 11:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Program Can Modify User Data:
-
-If this online programs recognizes the Synchronet MODUSER.DAT format
-or the RBBS/QuickBBS EXITINFO.BBS format and you want it to be able to
-modify the data of users who run the program, set this option to Yes.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Program Can Modify User Data",opt);
-				if(!k && !(xtrn[i]->misc&MODUSERDAT)) {
-					xtrn[i]->misc|=MODUSERDAT;
-					changes=1; }
-				else if(k==1 && xtrn[i]->misc&MODUSERDAT) {
-					xtrn[i]->misc&=~MODUSERDAT;
-					changes=1; }
-                break;
-			case 12:
-				k=0;
-				strcpy(opt[k++],"No");
-				strcpy(opt[k++],"Logon");
-				strcpy(opt[k++],"Logoff");
-				strcpy(opt[k++],"New User");
-				strcpy(opt[k++],"Birthday");
-				opt[k][0]=0;
-				switch(xtrn[i]->event) {
-					default:
-						k=0;
-						break;
-					case EVENT_LOGON:
-						k=1;
-						break;
-					case EVENT_LOGOFF:
-						k=2;
-						break;
-					case EVENT_NEWUSER:
-						k=3;
-						break;
-					case EVENT_BIRTHDAY:
-						k=4;
-						break; }
-				SETHELP(WHERE);
-/*
-Execute Online Program on Event:
-
-If you would like this online program to automatically execute on a
-specific user event, select the event. Otherwise, select No.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Execute on Event",opt);
-				if(k==-1)
-					break;
-				if(xtrn[i]->event!=k) {
-					xtrn[i]->event=k;
-					changes=1; }
-				if(!xtrn[i]->event)
-					break;
-				k=1;
-                strcpy(opt[0],"Yes");
-                strcpy(opt[1],"No");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Execute Online Program as Event Only:
-
-If you would like this online program to execute as an event only
-(not available to users on the online program menu), set this option
-to Yes.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k
-					,0,"Execute as Event Only"
-                    ,opt);
-                if(!k && !(xtrn[i]->misc&EVENTONLY)) {
-                    xtrn[i]->misc|=EVENTONLY;
-                    changes=1; }
-                else if(k==1 && xtrn[i]->misc&EVENTONLY) {
-                    xtrn[i]->misc&=~EVENTONLY;
-                    changes=1; }
-                break;
-			case 13:
-				k=0;
-				strcpy(opt[k++],"None");
-				sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
-				sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
-				sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
-				sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
-				sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
-				sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
-				sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
-				sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
-				sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
-				sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
-				sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
-				opt[k][0]=0;
-				k=xtrn[i]->type;
-				SETHELP(WHERE);
-/*
-Online Program BBS Drop File Type:
-
-If this online program requires a specific BBS data (drop) file
-format, select the file format from the list.
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"BBS Drop File Type",opt);
-				if(k==-1)
-					break;
-				if(xtrn[i]->type!=k) {
-					xtrn[i]->type=k;
-					changes=1; }
-				if(xtrn[i]->type && uq&UQ_ALIASES) {
-					strcpy(opt[0],"Yes");
-					strcpy(opt[1],"No");
-					opt[2][0]=0;
-					k=1;
-					k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Use Real Names",opt);
-					if(k==0 && !(xtrn[i]->misc&REALNAME)) {
-						xtrn[i]->misc|=REALNAME;
-						changes=1; }
-					else if(k==1 && xtrn[i]->misc&REALNAME) {
-						xtrn[i]->misc&=~REALNAME;
-						changes=1; } }
-				break;
-			case 14:
-				k=0;
-				strcpy(opt[0],"Node Directory");
-				strcpy(opt[1],"Start-up Directory");
-				opt[2][0]=0;
-				SETHELP(WHERE);
-/*
-Directory for Drop File:
-
-You can have the data file created in the current Node Directory or the
-Start-up Directory (if one is specified).
-*/
-				savnum=4;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Create Drop File In"
-                    ,opt);
-				if(!k && xtrn[i]->misc&STARTUPDIR) {
-					xtrn[i]->misc&=~STARTUPDIR;
-                    changes=1; }
-				else if(k==1 && !(xtrn[i]->misc&STARTUPDIR)) {
-					xtrn[i]->misc|=STARTUPDIR;
-                    changes=1; }
-				break;
-			case 15:
-				while(1) {
-					k=0;
-					if(xtrn[i]->textra)
-						sprintf(str,"%u minutes",xtrn[i]->textra);
-					else
-						strcpy(str,"None");
-					sprintf(opt[k++],"%-25.25s%s","Extra Time",str);
-					if(xtrn[i]->maxtime)
-						sprintf(str,"%u minutes",xtrn[i]->maxtime);
-					else
-						strcpy(str,"None");
-					sprintf(opt[k++],"%-25.25s%s","Maximum Time",str);
-					sprintf(opt[k++],"%-25.25s%s","Suspended (Free) Time"
-						,xtrn[i]->misc&FREETIME ? "Yes" : "No");
-					opt[k][0]=0;
-					SETHELP(WHERE);
-/*
-Online Program Time Options:
-
-This sub-menu allows you to define specific preferences regarding the
-time users spend running this program.
-*/
-					savnum=4;
-					k=ulist(WIN_SAV|WIN_ACT|WIN_RHT|WIN_BOT,0,0,40
-						,&time_dflt,0
-						,"Online Program Time Options",opt);
-					if(k==-1)
-						break;
-					savnum=5;
-					switch(k) {
-						case 0:
-							itoa(xtrn[i]->textra,str,10);
-							SETHELP(WHERE);
-/*
-Extra Time to Give User in Program:
-
-If you want to give users extra time while in this online program,
-set this value to the number of minutes to add to their current time
-left online.
-*/
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Extra Time to Give User (in minutes)"
-								,str,2,K_EDIT|K_NUMBER);
-							xtrn[i]->textra=atoi(str);
-							break;
-						case 1:
-							itoa(xtrn[i]->maxtime,str,10);
-							SETHELP(WHERE);
-/*
-Maximum Time Allowed in Program:
-
-If this program supports a drop file that contains the number of minutes
-left online for the current user, this option allows the sysop to set
-the maximum number of minutes that will be allowed in the drop file.
-
-Setting this option to 0, disables this feature.
-*/
-							uinput(WIN_MID|WIN_SAV,0,0
-								,"Maximum Time (in minutes, 0=disabled)"
-								,str,2,K_EDIT|K_NUMBER);
-							xtrn[i]->maxtime=atoi(str);
-							break;
-						case 2:
-							k=1;
-							strcpy(opt[0],"Yes");
-							strcpy(opt[1],"No");
-							opt[2][0]=0;
-							SETHELP(WHERE);
-/*
-Suspended (Free) Time:
-
-If you want the user's time online to be suspended while running this
-online program (e.g. Free Time), set this option to Yes.
-*/
-							k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-								,"Suspended (Free) Time",opt);
-							if(!k && !(xtrn[i]->misc&FREETIME)) {
-								xtrn[i]->misc|=FREETIME;
-								changes=1; }
-							else if(k==1 && xtrn[i]->misc&FREETIME) {
-								xtrn[i]->misc&=~FREETIME;
-								changes=1; }
-							break; } }
-					break;
-
-				} } }
-}
-
-void xedit_cfg()
-{
-	static int dflt,dfltopt,bar;
-	char str[81],code[81],done=0,*p;
-	int j,k;
-	uint i;
-	static xedit_t savxedit;
-
-while(1) {
-	for(i=0;i<total_xedits && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-8.8s    %.40s",xedit[i]->code,xedit[i]->lcmd);
-	opt[i][0]=0;
-	j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_RHT;
-	savnum=0;
-	if(total_xedits)
-		j|=WIN_DEL|WIN_GET;
-	if(total_xedits<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savxedit.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-External Editors:
-
-This is a list of the configured external editors.
-
-To add an editor, select the desired location and hit  INS .
-
-To delete an editor, select it and hit  DEL .
-
-To configure an editor, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&dflt,&bar,"External Editors",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-External Editor Name:
-
-This is the name or description of the external editor.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"External Editor Name",str,40
-			,0)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-External Editor Internal Code:
-
-This is the internal code for the external editor.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"External Editor Internal Code",code,8
-			,K_UPPER|K_EDIT)<1)
-            continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-
-		if((xedit=(xedit_t **)REALLOC(xedit
-            ,sizeof(xedit_t *)*(total_xedits+1)))==NULL) {
-            errormsg(WHERE,ERR_ALLOC,nulstr,total_xedits+1);
-			total_xedits=0;
-			bail(1);
-            continue; }
-		if(total_xedits)
-			for(j=total_xedits;j>i;j--)
-				xedit[j]=xedit[j-1];
-		if((xedit[i]=(xedit_t *)MALLOC(sizeof(xedit_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xedit_t));
-			continue; }
-		memset((xedit_t *)xedit[i],0,sizeof(xedit_t));
-		strcpy(xedit[i]->name,str);
-		strcpy(xedit[i]->code,code);
-		total_xedits++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(xedit[i]);
-		total_xedits--;
-		for(j=i;j<total_xedits;j++)
-			xedit[j]=xedit[j+1];
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savxedit=*xedit[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*xedit[i]=savxedit;
-		changes=1;
-        continue; }
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-32.32s%s","Name",xedit[i]->name);
-		sprintf(opt[k++],"%-32.32s%s","Internal Code",xedit[i]->code);
-		sprintf(opt[k++],"%-32.32s%.40s","Local Command Line",xedit[i]->lcmd);
-		sprintf(opt[k++],"%-32.32s%.40s","Remote Command Line",xedit[i]->rcmd);
-		sprintf(opt[k++],"%-32.32s%.40s","Access Requirements",xedit[i]->ar);
-		sprintf(opt[k++],"%-32.32s%s%s","Intercept I/O Interrupts"
-			,xedit[i]->misc&IO_INTS ? "Yes":"No"
-			,xedit[i]->misc&WWIVCOLOR ? ", WWIV" : nulstr);
-		sprintf(opt[k++],"%-32.32s%s","Quoted Text"
-			,xedit[i]->misc&QUOTEALL ? "All":xedit[i]->misc&QUOTENONE
-				? "None" : "Prompt User");
-		sprintf(opt[k++],"%-32.32s%s","QuickBBS Style (MSGTMP)"
-			,xedit[i]->misc&QUICKBBS ? "Yes":"No");
-		sprintf(opt[k++],"%-32.32s%s","Expand Line Feeds to CRLF"
-			,xedit[i]->misc&EXPANDLF ? "Yes":"No");
-		switch(xedit[i]->type) {
-			case XTRN_SBBS:
-				sprintf(str,"%-15s %s","Synchronet","XTRN.DAT");
-				break;
-			case XTRN_WWIV:
-				sprintf(str,"%-15s %s","WWIV","CHAIN.TXT");
-				break;
-			case XTRN_GAP:
-				sprintf(str,"%-15s %s","GAP","DOOR.SYS");
-				break;
-			case XTRN_RBBS:
-				sprintf(str,"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
-				break;
-			case XTRN_RBBS1:
-				sprintf(str,"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
-                break;
-			case XTRN_WILDCAT:
-				sprintf(str,"%-15s %s","Wildcat","CALLINFO.BBS");
-				break;
-			case XTRN_PCBOARD:
-				sprintf(str,"%-15s %s","PCBoard","PCBOARD.SYS");
-				break;
-			case XTRN_SPITFIRE:
-				sprintf(str,"%-15s %s","SpitFire","SFDOORS.DAT");
-				break;
-			case XTRN_UTI:
-				sprintf(str,"%-15s %s","MegaMail","UTIDOOR.TXT");
-				break;
-			case XTRN_SR:
-				sprintf(str,"%-15s %s","Solar Realms","DOORFILE.SR");
-				break;
-			case XTRN_TRIBBS:
-				sprintf(str,"%-15s %s","TriBBS","TRIBBS.SYS");
-                break;
-			default:
-				strcpy(str,"None");
-                break; }
-		sprintf(opt[k++],"%-32.32s%s","BBS Drop File Type",str);
-        opt[k][0]=0;
-		SETHELP(WHERE);
-/*
-External Editor Configuration:
-
-This menu allows you to change the settings for the selected external
-message editor. External message editors are very common on BBSs. Some
-popular editors include SyncEdit, WWIVedit, FEdit, GEdit, IceEdit,
-and many others.
-*/
-
-		savnum=1;
-		sprintf(str,"%s Editor",xedit[i]->name);
-		switch(ulist(WIN_SAV|WIN_ACT|WIN_L2R|WIN_BOT,0,0,70,&dfltopt,0
-			,str,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-External Editor Name:
-
-This is the name or description of the external editor.
-*/
-				strcpy(str,xedit[i]->name);
-				if(!uinput(WIN_MID|WIN_SAV,0,10,"External Editor Name"
-					,xedit[i]->name,40,K_EDIT))
-					strcpy(xedit[i]->name,str);
-				break;
-			case 1:
-				strcpy(str,xedit[i]->code);
-				SETHELP(WHERE);
-/*
-External Editor Internal Code:
-
-Every external editor must have its own unique internal code for
-Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(xedit[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-					helpbuf=0; }
-                break;
-			case 2:
-				SETHELP(WHERE);
-/*
-External Editor Local Command Line:
-
-This is the command line to execute when using this editor locally.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Local"
-					,xedit[i]->lcmd,50,K_EDIT);
-				break;
-
-		   case 3:
-				SETHELP(WHERE);
-/*
-External Editor Remote Command Line:
-
-This is the command line to execute when using this editor remotely.
-*/
-				uinput(WIN_MID|WIN_SAV,0,10,"Remote"
-					,xedit[i]->rcmd,50,K_EDIT);
-				break;
-			case 4:
-				savnum=2;
-				sprintf(str,"%s External Editor",xedit[i]->name);
-				getar(str,xedit[i]->ar);
-				break;
-			case 5:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Intercept I/O Interrupts:
-
-If this external editor has its own serial communication abilities or
-requires a FOSSIL driver, set this option to No.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Intercept I/O Interrupts"
-					,opt);
-				if(!k && !(xedit[i]->misc&IO_INTS)) {
-					xedit[i]->misc|=IO_INTS;
-					changes=1; }
-				else if(k==1 && xedit[i]->misc&IO_INTS) {
-					xedit[i]->misc&=~(IO_INTS|WWIVCOLOR);
-					changes=1; }
-				if(!(xedit[i]->misc&IO_INTS))
-					break;
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Editor Uses WWIV Color Codes:
-
-If this editor was written for use exclusively under WWIV, set this
-option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"Editor Uses WWIV Color Codes",opt);
-				if(!k && !(xedit[i]->misc&WWIVCOLOR)) {
-					xedit[i]->misc|=WWIVCOLOR;
-					changes=1; }
-				else if(k==1 && xedit[i]->misc&WWIVCOLOR) {
-					xedit[i]->misc&=~WWIVCOLOR;
-                    changes=1; }
-                break;
-			case 6:
-				k=3;
-				strcpy(opt[0],"All");
-				strcpy(opt[1],"None");
-				strcpy(opt[2],"Prompt User");
-				opt[3][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Quoted Text:
-
-If you want all the message text to be automatically entered into the
-message edit/quote file (INPUT.MSG or MSGTMP), select All.
-
-If you want the user to be prompted for which lines to quote before
-running the editor, select Prompt User.
-
-If you want none of the lines to be automatically quoted, select None.
-This option is mainly for use with editors that support the QUOTES.TXT
-drop file (like SyncEdit v2.x).
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Quoted Text"
-					,opt);
-				if(!k && !(xedit[i]->misc&QUOTEALL)) {
-					xedit[i]->misc|=QUOTEALL;
-					xedit[i]->misc&=~QUOTENONE;
-					changes=1; }
-				else if(k==1 && !(xedit[i]->misc&QUOTENONE)) {
-					xedit[i]->misc|=QUOTENONE;
-					xedit[i]->misc&=~QUOTEALL;
-                    changes=1; }
-				else if(k==2 && xedit[i]->misc&(QUOTENONE|QUOTEALL)) {
-					xedit[i]->misc&=~(QUOTENONE|QUOTEALL);
-					changes=1; }
-                break;
-			case 7:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-QuickBBS Style (MSGTMP):
-
-If this external editor uses the QuickBBS style MSGTMP interface, set
-this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"QuickBBS Style (MSGTMP)"
-					,opt);
-				if(!k && !(xedit[i]->misc&QUICKBBS)) {
-					xedit[i]->misc|=QUICKBBS;
-					changes=1; }
-				else if(k==1 && xedit[i]->misc&QUICKBBS) {
-					xedit[i]->misc&=~QUICKBBS;
-                    changes=1; }
-				break;
-			case 8:
-				k=1;
-				strcpy(opt[0],"Yes");
-				strcpy(opt[1],"No");
-				opt[2][0]=0;
-				savnum=2;
-				SETHELP(WHERE);
-/*
-Expand Line Feeds to Carriage Return/Line Feed Pairs:
-
-If this external editor saves new lines as a single line feed character
-instead of a carriage return/line feed pair, set this option to Yes.
-*/
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0,"Expand LF to CRLF"
-					,opt);
-				if(!k && !(xedit[i]->misc&EXPANDLF)) {
-					xedit[i]->misc|=EXPANDLF;
-					changes=1; }
-				else if(k==1 && xedit[i]->misc&EXPANDLF) {
-					xedit[i]->misc&=~EXPANDLF;
-                    changes=1; }
-				break;
-			case 9:
-				k=0;
-				strcpy(opt[k++],"None");
-				sprintf(opt[k++],"%-15s %s","Synchronet","XTRN.DAT");
-				sprintf(opt[k++],"%-15s %s","WWIV","CHAIN.TXT");
-				sprintf(opt[k++],"%-15s %s","GAP","DOOR.SYS");
-				sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO#.DEF");
-				sprintf(opt[k++],"%-15s %s","Wildcat","CALLINFO.BBS");
-				sprintf(opt[k++],"%-15s %s","PCBoard","PCBOARD.SYS");
-				sprintf(opt[k++],"%-15s %s","SpitFire","SFDOORS.DAT");
-				sprintf(opt[k++],"%-15s %s","MegaMail","UTIDOOR.TXT");
-				sprintf(opt[k++],"%-15s %s","Solar Realms","DOORFILE.SR");
-				sprintf(opt[k++],"%-15s %s","RBBS/QuickBBS","DORINFO1.DEF");
-				sprintf(opt[k++],"%-15s %s","TriBBS","TRIBBS.SYS");
-				opt[k][0]=0;
-				k=xedit[i]->type;
-				SETHELP(WHERE);
-/*
-External Program BBS Drop File Type:
-
-If this external editor requires a specific BBS data (drop) file
-format, select the file format from the list.
-*/
-				savnum=2;
-				k=ulist(WIN_MID|WIN_SAV,0,0,0,&k,0
-					,"BBS Drop File Type",opt);
-				if(k==-1)
-					break;
-				if(xedit[i]->type!=k) {
-					xedit[i]->type=k;
-					changes=1; }
-				break;
-
-				} } }
-}
-
-
-void swap_cfg()
-{
-	static int dflt,bar;
-	char str[81];
-	int j,k;
-	uint i;
-
-while(1) {
-	for(i=0;i<MAX_OPTS && i<total_swaps;i++)
-		sprintf(opt[i],"%-25s",swap[i]->cmd);
-	opt[i][0]=0;
-	j=WIN_ACT|WIN_CHE|WIN_L2R|WIN_SAV;
-	savnum=0;
-	if(total_swaps)
-		j|=WIN_DEL;
-	if(total_swaps<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	SETHELP(WHERE);
-/*
-External Program Global Swap List:
-
-This is a list of the external program (executable file) names to swap
-the BBS out of memory for. They are termed Global because if you add
-a program name to this list, the BBS will swap to run it regardless of
-when, where, or why the program is run from the BBS.
-
-Use  INS  and  DELETE  to add and remove swappable programs.
-
-To change the filename of a program, hit  ENTER .
-
-To swap whenever PKZIP is run, add PKZIP to the list.
-
-To swap for all DOS Shells, add COMMAND.COM to the list.
-*/
-	i=ulist(j,0,0,17,&dflt,&bar,"Global Swap List",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Swappable Program Name:
-
-This is the executable filename of the external program.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Program Name",str,12
-			,K_UPPER)<1)
-            continue;
-		if((swap=(swap_t **)REALLOC(swap
-			,sizeof(swap_t *)*(total_swaps+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_swaps+1);
-			total_swaps=0;
-			bail(1);
-            continue; }
-		if(total_swaps)
-			for(j=total_swaps;j>i;j--)
-				swap[j]=swap[j-1];
-		if((swap[i]=(swap_t *)MALLOC(sizeof(swap_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(swap_t));
-			continue; }
-		memset((swap_t *)swap[i],0,sizeof(swap_t));
-		strcpy(swap[i]->cmd,str);
-		total_swaps++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(swap[i]);
-		total_swaps--;
-		for(j=i;j<total_swaps;j++)
-			swap[j]=swap[j+1];
-		changes=1;
-		continue; }
-	SETHELP(WHERE);
-/*
-Swappable Program Name:
-
-This is the executable filename of the external program.
-*/
-	strcpy(str,swap[i]->cmd);
-	if(uinput(WIN_MID|WIN_SAV,0,5,"Program Name",str,12
-		,K_UPPER|K_EDIT)>0)
-		strcpy(swap[i]->cmd,str); }
-}
-
-int os2pgm_cfg()
-{
-	static int dflt,bar;
-	char str[81];
-	int j,k;
-	uint i;
-
-while(1) {
-	for(i=0;i<MAX_OPTS && i<total_os2pgms;i++)
-		sprintf(opt[i],"%-12s %-12s",os2pgm[i]->name
-			,os2pgm[i]->misc&OS2_POPEN ? "(port open)":nulstr);
-	opt[i][0]=0;
-	j=WIN_ACT|WIN_CHE|WIN_L2R|WIN_SAV;
-	savnum=0;
-	if(total_os2pgms)
-		j|=WIN_DEL;
-	if(total_os2pgms<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	SETHELP(WHERE);
-/*
-OS/2 Program List:
-
-This is a list of all native OS/2 external program (executable file)
-names that you may execute under Synchronet for OS/2. This list is not
-used in Synchronet for DOS. Any programs not listed here will be assumed
-to be DOS programs and executed accordingly.
-
-Use  INS  and  DELETE  to add and remove OS/2 programs.
-
-To change the filename of a program, hit  ENTER .
-*/
-	i=ulist(j,0,0,30,&dflt,&bar,"OS/2 Program List",opt);
-	if((signed)i==-1)
-		break;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-OS/2 Program Name:
-
-This is the executable filename of the OS/2 external program.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"OS/2 Program Name",str,12
-			,K_UPPER)<1)
-            continue;
-		if((os2pgm=(os2pgm_t **)REALLOC(os2pgm
-			,sizeof(os2pgm_t *)*(total_os2pgms+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_os2pgms+1);
-			total_os2pgms=0;
-			bail(1);
-            continue; }
-		if(total_os2pgms)
-			for(j=total_os2pgms;j>i;j--)
-				os2pgm[j]=os2pgm[j-1];
-		if((os2pgm[i]=(os2pgm_t *)MALLOC(sizeof(os2pgm_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(os2pgm_t));
-			continue; }
-		memset((os2pgm_t *)os2pgm[i],0,sizeof(os2pgm_t));
-		strcpy(os2pgm[i]->name,str);
-
-		SETHELP(WHERE);
-/*
-Leave COM Port Open During Execution:
-
-If this program accesses the COM port via handle (currently open COM
-port), set this option to Yes, otherwise set it to No.
-*/
-		strcpy(opt[0],"Yes (This Program Uses Port Handle)");
-		strcpy(opt[1],"No  (This Program Uses Port Number)");
-		opt[2][0]=0;
-		j=1;
-		if(ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-			,"Leave COM Port Open During Execution?",opt)==0)
-			os2pgm[i]->misc|=OS2_POPEN;
-		total_os2pgms++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(os2pgm[i]);
-		total_os2pgms--;
-		for(j=i;j<total_os2pgms;j++)
-			os2pgm[j]=os2pgm[j+1];
-		changes=1;
-		continue; }
-	SETHELP(WHERE);
-/*
-OS/2 Program Name:
-
-This is the executable filename of the OS/2 external program.
-*/
-	strcpy(str,os2pgm[i]->name);
-	if(uinput(WIN_MID|WIN_SAV,0,5,"OS/2 Program Name",str,12
-		,K_UPPER|K_EDIT)>0)
-		strcpy(os2pgm[i]->name,str);
-
-	SETHELP(WHERE);
-/*
-Leave COM Port Open During Execution:
-
-If this program accesses the COM port via handle (currently open COM
-port), set this option to Yes, otherwise set it to No.
-*/
-	strcpy(opt[0],"Yes (This Program Uses Port Handle)");
-	strcpy(opt[1],"No  (This Program Uses Port Number)");
-	opt[2][0]=0;
-	j=1;
-	savnum=1;
-	j=ulist(WIN_MID|WIN_SAV,0,0,0,&j,0
-		,"Leave COM Port Open During Execution",opt);
-	if(j==0 && !(os2pgm[i]->misc&OS2_POPEN)) {
-		os2pgm[i]->misc|=OS2_POPEN;
-		changes=1; }
-	else if(j==1 && os2pgm[i]->misc&OS2_POPEN) {
-		os2pgm[i]->misc&=~OS2_POPEN;
-		changes=1; }
-	}
-return(0);
-}
-
-
-void xtrnsec_cfg()
-{
-	static int xtrnsec_dflt,xtrnsec_opt;
-	char str[81],code[9],done=0,*p;
-	int j,k;
-	uint i;
-	static xtrnsec_t savxtrnsec;
-
-while(1) {
-	for(i=0;i<total_xtrnsecs && i<MAX_OPTS;i++)
-		sprintf(opt[i],"%-25s",xtrnsec[i]->name);
-	opt[i][0]=0;
-	j=WIN_SAV|WIN_ACT|WIN_CHE|WIN_BOT;
-	savnum=0;
-	if(total_xtrnsecs)
-		j|=WIN_DEL|WIN_GET;
-	if(total_xtrnsecs<MAX_OPTS)
-		j|=WIN_INS|WIN_INSACT|WIN_XTR;
-	if(savxtrnsec.name[0])
-		j|=WIN_PUT;
-	SETHELP(WHERE);
-/*
-Online Program Sections:
-
-This is a list of Online Program Sections configured for your system.
-
-To add an online program section, select the desired location with the
-arrow keys and hit  INS .
-
-To delete an online program section, select it and hit  DEL .
-
-To configure an online program section, select it and hit  ENTER .
-*/
-	i=ulist(j,0,0,45,&xtrnsec_dflt,0,"Online Program Sections",opt);
-	if((signed)i==-1)
-		return;
-	if((i&MSK_ON)==MSK_INS) {
-		i&=MSK_OFF;
-		SETHELP(WHERE);
-/*
-Online Program Section Name:
-
-This is the name of this section.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Online Program Section Name",str,40
-			,0)<1)
-            continue;
-		sprintf(code,"%.8s",str);
-		p=strchr(code,SP);
-		if(p) *p=0;
-        strupr(code);
-		SETHELP(WHERE);
-/*
-Online Program Section Internal Code:
-
-Every online program section must have its own unique internal code
-for Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-*/
-		if(uinput(WIN_MID|WIN_SAV,0,0,"Online Program Section Internal Code"
-			,code,8,K_EDIT|K_UPPER)<1)
-			continue;
-		if(!code_ok(code)) {
-			helpbuf=invalid_code;
-			umsg("Invalid Code");
-			helpbuf=0;
-            continue; }
-		if((xtrnsec=(xtrnsec_t **)REALLOC(xtrnsec
-			,sizeof(xtrnsec_t *)*(total_xtrnsecs+1)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrnsecs+1);
-			total_xtrnsecs=0;
-			bail(1);
-			continue; }
-		if(total_xtrnsecs) {
-			for(j=total_xtrnsecs;j>i;j--)
-				xtrnsec[j]=xtrnsec[j-1];
-			for(j=0;j<total_xtrns;j++)
-				if(xtrn[j]->sec>=i)
-					xtrn[j]->sec++; }
-
-
-		if((xtrnsec[i]=(xtrnsec_t *)MALLOC(sizeof(xtrnsec_t)))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(xtrnsec_t));
-			continue; }
-		memset((xtrnsec_t *)xtrnsec[i],0,sizeof(xtrnsec_t));
-		strcpy(xtrnsec[i]->name,str);
-		strcpy(xtrnsec[i]->code,code);
-		total_xtrnsecs++;
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_DEL) {
-		i&=MSK_OFF;
-		FREE(xtrnsec[i]);
-		for(j=0;j<total_xtrns;) {
-			if(xtrn[j]->sec==i) {	 /* delete xtrns of this group */
-				FREE(xtrn[j]);
-				total_xtrns--;
-				k=j;
-				while(k<total_xtrns) {	 /* move all xtrns down */
-					xtrn[k]=xtrn[k+1];
-					k++; } }
-			else j++; }
-		for(j=0;j<total_xtrns;j++)	 /* move xtrn group numbers down */
-			if(xtrn[j]->sec>i)
-				xtrn[j]->sec--;
-		total_xtrnsecs--;
-		while(i<total_xtrnsecs) {
-			xtrnsec[i]=xtrnsec[i+1];
-            i++; }
-		changes=1;
-		continue; }
-	if((i&MSK_ON)==MSK_GET) {
-		i&=MSK_OFF;
-		savxtrnsec=*xtrnsec[i];
-		continue; }
-	if((i&MSK_ON)==MSK_PUT) {
-		i&=MSK_OFF;
-		*xtrnsec[i]=savxtrnsec;
-		changes=1;
-        continue; }
-	done=0;
-	while(!done) {
-		k=0;
-		sprintf(opt[k++],"%-27.27s%s","Name",xtrnsec[i]->name);
-		sprintf(opt[k++],"%-27.27s%s","Internal Code",xtrnsec[i]->code);
-		sprintf(opt[k++],"%-27.27s%.40s","Access Requirements"
-			,xtrnsec[i]->ar);
-		sprintf(opt[k++],"%s","Available Online Programs...");
-		opt[k][0]=0;
-		savnum=1;
-		sprintf(str,"%s Program Section",xtrnsec[i]->name);
-		switch(ulist(WIN_SAV|WIN_ACT|WIN_MID,0,0,60,&xtrnsec_opt,0,str
-			,opt)) {
-			case -1:
-				done=1;
-				break;
-			case 0:
-				SETHELP(WHERE);
-/*
-Online Program Section Name:
-
-This is the name of this section.
-*/
-				strcpy(str,xtrnsec[i]->name);	 /* save */
-				if(!uinput(WIN_MID|WIN_SAV,0,10
-					,"Online Program Section Name"
-					,xtrnsec[i]->name,40,K_EDIT))
-					strcpy(xtrnsec[i]->name,str);
-				break;
-			case 1:
-				strcpy(str,xtrnsec[i]->code);
-				SETHELP(WHERE);
-/*
-Online Program Section Internal Code:
-
-Every online program section must have its own unique internal code
-for Synchronet to reference it by. It is helpful if this code is an
-abreviation of the name.
-*/
-				uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
-					,str,8,K_EDIT|K_UPPER);
-				if(code_ok(str))
-					strcpy(xtrnsec[i]->code,str);
-				else {
-					helpbuf=invalid_code;
-					umsg("Invalid Code");
-					helpbuf=0; }
-				break;
-			case 2:
-				getar(xtrnsec[i]->name,xtrnsec[i]->ar);
-                break;
-			case 3:
-				xtrn_cfg(i);
-				break; } } }
-}
diff --git a/src/sbbs2/scfg/wrcnf1.c b/src/sbbs2/scfg/wrcnf1.c
deleted file mode 100644
index e6d70020db89cfb8beda9064813de288c7b34eb4..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/wrcnf1.c
+++ /dev/null
@@ -1,577 +0,0 @@
-#line 2 "WRCNF1.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-extern int no_msghdr,all_msghdr;
-extern int no_dirchk;
-
-char *crlf="\r\n";
-char nulbuf[256]={0};
-int  pslen;
-
-#define put_int(var,stream) fwrite(&var,1,sizeof(var),stream)
-#define put_str(var,stream) { pslen=strlen(var); \
-							fwrite(var,1,pslen > sizeof(var) \
-								? sizeof(var) : pslen ,stream); \
-							fwrite(nulbuf,1,pslen > sizeof(var) \
-								? 0 : sizeof(var)-pslen,stream); }
-
-void write_node_cfg()
-{
-	char	str[128],cmd[64],c;
-	int 	i,file;
-	short	n;
-	FILE	*stream;
-
-memset(cmd,0,64);
-
-upop("Writing NODE.CNF...");
-sprintf(str,"%sNODE.CNF",node_path[node_num-1]);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_int(node_num,stream);
-put_str(node_name,stream);
-put_str(node_phone,stream);
-put_str(node_comspec,stream);				 /* Was node_logon */
-put_int(node_misc,stream);
-put_int(node_ivt,stream);
-put_int(node_swap,stream);
-if(node_swapdir[0]) {
-    backslash(node_swapdir);
-    md(node_swapdir); }              /* make sure it's a valid directory */
-put_str(node_swapdir,stream);
-put_int(node_valuser,stream);
-put_int(node_minbps,stream);
-put_str(node_ar,stream);
-put_int(node_dollars_per_call,stream);
-put_str(node_editor,stream);
-put_str(node_viewer,stream);
-put_str(node_daily,stream);
-put_int(node_scrnlen,stream);
-put_int(node_scrnblank,stream);
-backslash(ctrl_dir);
-put_str(ctrl_dir,stream);
-backslash(text_dir);
-put_str(text_dir,stream);
-backslash(temp_dir);
-put_str(temp_dir,stream);
-for(i=0;i<10;i++)
-	put_str(wfc_cmd[i],stream);
-for(i=0;i<12;i++)
-	put_str(wfc_scmd[i],stream);
-put_str(mdm_hang,stream);
-put_int(node_sem_check,stream);
-put_int(node_stat_check,stream);
-put_str(scfg_cmd,stream);
-put_int(sec_warn,stream);
-put_int(sec_hangup,stream);
-n=0;
-for(i=0;i<188;i++)					/* unused init to NULL */
-	fwrite(&n,1,2,stream);
-n=0xffff;							/* unused init to 0xff */
-for(i=0;i<256;i++)
-    fwrite(&n,1,2,stream);
-put_int(com_port,stream);
-put_int(com_irq,stream);
-put_int(com_base,stream);
-put_int(com_rate,stream);
-put_int(mdm_misc,stream);
-put_str(mdm_init,stream);
-put_str(mdm_spec,stream);
-put_str(mdm_term,stream);
-put_str(mdm_dial,stream);
-put_str(mdm_offh,stream);
-put_str(mdm_answ,stream);
-put_int(mdm_reinit,stream);
-put_int(mdm_ansdelay,stream);
-put_int(mdm_rings,stream);
-put_int(mdm_results,stream);
-for(i=0;i<mdm_results;i++) {
-	put_int(mdm_result[i].code,stream);
-	put_int(mdm_result[i].rate,stream);
-	put_int(mdm_result[i].cps,stream);
-	put_str(mdm_result[i].str,stream); }
-fclose(stream);
-}
-
-void free_node_cfg()
-{
-
-FREE(mdm_result);
-}
-
-void write_main_cfg()
-{
-	char	str[128],c=0;
-	int 	file;
-	short	i,j,n;
-	FILE	*stream;
-
-upop("Writing MAIN.CNF...");
-sprintf(str,"%sMAIN.CNF",ctrl_dir);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_str(sys_name,stream);
-put_str(sys_id,stream);
-put_str(sys_location,stream);
-put_str(sys_phonefmt,stream);
-put_str(sys_op,stream);
-put_str(sys_guru,stream);
-put_str(sys_pass,stream);
-put_int(sys_nodes,stream);
-for(i=0;i<sys_nodes;i++) {
-	backslash(node_path[i]);
-	fwrite(node_path[i],LEN_DIR+1,1,stream); }
-backslash(data_dir);
-put_str(data_dir,stream);
-
-/************************************************************/
-/* Create data and sub-dirs off data if not already created */
-/************************************************************/
-strcpy(str,data_dir);
-md(str);
-sprintf(str,"%sSUBS",data_dir);
-md(str);
-sprintf(str,"%sDIRS",data_dir);
-md(str);
-sprintf(str,"%sTEXT",data_dir);
-md(str);
-sprintf(str,"%sMSGS",data_dir);
-md(str);
-sprintf(str,"%sUSER",data_dir);
-md(str);
-sprintf(str,"%sUSER\\PTRS",data_dir);
-md(str);
-sprintf(str,"%sLOGS",data_dir);
-md(str);
-sprintf(str,"%sQNET",data_dir);
-md(str);
-sprintf(str,"%sFILE",data_dir);
-md(str);
-
-backslash(exec_dir);
-put_str(exec_dir,stream);
-put_str(sys_logon,stream);
-put_str(sys_logout,stream);
-put_str(sys_daily,stream);
-put_int(sys_timezone,stream);
-put_int(sys_misc,stream);
-put_int(sys_lastnode,stream);
-put_int(sys_autonode,stream);
-put_int(uq,stream);
-put_int(sys_pwdays,stream);
-put_int(sys_deldays,stream);
-put_int(sys_exp_warn,stream);
-put_int(sys_autodel,stream);
-put_int(sys_def_stat,stream);
-put_str(sys_chat_ar,stream);
-put_int(cdt_min_value,stream);
-put_int(max_minutes,stream);
-put_int(cdt_per_dollar,stream);
-put_str(new_pass,stream);
-put_str(new_magic,stream);
-put_str(new_sif,stream);
-put_str(new_sof,stream);
-
-put_int(new_level,stream);
-put_int(new_flags1,stream);
-put_int(new_flags2,stream);
-put_int(new_flags3,stream);
-put_int(new_flags4,stream);
-put_int(new_exempt,stream);
-put_int(new_rest,stream);
-put_int(new_cdt,stream);
-put_int(new_min,stream);
-put_str(new_xedit,stream);
-put_int(new_expire,stream);
-if(new_shell>total_shells)
-	new_shell=0;
-put_int(new_shell,stream);
-put_int(new_misc,stream);
-put_int(new_prot,stream);
-c=0;
-put_int(c,stream);
-n=0;
-for(i=0;i<7;i++)
-	put_int(n,stream);
-
-put_int(expired_level,stream);
-put_int(expired_flags1,stream);
-put_int(expired_flags2,stream);
-put_int(expired_flags3,stream);
-put_int(expired_flags4,stream);
-put_int(expired_exempt,stream);
-put_int(expired_rest,stream);
-
-put_str(logon_mod,stream);
-put_str(logoff_mod,stream);
-put_str(newuser_mod,stream);
-put_str(login_mod,stream);
-put_str(logout_mod,stream);
-put_str(sync_mod,stream);
-put_str(expire_mod,stream);
-put_int(c,stream);
-n=0;
-for(i=0;i<224;i++)
-	put_int(n,stream);
-n=0xffff;
-for(i=0;i<256;i++)
-	put_int(n,stream);
-
-n=0;
-for(i=0;i<10;i++) {
-	put_int(val_level[i],stream);
-	put_int(val_expire[i],stream);
-	put_int(val_flags1[i],stream);
-	put_int(val_flags2[i],stream);
-	put_int(val_flags3[i],stream);
-	put_int(val_flags4[i],stream);
-	put_int(val_cdt[i],stream);
-	put_int(val_exempt[i],stream);
-	put_int(val_rest[i],stream);
-	for(j=0;j<8;j++)
-		put_int(n,stream); }
-
-c=0;
-for(i=0;i<100 && !feof(stream);i++) {
-	put_int(level_timeperday[i],stream);
-	put_int(level_timepercall[i],stream);
-	put_int(level_callsperday[i],stream);
-	put_int(level_freecdtperday[i],stream);
-	put_int(level_linespermsg[i],stream);
-	put_int(level_postsperday[i],stream);
-	put_int(level_emailperday[i],stream);
-	put_int(level_misc[i],stream);
-	put_int(level_expireto[i],stream);
-	put_int(c,stream);
-	for(j=0;j<5;j++)
-		put_int(n,stream); }
-
-/* Command Shells */
-
-put_int(total_shells,stream);
-for(i=0;i<total_shells;i++) {
-	put_str(shell[i]->name,stream);
-	put_str(shell[i]->code,stream);
-	put_str(shell[i]->ar,stream);
-	put_int(shell[i]->misc,stream);
-	n=0;
-	for(j=0;j<8;j++)
-        put_int(n,stream); }
-
-fclose(stream);
-}
-
-void free_main_cfg()
-{
-	int i;
-
-for(i=0;i<sys_nodes;i++)
-	FREE(node_path[i]);
-FREE(node_path);
-for(i=0;i<total_shells;i++)
-	FREE(shell[i]);
-FREE(shell);
-}
-
-void write_msgs_cfg()
-{
-	char	str[128],c;
-	int 	i,j,k,file,x;
-	short	n;
-	long	l;
-	FILE	*stream;
-	smb_t	smb;
-
-upop("Writing MSGS.CNF...");
-sprintf(str,"%sMSGS.CNF",ctrl_dir);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_int(max_qwkmsgs,stream);
-put_int(mail_maxcrcs,stream);
-put_int(mail_maxage,stream);
-put_str(preqwk_ar,stream);
-put_int(smb_retry_time,stream);
-n=0;
-for(i=0;i<235;i++)
-	put_int(n,stream);
-n=0xffff;
-for(i=0;i<256;i++)
-	put_int(n,stream);
-
-/* Message Groups */
-
-put_int(total_grps,stream);
-for(i=0;i<total_grps;i++) {
-	put_str(grp[i]->lname,stream);
-	put_str(grp[i]->sname,stream);
-	put_str(grp[i]->ar,stream);
-	n=0;
-	for(j=0;j<32;j++)
-		put_int(n,stream);
-	n=0xffff;
-	for(j=0;j<16;j++)
-		put_int(n,stream); }
-
-/* Message Sub-boards */
-
-backslash(echomail_dir);
-
-str[0]=0;
-for(i=n=0;i<total_subs;i++)
-	if(sub[i]->grp<total_grps)		/* total VALID sub-boards */
-		n++;
-put_int(n,stream);
-for(i=0;i<total_subs;i++) {
-	if(sub[i]->grp>=total_grps) 	/* skip bogus group numbers */
-		continue;
-	put_int(sub[i]->grp,stream);
-	put_str(sub[i]->lname,stream);
-	put_str(sub[i]->sname,stream);
-	put_str(sub[i]->qwkname,stream);
-	put_str(sub[i]->code,stream);
-	if(sub[i]->data_dir[0])
-		backslash(sub[i]->data_dir);
-	put_str(sub[i]->data_dir,stream);
-	md(sub[i]->data_dir);
-	put_str(sub[i]->ar,stream);
-	put_str(sub[i]->read_ar,stream);
-	put_str(sub[i]->post_ar,stream);
-	put_str(sub[i]->op_ar,stream);
-	l=(sub[i]->misc&(~SUB_HDRMOD));    /* Don't write mod bit */
-	put_int(l,stream);
-	put_str(sub[i]->tagline,stream);
-	put_str(sub[i]->origline,stream);
-	put_str(sub[i]->echomail_sem,stream);
-	if(sub[i]->echopath)
-		backslash(sub[i]->echopath);
-	put_str(sub[i]->echopath,stream);
-	if(sub[i]->misc&SUB_FIDO && (echomail_dir[0] || sub[i]->echopath[0])) {
-		md(echomail_dir);
-		if(!sub[i]->echopath[0])
-			sprintf(sub[i]->echopath,"%s%s",echomail_dir,sub[i]->code);
-		md(sub[i]->echopath); }
-	put_int(sub[i]->faddr,stream);
-	put_int(sub[i]->maxmsgs,stream);
-	put_int(sub[i]->maxcrcs,stream);
-	put_int(sub[i]->maxage,stream);
-	put_int(sub[i]->ptridx,stream);
-	put_str(sub[i]->mod_ar,stream);
-	put_int(sub[i]->qwkconf,stream);
-	c=0;
-	put_int(c,stream);
-	n=0;
-	for(k=0;k<26;k++)
-		put_int(n,stream);
-
-	if(all_msghdr || (sub[i]->misc&SUB_HDRMOD && !no_msghdr)) {
-		if(!sub[i]->data_dir[0])
-			sprintf(smb.file,"%sSUBS\\%s",data_dir,sub[i]->code);
-		else
-			sprintf(smb.file,"%s%s",sub[i]->data_dir,sub[i]->code);
-		if((x=smb_open(&smb))!=0) {
-			errormsg(WHERE,ERR_OPEN,smb.file,x);
-			continue; }
-		if(!filelength(fileno(smb.shd_fp))) {
-			smb.status.max_crcs=sub[i]->maxcrcs;
-			smb.status.max_msgs=sub[i]->maxmsgs;
-			smb.status.max_age=sub[i]->maxage;
-			smb.status.attr=sub[i]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
-			if((x=smb_create(&smb))!=0)
-				errormsg(WHERE,ERR_CREATE,smb.file,x);
-			smb_close(&smb);
-			continue; }
-		if((x=smb_locksmbhdr(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_LOCK,smb.file,x);
-			continue; }
-		if((x=smb_getstatus(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_READ,smb.file,x);
-			continue; }
-		if((!(sub[i]->misc&SUB_HYPER) || smb.status.attr&SMB_HYPERALLOC)
-			&& smb.status.max_msgs==sub[i]->maxmsgs
-			&& smb.status.max_crcs==sub[i]->maxcrcs
-			&& smb.status.max_age==sub[i]->maxage) {	/* No change */
-			smb_close(&smb);
-			continue; }
-		smb.status.max_msgs=sub[i]->maxmsgs;
-		smb.status.max_crcs=sub[i]->maxcrcs;
-		smb.status.max_age=sub[i]->maxage;
-		if(sub[i]->misc&SUB_HYPER)
-			smb.status.attr|=SMB_HYPERALLOC;
-		if((x=smb_putstatus(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_WRITE,smb.file,x);
-			continue; }
-		smb_close(&smb); }
-
-				}
-
-/* FidoNet */
-
-put_int(total_faddrs,stream);
-for(i=0;i<total_faddrs;i++) {
-	put_int(faddr[i].zone,stream);
-	put_int(faddr[i].net,stream);
-	put_int(faddr[i].node,stream);
-	put_int(faddr[i].point,stream); }
-
-put_str(origline,stream);
-put_str(netmail_sem,stream);
-put_str(echomail_sem,stream);
-backslash(netmail_dir);
-put_str(netmail_dir,stream);
-put_str(echomail_dir,stream);
-backslash(fidofile_dir);
-put_str(fidofile_dir,stream);
-put_int(netmail_misc,stream);
-put_int(netmail_cost,stream);
-put_int(dflt_faddr,stream);
-n=0;
-for(i=0;i<28;i++)
-	put_int(n,stream);
-
-/* QWKnet Config */
-
-put_str(qnet_tagline,stream);
-
-put_int(total_qhubs,stream);
-for(i=0;i<total_qhubs;i++) {
-	put_str(qhub[i]->id,stream);
-	put_int(qhub[i]->time,stream);
-	put_int(qhub[i]->freq,stream);
-	put_int(qhub[i]->days,stream);
-	put_int(qhub[i]->node,stream);
-	put_str(qhub[i]->call,stream);
-	put_str(qhub[i]->pack,stream);
-	put_str(qhub[i]->unpack,stream);
-	put_int(qhub[i]->subs,stream);
-	for(j=0;j<qhub[i]->subs;j++) {
-		put_int(qhub[i]->conf[j],stream);
-		put_int(qhub[i]->sub[j],stream);
-		put_int(qhub[i]->mode[j],stream); }
-	n=0;
-	for(j=0;j<32;j++)
-		put_int(n,stream); }
-n=0;
-for(i=0;i<32;i++)
-    put_int(n,stream);
-
-/* PostLink Config */
-
-memset(str,0,11);
-fwrite(str,11,1,stream);	/* unused, used to be site name */
-put_int(sys_psnum,stream);
-
-put_int(total_phubs,stream);
-for(i=0;i<total_phubs;i++) {
-	put_str(phub[i]->name,stream);
-	put_int(phub[i]->time,stream);
-	put_int(phub[i]->freq,stream);
-	put_int(phub[i]->days,stream);
-	put_int(phub[i]->node,stream);
-	put_str(phub[i]->call,stream);
-	n=0;
-	for(j=0;j<32;j++)
-		put_int(n,stream); }
-
-put_str(sys_psname,stream);
-n=0;
-for(i=0;i<32;i++)
-    put_int(n,stream);
-
-put_str(sys_inetaddr,stream); /* Internet address */
-put_str(inetmail_sem,stream);
-put_int(inetmail_misc,stream);
-put_int(inetmail_cost,stream);
-
-fclose(stream);
-
-/* MUST BE AT END */
-
-if(!no_msghdr) {
-	backslash(data_dir);
-	sprintf(smb.file,"%sMAIL",data_dir);
-	if((x=smb_open(&smb))!=0) {
-		errormsg(WHERE,ERR_OPEN,smb.file,x);
-		return; }
-	if(!filelength(fileno(smb.shd_fp))) {
-		smb.status.max_crcs=mail_maxcrcs;
-		smb.status.max_msgs=MAX_SYSMAIL;
-		smb.status.max_age=mail_maxage;
-		smb.status.attr=SMB_EMAIL;
-		if((x=smb_create(&smb))!=0)
-			errormsg(WHERE,ERR_CREATE,smb.file,x);
-		smb_close(&smb);
-		return; }
-	if((x=smb_locksmbhdr(&smb))!=0) {
-		smb_close(&smb);
-		errormsg(WHERE,ERR_LOCK,smb.file,x);
-		return; }
-	if((x=smb_getstatus(&smb))!=0) {
-		smb_close(&smb);
-		errormsg(WHERE,ERR_READ,smb.file,x);
-		return; }
-	smb.status.max_msgs=MAX_SYSMAIL;
-	smb.status.max_crcs=mail_maxcrcs;
-	smb.status.max_age=mail_maxage;
-	if((x=smb_putstatus(&smb))!=0) {
-		smb_close(&smb);
-		errormsg(WHERE,ERR_WRITE,smb.file,x);
-		return; }
-	smb_close(&smb); }
-}
-
-void free_msgs_cfg()
-{
-	int i;
-
-for(i=0;i<total_grps;i++)
-	FREE(grp[i]);
-FREE(grp);
-grp=NULL;
-
-for(i=0;i<total_subs;i++)
-	FREE(sub[i]);
-FREE(sub);
-sub=NULL;
-
-FREE(faddr);
-total_faddrs=0;
-
-for(i=0;i<total_qhubs;i++) {
-	FREE(qhub[i]->mode);
-	FREE(qhub[i]->conf);
-	FREE(qhub[i]->sub);
-	FREE(qhub[i]); }
-FREE(qhub);
-qhub=NULL;
-
-for(i=0;i<total_phubs;i++)
-	FREE(phub[i]);
-FREE(phub);
-phub=NULL;
-
-}
-
diff --git a/src/sbbs2/scfg/wrcnf2.c b/src/sbbs2/scfg/wrcnf2.c
deleted file mode 100644
index d006ed3bb77da57d1830953d3a98031159c6f132..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfg/wrcnf2.c
+++ /dev/null
@@ -1,494 +0,0 @@
-#line 2 "WRCNF2.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "scfg.h"
-
-extern int no_msghdr,all_msghdr;
-extern int no_dirchk;
-
-extern char *crlf;
-extern char nulbuf[];
-extern int	pslen;
-
-#define put_int(var,stream) fwrite(&var,1,sizeof(var),stream)
-#define put_str(var,stream) { pslen=strlen(var); \
-							fwrite(var,1,pslen > sizeof(var) \
-								? sizeof(var) : pslen ,stream); \
-							fwrite(nulbuf,1,pslen > sizeof(var) \
-                                ? 0 : sizeof(var)-pslen,stream); }
-
-void backup(char *org)
-{
-	char old[128],new[128];
-	int i,x;
-
-x=strlen(org)-1;
-if(x<=0)
-	return;
-strcpy(old,org);
-strcpy(new,org);
-for(i=backup_level;i;i--) {
-	new[x]=(i-1)+'0';
-	if(i==backup_level)
-		remove(new);
-	if(i==1) {
-		rename(org,new);
-		continue; }
-	old[x]=(i-2)+'0';
-	rename(old,new); }
-}
-
-
-void write_file_cfg()
-{
-	char	str[128],cmd[LEN_CMD+1],c;
-	int 	i,j,k,file;
-	short	n;
-	long	l=0;
-	FILE	*stream;
-
-upop("Writing FILE.CNF...");
-sprintf(str,"%sFILE.CNF",ctrl_dir);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_int(min_dspace,stream);
-put_int(max_batup,stream);
-put_int(max_batdn,stream);
-put_int(max_userxfer,stream);
-put_int(l,stream);					/* unused */
-put_int(cdt_up_pct,stream);
-put_int(cdt_dn_pct,stream);
-put_int(l,stream);					/* unused */
-put_str(cmd,stream);
-put_int(leech_pct,stream);
-put_int(leech_sec,stream);
-n=0;
-for(i=0;i<32;i++)
-	put_int(n,stream);
-
-/* Extractable File Types */
-
-put_int(total_fextrs,stream);
-for(i=0;i<total_fextrs;i++) {
-	put_str(fextr[i]->ext,stream);
-	put_str(fextr[i]->cmd,stream);
-	put_str(fextr[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream); }
-
-/* Compressable File Types */
-
-put_int(total_fcomps,stream);
-for(i=0;i<total_fcomps;i++) {
-	put_str(fcomp[i]->ext,stream);
-	put_str(fcomp[i]->cmd,stream);
-	put_str(fcomp[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-        put_int(n,stream); }
-
-/* Viewable File Types */
-
-put_int(total_fviews,stream);
-for(i=0;i<total_fviews;i++) {
-	put_str(fview[i]->ext,stream);
-	put_str(fview[i]->cmd,stream);
-	put_str(fview[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-        put_int(n,stream); }
-
-/* Testable File Types */
-
-put_int(total_ftests,stream);
-for(i=0;i<total_ftests;i++) {
-	put_str(ftest[i]->ext,stream);
-	put_str(ftest[i]->cmd,stream);
-	put_str(ftest[i]->workstr,stream);
-	put_str(ftest[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-        put_int(n,stream); }
-
-/* Download Events */
-
-put_int(total_dlevents,stream);
-for(i=0;i<total_dlevents;i++) {
-	put_str(dlevent[i]->ext,stream);
-	put_str(dlevent[i]->cmd,stream);
-	put_str(dlevent[i]->workstr,stream);
-	put_str(dlevent[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-        put_int(n,stream); }
-
-/* File Transfer Protocols */
-
-put_int(total_prots,stream);
-for(i=0;i<total_prots;i++) {
-	put_int(prot[i]->mnemonic,stream);
-	put_str(prot[i]->name,stream);
-	put_str(prot[i]->ulcmd,stream);
-	put_str(prot[i]->dlcmd,stream);
-	put_str(prot[i]->batulcmd,stream);
-	put_str(prot[i]->batdlcmd,stream);
-	put_str(prot[i]->blindcmd,stream);
-	put_str(prot[i]->bicmd,stream);
-	put_int(prot[i]->misc,stream);
-	put_str(prot[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream); }
-
-/* Alternate File Paths */
-
-put_int(altpaths,stream);
-for(i=0;i<altpaths;i++) {
-	backslash(altpath[i]);
-	fwrite(altpath[i],LEN_DIR+1,1,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream); }
-
-/* File Libraries */
-
-put_int(total_libs,stream);
-for(i=0;i<total_libs;i++) {
-	put_str(lib[i]->lname,stream);
-	put_str(lib[i]->sname,stream);
-	put_str(lib[i]->ar,stream);
-	n=0;
-	for(j=0;j<32;j++)
-		put_int(n,stream);
-	n=0xffff;
-	for(j=0;j<16;j++)
-		put_int(n,stream); }
-
-/* File Directories */
-
-put_int(total_dirs,stream);
-for(j=0;j<total_libs;j++)
-    for(i=0;i<total_dirs;i++)
-        if(dir[i]->lib==j) {
-			put_int(dir[i]->lib,stream);
-			put_str(dir[i]->lname,stream);
-			put_str(dir[i]->sname,stream);
-			put_str(dir[i]->code,stream);
-			if(dir[i]->data_dir[0])
-				backslash(dir[i]->data_dir);
-			md(dir[i]->data_dir);
-			put_str(dir[i]->data_dir,stream);
-			put_str(dir[i]->ar,stream);
-			put_str(dir[i]->ul_ar,stream);
-			put_str(dir[i]->dl_ar,stream);
-			put_str(dir[i]->op_ar,stream);
-			backslash(dir[i]->path);
-			put_str(dir[i]->path,stream);
-			if(dir[i]->misc&DIR_FCHK) {
-				strcpy(str,dir[i]->path);
-				md(str); }
-
-			put_str(dir[i]->upload_sem,stream);
-			put_int(dir[i]->maxfiles,stream);
-			put_str(dir[i]->exts,stream);
-			put_int(dir[i]->misc,stream);
-			put_int(dir[i]->seqdev,stream);
-			put_int(dir[i]->sort,stream);
-			put_str(dir[i]->ex_ar,stream);
-			put_int(dir[i]->maxage,stream);
-			put_int(dir[i]->up_pct,stream);
-			put_int(dir[i]->dn_pct,stream);
-			c=0;
-			put_int(c,stream);
-			n=0;
-			for(k=0;k<8;k++)
-				put_int(n,stream);
-			n=0xffff;
-			for(k=0;k<16;k++)
-				put_int(n,stream);
-			}
-
-/* Text File Sections */
-
-put_int(total_txtsecs,stream);
-for(i=0;i<total_txtsecs;i++) {
-	sprintf(str,"%sTEXT\\%s",data_dir,txtsec[i]->code);
-	md(str);
-	put_str(txtsec[i]->name,stream);
-	put_str(txtsec[i]->code,stream);
-	put_str(txtsec[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream); }
-
-fclose(stream);
-}
-
-void free_file_cfg()
-{
-	int i;
-
-for(i=0;i<total_fextrs;i++)
-	FREE(fextr[i]);
-FREE(fextr);
-
-for(i=0;i<total_fcomps;i++)
-	FREE(fcomp[i]);
-FREE(fcomp);
-
-for(i=0;i<total_fviews;i++)
-	FREE(fview[i]);
-FREE(fview);
-
-for(i=0;i<total_ftests;i++)
-	FREE(ftest[i]);
-FREE(ftest);
-
-for(i=0;i<total_dlevents;i++)
-	FREE(dlevent[i]);
-FREE(dlevent);
-
-for(i=0;i<total_prots;i++)
-	FREE(prot[i]);
-FREE(prot);
-
-for(i=0;i<altpaths;i++)
-	FREE(altpath[i]);
-FREE(altpath);
-
-for(i=0;i<total_libs;i++)
-	FREE(lib[i]);
-FREE(lib);
-
-for(i=0;i<total_dirs;i++)
-	FREE(dir[i]);
-FREE(dir);
-
-for(i=0;i<total_txtsecs;i++)
-	FREE(txtsec[i]);
-FREE(txtsec);
-}
-
-
-void write_chat_cfg()
-{
-	char	str[128];
-	int 	i,j,file;
-	short	n;
-	FILE	*stream;
-
-upop("Writing CHAT.CNF...");
-sprintf(str,"%sCHAT.CNF",ctrl_dir);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_int(total_gurus,stream);
-for(i=0;i<total_gurus;i++) {
-    put_str(guru[i]->name,stream);
-    put_str(guru[i]->code,stream);
-    put_str(guru[i]->ar,stream);
-    n=0;
-    for(j=0;j<8;j++)
-        put_int(n,stream);
-    }
-
-put_int(total_actsets,stream);
-for(i=0;i<total_actsets;i++)
-	put_str(actset[i]->name,stream);
-
-put_int(total_chatacts,stream);
-for(i=0;i<total_chatacts;i++) {
-	put_int(chatact[i]->actset,stream);
-	put_str(chatact[i]->cmd,stream);
-	put_str(chatact[i]->out,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream);
-	}
-
-put_int(total_chans,stream);
-for(i=0;i<total_chans;i++) {
-	put_int(chan[i]->actset,stream);
-	put_str(chan[i]->name,stream);
-	put_str(chan[i]->code,stream);
-	put_str(chan[i]->ar,stream);
-	put_int(chan[i]->cost,stream);
-	put_int(chan[i]->guru,stream);
-	put_int(chan[i]->misc,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream);
-	}
-
-put_int(total_pages,stream);
-for(i=0;i<total_pages;i++) {
-    put_int(page[i]->cmd,stream);
-    put_int(page[i]->ar,stream);
-    put_int(page[i]->misc,stream);
-    n=0;
-    for(j=0;j<8;j++)
-        put_int(n,stream);
-    }
-
-fclose(stream);
-}
-
-void free_chat_cfg()
-{
-	int i;
-
-for(i=0;i<total_actsets;i++)
-	FREE(actset[i]);
-FREE(actset);
-
-for(i=0;i<total_chatacts;i++)
-	FREE(chatact[i]);
-FREE(chatact);
-
-for(i=0;i<total_chans;i++)
-	FREE(chan[i]);
-FREE(chan);
-
-for(i=0;i<total_gurus;i++)
-	FREE(guru[i]);
-FREE(guru);
-
-for(i=0;i<total_pages;i++)
-	FREE(page[i]);
-FREE(page);
-
-}
-
-void write_xtrn_cfg()
-{
-	uchar	str[128],c;
-	int 	i,j,sec,file;
-	short	n;
-	long	l;
-	FILE	*stream;
-
-upop("Writing XTRN.CNF...");
-sprintf(str,"%sXTRN.CNF",ctrl_dir);
-backup(str);
-
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-	|| (stream=fdopen(file,"wb"))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return; }
-setvbuf(stream,NULL,_IOFBF,2048);
-
-put_int(total_swaps,stream);
-for(i=0;i<total_swaps;i++)
-	put_str(swap[i]->cmd,stream);
-
-put_int(total_xedits,stream);
-for(i=0;i<total_xedits;i++) {
-	put_str(xedit[i]->name,stream);
-	put_str(xedit[i]->code,stream);
-	put_str(xedit[i]->lcmd,stream);
-	put_str(xedit[i]->rcmd,stream);
-	put_int(xedit[i]->misc,stream);
-	put_str(xedit[i]->ar,stream);
-	put_int(xedit[i]->type,stream);
-	c=0;
-	put_int(c,stream);
-	n=0;
-	for(j=0;j<7;j++)
-		put_int(n,stream);
-	}
-
-put_int(total_xtrnsecs,stream);
-for(i=0;i<total_xtrnsecs;i++) {
-	put_str(xtrnsec[i]->name,stream);
-	put_str(xtrnsec[i]->code,stream);
-	put_str(xtrnsec[i]->ar,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream);
-	}
-
-put_int(total_xtrns,stream);
-for(sec=0;sec<total_xtrnsecs;sec++)
-	for(i=0;i<total_xtrns;i++) {
-		if(xtrn[i]->sec!=sec)
-			continue;
-		put_int(xtrn[i]->sec,stream);
-		put_str(xtrn[i]->name,stream);
-		put_str(xtrn[i]->code,stream);
-		put_str(xtrn[i]->ar,stream);
-		put_str(xtrn[i]->run_ar,stream);
-		put_int(xtrn[i]->type,stream);
-		put_int(xtrn[i]->misc,stream);
-		put_int(xtrn[i]->event,stream);
-		put_int(xtrn[i]->cost,stream);
-		put_str(xtrn[i]->cmd,stream);
-		put_str(xtrn[i]->clean,stream);
-		put_str(xtrn[i]->path,stream);
-		put_int(xtrn[i]->textra,stream);
-		put_int(xtrn[i]->maxtime,stream);
-		n=0;
-		for(j=0;j<7;j++)
-			put_int(n,stream);
-		}
-
-put_int(total_events,stream);
-for(i=0;i<total_events;i++) {
-	put_str(event[i]->code,stream);
-	put_str(event[i]->cmd,stream);
-	put_int(event[i]->days,stream);
-	put_int(event[i]->time,stream);
-	put_int(event[i]->node,stream);
-	put_int(event[i]->misc,stream);
-	put_int(event[i]->dir,stream);
-	n=0;
-	for(j=0;j<8;j++)
-		put_int(n,stream);
-	}
-
-put_int(total_os2pgms,stream);
-for(i=0;i<total_os2pgms;i++)
-	put_str(os2pgm[i]->name,stream);
-for(i=0;i<total_os2pgms;i++)
-	put_int(os2pgm[i]->misc,stream);
-
-fclose(stream);
-}
-
-void free_xtrn_cfg()
-{
-	int i;
-
-for(i=0;i<total_swaps;i++)
-	FREE(swap[i]);
-FREE(swap);
-
-for(i=0;i<total_xedits;i++)
-	FREE(xedit[i]);
-FREE(xedit);
-
-for(i=0;i<total_xtrnsecs;i++)
-	FREE(xtrnsec[i]);
-FREE(xtrnsec);
-
-for(i=0;i<total_xtrns;i++)
-	FREE(xtrn[i]);
-FREE(xtrn);
-
-for(i=0;i<total_events;i++)
-	FREE(event[i]);
-FREE(event);
-
-}
diff --git a/src/sbbs2/scfglib.h b/src/sbbs2/scfglib.h
deleted file mode 100644
index b0a5c22d4f93e3bf1e1ee658bcc6410a83e6fdc6..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfglib.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SCFGLIB.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _SCFGLIB_H
-#define _SCFGLIB_H
-
-#define SAVE_MEMORY
-
-#define get_int(var,stream) { if(!fread(&var,1,sizeof(var),stream)) \
-								memset(&var,0,sizeof(var)); \
-							  offset+=sizeof(var); }
-#define get_str(var,stream) { if(!fread(var,1,sizeof(var),stream)) \
-								memset(var,0,sizeof(var)); \
-                              offset+=sizeof(var); }
-
-typedef struct {
-    char    *openerr,
-            *reading,
-            *readit,
-            *allocerr,
-            *error;
-            } read_cfg_text_t;
-
-char *get_alloc(long *offset, char *outstr, int maxlen, FILE *instream);
-void allocerr(read_cfg_text_t txt, long offset, char *fname, uint size);
-char *readline(long *offset, char *str, int maxlen, FILE *stream);
-void read_node_cfg(read_cfg_text_t txt);
-void read_main_cfg(read_cfg_text_t txt);
-void read_text_cfg(read_cfg_text_t txt);
-void read_xtrn_cfg(read_cfg_text_t txt);
-void read_file_cfg(read_cfg_text_t txt);
-void read_msgs_cfg(read_cfg_text_t txt);
-void read_attr_cfg(read_cfg_text_t txt);
-void read_chat_cfg(read_cfg_text_t txt);
-long aftol(char *str);              /* Converts flag string to long */
-char *ltoaf(long l, char *str);     /* Converts long to flag string */
-faddr_t atofaddr(char *str);    /* ASCII text to FidoNet address conversion */
-char *faddrtoa(faddr_t addr);   /* FidoNet address to ASCII text conversion */
-char chardupe(char *str);       /* Searches for duplicate chars in str */
-int  attrstr(char *str);		/* Convert ATTR string into attribute int */
-
-#endif	/* Don't add anything after this line */
diff --git a/src/sbbs2/scfglib1.c b/src/sbbs2/scfglib1.c
deleted file mode 100644
index aaabc373f9ca85ee080ebdde6d7db760e8f007b0..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfglib1.c
+++ /dev/null
@@ -1,874 +0,0 @@
-#line 1 "SCFGLIB1.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "scfglib.h"
-
-void prep_path(char *path)
-{
-	char str[LEN_DIR*2];
-	int i;
-
-if(!path[0])
-	return;
-if(path[0]!='\\' && path[1]!=':')           /* Relative to NODE directory */
-	sprintf(str,"%s%s",node_dir,path);
-else
-	strcpy(str,path);
-i=strlen(str);
-if(str[i-1]!=':' && str[i-1]!='\\')
-	strcat(str,"\\");
-strcat(str,".");                // Change C: to C:. and C:\SBBS\ to C:\SBBS\.
-_fullpath(path,str,LEN_DIR+1);	// Change C:\SBBS\NODE1\..\EXEC to C:\SBBS\EXEC
-i=strlen(path);
-if(i && path[i-1]!='\\')
-	strcat(path,"\\");
-}
-
-char *get_alloc(long *offset, char *outstr, int maxlen, FILE *instream)
-{
-
-#ifdef SCFG
-	fread(outstr,1,maxlen+1,instream);
-	(*offset)+=maxlen+1;
-#else
-	char str[257];
-
-	fread(str,1,maxlen+1,instream);
-//	  lprintf("%s %d %p\r\n",__FILE__,__LINE__,offset);
-	(*offset)+=maxlen+1;	// this line was commented out (04/12/97) why?
-	if(!str[0]) 			/* Save memory */
-		return(scfgnulstr);
-	if((outstr=(char *)MALLOC(strlen(str)+1))==NULL)
-		return(NULL);
-	strcpy(outstr,str);
-#endif
-
-return(outstr);
-}
-
-#ifdef SCFG 	/* SCFG allocate max length */
-	#define readline_alloc(l,s,m,i) readline(l,s,m,i)
-#else
-	char *readline_alloc(long *offset, char *outstr, int maxline
-		, FILE *instream);
-	#define readline_alloc(l,s,m,i) s=readline_alloc(l,s,m,i)
-	#define get_alloc(o,s,l,i) s=get_alloc(o,s,l,i)
-#endif
-
-/***********************************************************/
-/* These functions are called from here and must be linked */
-/***********************************************************/
-/***
-	nopen()
-	truncsp()
-***/
-
-void allocerr(read_cfg_text_t txt, long offset, char *fname, uint size)
-{
-lprintf(txt.error,offset,fname);
-lprintf(txt.allocerr,size);
-bail(1);
-}
-
-#ifndef NO_NODE_CFG
-
-/****************************************************************************/
-/* Reads in NODE.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_node_cfg(read_cfg_text_t txt)
-{
-	char	c,str[256],cmd[64],fname[13],*p;
-	int 	i;
-	short	n;
-	long	offset=0;
-	FILE	*instream;
-
-strcpy(fname,"NODE.CNF");
-sprintf(str,"%s%s",node_dir,fname);
-if((instream=fnopen(&i,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-#ifdef SBBS
-	lprintf("\r\nSBBS must be run from a NODE directory (e.g. ");
-	lclatr(WHITE);
-	lprintf("C:\\SBBS\\NODE1");
-	lclatr(LIGHTGRAY);
-	lprintf(").\r\n");
-#endif
-	bail(1); }
-
-lprintf(txt.reading,fname);
-get_int(node_num,instream);
-if(!node_num) {
-	lprintf(txt.error,offset,fname);
-	lprintf("Node number must be non-zero\r\n");
-	bail(1); }
-get_str(node_name,instream);
-get_str(node_phone,instream);
-get_str(node_comspec,instream);
-if(!node_comspec[0])
-	strcpy(node_comspec,"C:\\OS2\\MDOS\\COMMAND.COM");
-get_int(node_misc,instream);
-get_int(node_ivt,instream);
-get_int(node_swap,instream);
-get_str(node_swapdir,instream);
-#ifndef SCFG
-if(!node_swapdir[0])
-	strcpy(node_swapdir,node_dir);
-else
-	prep_path(node_swapdir);
-#endif
-get_int(node_valuser,instream);
-get_int(node_minbps,instream);
-#ifdef SCFG
-get_str(node_ar,instream);
-#else
-fread(str,1,LEN_ARSTR+1,instream);
-offset+=LEN_ARSTR+1;
-node_ar=arstr(0,str);
-#endif
-get_int(node_dollars_per_call,instream);
-get_str(node_editor,instream);
-get_str(node_viewer,instream);
-get_str(node_daily,instream);
-get_int(c,instream);
-if(c) node_scrnlen=c;
-get_int(node_scrnblank,instream);
-get_str(ctrl_dir,instream); 				/* ctrl directory */
-get_str(text_dir,instream); 				/* text directory */
-get_str(temp_dir,instream); 				/* temp directory */
-if(!temp_dir[0])
-	strcpy(temp_dir,"TEMP");
-
-#ifndef SCFG
-prep_path(ctrl_dir);
-prep_path(text_dir);
-prep_path(temp_dir);
-#endif
-
-for(i=0;i<10;i++) { 						/* WFC 0-9 DOS commands */
-	get_alloc(&offset,wfc_cmd[i],LEN_CMD,instream); }
-for(i=0;i<12;i++) { 						/* WFC F1-F12 shrinking DOS cmds */
-	get_alloc(&offset,wfc_scmd[i],LEN_CMD,instream); }
-get_str(mdm_hang,instream);
-get_int(node_sem_check,instream);
-if(!node_sem_check) node_sem_check=60;
-get_int(node_stat_check,instream);
-if(!node_stat_check) node_stat_check=10;
-get_str(scfg_cmd,instream);
-if(!scfg_cmd[0])
-	strcpy(scfg_cmd,"%!scfg %k");
-get_int(sec_warn,instream);
-if(!sec_warn)
-	sec_warn=180;
-get_int(sec_hangup,instream);
-if(!sec_hangup)
-	sec_hangup=300;
-for(i=0;i<188;i++) {				/* Unused - initialized to NULL */
-	fread(&n,1,2,instream);
-	offset+=2; }
-for(i=0;i<256;i++) {				/* Unused - initialized to 0xff */
-	fread(&n,1,2,instream);
-	offset+=2; }
-
-/***************/
-/* Modem Stuff */
-/***************/
-
-get_int(com_port,instream);
-get_int(com_irq,instream);
-get_int(com_base,instream);
-get_int(com_rate,instream);
-get_int(mdm_misc,instream);
-get_str(mdm_init,instream);
-get_str(mdm_spec,instream);
-get_str(mdm_term,instream);
-get_str(mdm_dial,instream);
-get_str(mdm_offh,instream);
-get_str(mdm_answ,instream);
-get_int(mdm_reinit,instream);
-get_int(mdm_ansdelay,instream);
-get_int(mdm_rings,instream);
-
-get_int(mdm_results,instream);
-
-if(mdm_results) {
-	if((mdm_result=(mdm_result_t *)MALLOC(sizeof(mdm_result_t)*mdm_results))
-		==NULL)
-	allocerr(txt,offset,fname,sizeof(mdm_result_t *)*mdm_results); }
-else
-	mdm_result=NULL;
-
-for(i=0;i<mdm_results;i++) {
-	if(feof(instream)) break;
-	get_int(mdm_result[i].code,instream);
-	get_int(mdm_result[i].rate,instream);
-	get_int(mdm_result[i].cps,instream);
-	get_alloc(&offset,mdm_result[i].str,LEN_MODEM,instream); }
-mdm_results=i;
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
-#endif
-
-#ifndef NO_MAIN_CFG
-
-/****************************************************************************/
-/* Reads in MAIN.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_main_cfg(read_cfg_text_t txt)
-{
-	char	str[256],fname[13],*p,c;
-	int 	file;
-	short	i,j,n;
-	long	offset=0;
-	FILE	*instream;
-
-strcpy(fname,"MAIN.CNF");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-
-lprintf(txt.reading,fname);
-get_str(sys_name,instream);
-get_str(sys_id,instream);
-get_str(sys_location,instream);
-get_str(sys_phonefmt,instream);
-get_str(sys_op,instream);
-get_str(sys_guru,instream);
-get_str(sys_pass,instream);
-get_int(sys_nodes,instream);
-
-if(!sys_nodes || sys_nodes<node_num || sys_nodes>MAX_NODES) {
-	lprintf(txt.error,offset,fname);
-	if(!sys_nodes)
-		lprintf("Total nodes on system must be non-zero.\r\n");
-	else if(sys_nodes>MAX_NODES)
-		lprintf("Total nodes exceeds %u.\r\n",MAX_NODES);
-	else
-		lprintf("Total nodes (%u) < node number in NODE.CNF (%u)\r\n"
-			,sys_nodes,node_num);
-	bail(1); }
-
-if((node_path=(char **)MALLOC(sizeof(char *)*sys_nodes))==NULL)
-	allocerr(txt,offset,fname,sizeof(char *)*sys_nodes);
-
-for(i=0;i<sys_nodes;i++) {
-	if(feof(instream)) break;
-	fread(str,LEN_DIR+1,1,instream);
-	offset+=LEN_DIR+1;
-	if((node_path[i]=(char *)MALLOC(strlen(str)+1))==NULL)
-		allocerr(txt,offset,fname,strlen(str)+1);
-	strcpy(node_path[i],str); }
-
-get_str(data_dir,instream); 			  /* data directory */
-get_str(exec_dir,instream); 			  /* exec directory */
-
-#ifndef SCFG
-prep_path(data_dir);
-prep_path(exec_dir);
-#endif
-
-get_str(sys_logon,instream);
-get_str(sys_logout,instream);
-get_str(sys_daily,instream);
-get_int(sys_timezone,instream);
-get_int(sys_misc,instream);
-get_int(sys_lastnode,instream);
-get_int(sys_autonode,instream);
-get_int(uq,instream);
-get_int(sys_pwdays,instream);
-get_int(sys_deldays,instream);
-get_int(sys_exp_warn,instream); 	/* Days left till expiration warning */
-get_int(sys_autodel,instream);
-get_int(sys_def_stat,instream); 	/* default status line */
-
-#ifdef SCFG
-get_str(sys_chat_ar,instream);
-#else
-fread(str,1,LEN_ARSTR+1,instream);
-offset+=LEN_ARSTR+1;
-sys_chat_ar=arstr(0,str);
-#endif
-
-get_int(cdt_min_value,instream);
-get_int(max_minutes,instream);
-get_int(cdt_per_dollar,instream);
-get_str(new_pass,instream);
-get_str(new_magic,instream);
-get_str(new_sif,instream);
-get_str(new_sof,instream);
-if(!new_sof[0])		/* if output not specified, use input file */
-	strcpy(new_sof,new_sif);
-
-/*********************/
-/* New User Settings */
-/*********************/
-
-get_int(new_level,instream);
-get_int(new_flags1,instream);
-get_int(new_flags2,instream);
-get_int(new_flags3,instream);
-get_int(new_flags4,instream);
-get_int(new_exempt,instream);
-get_int(new_rest,instream);
-get_int(new_cdt,instream);
-get_int(new_min,instream);
-get_str(new_xedit,instream);
-get_int(new_expire,instream);
-get_int(new_shell,instream);
-get_int(new_misc,instream);
-get_int(new_prot,instream);
-if(new_prot<SP)
-	new_prot=SP;
-get_int(c,instream);
-for(i=0;i<7;i++)
-	get_int(n,instream);
-
-/*************************/
-/* Expired User Settings */
-/*************************/
-
-get_int(expired_level,instream);
-get_int(expired_flags1,instream);
-get_int(expired_flags2,instream);
-get_int(expired_flags3,instream);
-get_int(expired_flags4,instream);
-get_int(expired_exempt,instream);
-get_int(expired_rest,instream);
-
-get_str(logon_mod,instream);
-get_str(logoff_mod,instream);
-get_str(newuser_mod,instream);
-get_str(login_mod,instream);
-if(!login_mod[0]) strcpy(login_mod,"LOGIN");
-get_str(logout_mod,instream);
-get_str(sync_mod,instream);
-get_str(expire_mod,instream);
-get_int(c,instream);
-
-for(i=0;i<224;i++)					/* unused - initialized to NULL */
-	get_int(n,instream);
-for(i=0;i<256;i++)					/* unused - initialized to 0xff */
-	get_int(n,instream);
-
-/*******************/
-/* Validation Sets */
-/*******************/
-
-for(i=0;i<10 && !feof(instream);i++) {
-	get_int(val_level[i],instream);
-	get_int(val_expire[i],instream);
-	get_int(val_flags1[i],instream);
-	get_int(val_flags2[i],instream);
-	get_int(val_flags3[i],instream);
-	get_int(val_flags4[i],instream);
-	get_int(val_cdt[i],instream);
-	get_int(val_exempt[i],instream);
-	get_int(val_rest[i],instream);
-	for(j=0;j<8;j++)
-		get_int(n,instream); }
-
-/***************************/
-/* Security Level Settings */
-/***************************/
-
-for(i=0;i<100 && !feof(instream);i++) {
-	get_int(level_timeperday[i],instream);
-	if(level_timeperday[i]>500)
-		level_timeperday[i]=500;
-	get_int(level_timepercall[i],instream);
-	if(level_timepercall[i]>500)
-		level_timepercall[i]=500;
-	get_int(level_callsperday[i],instream);
-	get_int(level_freecdtperday[i],instream);
-	get_int(level_linespermsg[i],instream);
-	get_int(level_postsperday[i],instream);
-	get_int(level_emailperday[i],instream);
-	get_int(level_misc[i],instream);
-	get_int(level_expireto[i],instream);
-	get_int(c,instream);
-	for(j=0;j<5;j++)
-		get_int(n,instream); }
-if(i!=100) {
-	lprintf(txt.error,offset,fname);
-	lprintf("Insufficient User Level Information\r\n"
-		"%d user levels read, 100 needed.\r\n",i);
-	bail(1); }
-
-get_int(total_shells,instream);
-#ifdef SBBS
-if(!total_shells) {
-	lprintf(txt.error,offset,fname);
-	lprintf("At least one command shell must be configured.\r\n");
-	bail(1); }
-#endif
-
-if(total_shells) {
-	if((shell=(shell_t **)MALLOC(sizeof(shell_t *)*total_shells))==NULL)
-		allocerr(txt,offset,fname,sizeof(shell_t *)*total_shells); }
-else
-	shell=NULL;
-
-for(i=0;i<total_shells;i++) {
-	if(feof(instream)) break;
-	if((shell[i]=(shell_t *)MALLOC(sizeof(shell_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(shell_t));
-	memset(shell[i],0,sizeof(shell_t));
-
-	get_alloc(&offset,shell[i]->name,40,instream);
-	get_str(shell[i]->code,instream);
-#ifdef SCFG
-	get_str(shell[i]->ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	shell[i]->ar=arstr(0,str);
-#endif
-	get_int(shell[i]->misc,instream);
-	for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-total_shells=i;
-
-
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
-#endif
-
-#ifndef NO_MSGS_CFG
-
-
-/****************************************************************************/
-/* Reads in MSGS.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_msgs_cfg(read_cfg_text_t txt)
-{
-	char	str[256],fname[13],tmp[128],c;
-	int 	file;
-	short	i,j,k,l,n;
-	long	offset=0;
-	FILE	*instream;
-
-#ifndef SCFG
-
-sprintf(data_dir_subs,"%sSUBS\\",data_dir);
-prep_path(data_dir_subs);
-
-#endif
-
-strcpy(fname,"MSGS.CNF");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-
-lprintf(txt.reading,fname);
-
-/*************************/
-/* General Message Stuff */
-/*************************/
-
-get_int(max_qwkmsgs,instream);
-get_int(mail_maxcrcs,instream);
-get_int(mail_maxage,instream);
-#ifdef SCFG
-	get_str(preqwk_ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	preqwk_ar=arstr(0,str);
-#endif
-get_int(smb_retry_time,instream);	 /* odd byte */
-if(!smb_retry_time)
-	smb_retry_time=30;
-for(i=0;i<235;i++)	/* NULL */
-	get_int(n,instream);
-for(i=0;i<256;i++)	/* 0xff */
-    get_int(n,instream);
-
-
-/******************/
-/* Message Groups */
-/******************/
-
-get_int(total_grps,instream);
-
-
-if(total_grps) {
-	if((grp=(grp_t **)MALLOC(sizeof(grp_t *)*total_grps))==NULL)
-		allocerr(txt,offset,fname,sizeof(grp_t *)*total_grps); }
-else
-	grp=NULL;
-
-
-#ifdef SBBS
-
-if(total_grps) {
-
-	if((cursub=(uint *)MALLOC(sizeof(uint)*total_grps))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_grps);
-
-	if((usrgrp=(uint *)MALLOC(sizeof(uint)*total_grps))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_grps);
-
-	if((usrsubs=(uint *)MALLOC(sizeof(uint)*total_grps))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_grps);
-
-	if((usrsub=(uint **)MALLOC(sizeof(uint *)*total_grps))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint *)*total_grps); }
-
-#endif
-
-for(i=0;i<total_grps;i++) {
-
-	if(feof(instream)) break;
-	if((grp[i]=(grp_t *)MALLOC(sizeof(grp_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(grp_t));
-	memset(grp[i],0,sizeof(grp_t));
-
-	get_alloc(&offset,grp[i]->lname,LEN_GLNAME,instream);
-	get_alloc(&offset,grp[i]->sname,LEN_GSNAME,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY)	  /* Save memory */
-	if(!strcmp(grp[i]->lname,grp[i]->sname) && grp[i]->sname!=scfgnulstr) {
-		FREE(grp[i]->sname);
-		grp[i]->sname=grp[i]->lname; }
-#endif
-
-#ifdef SCFG
-	get_str(grp[i]->ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	grp[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<48;j++)
-		get_int(n,instream);
-	}
-total_grps=i;
-
-/**********************/
-/* Message Sub-boards */
-/**********************/
-
-get_int(total_subs,instream);
-
-if(total_subs) {
-	if((sub=(sub_t **)MALLOC(sizeof(sub_t *)*total_subs))==NULL)
-		allocerr(txt,offset,fname,sizeof(sub_t *)*total_subs); }
-else
-	sub=NULL;
-
-#ifdef SBBS
-
-if(total_subs) {
-
-	if((sub_misc=(char *)MALLOC(sizeof(char)*total_subs))==NULL)
-		allocerr(txt,offset,fname,sizeof(char)*total_subs);
-
-	if((sub_ptr=(ulong *)MALLOC(sizeof(ulong)*total_subs))==NULL)
-		allocerr(txt,offset,fname,sizeof(ulong)*total_subs);
-
-	if((sub_last=(ulong *)MALLOC(sizeof(ulong)*total_subs))==NULL)
-		allocerr(txt,offset,fname,sizeof(ulong)*total_subs); }
-
-#endif
-
-for(i=0;i<total_subs;i++) {
-	if(feof(instream)) break;
-	if((sub[i]=(sub_t *)MALLOC(sizeof(sub_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(sub_t));
-	memset(sub[i],0,sizeof(sub_t));
-
-	get_int(sub[i]->grp,instream);
-	get_alloc(&offset,sub[i]->lname,LEN_SLNAME,instream);
-	get_alloc(&offset,sub[i]->sname,LEN_SSNAME,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY) /* Save memory */
-	if(!strcmp(sub[i]->lname,sub[i]->sname) && sub[i]->sname!=scfgnulstr) {
-		FREE(sub[i]->sname);
-		sub[i]->sname=sub[i]->lname; }
-#endif
-
-	get_alloc(&offset,sub[i]->qwkname,10,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY)	/* Save memory */
-	if(!strcmp(sub[i]->qwkname,sub[i]->sname) && sub[i]->qwkname!=scfgnulstr) {
-		FREE(sub[i]->qwkname);
-		sub[i]->qwkname=sub[i]->sname; }
-#endif
-
-	get_str(sub[i]->code,instream);
-
-#ifdef SCFG
-	get_str(sub[i]->data_dir,instream);
-#else
-	fread(str,LEN_DIR+1,1,instream);   /* substitute data dir */
-	offset+=LEN_DIR+1;
-	if(str[0]) {
-		prep_path(str);
-		if((sub[i]->data_dir=(char *)MALLOC(strlen(str)+1))==NULL)
-			allocerr(txt,offset,fname,strlen(str)+1);
-		strcpy(sub[i]->data_dir,str); }
-	else
-		sub[i]->data_dir=data_dir_subs;
-#endif
-
-
-#ifdef SCFG
-	get_str(sub[i]->ar,instream);
-	get_str(sub[i]->read_ar,instream);
-	get_str(sub[i]->post_ar,instream);
-	get_str(sub[i]->op_ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	sub[i]->ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	sub[i]->read_ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	sub[i]->post_ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	sub[i]->op_ar=arstr(0,str);
-#endif
-	get_int(sub[i]->misc,instream);
-
-
-#ifdef SCFG
-	get_str(sub[i]->tagline,instream);
-#else
-	fread(str,81,1,instream);	/* substitute tagline */
-	offset+=81;
-	if(str[0]) {
-		if((sub[i]->tagline=(char *)MALLOC(strlen(str)+1))==NULL)
-			allocerr(txt,offset,fname,strlen(str)+1);
-		strcpy(sub[i]->tagline,str); }
-	else
-		sub[i]->tagline=qnet_tagline;
-#endif
-
-#ifdef SCFG
-	get_str(sub[i]->origline,instream);
-#else
-	fread(str,1,51,instream);	/* substitute origin line */
-	offset+=51;
-	if(str[0]) {
-		if((sub[i]->origline=(char *)MALLOC(strlen(str)+1))==NULL)
-			allocerr(txt,offset,fname,strlen(str)+1);
-		strcpy(sub[i]->origline,str); }
-	else
-		sub[i]->origline=origline;
-#endif
-
-#ifdef SCFG
-	get_str(sub[i]->echomail_sem,instream);
-#else
-	fread(str,1,LEN_DIR+1,instream);   /* substitute echomail semaphore */
-	offset+=LEN_DIR+1;
-	if(str[0]) {
-		if((sub[i]->echomail_sem=(char *)MALLOC(strlen(str)+1))==NULL)
-			allocerr(txt,offset,fname,strlen(str)+1);
-		strcpy(sub[i]->echomail_sem,str); }
-	else
-		sub[i]->echomail_sem=echomail_sem;
-#endif
-	fread(str,1,LEN_DIR+1,instream);   /* substitute EchoMail path */
-	offset+=LEN_DIR+1;
-#ifndef SBBS
-	backslash(str);
-	strcpy(sub[i]->echopath,str);
-#endif
-	get_int(sub[i]->faddr,instream);			/* FidoNet address */
-
-	get_int(sub[i]->maxmsgs,instream);
-	get_int(sub[i]->maxcrcs,instream);
-	get_int(sub[i]->maxage,instream);
-	get_int(sub[i]->ptridx,instream);
-#ifdef SBBS
-	for(j=0;j<i;j++)
-		if(sub[i]->ptridx==sub[j]->ptridx) {
-			lprintf(txt.error,offset,fname);
-			lprintf("Duplicate pointer index for subs #%d and #%d\r\n"
-				,i+1,j+1);
-			bail(1); }
-#endif
-
-#ifdef SCFG
-	get_str(sub[i]->mod_ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	sub[i]->mod_ar=arstr(0,str);
-#endif
-	get_int(sub[i]->qwkconf,instream);
-	get_int(c,instream);
-	for(j=0;j<26;j++)
-		get_int(n,instream);
-	}
-total_subs=i;
-
-#ifdef SBBS
-for(i=l=0;i<total_grps;i++) {
-	for(j=k=0;j<total_subs;j++)
-		if(sub[j]->grp==i)
-			k++;	/* k = number of subs per grp[i] */
-	if(k>l) l=k; }	/* l = the largest number of subs per grp */
-if(l)
-	for(i=0;i<total_grps;i++)
-		if((usrsub[i]=(uint *)MALLOC(sizeof(uint)*l))==NULL)
-			allocerr(txt,offset,fname,sizeof(uint)*l);
-
-if(sys_status&SS_INITIAL) {
-	fclose(instream);
-	lprintf(txt.readit,fname);
-	return; }
-#endif
-
-/***********/
-/* FidoNet */
-/***********/
-
-get_int(total_faddrs,instream);
-
-if(total_faddrs) {
-	if((faddr=(faddr_t *)MALLOC(sizeof(faddr_t)*total_faddrs))==NULL)
-		allocerr(txt,offset,fname,sizeof(faddr_t)*total_faddrs); }
-else
-	faddr=NULL;
-
-for(i=0;i<total_faddrs;i++)
-	get_int(faddr[i],instream);
-
-get_str(origline,instream);
-get_str(netmail_sem,instream);
-get_str(echomail_sem,instream);
-get_str(netmail_dir,instream);
-get_str(echomail_dir,instream);
-get_str(fidofile_dir,instream);
-get_int(netmail_misc,instream);
-get_int(netmail_cost,instream);
-get_int(dflt_faddr,instream);
-for(i=0;i<28;i++)
-    get_int(n,instream);
-
-
-/**********/
-/* QWKnet */
-/**********/
-
-get_str(qnet_tagline,instream);
-
-get_int(total_qhubs,instream);
-
-if(total_qhubs) {
-	if((qhub=(qhub_t **)MALLOC(sizeof(qhub_t *)*total_qhubs))==NULL)
-		allocerr(txt,offset,fname,sizeof(qhub_t*)*total_qhubs); }
-else
-	qhub=NULL;
-
-for(i=0;i<total_qhubs;i++) {
-    if(feof(instream)) break;
-	if((qhub[i]=(qhub_t *)MALLOC(sizeof(qhub_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(qhub_t));
-    memset(qhub[i],0,sizeof(qhub_t));
-
-	get_str(qhub[i]->id,instream);
-	get_int(qhub[i]->time,instream);
-	get_int(qhub[i]->freq,instream);
-	get_int(qhub[i]->days,instream);
-	get_int(qhub[i]->node,instream);
-	get_alloc(&offset,qhub[i]->call,LEN_CMD,instream);
-	get_alloc(&offset,qhub[i]->pack,LEN_CMD,instream);
-	get_alloc(&offset,qhub[i]->unpack,LEN_CMD,instream);
-	get_int(k,instream);
-
-	if(k) {
-		if((qhub[i]->sub=(ushort *)MALLOC(sizeof(ushort)*k))==NULL)
-			allocerr(txt,offset,fname,sizeof(uint)*k);
-		if((qhub[i]->conf=(ushort *)MALLOC(sizeof(ushort)*k))==NULL)
-			allocerr(txt,offset,fname,sizeof(ushort)*k);
-		if((qhub[i]->mode=(uchar *)MALLOC(sizeof(uchar)*k))==NULL)
-			allocerr(txt,offset,fname,sizeof(uchar)*k); }
-
-	for(j=0;j<k;j++) {
-		if(feof(instream)) break;
-		get_int(qhub[i]->conf[qhub[i]->subs],instream);
-		get_int(qhub[i]->sub[qhub[i]->subs],instream);
-		get_int(qhub[i]->mode[qhub[i]->subs],instream);
-		if(qhub[i]->sub[qhub[i]->subs]<total_subs)
-            sub[qhub[i]->sub[qhub[i]->subs]]->misc|=SUB_QNET;
-		else
-			continue;
-		if(qhub[i]->sub[qhub[i]->subs]!=INVALID_SUB)
-			qhub[i]->subs++; }
-	for(j=0;j<32;j++)
-		get_int(n,instream); }
-
-total_qhubs=i;
-
-for(j=0;j<32;j++)
-	get_int(n,instream);
-
-/************/
-/* PostLink */
-/************/
-
-fread(str,11,1,instream);		/* Unused - used to be Site Name */
-offset+=11;
-get_int(sys_psnum,instream);	/* Site Number */
-get_int(total_phubs,instream);
-
-if(total_phubs) {
-	if((phub=(phub_t **)MALLOC(sizeof(phub_t *)*total_phubs))==NULL)
-		allocerr(txt,offset,fname,sizeof(phub_t*)*total_phubs); }
-else
-	phub=NULL;
-
-for(i=0;i<total_phubs;i++) {
-    if(feof(instream)) break;
-    if((phub[i]=(phub_t *)MALLOC(sizeof(phub_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(phub_t));
-	memset(phub[i],0,sizeof(phub_t));
-#ifdef SCFG
-	get_str(phub[i]->name,instream);
-#else
-	fread(str,11,1,instream);
-	offset+=11;
-#endif
-	get_int(phub[i]->time,instream);
-	get_int(phub[i]->freq,instream);
-	get_int(phub[i]->days,instream);
-	get_int(phub[i]->node,instream);
-	get_alloc(&offset,phub[i]->call,LEN_CMD,instream);
-	for(j=0;j<32;j++)
-		get_int(n,instream); }
-
-total_phubs=i;
-
-get_str(sys_psname,instream);	/* Site Name */
-
-for(j=0;j<32;j++)
-    get_int(n,instream);
-
-/* Internet */
-
-get_str(sys_inetaddr,instream); /* Internet address */
-get_str(inetmail_sem,instream);
-get_int(inetmail_misc,instream);
-get_int(inetmail_cost,instream);
-
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
-#endif
-
diff --git a/src/sbbs2/scfglib2.c b/src/sbbs2/scfglib2.c
deleted file mode 100644
index e7b638684dcc1f3f606c81fa2d9095339772edaf..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfglib2.c
+++ /dev/null
@@ -1,1106 +0,0 @@
-#line 1 "SCFGLIB2.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "scfglib.h"
-
-#ifdef SCFG 	/* SCFG allocate max length */
-	#define readline_alloc(l,s,m,i) readline(l,s,m,i)
-#else
-	char *readline_alloc(long *offset, char *outstr, int maxline
-		, FILE *instream);
-	#define readline_alloc(l,s,m,i) s=readline_alloc(l,s,m,i)
-	#define get_alloc(o,s,l,i) s=get_alloc(o,s,l,i)
-#endif
-
-
-#ifndef NO_FILE_CFG
-
-/****************************************************************************/
-/* Reads in LIBS.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_file_cfg(read_cfg_text_t txt)
-{
-	char	str[256],fname[13],c,cmd[LEN_CMD+1];
-	int 	file;
-	short	i,j,k,l,n;
-	long	offset=0,t;
-	FILE	*instream;
-
-#ifndef SCFG
-
-sprintf(data_dir_dirs,"%sDIRS\\",data_dir);
-
-#endif
-
-strcpy(fname,"FILE.CNF");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-
-lprintf(txt.reading,fname);
-
-get_int(min_dspace,instream);
-get_int(max_batup,instream);
-
-#ifdef SBBS
-if(max_batup) {
-    if((batup_desc=(char **)MALLOC(sizeof(char *)*max_batup))==NULL)
-        allocerr(txt,offset,fname,sizeof(char *)*max_batup);
-    if((batup_name=(char **)MALLOC(sizeof(char *)*max_batup))==NULL)
-        allocerr(txt,offset,fname,sizeof(char *)*max_batup);
-    if((batup_misc=(char *)MALLOC(sizeof(char)*max_batup))==NULL)
-        allocerr(txt,offset,fname,sizeof(char)*max_batup);
-    if((batup_dir=(uint *)MALLOC(sizeof(uint)*max_batup))==NULL)
-        allocerr(txt,offset,fname,sizeof(uint)*max_batup);
-	if((batup_alt=(ushort *)MALLOC(sizeof(ushort)*max_batup))==NULL)
-		allocerr(txt,offset,fname,sizeof(ushort)*max_batup);
-    for(i=0;i<max_batup;i++) {
-        if((batup_desc[i]=(char *)MALLOC(59))==NULL)
-            allocerr(txt,offset,fname,59);
-        if((batup_name[i]=(char *)MALLOC(13))==NULL)
-            allocerr(txt,offset,fname,13); } }
-#endif
-get_int(max_batdn,instream);
-
-#ifdef SBBS
-if(max_batdn) {
-    if((batdn_name=(char **)MALLOC(sizeof(char *)*max_batdn))==NULL)
-        allocerr(txt,offset,fname,sizeof(char *)*max_batdn);
-    if((batdn_dir=(uint *)MALLOC(sizeof(uint)*max_batdn))==NULL)
-        allocerr(txt,offset,fname,sizeof(uint)*max_batdn);
-    if((batdn_offset=(long *)MALLOC(sizeof(long)*max_batdn))==NULL)
-        allocerr(txt,offset,fname,sizeof(long)*max_batdn);
-    if((batdn_size=(ulong *)MALLOC(sizeof(ulong)*max_batdn))==NULL)
-        allocerr(txt,offset,fname,sizeof(ulong)*max_batdn);
-    if((batdn_cdt=(ulong *)MALLOC(sizeof(ulong)*max_batdn))==NULL)
-        allocerr(txt,offset,fname,sizeof(ulong)*max_batdn);
-	if((batdn_alt=(ushort *)MALLOC(sizeof(ushort)*max_batdn))==NULL)
-		allocerr(txt,offset,fname,sizeof(ushort)*max_batdn);
-    for(i=0;i<max_batdn;i++)
-        if((batdn_name[i]=(char *)MALLOC(13))==NULL)
-            allocerr(txt,offset,fname,13); }
-#endif
-get_int(max_userxfer,instream);
-
-get_int(t,instream);	/* unused - was cdt_byte_value */
-get_int(cdt_up_pct,instream);
-get_int(cdt_dn_pct,instream);
-get_int(t,instream);	/* unused - was temp_ext */
-get_str(cmd,instream);	/* unused - was temp_cmd */
-get_int(leech_pct,instream);
-get_int(leech_sec,instream);
-
-for(i=0;i<32;i++)
-	get_int(n,instream);
-
-/**************************/
-/* Extractable File Types */
-/**************************/
-
-get_int(total_fextrs,instream);
-
-if(total_fextrs) {
-	if((fextr=(fextr_t **)MALLOC(sizeof(fextr_t *)*total_fextrs))==NULL)
-		allocerr(txt,offset,fname,sizeof(fextr_t*)*total_fextrs); }
-else
-	fextr=NULL;
-
-for(i=0; i<total_fextrs; i++) {
-	if(feof(instream))
-		break;
-	if((fextr[i]=(fextr_t *)MALLOC(sizeof(fextr_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(fextr_t));
-    memset(fextr[i],0,sizeof(fextr_t));
-	get_str(fextr[i]->ext,instream);
-	get_alloc(&offset,fextr[i]->cmd,LEN_CMD,instream);
-#ifdef SCFG
-	get_str(fextr[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	fextr[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-total_fextrs=i;
-
-/***************************/
-/* Compressable File Types */
-/***************************/
-
-get_int(total_fcomps,instream);
-
-if(total_fcomps) {
-	if((fcomp=(fcomp_t **)MALLOC(sizeof(fcomp_t *)*total_fcomps))==NULL)
-		allocerr(txt,offset,fname,sizeof(fcomp_t*)*total_fcomps); }
-else
-	fcomp=NULL;
-
-for(i=0; i<total_fcomps; i++) {
-	if(feof(instream))
-		break;
-	if((fcomp[i]=(fcomp_t *)MALLOC(sizeof(fcomp_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(fcomp_t));
-	memset(fcomp[i],0,sizeof(fcomp_t));
-	get_str(fcomp[i]->ext,instream);
-	get_alloc(&offset,fcomp[i]->cmd,LEN_CMD,instream);
-#ifdef SCFG
-	get_str(fcomp[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	fcomp[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-total_fcomps=i;
-
-/***********************/
-/* Viewable File Types */
-/***********************/
-
-get_int(total_fviews,instream);
-
-if(total_fviews) {
-	if((fview=(fview_t **)MALLOC(sizeof(fview_t *)*total_fviews))==NULL)
-		allocerr(txt,offset,fname,sizeof(fview_t*)*total_fviews); }
-else
-	fview=NULL;
-
-for(i=0; i<total_fviews; i++) {
-    if(feof(instream)) break;
-	if((fview[i]=(fview_t *)MALLOC(sizeof(fview_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(fview_t));
-    memset(fview[i],0,sizeof(fview_t));
-	get_str(fview[i]->ext,instream);
-	get_alloc(&offset,fview[i]->cmd,LEN_CMD,instream);
-#ifdef SCFG
-	get_str(fview[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	fview[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-    }
-total_fviews=i;
-
-/***********************/
-/* Testable File Types */
-/***********************/
-
-get_int(total_ftests,instream);
-
-if(total_ftests) {
-	if((ftest=(ftest_t **)MALLOC(sizeof(ftest_t *)*total_ftests))==NULL)
-		allocerr(txt,offset,fname,sizeof(ftest_t*)*total_ftests); }
-else
-	ftest=NULL;
-
-for(i=0; i<total_ftests; i++) {
-    if(feof(instream)) break;
-    if((ftest[i]=(ftest_t *)MALLOC(sizeof(ftest_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(ftest_t));
-    memset(ftest[i],0,sizeof(ftest_t));
-	get_str(ftest[i]->ext,instream);
-	get_alloc(&offset,ftest[i]->cmd,LEN_CMD,instream);
-	get_alloc(&offset,ftest[i]->workstr,40,instream);
-#ifdef SCFG
-	get_str(ftest[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	ftest[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-    }
-total_ftests=i;
-
-/*******************/
-/* Download events */
-/*******************/
-
-get_int(total_dlevents,instream);
-
-if(total_dlevents) {
-	if((dlevent=(dlevent_t **)MALLOC(sizeof(dlevent_t *)*total_dlevents))
-		==NULL)
-		allocerr(txt,offset,fname,sizeof(dlevent_t*)*total_dlevents); }
-else
-	dlevent=NULL;
-
-for(i=0; i<total_dlevents; i++) {
-    if(feof(instream)) break;
-	if((dlevent[i]=(dlevent_t *)MALLOC(sizeof(dlevent_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(dlevent_t));
-	memset(dlevent[i],0,sizeof(dlevent_t));
-	get_str(dlevent[i]->ext,instream);
-	get_alloc(&offset,dlevent[i]->cmd,LEN_CMD,instream);
-	get_alloc(&offset,dlevent[i]->workstr,40,instream);
-#ifdef SCFG
-	get_str(dlevent[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	dlevent[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-    }
-total_dlevents=i;
-
-
-/***************************/
-/* File Transfer Protocols */
-/***************************/
-
-get_int(total_prots,instream);
-
-if(total_prots) {
-	if((prot=(prot_t **)MALLOC(sizeof(prot_t *)*total_prots))==NULL)
-		allocerr(txt,offset,fname,sizeof(prot_t*)*total_prots); }
-else
-	prot=NULL;
-
-for(i=0;i<total_prots;i++) {
-    if(feof(instream)) break;
-	if((prot[i]=(prot_t *)MALLOC(sizeof(prot_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(prot_t));
-    memset(prot[i],0,sizeof(prot_t));
-
-	get_int(prot[i]->mnemonic,instream);
-	get_alloc(&offset,prot[i]->name,25,instream);
-	get_alloc(&offset,prot[i]->ulcmd,LEN_CMD,instream);
-	get_alloc(&offset,prot[i]->dlcmd,LEN_CMD,instream);
-	get_alloc(&offset,prot[i]->batulcmd,LEN_CMD,instream);
-	get_alloc(&offset,prot[i]->batdlcmd,LEN_CMD,instream);
-	get_alloc(&offset,prot[i]->blindcmd,LEN_CMD,instream);
-	get_alloc(&offset,prot[i]->bicmd,LEN_CMD,instream);
-	get_int(prot[i]->misc,instream);
-#ifdef SCFG
-	get_str(prot[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	prot[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-	}
-
-/************************/
-/* Alternate File Paths */
-/************************/
-
-get_int(altpaths,instream);
-
-if(altpaths) {
-	if((altpath=(char **)MALLOC(sizeof(char *)*altpaths))==NULL)
-		allocerr(txt,offset,fname,sizeof(char *)*altpaths); }
-else
-	altpath=NULL;
-
-for(i=0;i<altpaths;i++) {
-    if(feof(instream)) break;
-	fread(str,LEN_DIR+1,1,instream);
-	offset+=LEN_DIR+1;
-    backslash(str);
-#ifdef SCFG
-    j=LEN_DIR+1;
-#else
-    j=strlen(str)+1;
-#endif
-	if((altpath[i]=(char *)MALLOC(j))==NULL)
-        allocerr(txt,offset,fname,j);
-	memset(altpath[i],0,j);
-	strcpy(altpath[i],str);
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-	}
-
-altpaths=i;
-
-/******************/
-/* File Libraries */
-/******************/
-
-get_int(total_libs,instream);
-
-if(total_libs) {
-	if((lib=(lib_t **)MALLOC(sizeof(lib_t *)*total_libs))==NULL)
-		allocerr(txt,offset,fname,sizeof(lib_t *)*total_libs); }
-else
-	lib=NULL;
-
-#ifdef SBBS
-
-if(total_libs) {
-	if((curdir=(uint *)MALLOC(sizeof(uint)*total_libs))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_libs);
-
-	if((usrlib=(uint *)MALLOC(sizeof(uint)*total_libs))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_libs);
-
-	if((usrdirs=(uint *)MALLOC(sizeof(uint)*total_libs))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*total_libs);
-
-	if((usrdir=(uint **)MALLOC(sizeof(uint *)*total_libs))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint *)*total_libs); }
-
-#endif
-for(i=0;i<total_libs;i++) {
-	if(feof(instream)) break;
-	if((lib[i]=(lib_t *)MALLOC(sizeof(lib_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(lib_t));
-    memset(lib[i],0,sizeof(lib_t));
-	lib[i]->offline_dir=INVALID_DIR;
-
-	get_alloc(&offset,lib[i]->lname,LEN_GLNAME,instream);
-	get_alloc(&offset,lib[i]->sname,LEN_GSNAME,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY)	  /* Save memory */
-	if(!strcmp(lib[i]->lname,lib[i]->sname) && lib[i]->sname!=scfgnulstr) {
-		FREE(lib[i]->sname);
-		lib[i]->sname=lib[i]->lname; }
-#endif
-
-#ifdef SCFG
-	get_str(lib[i]->ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	lib[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<48;j++)
-		get_int(n,instream);
-	}
-total_libs=i;
-
-/********************/
-/* File Directories */
-/********************/
-
-sysop_dir=user_dir=upload_dir=INVALID_DIR;
-get_int(total_dirs,instream);
-
-if(total_dirs) {
-	if((dir=(dir_t **)MALLOC(sizeof(dir_t *)*(total_dirs+1)))==NULL)
-		allocerr(txt,offset,fname,sizeof(dir_t *)*(total_dirs+1)); }
-else
-	dir=NULL;
-
-for(i=0;i<total_dirs;i++) {
-	if(feof(instream)) break;
-	if((dir[i]=(dir_t *)MALLOC(sizeof(dir_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(dir_t));
-	memset(dir[i],0,sizeof(dir_t));
-
-	get_int(dir[i]->lib,instream);
-	get_alloc(&offset,dir[i]->lname,LEN_SLNAME,instream);
-	get_alloc(&offset,dir[i]->sname,LEN_SSNAME,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY)	  /* Save memory */
-	if(!strcmp(dir[i]->lname,dir[i]->sname) && dir[i]->sname!=scfgnulstr) {
-		FREE(dir[i]->sname);
-		dir[i]->sname=dir[i]->lname; }
-#endif
-
-	if(!strcmpi(dir[i]->sname,"SYSOP"))			/* Sysop upload directory */
-		sysop_dir=i;
-	else if(!strcmpi(dir[i]->sname,"USER"))		/* User to User xfer dir */
-		user_dir=i;
-	else if(!strcmpi(dir[i]->sname,"UPLOADS"))  /* Upload directory */
-		upload_dir=i;
-	else if(!strcmpi(dir[i]->sname,"OFFLINE"))	/* Offline files dir */
-		lib[dir[i]->lib]->offline_dir=i;
-
-	get_str(dir[i]->code,instream);
-
-#ifdef SCFG
-	get_str(dir[i]->data_dir,instream);
-#else
-	fread(str,LEN_DIR+1,1,instream);   /* substitute data dir */
-	offset+=LEN_DIR+1;
-	if(str[0]) {
-		backslash(str);
-		if((dir[i]->data_dir=(char *)MALLOC(strlen(str)+1))==NULL)
-			allocerr(txt,offset,fname,strlen(str)+1);
-		strcpy(dir[i]->data_dir,str); }
-	else
-		dir[i]->data_dir=data_dir_dirs;
-#endif
-
-#ifdef SCFG
-	get_str(dir[i]->ar,instream);
-	get_str(dir[i]->ul_ar,instream);
-	get_str(dir[i]->dl_ar,instream);
-	get_str(dir[i]->op_ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	dir[i]->ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	dir[i]->ul_ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	dir[i]->dl_ar=arstr(0,str);
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	dir[i]->op_ar=arstr(0,str);
-#endif
-	fread(str,1,LEN_DIR+1,instream);
-	offset+=LEN_DIR+1;
-	if(!str[0]) 				   /* no path specified */
-		sprintf(str,"%sDIRS\\%s\\",data_dir,dir[i]->code);
-
-#ifndef SCFG
-	if((dir[i]->path=(char *)MALLOC(strlen(str)+1))==NULL)
-		allocerr(txt,offset,fname,strlen(str)+1);
-#endif
-	strcpy(dir[i]->path,str);
-	get_alloc(&offset,dir[i]->upload_sem,LEN_DIR,instream);
-	get_int(dir[i]->maxfiles,instream);
-	if(dir[i]->maxfiles>MAX_FILES)
-		dir[i]->maxfiles=MAX_FILES;
-	get_alloc(&offset,dir[i]->exts,40,instream);
-	get_int(dir[i]->misc,instream);
-	get_int(dir[i]->seqdev,instream);
-	get_int(dir[i]->sort,instream);
-#ifdef SCFG
-	get_str(dir[i]->ex_ar,instream);
-#else
-	fread(str,1,LEN_ARSTR+1,instream);
-	offset+=LEN_ARSTR+1;
-	dir[i]->ex_ar=arstr(0,str);
-#endif
-	get_int(dir[i]->maxage,instream);
-	get_int(dir[i]->up_pct,instream);
-	get_int(dir[i]->dn_pct,instream);
-	get_int(c,instream);
-	for(j=0;j<24;j++)
-		get_int(n,instream); }
-
-total_dirs=i;
-
-#ifndef NO_TEXT_CFG 		/* This must be the last section in CFG file */
-
-/**********************/
-/* Text File Sections */
-/**********************/
-
-get_int(total_txtsecs,instream);
-
-
-if(total_txtsecs) {
-	if((txtsec=(txtsec_t **)MALLOC(sizeof(txtsec_t *)*total_txtsecs))==NULL)
-		allocerr(txt,offset,fname,sizeof(txtsec_t *)*total_txtsecs); }
-else
-	txtsec=NULL;
-
-for(i=0;i<total_txtsecs;i++) {
-    if(feof(instream)) break;
-    if((txtsec[i]=(txtsec_t *)MALLOC(sizeof(txtsec_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(txtsec_t));
-	memset(txtsec[i],0,sizeof(txtsec_t));
-
-    get_alloc(&offset,txtsec[i]->name,40,instream);
-    get_str(txtsec[i]->code,instream);
-#ifdef SCFG
-    get_str(txtsec[i]->ar,instream);
-#else
-    fread(str,LEN_ARSTR+1,1,instream);
-    offset+=LEN_ARSTR+1;
-	txtsec[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-total_txtsecs=i;
-
-#endif
-
-fclose(instream);
-lprintf(txt.readit,fname);
-#ifdef SBBS
-for(i=l=0;i<total_libs;i++) {
-	for(j=k=0;j<total_dirs;j++)
-		if(dir[j]->lib==i)
-			k++;
-	if(k>l) l=k; }	/* l = largest number of dirs in a lib */
-for(i=0;i<total_libs;i++)
-	if(l && (usrdir[i]=(uint *)MALLOC(sizeof(uint)*l))==NULL)
-		allocerr(txt,offset,fname,sizeof(uint)*l);
-#endif
-}
-
-#endif
-
-
-#ifndef NO_XTRN_CFG
-
-/****************************************************************************/
-/* Reads in XTRN.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_xtrn_cfg(read_cfg_text_t txt)
-{
-	char	str[256],fname[13],*p,c;
-	int 	file;
-	short	i,j,n;
-	long	offset=0;
-	FILE	*instream;
-
-strcpy(fname,"XTRN.CNF");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-
-lprintf(txt.reading,fname);
-
-/*************/
-/* Swap list */
-/*************/
-
-get_int(total_swaps,instream);
-
-if(total_swaps) {
-	if((swap=(swap_t **)MALLOC(sizeof(swap_t *)*total_swaps))==NULL)
-		allocerr(txt,offset,fname,sizeof(swap_t *)*total_swaps); }
-else
-	swap=NULL;
-
-for(i=0;i<total_swaps;i++) {
-	if(feof(instream)) break;
-	if((swap[i]=(swap_t *)MALLOC(sizeof(swap_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(swap_t));
-	get_alloc(&offset,swap[i]->cmd,LEN_CMD,instream); }
-total_swaps=i;
-
-/********************/
-/* External Editors */
-/********************/
-
-get_int(total_xedits,instream);
-
-if(total_xedits) {
-	if((xedit=(xedit_t **)MALLOC(sizeof(xedit_t *)*total_xedits))==NULL)
-		allocerr(txt,offset,fname,sizeof(xedit_t *)*total_xedits); }
-else
-	xedit=NULL;
-
-for(i=0;i<total_xedits;i++) {
-	if(feof(instream)) break;
-	if((xedit[i]=(xedit_t *)MALLOC(sizeof(xedit_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(xedit_t));
-	memset(xedit[i],0,sizeof(xedit_t));
-
-	get_alloc(&offset,xedit[i]->name,40,instream);
-	get_str(xedit[i]->code,instream);
-	get_alloc(&offset,xedit[i]->lcmd,LEN_CMD,instream);
-	get_alloc(&offset,xedit[i]->rcmd,LEN_CMD,instream);
-
-#if !defined(SCFG) && defined(SAVE_MEMORY)	  /* Save memory */
-	if(!strcmp(xedit[i]->lcmd,xedit[i]->rcmd) && xedit[i]->rcmd!=scfgnulstr) {
-		FREE(xedit[i]->rcmd);
-		xedit[i]->rcmd=xedit[i]->lcmd; }
-#endif
-
-	get_int(xedit[i]->misc,instream);
-#ifdef SCFG
-	get_str(xedit[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	xedit[i]->ar=arstr(0,str);
-#endif
-	get_int(xedit[i]->type,instream);
-	get_int(c,instream);
-	for(j=0;j<7;j++)
-		get_int(n,instream);
-	}
-total_xedits=i;
-
-
-/*****************************/
-/* External Program Sections */
-/*****************************/
-
-get_int(total_xtrnsecs,instream);
-
-if(total_xtrnsecs) {
-	if((xtrnsec=(xtrnsec_t **)MALLOC(sizeof(xtrnsec_t *)*total_xtrnsecs))
-		==NULL)
-		allocerr(txt,offset,fname,sizeof(xtrnsec_t *)*total_xtrnsecs); }
-else
-	xtrnsec=NULL;
-
-for(i=0;i<total_xtrnsecs;i++) {
-	if(feof(instream)) break;
-	if((xtrnsec[i]=(xtrnsec_t *)MALLOC(sizeof(xtrnsec_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(xtrnsec_t));
-	memset(xtrnsec[i],0,sizeof(xtrnsec_t));
-
-	get_alloc(&offset,xtrnsec[i]->name,40,instream);
-	get_str(xtrnsec[i]->code,instream);
-#ifdef SCFG
-	get_str(xtrnsec[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	xtrnsec[i]->ar=arstr(0,str);
-#endif
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-	}
-total_xtrnsecs=i;
-
-
-/*********************/
-/* External Programs */
-/*********************/
-
-get_int(total_xtrns,instream);
-
-if(total_xtrns) {
-	if((xtrn=(xtrn_t **)MALLOC(sizeof(xtrn_t *)*total_xtrns))==NULL)
-		allocerr(txt,offset,fname,sizeof(xtrn_t *)*total_xtrns); }
-else
-	xtrn=NULL;
-
-for(i=0;i<total_xtrns;i++) {
-	if(feof(instream)) break;
-	if((xtrn[i]=(xtrn_t *)MALLOC(sizeof(xtrn_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(xtrn_t));
-	memset(xtrn[i],0,sizeof(xtrn_t));
-
-	get_int(xtrn[i]->sec,instream);
-	get_alloc(&offset,xtrn[i]->name,40,instream);
-	get_str(xtrn[i]->code,instream);
-#ifdef SCFG
-	get_str(xtrn[i]->ar,instream);
-	get_str(xtrn[i]->run_ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	xtrn[i]->ar=arstr(0,str);
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	xtrn[i]->run_ar=arstr(0,str);
-#endif
-	get_int(xtrn[i]->type,instream);
-	get_int(xtrn[i]->misc,instream);
-	get_int(xtrn[i]->event,instream);
-	get_int(xtrn[i]->cost,instream);
-	get_alloc(&offset,xtrn[i]->cmd,LEN_CMD,instream);
-	get_alloc(&offset,xtrn[i]->clean,LEN_CMD,instream);
-	fread(str,LEN_DIR+1,1,instream);
-	offset+=LEN_DIR+1;
-	if(strcmp(str+1,":\\") && str[strlen(str)-1]=='\\') // C:\ is valid
-		str[strlen(str)-1]=0;		// C:\SBBS\XTRN\GAME\ is not
-#ifdef SBBS
-	if(!str[0]) 			  /* Minimum path of '.' */
-		strcpy(str,".");
-	if((xtrn[i]->path=(char *)MALLOC(strlen(str)+1))==NULL)
-		allocerr(txt,offset,fname,strlen(str)+1);
-#endif
-	strcpy(xtrn[i]->path,str);
-	get_int(xtrn[i]->textra,instream);
-	get_int(xtrn[i]->maxtime,instream);
-	for(j=0;j<7;j++)
-        get_int(n,instream);
-	}
-total_xtrns=i;
-
-
-/****************/
-/* Timed Events */
-/****************/
-
-get_int(total_events,instream);
-
-if(total_events) {
-	if((event=(event_t **)MALLOC(sizeof(event_t *)*total_events))==NULL)
-		allocerr(txt,offset,fname,sizeof(event_t *)*total_events); }
-else
-	event=NULL;
-
-for(i=0;i<total_events;i++) {
-	if(feof(instream)) break;
-	if((event[i]=(event_t *)MALLOC(sizeof(event_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(event_t));
-	memset(event[i],0,sizeof(event_t));
-
-	get_str(event[i]->code,instream);
-	get_alloc(&offset,event[i]->cmd,LEN_CMD,instream);
-	get_int(event[i]->days,instream);
-	get_int(event[i]->time,instream);
-	get_int(event[i]->node,instream);
-	get_int(event[i]->misc,instream);
-	get_alloc(&offset,event[i]->dir,LEN_DIR,instream);
-	if(event[i]->dir[0] 									// blank is valid
-		&& strcmp(event[i]->dir+1,":\\")                    // C:\ is valid
-		&& event[i]->dir[strlen(event[i]->dir)-1]=='\\')    // C:\DIR\ !valid
-		event[i]->dir[strlen(event[i]->dir)-1]=0;			// Remove \
-	for(j=0;j<8;j++)
-        get_int(n,instream);
-	}
-total_events=i;
-
-#if defined(SCFG) || defined(__OS2__)
-
-/********************/
-/* DOS Program list */
-/********************/
-
-get_int(total_os2pgms,instream);
-
-if(total_os2pgms) {
-	if((os2pgm=(os2pgm_t **)MALLOC(sizeof(os2pgm_t *)*total_os2pgms))==NULL)
-		allocerr(txt,offset,fname,sizeof(os2pgm_t *)*total_os2pgms); }
-else
-	os2pgm=NULL;
-
-for(i=0;i<total_os2pgms;i++) {
-	if(feof(instream)) break;
-	if((os2pgm[i]=(os2pgm_t *)MALLOC(sizeof(os2pgm_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(os2pgm_t));
-	get_alloc(&offset,os2pgm[i]->name,12,instream);
-	os2pgm[i]->misc=0; }
-total_os2pgms=i;
-for(i=0;i<total_os2pgms;i++) {
-    if(feof(instream)) break;
-	get_int(os2pgm[i]->misc,instream); }
-
-#endif	// Don't add anything non-OS2 specific after this (without moding ^^ )
-
-
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
-#endif
-
-
-#ifndef NO_CHAT_CFG
-
-/****************************************************************************/
-/* Reads in CHAT.CNF and initializes the associated variables				*/
-/****************************************************************************/
-void read_chat_cfg(read_cfg_text_t txt)
-{
-	char	str[256],fname[13],*p;
-	int 	file;
-	short	i,j,n;
-	long	offset=0;
-	FILE	*instream;
-
-strcpy(fname,"CHAT.CNF");
-sprintf(str,"%s%s",ctrl_dir,fname);
-if((instream=fnopen(&file,str,O_RDONLY))==NULL) {
-	lprintf(txt.openerr,str);
-	bail(1); }
-
-lprintf(txt.reading,fname);
-
-/*********/
-/* Gurus */
-/*********/
-
-get_int(total_gurus,instream);
-
-if(total_gurus) {
-    if((guru=(guru_t **)MALLOC(sizeof(guru_t *)*total_gurus))==NULL)
-        allocerr(txt,offset,fname,sizeof(guru_t *)*total_gurus); }
-else
-    guru=NULL;
-
-for(i=0;i<total_gurus;i++) {
-    if(feof(instream)) break;
-    if((guru[i]=(guru_t *)MALLOC(sizeof(guru_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(guru_t));
-    memset(guru[i],0,sizeof(guru_t));
-
-    get_alloc(&offset,guru[i]->name,25,instream);
-    get_str(guru[i]->code,instream);
-
-#ifdef SCFG
-    get_str(guru[i]->ar,instream);
-#else
-    fread(str,LEN_ARSTR+1,1,instream);
-    offset+=LEN_ARSTR+1;
-	guru[i]->ar=arstr(0,str);
-#endif
-    for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-total_chans=i;
-
-
-/********************/
-/* Chat Action Sets */
-/********************/
-
-get_int(total_actsets,instream);
-
-if(total_actsets) {
-	if((actset=(actset_t **)MALLOC(sizeof(actset_t *)*total_actsets))==NULL)
-		allocerr(txt,offset,fname,sizeof(actset_t *)*total_actsets); }
-else
-	actset=NULL;
-
-for(i=0;i<total_actsets;i++) {
-	if(feof(instream)) break;
-	if((actset[i]=(actset_t *)MALLOC(sizeof(actset_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(actset_t));
-	get_alloc(&offset,actset[i]->name,25,instream);
-	}
-total_actsets=i;
-
-
-/****************/
-/* Chat Actions */
-/****************/
-
-get_int(total_chatacts,instream);
-
-if(total_chatacts) {
-	if((chatact=(chatact_t **)MALLOC(sizeof(chatact_t *)*total_chatacts))
-		==NULL)
-		allocerr(txt,offset,fname,sizeof(chatact_t *)*total_chatacts); }
-else
-	chatact=NULL;
-
-for(i=0;i<total_chatacts;i++) {
-	if(feof(instream)) break;
-	if((chatact[i]=(chatact_t *)MALLOC(sizeof(chatact_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(chatact_t));
-	memset(chatact[i],0,sizeof(chatact_t));
-
-	get_int(chatact[i]->actset,instream);
-	get_alloc(&offset,chatact[i]->cmd,LEN_CHATACTCMD,instream);
-	get_alloc(&offset,chatact[i]->out,LEN_CHATACTOUT,instream);
-	for(j=0;j<8;j++)
-		get_int(n,instream);
-	}
-
-total_chatacts=i;
-
-
-/***************************/
-/* Multinode Chat Channels */
-/***************************/
-
-get_int(total_chans,instream);
-
-if(total_chans) {
-	if((chan=(chan_t **)MALLOC(sizeof(chan_t *)*total_chans))==NULL)
-		allocerr(txt,offset,fname,sizeof(chan_t *)*total_chans); }
-else
-	chan=NULL;
-
-for(i=0;i<total_chans;i++) {
-	if(feof(instream)) break;
-	if((chan[i]=(chan_t *)MALLOC(sizeof(chan_t)))==NULL)
-		allocerr(txt,offset,fname,sizeof(chan_t));
-	memset(chan[i],0,sizeof(chan_t));
-
-	get_int(chan[i]->actset,instream);
-	get_alloc(&offset,chan[i]->name,25,instream);
-
-	get_str(chan[i]->code,instream);
-
-#ifdef SCFG
-	get_str(chan[i]->ar,instream);
-#else
-	fread(str,LEN_ARSTR+1,1,instream);
-	offset+=LEN_ARSTR+1;
-	chan[i]->ar=arstr(0,str);
-#endif
-	get_int(chan[i]->cost,instream);
-	get_int(chan[i]->guru,instream);
-	get_int(chan[i]->misc,instream);
-	for(j=0;j<8;j++)
-		get_int(n,instream); }
-total_chans=i;
-
-
-/**************/
-/* Chat Pages */
-/**************/
-
-get_int(total_pages,instream);
-
-if(total_pages) {
-    if((page=(page_t **)MALLOC(sizeof(page_t *)*total_pages))==NULL)
-        allocerr(txt,offset,fname,sizeof(page_t *)*total_pages); }
-else
-    page=NULL;
-
-for(i=0;i<total_pages;i++) {
-    if(feof(instream)) break;
-    if((page[i]=(page_t *)MALLOC(sizeof(page_t)))==NULL)
-        allocerr(txt,offset,fname,sizeof(page_t));
-    memset(page[i],0,sizeof(page_t));
-
-    get_alloc(&offset,page[i]->cmd,LEN_CMD,instream);
-
-#ifdef SCFG
-    get_str(page[i]->ar,instream);
-#else
-    fread(str,LEN_ARSTR+1,1,instream);
-    offset+=LEN_ARSTR+1;
-	page[i]->ar=arstr(0,str);
-#endif
-    get_int(page[i]->misc,instream);
-    for(j=0;j<8;j++)
-        get_int(n,instream);
-    }
-total_pages=i;
-
-
-fclose(instream);
-lprintf(txt.readit,fname);
-}
-
-#endif
-
-/****************************************************************************/
-/* Read one line of up two 256 characters from the file pointed to by       */
-/* 'stream' and put upto 'maxlen' number of character into 'outstr' and     */
-/* truncate spaces off end of 'outstr'.                                     */
-/****************************************************************************/
-char *readline(long *offset, char *outstr, int maxlen, FILE *instream)
-{
-	char str[257];
-
-if(fgets(str,256,instream)==NULL)
-	return(NULL);
-sprintf(outstr,"%.*s",maxlen,str);
-truncsp(outstr);
-(*offset)+=maxlen;
-return(outstr);
-}
-
-#undef readline_alloc
-
-char *readline_alloc(long *offset, char *outstr, int maxline, FILE *instream)
-{
-	char str[257];
-
-readline(offset,str,maxline,instream);
-if((outstr=(char *)MALLOC(strlen(str)+1))==NULL)
-	return(NULL);
-strcpy(outstr,str);
-return(outstr);
-}
-
-/****************************************************************************/
-/* Turns char string of flags into a long									*/
-/****************************************************************************/
-long aftol(char *str)
-{
-	char c=0;
-	ulong l=0UL;
-
-strupr(str);
-while(str[c]) {
-	if(str[c]>='A' && str[c]<='Z')
-		l|=FLAG(str[c]);
-	c++; }
-return(l);
-}
-
-/*****************************************************************************/
-/* Converts a long into an ASCII Flag string (A-Z) that represents bits 0-25 */
-/*****************************************************************************/
-char *ltoaf(long l,char *str)
-{
-	char c=0;
-
-while(c<26) {
-	if(l&(long)(1L<<c))
-		str[c]='A'+c;
-	else str[c]=SP;
-	c++; }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Returns the actual attribute code from a string of ATTR characters       */
-/****************************************************************************/
-int attrstr(char *str)
-{
-	ulong l=0;
-	short atr;
-
-atr=LIGHTGRAY;
-while(str[l]) {
-	switch(str[l]) {
-		case 'H': 	/* High intensity */
-			atr|=HIGH;
-			break;
-		case 'I':	/* Blink */
-			atr|=BLINK;
-			break;
-		case 'K':	/* Black */
-			atr=(atr&0xf8)|BLACK;
-			break;
-		case 'W':	/* White */
-			atr=(atr&0xf8)|LIGHTGRAY;
-			break;
-		case '0':	/* Black Background */
-			atr=(atr&0x8f)|(BLACK<<4);
-			break;
-		case '7':	/* White Background */
-			atr=(atr&0x8f)|(LIGHTGRAY<<4);
-			break;
-		case 'R':
-			atr=(atr&0xf8)|RED;
-			break;
-		case 'G':
-			atr=(atr&0xf8)|GREEN;
-			break;
-		case 'Y':   /* Yellow */
-			atr=(atr&0xf8)|BROWN;
-			break;
-		case 'B':
-			atr=(atr&0xf8)|BLUE;
-			break;
-		case 'M':
-			atr=(atr&0xf8)|MAGENTA;
-			break;
-		case 'C':
-			atr=(atr&0xf8)|CYAN;
-			break;
-		case '1':	/* Red Background */
-			atr=(atr&0x8f)|(RED<<4);
-			break;
-		case '2':	/* Green Background */
-			atr=(atr&0x8f)|(GREEN<<4);
-			break;
-		case '3':	/* Yellow Background */
-			atr=(atr&0x8f)|(BROWN<<4);
-			break;
-		case '4':	/* Blue Background */
-			atr=(atr&0x8f)|(BLUE<<4);
-			break;
-		case '5':	/* Magenta Background */
-			atr=(atr&0x8f)|(MAGENTA<<4);
-			break;
-		case '6':	/* Cyan Background */
-			atr=(atr&0x8f)|(CYAN<<4);
-			break; }
-	l++; }
-return(atr);
-}
-
-
diff --git a/src/sbbs2/scfgvars.c b/src/sbbs2/scfgvars.c
deleted file mode 100644
index d637844daf417ff4ca96514e84cb80c720f343ec..0000000000000000000000000000000000000000
--- a/src/sbbs2/scfgvars.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* SCFGVARS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/**********************************************************************/
-/* External (Global/Public) Variables for use with both SBBS and SCFG */
-/**********************************************************************/
-
-#ifndef GLOBAL
-#define GLOBAL
-	   char *scfgnulstr="";
-#else
-extern char *scfgnulstr;
-#endif
-
-#include "sbbsdefs.h"
-
-GLOBAL grp_t		**grp;				/* Each message group */
-GLOBAL ushort		total_grps; 		/* Total number of groups */
-GLOBAL sub_t		**sub;				/* Each message sub */
-GLOBAL ushort		total_subs; 		/* Total number of subs */
-GLOBAL lib_t		**lib;				/* Each library */
-GLOBAL ushort		total_libs; 		/* Total number of libraries */
-GLOBAL dir_t		**dir;				/* Each message directory */
-GLOBAL ushort		total_dirs; 		/* Total number of directories */
-GLOBAL txtsec_t 	**txtsec;			/* Each text section */
-GLOBAL ushort		total_txtsecs;		/* Total number of text sections */
-GLOBAL xtrnsec_t	**xtrnsec;			/* Each external section */
-GLOBAL ushort		total_xtrnsecs; 	/* Total number of external sections */
-GLOBAL xtrn_t		**xtrn; 			/* Each external program */
-GLOBAL ushort		total_xtrns;		/* Total number of externals */
-GLOBAL mdm_result_t *mdm_result;		/* Each Modem Result Code */
-GLOBAL ushort		mdm_results;		/* Total number of Modem Results */
-GLOBAL prot_t		**prot; 			/* Each Transfer Protocol */
-GLOBAL ushort		total_prots;		/* Total Transfer Protocols */
-GLOBAL fextr_t		**fextr;			/* Each extractable file type */
-GLOBAL ushort		total_fextrs;		/* Total extractable file types */
-GLOBAL fcomp_t		**fcomp;			/* Each compressable file type */
-GLOBAL ushort		total_fcomps;		/* Total */
-GLOBAL fview_t		**fview;			/* Each veiwable file type */
-GLOBAL ushort		total_fviews;		/* Total viewable file types */
-GLOBAL ftest_t		**ftest;			/* Each testable file type */
-GLOBAL ushort		total_ftests;		/* Total testable file types */
-GLOBAL xedit_t		**xedit;			/* Each external editor */
-GLOBAL ushort		total_xedits;		/* Total external editors */
-GLOBAL qhub_t		**qhub; 			/* QWK network hubs */
-GLOBAL ushort		total_qhubs;		/* Total qwk network hubs */
-GLOBAL phub_t		**phub; 			/* PostLink/PCRelay network hubs */
-GLOBAL ushort		total_phubs;		/* Total PostLink/PCRelay hubs */
-GLOBAL chan_t		**chan; 			/* Each chat channel */
-GLOBAL ushort		total_chans;		/* Total number of chat channels */
-GLOBAL chatact_t	**chatact;			/* Chat action commands */
-GLOBAL ushort       total_chatacts;     /* Total number of action commands */
-GLOBAL actset_t 	**actset;			/* Name of action set */
-GLOBAL ushort		total_actsets;		/* Total number of action sets */
-GLOBAL page_t		**page; 			/* External chat page */
-GLOBAL ushort		total_pages;		/* Total number of external pages */
-GLOBAL event_t		**event;			/* Timed events */
-GLOBAL ushort		total_events;		/* Total number of timed events */
-GLOBAL dlevent_t	**dlevent;			/* Download events */
-GLOBAL ushort		total_dlevents; 	/* Total download events */
-GLOBAL faddr_t		*faddr; 			/* FidoNet addresses */
-GLOBAL ushort		total_faddrs;		/* Total number of fido addresses */
-GLOBAL swap_t		**swap; 			/* Swapping externals */
-GLOBAL ushort		total_swaps;		/* Total number of non-swap xtrns */
-GLOBAL os2pgm_t 	**os2pgm;			/* DOS Programs */
-GLOBAL ushort		total_os2pgms;		/* Total number of DOS pgms */
-GLOBAL guru_t		**guru; 			/* Gurus */
-GLOBAL ushort		total_gurus;		/* Total number of guru files */
-GLOBAL shell_t		**shell;			/* Command shells */
-GLOBAL ushort		total_shells;		/* Total number of command shells */
-
-									/* COM port registers: */
-GLOBAL ushort	com_base,			/* COM base address */
-				com_irq;			/* irq line number	   */
-GLOBAL ulong	com_rate;			/* DTE rate in bps	   */
-GLOBAL char  	com_port;			/* Number of COM port  */
-
-									/* Modem command strings */
-GLOBAL char 	mdm_init[64],		/* Initialization */
-				mdm_spec[64],		/* Special Initialization */
-				mdm_term[64],		/* Terminal Initialization String */
-				mdm_dial[64],		/* Dial */
-				mdm_offh[64],		/* Off hook */
-				mdm_answ[64],		/* Answer */
-				mdm_hang[64];		/* Hang-up */
-GLOBAL ulong	mdm_misc;			/* Misc bits used for flags */
-GLOBAL ushort	mdm_reinit; 		/* Modem reinitialization minute count */
-GLOBAL ushort	mdm_ansdelay;		/* Modem seconds to delay after answer */
-GLOBAL uchar	mdm_rings;			/* Rings to wait till answer */
-
-GLOBAL long 	sys_misc;			/* System Misc Settings */
-GLOBAL char 	sys_pass[41];		/* System Pass Word */
-GLOBAL char 	sys_name[41];		/* System Name */
-GLOBAL char 	sys_id[9];			/* System ID for QWK Packets */
-GLOBAL char 	sys_psname[13]; 	/* PostLink and PCRelay Site Name */
-GLOBAL ulong	sys_psnum;			/* PostLink and PCRelay Site Number */
-GLOBAL char 	sys_inetaddr[128];	/* System's internet address */
-GLOBAL char 	sys_location[41];	/* System Location */
-GLOBAL short	sys_timezone;		/* Time Zone of BBS */
-GLOBAL char 	sys_daily[LEN_CMD+1];	   /* Daily event */
-GLOBAL char 	sys_logon[LEN_CMD+1];	   /* Logon event */
-GLOBAL char 	sys_logout[LEN_CMD+1];	   /* Logoff event */
-GLOBAL ushort	sys_pwdays; 		/* Max days between password change */
-GLOBAL ushort	sys_deldays;		/* Days to keep deleted users */
-GLOBAL ushort	sys_autodel;		/* Autodeletion after x days inactive */
-GLOBAL ushort	sys_nodes;			/* Number of local nodes on system	*/
-GLOBAL char     sys_op[41];         /* Name of system operator */
-GLOBAL char     sys_guru[41];       /* Name of system guru */
-GLOBAL uchar	sys_exp_warn;		/* Days left till expire to notify */
-GLOBAL char 	sys_def_stat;		/* Default status line */
-GLOBAL char 	sys_phonefmt[LEN_PHONE+1];	/* format of phone numbers */
-GLOBAL ushort	sys_lastnode;		/* Last displayable node number */
-GLOBAL ushort	sys_autonode;		/* First node number for autonode */
-#ifdef SCFG
-GLOBAL uchar	sys_chat_ar[LEN_ARSTR+1];	/* chat override */
-#else
-GLOBAL uchar	*sys_chat_ar;
-#endif
-
-GLOBAL uchar	node_comspec[LEN_CMD+1];	/* DOS COMMAND.COM to use */
-GLOBAL uchar	node_editor[LEN_CMD+1]; /* Local text editor command line to use */
-GLOBAL uchar	node_viewer[LEN_CMD+1]; /* Local text viewer command line */
-GLOBAL uchar	node_daily[LEN_CMD+1];	/* Name of node's daily event */
-GLOBAL uchar	node_scrnlen;		/* Length of screen (rows) */
-GLOBAL uchar	node_scrnblank; 	/* Min of inactivity for blank screen */
-GLOBAL ulong	node_misc;			/* Misc bits for node setup */
-GLOBAL ushort	node_valuser;		/* User validation mail goes to */
-GLOBAL ushort	node_ivt;			/* Time-slice APIs */
-GLOBAL uchar	node_swap;			/* Swap types allowed */
-GLOBAL uchar	node_swapdir[LEN_DIR+1];	/* Swap directory */
-GLOBAL ushort	node_minbps;		/* Minimum connect rate of this node */
-GLOBAL ushort	node_num;			/* Local node number of this node */
-GLOBAL uchar	node_phone[13], 	/* Phone number of this node */
-				node_name[41];     	/* Name of this node */
-#ifdef SCFG
-GLOBAL uchar	node_ar[LEN_ARSTR+1]; /* Node minimum requirements */
-#else
-GLOBAL uchar	*node_ar;
-#endif
-GLOBAL ulong	node_cost;			/* Node cost to call - in credits */
-GLOBAL uchar	node_dollars_per_call;	/* Billing Node Dollars Per Call */
-GLOBAL ushort	node_sem_check; 	/* Seconds between semaphore checks */
-GLOBAL ushort	node_stat_check;	/* Seconds between statistic checks */
-
-GLOBAL char 	new_pass[41];		/* New User Password */
-GLOBAL char 	new_magic[21];		/* New User Magic Word */
-GLOBAL char 	new_sif[9]; 		/* New User SIF Questionaire */
-GLOBAL char 	new_sof[9]; 		/* New User SIF Questionaire output SIF */
-GLOBAL char 	new_level;			/* New User Main Level */
-GLOBAL ulong	new_flags1; 		/* New User Main Flags from set #1*/
-GLOBAL ulong	new_flags2; 		/* New User Main Flags from set #2*/
-GLOBAL ulong	new_flags3; 		/* New User Main Flags from set #3*/
-GLOBAL ulong	new_flags4; 		/* New User Main Flags from set #4*/
-GLOBAL ulong	new_exempt;			/* New User Exemptions */
-GLOBAL ulong	new_rest;			/* New User Restrictions */
-GLOBAL ulong	new_cdt;			/* New User Credits */
-GLOBAL ulong	new_min;			/* New User Minutes */
-GLOBAL uchar	new_xedit[9];		/* New User Default Editor */
-GLOBAL ushort	new_shell;			/* New User Default Command Set */
-GLOBAL ulong	new_misc;			/* New User Miscellaneous Defaults */
-GLOBAL ushort	new_expire; 		/* Expiration days for new user */
-GLOBAL uchar	new_prot;			/* New User Default Download Protocol */
-GLOBAL char 	val_level[10];		/* Validation User Main Level */
-GLOBAL ulong	val_flags1[10]; 	/* Validation User Flags from set #1*/
-GLOBAL ulong	val_flags2[10]; 	/* Validation User Flags from set #2*/
-GLOBAL ulong	val_flags3[10]; 	/* Validation User Flags from set #3*/
-GLOBAL ulong	val_flags4[10]; 	/* Validation User Flags from set #4*/
-GLOBAL ulong	val_exempt[10]; 	/* Validation User Exemption Flags */
-GLOBAL ulong	val_rest[10];		/* Validation User Restriction Flags */
-GLOBAL ulong	val_cdt[10];		/* Validation User Additional Credits */
-GLOBAL ushort	val_expire[10]; 	/* Validation User Extend Expire #days */
-GLOBAL uchar	level_expireto[100];
-GLOBAL ushort	level_timepercall[100], /* Security level settings */
-				level_timeperday[100],
-				level_callsperday[100],
-				level_linespermsg[100],
-				level_postsperday[100],
-				level_emailperday[100];
-GLOBAL long 	level_freecdtperday[100];
-GLOBAL long 	level_misc[100];
-GLOBAL char 	expired_level;	/* Expired user's ML */
-GLOBAL ulong	expired_flags1; /* Flags from set #1 to remove when expired */
-GLOBAL ulong	expired_flags2; /* Flags from set #2 to remove when expired */
-GLOBAL ulong	expired_flags3; /* Flags from set #3 to remove when expired */
-GLOBAL ulong	expired_flags4; /* Flags from set #4 to remove when expired */
-GLOBAL ulong	expired_exempt; /* Exemptions to remove when expired */
-GLOBAL ulong	expired_rest;	/* Restrictions to add when expired */
-GLOBAL ushort	min_dspace; 	/* Minimum amount of free space for uploads */
-GLOBAL ushort	max_batup;		/* Max number of files in upload queue */
-GLOBAL ushort	max_batdn;		/* Max number of files in download queue */
-GLOBAL ushort	max_userxfer;	/* Max dest. users of user to user xfer */
-GLOBAL ulong	max_minutes;	/* Maximum minutes a user can have */
-GLOBAL ulong	max_qwkmsgs;	/* Maximum messages per QWK packet */
-#ifdef SCFG
-GLOBAL uchar	preqwk_ar[LEN_ARSTR+1]; /* pre pack QWK */
-#else
-GLOBAL uchar	*preqwk_ar;
-#endif
-GLOBAL ushort	cdt_min_value;	/* Minutes per 100k credits */
-GLOBAL ulong	cdt_per_dollar; /* Credits per dollar */
-GLOBAL ushort	cdt_up_pct; 	/* Pct of credits credited on uploads */
-GLOBAL ushort	cdt_dn_pct; 	/* Pct of credits credited per download */
-GLOBAL char 	node_dir[LEN_DIR+1];
-GLOBAL char 	ctrl_dir[LEN_DIR+1];
-GLOBAL char 	data_dir[LEN_DIR+1];
-GLOBAL char 	text_dir[LEN_DIR+1];
-GLOBAL char 	exec_dir[LEN_DIR+1];
-GLOBAL char 	temp_dir[LEN_DIR+1];
-GLOBAL char 	**node_path;		/* paths to all node dirs */
-GLOBAL ushort	sysop_dir;			/* Destination for uploads to sysop */
-GLOBAL ushort	user_dir;			/* Directory for user to user xfers */
-GLOBAL ushort	upload_dir; 		/* Directory where all uploads go */
-GLOBAL char 	**altpath;			/* Alternate paths for files */
-GLOBAL ushort	altpaths;			/* Total number of alternate paths */
-GLOBAL ushort	leech_pct;			/* Leech detection percentage */
-GLOBAL ushort	leech_sec;			/* Minimum seconds before possible leech */
-GLOBAL ulong	netmail_cost;		/* Cost in credits to send netmail */
-GLOBAL char 	netmail_dir[LEN_DIR+1];    /* Directory to store netmail */
-GLOBAL ushort	netmail_misc;		/* Miscellaneous bits regarding netmail */
-GLOBAL ulong	inetmail_misc;		/* Miscellaneous bits regarding inetmail */
-GLOBAL ulong	inetmail_cost;		/* Cost in credits to send Internet mail */
-GLOBAL uchar	inetmail_sem[LEN_DIR+1];	/* Internet Mail semaphore file */
-GLOBAL char 	echomail_dir[LEN_DIR+1];   /* Directory to store echomail in */
-GLOBAL char 	fidofile_dir[LEN_DIR+1];   /* Directory where inbound files go */
-GLOBAL char 	netmail_sem[LEN_DIR+1];    /* FidoNet NetMail semaphore */
-GLOBAL char 	echomail_sem[LEN_DIR+1];   /* FidoNet EchoMail semaphore  */
-GLOBAL char 	origline[51];		/* Default EchoMail origin line */
-GLOBAL char 	qnet_tagline[128];	/* Default QWK Network tagline */
-GLOBAL long 	uq; 					/* User Questions */
-GLOBAL ulong	mail_maxcrcs;			/* Dupe checking in e-mail */
-GLOBAL ushort	mail_maxage;			/* Maximum age of e-mail */
-GLOBAL faddr_t	dflt_faddr; 			/* Default FidoNet address */
-GLOBAL uchar	logon_mod[9];			/* Logon module */
-GLOBAL uchar	logoff_mod[9];			/* Logoff module */
-GLOBAL uchar	newuser_mod[9]; 		/* New User Module */
-GLOBAL uchar	login_mod[9];			/* Login module */
-GLOBAL uchar	logout_mod[9];			/* Logout module */
-GLOBAL uchar	sync_mod[9];			/* Synchronization module */
-GLOBAL uchar	expire_mod[9];			/* User expiration module */
-GLOBAL uchar	scfg_cmd[LEN_CMD+1];	/* SCFG command line */
-GLOBAL uchar	smb_retry_time; 		/* Seconds to retry on SMBs */
-GLOBAL ushort	sec_warn;				/* Seconds before inactivity warning */
-GLOBAL ushort	sec_hangup; 			/* Seconds before inactivity hang-up */
-
-#ifndef SCFG
-
-GLOBAL uchar	data_dir_subs[128]; 	/* DATA\SUBS directory */
-GLOBAL uchar    data_dir_dirs[128];     /* DATA\DIRS directory */
-
-#endif
-
-#ifdef SCFG
-
-GLOBAL char 	wfc_cmd[10][LEN_CMD+1];    /* 0-9 WFC DOS commands */
-GLOBAL char 	wfc_scmd[12][LEN_CMD+1];   /* F1-F12 WFC shrinking DOS commands */
-
-#else
-
-GLOBAL char 	*wfc_cmd[10];		/* 0-9 WFC DOS commands */
-GLOBAL char     *wfc_scmd[12];      /* F1-F12 WFC shrinking DOS commands */
-
-#endif
-
diff --git a/src/sbbs2/slog/make.bat b/src/sbbs2/slog/make.bat
deleted file mode 100755
index 0d8ba2a2b7523e0e5b2d9a5aa04e41613f669e53..0000000000000000000000000000000000000000
--- a/src/sbbs2/slog/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -I.. -ml -ndos slog.c
diff --git a/src/sbbs2/slog/make.cmd b/src/sbbs2/slog/make.cmd
deleted file mode 100755
index e223e5c79c008e93102d4739fee621e2f9d871ed..0000000000000000000000000000000000000000
--- a/src/sbbs2/slog/make.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -I.. -nos2 slog.c
diff --git a/src/sbbs2/slog/slog.c b/src/sbbs2/slog/slog.c
deleted file mode 100644
index 4a8170fb2515e517aefd92fcd0536ab1b8c452df..0000000000000000000000000000000000000000
--- a/src/sbbs2/slog/slog.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* SLOG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys\stat.h>
-#include <io.h>
-#include <dos.h>
-#include <alloc.h>
-#include <time.h>
-#include <errno.h>
-
-#include "sbbsdefs.h"
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char	logstr[256];
-	int 	file,share,count=0;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-	else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(count)
-	printf("NOPEN COLLISION - File: %s Count: %d"
-		,str,count);
-if(file==-1 && errno==EACCES)
-	printf("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-
-/****************************************************************************/
-/* Lists system statistics for everyday the bbs has been running.           */
-/* Either for the current node (node=1) or the system (node=0)              */
-/****************************************************************************/
-int main(int argc, char **argv)
-{
-	char str[256],dir[256]={""},*p;
-    uchar *buf;
-	int i,file,pause=0,lncntr=0;
-    time_t timestamp;
-    long l;
-    ulong   length,
-            logons,
-            timeon,
-            posts,
-            emails,
-            fbacks,
-            ulb,
-            uls,
-            dlb,
-            dls;
-	 struct date date;
-	 struct time curtime;
-
-
-printf("\nSynchronet System/Node Statistics Log Viewer v1.02\n\n");
-
-for(i=1;i<argc;i++)
-	if(!stricmp(argv[i],"/P"))
-		pause=1;
-	else
-		strcpy(dir,argv[1]);
-if(!dir[0]) {
-	p=getenv("SBBSCTRL");
-	if(p!=NULL)
-		strcpy(dir,p); }
-
-if(dir[0] && dir[strlen(dir)-1]!='\\')
-	strcat(dir,"\\");
-
-sprintf(str,"%sCSTS.DAB",dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("Error opening %s\r\n",str);
-	return(1); }
-length=filelength(file);
-if(length<40) {
-    close(file);
-	return(1); }
-if((buf=(char *)MALLOC(length))==0) {
-    close(file);
-	printf("error allocating %lu bytes\r\n",length);
-	return(1); }
-read(file,buf,length);
-close(file);
-l=length-4;
-while(l>-1L) {
-    fbacks=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    emails=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    posts=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    dlb=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    dls=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    ulb=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    uls=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    timeon=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    logons=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    timestamp=buf[l]|((long)buf[l+1]<<8)|((long)buf[l+2]<<16)
-        |((long)buf[l+3]<<24);
-    l-=4;
-    unixtodos(timestamp-(24*60*60),&date,&curtime); /* 1 day less than stamp */
-	printf("%2.2d/%2.2d/%2.2d T:%5lu   L:%3lu   P:%3lu   "
-		"E:%3lu   F:%3lu   U:%6luk %3lu  D:%6luk %3lu\n"
-		,date.da_mon,date.da_day,date.da_year%100,timeon,logons,posts,emails
-		,fbacks,ulb/1024,uls,dlb/1024,dls);
-	lncntr++;
-	if(pause && lncntr>=20) {
-		printf("[Hit a key]");
-		if(getch()==3)
-			break;
-		printf("\r");
-		lncntr=0; } }
-FREE(buf);
-return(0);
-}
diff --git a/src/sbbs2/smb/121a/chksmb.c b/src/sbbs2/smb/121a/chksmb.c
deleted file mode 100644
index 5cb0c8bdf74cf45045908a5c6df5886cfdb41514..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/chksmb.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/* CHKSMB.C */
-
-#include <dos.h>
-#include "smblib.h"
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-
-if(!_dos_findfirst(filespec,0,&f))
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns in 'string' a character representation of the number in l with   */
-/* commas.																	*/
-/****************************************************************************/
-char *ultoac(ulong l, char *string)
-{
-	char str[256];
-	signed char i,j,k;
-
-ultoa(l,str,10);
-i=strlen(str)-1;
-j=i/3+1+i;
-string[j--]=0;
-for(k=1;i>-1;k++) {
-	string[j--]=str[i--];
-	if(j>0 && !(k%3))
-		string[j--]=','; }
-return(string);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(fidoaddr_t addr)
-{
-	static char str[25];
-	char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-	sprintf(point,".%u",addr.point);
-	strcat(str,point); }
-return(str);
-}
-
-char *usage="\nusage: chksmb [/opts] <filespec.SHD>\n"
-			"\n"
-			" opts:\n"
-			"       s - stop after errored message base\n"
-			"       p - pause after errored messsage base\n"
-			"       q - quiet mode (no beeps while checking)\n"
-			"       t - don't check translation strings\n"
-			"       e - display extended info on corrupted msgs\n";
-
-int main(int argc, char **argv)
-{
-	char		str[128],*p,*s,*beep="\7";
-	int 		i,j,x,y,lzh,errors,errlast,stop_on_error=0,pause_on_error=0
-				,chkxlat=1,lzhmsg,extinfo=0,msgerr;
-	ushort		xlat;
-	ulong		l,m,n,length,size,total=0,orphan=0,deleted=0,headers=0
-				,*offset,*number,xlaterr
-				,delhdrblocks,deldatblocks,hdrerr=0,lockerr=0,hdrnumerr=0
-				,acthdrblocks,actdatblocks
-				,dfieldlength=0,dfieldoffset=0
-				,dupenum=0,dupenumhdr=0,dupeoff=0,attr=0,actalloc=0
-				,datactalloc=0,misnumbered=0,timeerr=0,idxofferr=0,idxerr
-				,zeronum,idxzeronum,idxnumerr,packable=0L,totallzhsaved=0L
-				,totalmsgs=0,totallzhmsgs=0,totaldelmsgs=0,totalmsgbytes=0L
-				,lzhblocks,lzhsaved;
-	idxrec_t	idx;
-	smbmsg_t	msg;
-    smbstatus_t status;
-
-fprintf(stderr,"\nCHKSMB v1.24 � Check Synchronet Message Base � "
-	"Copyright 1995 Digital Dynamics\n");
-
-if(argc<2) {
-	printf("%s",usage);
-	exit(1); }
-
-errlast=errors=0;
-for(x=1;x<argc;x++) {
-	if(stop_on_error && errors)
-		break;
-	if(pause_on_error && errlast!=errors) {
-		fprintf(stderr,"\7\nHit any key to continue...");
-        if(!getch())
-            getch();
-        printf("\n"); }
-	errlast=errors;
-	if(argv[x][0]=='/') {
-		for(y=1;argv[x][y];y++)
-			switch(toupper(argv[x][y])) {
-				case 'Q':
-					beep="";
-					break;
-				case 'P':
-					pause_on_error=1;
-					break;
-				case 'S':
-					stop_on_error=1;
-					break;
-				case 'T':
-					chkxlat=0;
-					break;
-				case 'E':
-					extinfo=1;
-					break;
-				default:
-					printf("%s",usage);
-					exit(1); }
-		continue; }
-
-strcpy(smb_file,argv[x]);
-p=strrchr(smb_file,'.');
-s=strrchr(smb_file,'\\');
-if(p>s) *p=0;
-strupr(smb_file);
-
-sprintf(str,"%s.SHD",smb_file);
-if(!fexist(str)) {
-	printf("\n%s doesn't exist.\n",smb_file);
-	continue; }
-
-fprintf(stderr,"\nChecking %s Headers\n\n",smb_file);
-
-if((i=smb_open(10))!=0) {
-	printf("smb_open returned %d\n",i);
-	errors++;
-	continue; }
-
-if(filelength(fileno(shd_fp))<sizeof(smbhdr_t)) {
-	printf("Empty\n");
-	smb_close();
-	continue; }
-
-if((i=smb_locksmbhdr(10))!=0) {
-	smb_close();
-	printf("smb_locksmbhdr returned %d\n",i);
-	errors++;
-	continue; }
-
-if((i=smb_getstatus(&status))!=0) {
-	smb_unlocksmbhdr();
-	smb_close();
-	printf("smb_getstatus returned %d\n",i);
-	errors++;
-	continue; }
-
-
-length=filelength(fileno(shd_fp));
-
-if((length/SHD_BLOCK_LEN)*sizeof(ulong)) {
-	if((number=(ulong *)MALLOC(((length/SHD_BLOCK_LEN)+2)*sizeof(ulong)))
-		==NULL) {
-		printf("Error allocating %lu bytes of memory\n"
-			,(length/SHD_BLOCK_LEN)*sizeof(ulong));
-		return(++errors); } }
-else
-	number=NULL;
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	if((i=smb_open_ha(10))!=0) {
-		printf("smb_open_ha returned %d\n",i);
-		return(++errors); }
-
-	if((i=smb_open_da(10))!=0) {
-		printf("smb_open_da returned %d\n",i);
-		return(++errors); } }
-
-headers=deleted=orphan=dupenumhdr=attr=zeronum=timeerr=lockerr=hdrerr=0;
-actalloc=datactalloc=deldatblocks=delhdrblocks=xlaterr=0;
-lzhblocks=lzhsaved=acthdrblocks=actdatblocks=0;
-
-for(l=status.header_offset;l<length;l+=size) {
-	fprintf(stderr,"\r%2u%%  ",(long)(100.0/((float)length/l)));
-	msg.idx.offset=l;
-	msgerr=0;
-	if((i=smb_lockmsghdr(msg,10))!=0) {
-		printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-		lockerr++;
-		headers++;
-		size=SHD_BLOCK_LEN;
-		continue; }
-	if((i=smb_getmsghdr(&msg))!=0) {
-		smb_unlockmsghdr(msg);
-		if(!(status.attr&SMB_HYPERALLOC)) {
-			fseek(sha_fp,(l-status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-			j=fgetc(sha_fp);
-			if(j) { 			/* Allocated block or at EOF */
-				printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i);
-				hdrerr++; }
-			else
-				delhdrblocks++; }
-		else {
-			/* printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i); */
-			delhdrblocks++; }
-		size=SHD_BLOCK_LEN;
-		continue; }
-	smb_unlockmsghdr(msg);
-	fprintf(stderr,"#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
-
-	lzhmsg=0;
-	if(msg.hdr.attr&MSG_DELETE) {
-		deleted++;
-		if(number)
-			number[headers]=0;
-		if(status.attr&SMB_HYPERALLOC)
-			deldatblocks+=smb_datblocks(smb_getmsgdatlen(msg)); }
-	else {
-		actdatblocks+=smb_datblocks(smb_getmsgdatlen(msg));
-		if(msg.hdr.number>status.last_msg) {
-			fprintf(stderr,"%sOut-Of-Range message number\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number (%lu) greater than last (%lu)\n"
-					,msg.hdr.number,status.last_msg);
-			hdrnumerr++; }
-
-		if(smb_getmsgidx(&msg)) {
-			fprintf(stderr,"%sNot found in index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number (%lu) not found in index\n"
-					,msg.hdr.number);
-			orphan++; }
-		else if(msg.hdr.attr!=msg.idx.attr) {
-			fprintf(stderr,"%sAttributes mismatch index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header attributes (%04X) do not match index "
-					"attributes (%04X)\n"
-					,msg.hdr.attr,msg.idx.attr);
-			attr++; }
-		else if(msg.hdr.when_imported.time!=msg.idx.time) {
-			fprintf(stderr,"%sImport date/time mismatch index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header import date/time does not match "
-					"index import date/time\n");
-			timeerr++; }
-
-		if(msg.hdr.number==0) {
-			fprintf(stderr,"%sZero message number\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number is zero (invalid)\n");
-			zeronum++; }
-		if(number) {
-			for(m=0;m<headers;m++)
-				if(number[m] && msg.hdr.number==number[m]) {
-					fprintf(stderr,"%sDuplicate message number\n",beep);
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Header number (%lu) duplicated\n"
-							,msg.hdr.number);
-					dupenumhdr++;
-					break; }
-			number[headers]=msg.hdr.number; }
-		if(chkxlat) {		/* Check translation strings */
-			for(i=0;i<msg.hdr.total_dfields;i++) {
-				fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
-				if(!fread(&xlat,2,1,sdt_fp))
-					xlat=0xffff;
-				lzh=0;
-				if(xlat==XLAT_LZH) {
-					lzh=1;
-					if(!fread(&xlat,2,1,sdt_fp))
-						xlat=0xffff; }
-				if(xlat!=XLAT_NONE) {
-					fprintf(stderr,"%sUnsupported Xlat %04X dfield[%u]\n"
-						,beep,xlat,i);
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Unsupported translation type (%04X) "
-							"in dfield[%u]\n"
-							,xlat,i);
-					xlaterr++; }
-				else {
-					if(lzh) {
-						lzhmsg=1;
-						if(fread(&m,4,1,sdt_fp)) { /* Get uncompressed len */
-							lzhsaved+=(smb_datblocks(m+2)
-								-smb_datblocks(msg.dfield[i].length))
-								*SDT_BLOCK_LEN;
-							lzhblocks+=smb_datblocks(msg.dfield[i].length);
-						} } } } } }
-
-	size=smb_getmsghdrlen(msg);
-	while(size%SHD_BLOCK_LEN)
-		size++;
-
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		fseek(sha_fp,(l-status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-		for(m=0;m<size;m+=SHD_BLOCK_LEN) {
-/***
-			if(msg.hdr.attr&MSG_DELETE && (i=fgetc(sha_fp))!=0) {
-				fprintf(stderr,"%sDeleted Header Block %lu marked %02X\n"
-					,beep,m/SHD_BLOCK_LEN,i);
-				msgerr=1;
-				delalloc++; }
-***/
-			if(!(msg.hdr.attr&MSG_DELETE) && (i=fgetc(sha_fp))!=1) {
-				fprintf(stderr,"%sActive Header Block %lu marked %02X\n"
-					,beep,m/SHD_BLOCK_LEN,i);
-				msgerr=1;
-				if(extinfo)
-					printf("MSGERR: Active header block %lu marked %02X "
-						"instead of 01\n"
-						,m/SHD_BLOCK_LEN,i);
-				actalloc++; } }
-
-		if(!(msg.hdr.attr&MSG_DELETE)) {
-			acthdrblocks+=(size/SHD_BLOCK_LEN);
-			for(n=0;n<msg.hdr.total_dfields;n++) {
-				if(msg.dfield[n].offset&0x80000000UL) {
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Invalid Data Field [%u] Offset: %lu\n"
-							,n,msg.dfield[n].offset);
-					dfieldoffset++; }
-				if(msg.dfield[n].length&0x80000000UL) {
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Invalid Data Field [%u] Length: %lu\n"
-							,n,msg.dfield[n].length);
-					dfieldlength++; }
-				fseek(sda_fp
-					,((msg.hdr.offset+msg.dfield[n].offset)/SDT_BLOCK_LEN)*2
-					,SEEK_SET);
-				for(m=0;m<msg.dfield[n].length;m+=SDT_BLOCK_LEN) {
-					if(!fread(&i,2,1,sda_fp) || !i) {
-						fprintf(stderr
-							,"%sActive Data Block %lu.%lu marked free\n"
-							,beep,n,m/SHD_BLOCK_LEN);
-						msgerr=1;
-						if(extinfo)
-							printf("MSGERR: Active Data Block %lu.%lu "
-								"marked free\n"
-								,n,m/SHD_BLOCK_LEN);
-						datactalloc++; } } } }
-		else
-			delhdrblocks+=(size/SHD_BLOCK_LEN); }
-
-	else {	 /* Hyper Alloc */
-		if(msg.hdr.attr&MSG_DELETE)
-			delhdrblocks+=(size/SHD_BLOCK_LEN);
-		else
-			acthdrblocks+=(size/SHD_BLOCK_LEN); }
-
-	totallzhmsgs+=lzhmsg;
-	headers++;
-	if(msgerr && extinfo) {
-		printf("\n");
-		printf("%-20s: %s\n","Message Base",smb_file);
-		printf("%-20s: %lu (%lu)\n","Message Number"
-			,msg.hdr.number,msg.offset+1);
-		printf("%-20s: %s\n","Subject",msg.subj);
-		printf("%-20s: %s","To",msg.to);
-		if(msg.to_net.type)
-			printf(" (%s)",msg.to_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-		printf("\n%-20s: %s","From",msg.from);
-		if(msg.from_net.type)
-			printf(" (%s)",msg.from_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
-                    : msg.from_net.addr);
-		printf("\n");
-		printf("%-20s: %.24s\n","When Written"
-			,ctime((time_t *)&msg.hdr.when_written.time));
-		printf("%-20s: %.24s\n","When Imported"
-			,ctime((time_t *)&msg.hdr.when_imported.time));
-		printf("%-20s: %04hXh\n","Type"
-			,msg.hdr.type);
-		printf("%-20s: %04hXh\n","Version"
-			,msg.hdr.version);
-		printf("%-20s: %u\n","Length"
-			,msg.hdr.length);
-		printf("%-20s: %04hXh\n","Attributes"
-			,msg.hdr.attr);
-		printf("%-20s: %08lXh\n","Auxilary Attributes"
-			,msg.hdr.auxattr);
-		printf("%-20s: %08lXh\n","Network Attributes"
-			,msg.hdr.netattr);
-		printf("%-20s: %06lXh\n","Header Offset"
-			,msg.idx.offset);
-		printf("%-20s: %06lXh\n","Data Offset"
-			,msg.hdr.offset);
-		printf("%-20s: %u\n","Total Data Fields"
-			,msg.hdr.total_dfields);
-		printf("\n"); }
-
-    smb_freemsgmem(msg); }
-
-if(number)
-    FREE(number);
-
-fprintf(stderr,"\r%79s\r100%%\n","");
-
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-
-	fprintf(stderr,"\nChecking %s Data Blocks\n\n",smb_file);
-
-	length=filelength(fileno(sda_fp));
-
-	fseek(sda_fp,0L,SEEK_SET);
-	for(l=0;l<length;l+=2) {
-		fprintf(stderr,"\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-		i=0;
-		if(!fread(&i,2,1,sda_fp))
-			break;
-		if(!i)
-			deldatblocks++; }
-
-	fclose(sha_fp);
-	fclose(sda_fp);
-
-	fprintf(stderr,"\r%79s\r100%%\n",""); }
-
-total=filelength(fileno(sid_fp))/sizeof(idxrec_t);
-
-dupenum=dupeoff=misnumbered=idxzeronum=idxnumerr=idxofferr=idxerr=0;
-
-if(total) {
-
-fprintf(stderr,"\nChecking %s Index\n\n",smb_file);
-
-if((offset=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
-    printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
-	return(++errors); }
-if((number=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
-    printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
-	return(++errors); }
-fseek(sid_fp,0L,SEEK_SET);
-
-for(l=0;l<total;l++) {
-	fprintf(stderr,"\r%2lu%%  %5lu ",l ? (long)(100.0/((float)total/l)) : 0,l);
-	if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
-		break;
-	fprintf(stderr,"#%-5lu (%06lX) 1st Pass ",idx.number,idx.offset);
-/***
-	if(idx.attr&MSG_DELETE) {
-		fprintf(stderr,"%sMarked for deletion\n",beep);
-		delidx++; }
-***/
-	for(m=0;m<l;m++)
-        if(number[m]==idx.number) {
-			fprintf(stderr,"%sDuplicate message number\n",beep);
-			dupenum++;
-			break; }
-	for(m=0;m<l;m++)
-        if(offset[m]==idx.offset) {
-			fprintf(stderr,"%sDuplicate offset\n",beep,idx.offset);
-			dupeoff++;
-			break; }
-	if(idx.offset<status.header_offset) {
-		fprintf(stderr,"%sInvalid offset\n",beep);
-		idxofferr++;
-		break; }
-	if(idx.number==0) {
-		fprintf(stderr,"%sZero message number\n",beep);
-		idxzeronum++;
-		break; }
-	if(idx.number>status.last_msg) {
-		fprintf(stderr,"%sOut-Of-Range message number\n",beep);
-		idxnumerr++;
-		break; }
-    number[l]=idx.number;
-    offset[l]=idx.offset; }
-
-if(l<total) {
-	fprintf(stderr,"%sError reading index record\n",beep);
-	idxerr=1; }
-else {
-	fprintf(stderr,"\r%79s\r","");
-	for(m=0;m<total;m++) {
-		fprintf(stderr,"\r%2lu%%  %5lu ",m ? (long)(100.0/((float)total/m)) : 0,m);
-		fprintf(stderr,"#%-5lu (%06lX) 2nd Pass ",number[m],offset[m]);
-		for(n=0;n<m;n++)
-			if(number[m] && number[n] && number[m]<number[n]) {
-				fprintf(stderr,"%sMisordered message number\n",beep);
-				misnumbered++;
-				number[n]=0;
-				break; } }
-	fprintf(stderr,"\r%79s\r100%%\n",""); }
-FREE(number);
-FREE(offset);
-
-}	/* if(total) */
-
-totalmsgs+=status.total_msgs;
-totalmsgbytes+=(acthdrblocks*SHD_BLOCK_LEN)+(actdatblocks*SDT_BLOCK_LEN);
-totaldelmsgs+=deleted;
-totallzhsaved+=lzhsaved;
-printf("\n");
-printf("%-35.35s (=): %lu\n"
-	,"Status Total"
-	,status.total_msgs);
-printf("%-35.35s (=): %lu\n"
-	,"Index Records"
-	,total);
-printf("%-35.35s (=): %lu\n"
-	,"Active Headers"
-	,headers-deleted);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Active Header Blocks"
-	,acthdrblocks,ultoac(acthdrblocks*SHD_BLOCK_LEN,str));
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Active Data Blocks"
-	,actdatblocks,ultoac(actdatblocks*SDT_BLOCK_LEN,str));
-if(lzhblocks)
-	printf("%-35.35s ( ): %-8lu %13s bytes saved\n"
-		,"Active LZH Compressed Data Blocks"
-		,lzhblocks,ultoac(lzhsaved,str));
-printf("%-35.35s ( ): %lu\n"
-	,"Header Records"
-    ,headers);
-printf("%-35.35s ( ): %lu\n"
-	,"Deleted Headers"
-	,deleted);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Deleted Header Blocks"
-	,delhdrblocks,ultoac(delhdrblocks*SHD_BLOCK_LEN,str));
-packable+=(delhdrblocks*SHD_BLOCK_LEN);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Deleted Data Blocks"
-	,deldatblocks,ultoac(deldatblocks*SDT_BLOCK_LEN,str));
-packable+=(deldatblocks*SDT_BLOCK_LEN);
-
-if(orphan)
-	printf("%-35.35s (!): %lu\n"
-		,"Orphaned Headers"
-		,orphan);
-if(idxzeronum)
-	printf("%-35.35s (!): %lu\n"
-		,"Zeroed Index Numbers"
-		,idxzeronum);
-if(zeronum)
-	printf("%-35.35s (!): %lu\n"
-		,"Zeroed Header Numbers"
-		,zeronum);
-/***
-if(delidx)
-	printf("%-35.35s (!): %lu\n"
-		,"Deleted Index Records"
-		,delidx);
-***/
-if(idxofferr)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Index Offsets"
-		,idxofferr);
-if(dupenum)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Index Numbers"
-		,dupenum);
-if(dupeoff)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Index Offsets"
-		,dupeoff);
-if(dupenumhdr)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Header Numbers"
-		,dupenumhdr);
-if(misnumbered)
-	printf("%-35.35s (!): %lu\n"
-		,"Misordered Index Numbers"
-		,misnumbered);
-if(lockerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Unlockable Header Records"
-		,lockerr);
-if(hdrerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Unreadable Header Records"
-		,hdrerr);
-if(idxnumerr)
-    printf("%-35.35s (!): %lu\n"
-		,"Out-Of-Range Index Numbers"
-		,idxnumerr);
-if(hdrnumerr)
-    printf("%-35.35s (!): %lu\n"
-		,"Out-Of-Range Header Numbers"
-		,hdrnumerr);
-if(attr)
-	printf("%-35.35s (!): %lu\n"
-		,"Mismatched Header Attributes"
-		,attr);
-if(timeerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Mismatched Header Import Time"
-		,timeerr);
-if(xlaterr)
-    printf("%-35.35s (!): %lu\n"
-        ,"Unsupported Translation Types"
-        ,xlaterr);
-if(datactalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Active Data Blocks"
-		,datactalloc);
-if(actalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Active Header Blocks"
-		,actalloc);
-/***
-if(delalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Deleted Header Blocks"
-		,delalloc);
-***/
-
-if(dfieldoffset)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Data Field Offsets"
-		,dfieldoffset);
-
-if(dfieldlength)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Data Field Lengths"
-		,dfieldlength);
-
-
-printf("\n%s Message Base ",smb_file);
-if((headers-deleted)!=status.total_msgs || total!=status.total_msgs
-	|| (headers-deleted)!=total || idxzeronum || zeronum
-	|| orphan || dupenumhdr || dupenum || dupeoff || attr
-	|| lockerr || hdrerr || hdrnumerr || idxnumerr || idxofferr
-	|| actalloc || datactalloc || misnumbered || timeerr
-	|| dfieldoffset || dfieldlength || xlaterr || idxerr) {
-	printf("%shas Errors!\n",beep);
-	errors++; }
-else
-	printf("is OK\n");
-
-smb_unlocksmbhdr();
-smb_close();
-}
-if(pause_on_error && errlast!=errors) {
-	fprintf(stderr,"\7\nHit any key to continue...");
-	if(!getch())
-		getch();
-	fprintf(stderr,"\n"); }
-
-if((totalmsgs && (totalmsgs!=status.total_msgs || totallzhmsgs))
-	|| packable)
-	printf("\n");
-if(totalmsgs && totalmsgs!=status.total_msgs)
-	printf("%-39.39s: %-8lu %13s bytes used\n"
-		,"Total Active Messages"
-		,totalmsgs,ultoac(totalmsgbytes,str));
-if(totallzhmsgs && totalmsgs!=status.total_msgs)
-	printf("%-39.39s: %-8lu %13s bytes saved\n"
-		,"Total LZH Compressed Messages"
-		,totallzhmsgs,ultoac(totallzhsaved,str));
-if(packable)
-	printf("%-39.39s: %-8lu %13s bytes used\n"
-		,"Total Deleted Messages"
-		,totaldelmsgs,ultoac(packable,str));
-
-return(errors);
-}
diff --git a/src/sbbs2/smb/121a/chksmb.mak b/src/sbbs2/smb/121a/chksmb.mak
deleted file mode 100644
index 1609c16ece6318aafb731e4aafce3f5910eecb25..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/chksmb.mak
+++ /dev/null
@@ -1,50 +0,0 @@
-###############################
-# Makefile for CHKSMB         #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-MAIN	= chksmb.exe
-OBJS	= $(MODEL)\chksmb.obj $(MODEL)\smblib.obj $(MODEL)\smbvars.obj
-HEADERS = smblib.h smbdefs.h crc32.h
-
-!ifdef __OS2__
-CC      = c:\bcos2\bin\bcc
-LD      = c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;smb
-LIB     = c:\bcos2\lib
-CFLAGS	= -d -C -I$(INCLUDE)
-LFLAGS  = -c -w-srf
-!endif
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(MODEL) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\os2.lib $(LI$(MODEL)\B)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# All .obj modules
-$(MODEL)\chksmb.obj:	 $(HEADERS)
-$(MODEL)\smbvars.obj:	 $(HEADERS)
-$(MODEL)\smblib.obj:	 $(HEADERS)
diff --git a/src/sbbs2/smb/121a/crc16.c b/src/sbbs2/smb/121a/crc16.c
deleted file mode 100644
index dc899629401fb12ee443dd2dd22c36c65911c731..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/crc16.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* CRC16.C */
-
-/* 16-bit CRC routines */
-
-#include "smblib.h"
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
diff --git a/src/sbbs2/smb/121a/crc32.h b/src/sbbs2/smb/121a/crc32.h
deleted file mode 100644
index a5d5162fb2fbae6acfb7b5a18d0502d2d1339b93..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/crc32.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 32-bit CRC */
-
-long crc32tbl[]={	/* CRC polynomial 0xedb88320 */
-0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-#define ucrc32(ch,crc) (crc32tbl[(crc^ch)&0xff]^(crc>>8))
-
-
diff --git a/src/sbbs2/smb/121a/fido2smb.c b/src/sbbs2/smb/121a/fido2smb.c
deleted file mode 100644
index c366b56fbce2634d7fba0483a6d99eba86d5b7e8..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/fido2smb.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/* FIDO2SMB.C */
-
-/* Converts FidoNet FTSC-1 (*.MSG) message base to SMB format */
-
-/* The intention of this source code is an example of how to use the SMBLIB */
-/* library functions to access an SMB format message base.					*/
-
-/* This program and source code are freeware. May be used in part or whole	*/
-/* for any purpose without consent or notification of Digital Dynamics. 	*/
-
-/* Digital Dynamics does request that developers that release products that */
-/* support the SMB format notify Digital Dynamics so the implementation 	*/
-/* and contact chapters in the technical specification may be updated.		*/
-
-#include "smblib.h"
-#include "crc32.h"
-#include <dos.h>
-									/* Attribute bits for fido msg header */
-#define FIDO_PRIVATE	(1<<0)		/* Private message */
-#define FIDO_CRASH		(1<<1)		/* Crash-mail (send immediately) */
-#define FIDO_RECV		(1<<2)		/* Received successfully */
-#define FIDO_SENT		(1<<3)		/* Sent successfully */
-#define FIDO_FILE		(1<<4)		/* File attached */
-#define FIDO_INTRANS	(1<<5)		/* In transit */
-#define FIDO_ORPHAN 	(1<<6)		/* Orphan */
-#define FIDO_KILLSENT	(1<<7)		/* Kill it after sending it */
-#define FIDO_LOCAL		(1<<8)		/* Created locally - on this system */
-#define FIDO_HOLD		(1<<9)		/* Hold - don't send it yet */
-#define FIDO_FREQ		(1<<11) 	/* File request */
-#define FIDO_RRREQ		(1<<12) 	/* Return receipt request */
-#define FIDO_RR 		(1<<13) 	/* This is a return receipt */
-#define FIDO_AUDIT		(1<<14) 	/* Audit request */
-#define FIDO_FUPREQ     (1<<15)     /* File update request */
-
-typedef struct {						/* FidoNet msg header */
-	uchar	from[36],					/* From user */
-			to[36], 					/* To user */
-			subj[72],					/* Message title */
-			time[20];					/* Time in goof-ball ASCII format */
-	short	read,						/* Times read */
-			destnode,					/* Destination node */
-			orignode,					/* Origin node */
-			cost,						/* Cost in pennies */
-			orignet,					/* Origin net */
-			destnet,					/* Destination net */
-			destzone,					/* Destination zone */
-			origzone,					/* Origin zone */
-			destpoint,					/* Destination point */
-			origpoint,					/* Origin point */
-			re, 						/* Message number regarding */
-			attr,						/* Attributes - see FIDO_* */
-			next;						/* Next message number in stream */
-            } fmsghdr_t;
-
-/******************************************/
-/* CRC-16 routines required for SMB index */
-/******************************************/
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=' ') c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(f.ff_fsize);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-fidoaddr_t atofaddr(char *str)
-{
-    char *p;
-	fidoaddr_t addr;
-
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-	addr.zone=atoi(str);
-	addr.net=atoi(p+1); }
-else {
-	addr.zone=1;
-	addr.net=atoi(str); }
-if(!addr.zone)				/* no such thing as zone 0 */
-	addr.zone=1;
-if((p=strchr(str,'/'))!=NULL)
-    addr.node=atoi(p+1);
-else {
-	addr.net=1;
-	addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL)
-    addr.point=atoi(p+1);
-return(addr);
-}
-
-/****************************************************************************/
-/* Converts goofy FidoNet time format into Unix format						*/
-/****************************************************************************/
-time_t fmsgtime(char *str)
-{
-	char month[4];
-	struct date date;
-	struct time t;
-
-if(isdigit(str[1])) {	/* Regular format: "01 Jan 86  02:34:56" */
-	date.da_day=atoi(str);
-	sprintf(month,"%3.3s",str+3);
-	if(!stricmp(month,"jan"))
-		date.da_mon=1;
-	else if(!stricmp(month,"feb"))
-		date.da_mon=2;
-	else if(!stricmp(month,"mar"))
-		date.da_mon=3;
-	else if(!stricmp(month,"apr"))
-		date.da_mon=4;
-	else if(!stricmp(month,"may"))
-		date.da_mon=5;
-	else if(!stricmp(month,"jun"))
-		date.da_mon=6;
-	else if(!stricmp(month,"jul"))
-		date.da_mon=7;
-	else if(!stricmp(month,"aug"))
-		date.da_mon=8;
-	else if(!stricmp(month,"sep"))
-		date.da_mon=9;
-	else if(!stricmp(month,"oct"))
-		date.da_mon=10;
-	else if(!stricmp(month,"nov"))
-		date.da_mon=11;
-	else
-		date.da_mon=12;
-	date.da_year=1900+atoi(str+7);
-	t.ti_hour=atoi(str+11);
-	t.ti_min=atoi(str+14);
-	t.ti_sec=atoi(str+17); }
-
-else {					/* SEAdog  format: "Mon  1 Jan 86 02:34" */
-	date.da_day=atoi(str+4);
-	sprintf(month,"%3.3s",str+7);
-	if(!stricmp(month,"jan"))
-		date.da_mon=1;
-	else if(!stricmp(month,"feb"))
-		date.da_mon=2;
-	else if(!stricmp(month,"mar"))
-		date.da_mon=3;
-	else if(!stricmp(month,"apr"))
-		date.da_mon=4;
-	else if(!stricmp(month,"may"))
-		date.da_mon=5;
-	else if(!stricmp(month,"jun"))
-		date.da_mon=6;
-	else if(!stricmp(month,"jul"))
-		date.da_mon=7;
-	else if(!stricmp(month,"aug"))
-		date.da_mon=8;
-	else if(!stricmp(month,"sep"))
-		date.da_mon=9;
-	else if(!stricmp(month,"oct"))
-		date.da_mon=10;
-	else if(!stricmp(month,"nov"))
-		date.da_mon=11;
-	else
-		date.da_mon=12;
-	date.da_year=1900+atoi(str+11);
-	t.ti_hour=atoi(str+14);
-	t.ti_min=atoi(str+17);
-	t.ti_sec=0; }
-return(dostounix(&date,&t));
-}
-
-/****************************************************************************/
-/* Entry point - if you didn't know that, maybe you shouldn't be reading :) */
-/****************************************************************************/
-int main(int argc, char **argv)
-{
-	uchar	*p,str[128],*fbuf,*sbody,*stail,ch,done;
-	ushort	xlat,net;
-	int 	i,j,file,col,cr,esc,orig,last,msgs,found;
-	ulong	l,m,length,bodylen,taillen,crc;
-	struct	ffblk ff;
-	smbmsg_t	msg;
-	smbstatus_t status;
-	fmsghdr_t	fmsghdr;
-	fidoaddr_t	destaddr,origaddr,faddr;
-
-if(argc<3) {
-	printf("usage: fido2smb <fido_dir> <smb_name>\r\n");
-	exit(1); }
-
-strcpy(smb_file,argv[2]);
-strupr(smb_file);
-
-smb_open(10);
-if(!filelength(fileno(shd_fp)))
-	smb_create(2000,2000,0,0,10);
-
-smb_getstatus(&status); 	  // Initialized for first call to smb_addcrc()
-
-/*********************************************/
-/* Get the total number of .MSG files in dir */
-/*********************************************/
-printf("\nCounting messages...");
-sprintf(str,"%s\\*.MSG",argv[1]);
-last=findfirst(str,&ff,0);
-for(msgs=0;!last;msgs++)
-	last=findnext(&ff);
-printf("\n%u messages.\n",msgs);
-
-/******************************************/
-/* Convert in sequence, starting at 1.MSG */
-/******************************************/
-for(i=1,found=0;found<msgs && i<2000;i++) {
-	sprintf(str,"%s\\%u.MSG",argv[1],i);
-	if((file=open(str,O_RDONLY|O_BINARY))==-1)
-		continue;
-	found++;
-	strupr(str);
-	printf("%s\n",str);
-	read(file,&fmsghdr,sizeof(fmsghdr_t));
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=SMB_VERSION;
-	if(fmsghdr.attr&FIDO_PRIVATE)
-		msg.idx.attr|=MSG_PRIVATE;
-	msg.hdr.attr=msg.idx.attr;
-
-	msg.hdr.when_imported.time=time(NULL);
-	msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
-
-	origaddr.zone=fmsghdr.origzone; 	/* only valid if NetMail */
-	origaddr.net=fmsghdr.orignet;
-	origaddr.node=fmsghdr.orignode;
-	origaddr.point=fmsghdr.origpoint;
-
-	destaddr.zone=fmsghdr.destzone; 	/* only valid if NetMail */
-	destaddr.net=fmsghdr.destnet;
-	destaddr.node=fmsghdr.destnode;
-	destaddr.point=fmsghdr.destpoint;
-
-	smb_hfield(&msg,SENDER,strlen(fmsghdr.from),fmsghdr.from);
-	strlwr(fmsghdr.from);
-	msg.idx.from=crc16(fmsghdr.from);
-
-	smb_hfield(&msg,RECIPIENT,strlen(fmsghdr.to),fmsghdr.to);
-	strlwr(fmsghdr.to);
-	msg.idx.to=crc16(fmsghdr.to);
-
-	smb_hfield(&msg,SUBJECT,strlen(fmsghdr.subj),fmsghdr.subj);
-	strlwr(fmsghdr.subj);
-	msg.idx.subj=crc16(fmsghdr.subj);
-
-	length=filelength(file)-sizeof(fmsghdr_t);
-	if((fbuf=(char *)MALLOC(length))==NULL) {
-		printf("alloc error\n");
-		exit(1); }
-	if((sbody=(char *)MALLOC(length*2L))==NULL) {
-		printf("alloc error\n");
-        exit(1); }
-	if((stail=(char *)MALLOC(length))==NULL) {
-		printf("alloc error\n");
-        exit(1); }
-	read(file,fbuf,length);
-	close(file);
-
-	for(col=l=esc=done=bodylen=taillen=orig=0,cr=1;l<length;l++) {
-		ch=fbuf[l];
-		if(ch==1 && cr) {	/* kludge line */
-
-			if(!strncmp(fbuf+l+1,"TOPT ",5))
-				destaddr.point=atoi(fbuf+l+6);
-
-			else if(!strncmp(fbuf+l+1,"FMPT ",5))
-				origaddr.point=atoi(fbuf+l+6);
-
-			else if(!strncmp(fbuf+l+1,"INTL ",5)) {
-				faddr=atofaddr(fbuf+l+6);
-				destaddr.zone=faddr.zone;
-				destaddr.net=faddr.net;
-				destaddr.node=faddr.node;
-				l+=6;
-				while(l<length && fbuf[l]!=SP) l++;
-				faddr=atofaddr(fbuf+l+1);
-				origaddr.zone=faddr.zone;
-				origaddr.net=faddr.net;
-				origaddr.node=faddr.node; }
-
-			else if(!strncmp(fbuf+l+1,"MSGID:",6)) {
-				l+=7;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOMSGID,m-l,fbuf+l); }
-
-			else if(!strncmp(fbuf+l+1,"REPLY:",6)) {
-				l+=7;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOREPLYID,m-l,fbuf+l); }
-
-			else if(!strncmp(fbuf+l+1,"FLAGS:",6)) {
-				l+=7;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOFLAGS,m-l,fbuf+l); }
-
-			else if(!strncmp(fbuf+l+1,"PATH:",5)) {
-				l+=6;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOPATH,m-l,fbuf+l); }
-
-			else if(!strncmp(fbuf+l+1,"PID:",4)) {
-				l+=5;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOPID,m-l,fbuf+l); }
-
-			else {		/* Unknown kludge line */
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOCTRL,m-l,fbuf+l); }
-
-			while(l<length && fbuf[l]!=CR) l++;
-			continue; }
-
-		if(ch!=LF && ch!=0x8d) {	/* ignore LF and soft CRs */
-			if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
-				|| !strncmp((char *)fbuf+l,"---\r",4)))
-				done=1; 			/* tear line and down go into tail */
-			if(done && cr && !strncmp(fbuf+l,"SEEN-BY:",8)) {
-				l+=8;
-				while(l<length && fbuf[l]<=SP) l++;
-				m=l;
-				while(m<length && fbuf[m]!=CR) m++;
-				while(m && fbuf[m-1]<=SP) m--;
-				if(m>l)
-					smb_hfield(&msg,FIDOSEENBY,m-l,fbuf+l);
-				while(l<length && fbuf[l]!=CR) l++;
-				continue;  }  /* skip the CR */
-			if(done)
-				stail[taillen++]=ch;
-			else
-				sbody[bodylen++]=ch;
-			col++;
-			if(ch==CR) {
-				cr=1;
-				col=0;
-				if(done)
-					stail[taillen++]=LF;
-				else
-					sbody[bodylen++]=LF; }
-			else {
-				cr=0;
-				if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
-					p=strchr(fbuf+l+11,CR); 	 /* find carriage return */
-					while(p && *p!='(') p--;     /* rewind to '(' */
-					if(p)
-						origaddr=atofaddr(p+1); 	/* get orig address */
-					orig=done=1; }
-				if(done)
-					continue;
-
-				if(ch==ESC) esc=1;		/* ANSI codes */
-				if(ch==SP && col>40 && !esc) {	/* word wrap */
-					for(m=l+1;m<length;m++) 	/* find next space */
-						if(fbuf[m]<=SP)
-							break;
-					if(m<length && m-l>80-col) {  /* if it's beyond the eol */
-						sbody[bodylen++]=CR;
-						sbody[bodylen++]=LF;
-						col=0; } }
-				} } }
-
-	if(bodylen>=2 && sbody[bodylen-2]==CR && sbody[bodylen-1]==LF)
-		bodylen-=2; 						/* remove last CRLF if present */
-
-	for(l=0,crc=0xffffffff;l<bodylen;l++)
-		crc=ucrc32(sbody[l],crc);
-	crc=~crc;
-
-	j=smb_addcrc(status.max_crcs,crc,10);
-	if(j) {
-		if(j==1) {
-			printf("\nDuplicate message\n");
-			smb_freemsgmem(msg);
-			FREE(fbuf);
-			FREE(sbody);
-			FREE(stail);
-			continue; }
-		printf("smb_addcrc returned %d\n",j);
-        exit(1); }
-
-	while(taillen && stail[taillen-1]<=SP)	/* trim all garbage off the tail */
-		taillen--;
-
-	net=NET_FIDO;	/* Record origin address */
-	smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
-	smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr);
-
-	if(!orig) { 	/* No origin line means NetMail, so add dest addr */
-		smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
-		smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr); }
-
-	if(smb_open_da(10)) {
-		printf("error opening %s.SDA\n",smb_file);
-        exit(1); }
-	l=bodylen+2;
-	if(taillen)
-		l+=(taillen+2);
-	msg.hdr.offset=smb_fallocdat(l,1);
-	fclose(sda_fp);
-	if(msg.hdr.offset && msg.hdr.offset<1L) {
-		printf("error %ld allocating records\r\n",msg.hdr.offset);
-        exit(1); }
-	fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
-    xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,sdt_fp);
-	l=ftell(sdt_fp);
-	fwrite(sbody,SDT_BLOCK_LEN,smb_datblocks(bodylen),sdt_fp);
-	if(taillen) {
-		fseek(sdt_fp,l+bodylen,SEEK_SET);
-		fwrite(&xlat,2,1,sdt_fp);
-		fwrite(stail,SDT_BLOCK_LEN,smb_datblocks(taillen),sdt_fp); }
-	fflush(sdt_fp);
-	FREE(fbuf);
-	FREE(sbody);
-	FREE(stail);
-
-	smb_dfield(&msg,TEXT_BODY,bodylen+2);
-	if(taillen)
-		smb_dfield(&msg,TEXT_TAIL,taillen+2);
-
-	smb_addmsghdr(&msg,&status,1,10);
-	smb_freemsgmem(msg); }
-
-printf("\n%u messages converted.\n",found);
-return(0);
-}
-
diff --git a/src/sbbs2/smb/121a/fido2smb.mak b/src/sbbs2/smb/121a/fido2smb.mak
deleted file mode 100644
index 018d5792e571dfb762346262d47d811a2fff8992..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/fido2smb.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-###############################
-# Makefile for FIDO2SMB       #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= s
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-MAIN	= fido2smb.exe
-OBJS	= fido2smb.obj smblib.obj smbvars.obj
-HEADERS = smblib.h smbdefs.h crc32.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) 
-+ $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-fido2smb.obj:	$(HEADERS)
-smbvars.obj:    $(HEADERS)
-smblib.obj:     $(HEADERS)
diff --git a/src/sbbs2/smb/121a/file_id.diz b/src/sbbs2/smb/121a/file_id.diz
deleted file mode 100644
index be69095651638e4ab36f209e25fa0b20d95b59f5..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/file_id.diz
+++ /dev/null
@@ -1,10 +0,0 @@
-Synchronet Message Base Specification v1.21a
-Released 08/31/95. Designed for high volume,
-high speed, multi-network, multimedia e-mail
-storage and retrieval. Includes comprehensive
-95 page technical specification, 38 function
-royalty free C library, tons of C source code
-including conversion programs from QWK, Fido
-(FTSC-1), and Internet (RFC-822) messages.
-New: Hyper Allocation storage method and LZH
-compression/decompression functions.
diff --git a/src/sbbs2/smb/121a/fixsmb.c b/src/sbbs2/smb/121a/fixsmb.c
deleted file mode 100644
index cf522e0175b1913359a6cc9c8fee895c0de6e85a..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/fixsmb.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/* FIXSMB.C */
-
-/* Re-generates an SMB message base based on SHD and SDT files */
-
-#include "smblib.h"
-
-char *usage="usage: fixsmb [/opts] <smb_file>\n"
-			"\n"
-			" opts:\n"
-			"       m - force mail format instead of sub-board format\n"
-			"\n"
-			"   ex: FIXSMB /M MAIL\n"
-			"   or: FIXSMB DEBATE\n";
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-#define MAIL (1<<0)
-
-int main(int argc, char **argv)
-{
-	char		str[128],c;
-	int 		i,w,mode=0;
-	ulong		l,length,size,n,m;
-	smbmsg_t	msg;
-	smbstatus_t status;
-
-printf("\nFIXSMB v1.22 � Rebuild Synchronet Message Base � Copyright 1995 "
-	"Digital Dynamics\n");
-
-smb_file[0]=0;
-for(i=1;i<argc;i++)
-	if(argv[i][0]=='/')
-		switch(toupper(argv[i][1])) {
-			case 'M':
-				mode|=MAIL;
-				break;
-			default:
-				printf(usage);
-				exit(1); }
-	else
-		strcpy(smb_file,argv[i]);
-
-if(!smb_file[0]) {
-	printf(usage);
-	exit(1); }
-
-strupr(smb_file);
-
-if((i=smb_open(10))!=0) {
-	printf("smb_open returned %d\n",i);
-	exit(1); }
-
-if((i=smb_locksmbhdr(10))!=0) {
-	smb_close();
-	printf("smb_locksmbhdr returned %d\n",i);
-	exit(1); }
-
-if((i=smb_getstatus(&status))!=0) {
-	smb_unlocksmbhdr();
-	smb_close();
-	printf("smb_getstatus returned %d\n",i);
-	exit(1); }
-
-if(mode&MAIL && !(status.attr&SMB_EMAIL)) {
-	status.attr|=SMB_EMAIL;
-	if((i=smb_putstatus(status))!=0) {
-		smb_unlocksmbhdr();
-		smb_close();
-		printf("smb_putstatus returned %d\n",i);
-		exit(1); } }
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-
-	if((i=smb_open_ha(10))!=0) {
-		smb_close();
-		printf("smb_open_ha returned %d\n",i);
-		exit(1); }
-
-	if((i=smb_open_da(10))!=0) {
-		smb_close();
-		printf("smb_open_da returned %d\n",i);
-		exit(1); }
-
-	rewind(sha_fp);
-	chsize(fileno(sha_fp),0L);			/* Truncate the header allocation file */
-	rewind(sda_fp);
-	chsize(fileno(sda_fp),0L);			/* Truncate the data allocation file */
-	}
-
-rewind(sid_fp);
-chsize(fileno(sid_fp),0L);			/* Truncate the index */
-
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	length=filelength(fileno(sdt_fp));
-	w=0;
-	for(l=0;l<length;l+=SDT_BLOCK_LEN)	/* Init .SDA file to NULL */
-		fwrite(&w,2,1,sda_fp);
-
-	length=filelength(fileno(shd_fp));
-	c=0;
-	for(l=0;l<length;l+=SHD_BLOCK_LEN)	/* Init .SHD file to NULL */
-		fwrite(&c,1,1,sha_fp); }
-else
-	length=filelength(fileno(shd_fp));
-
-n=1;	/* messsage number */
-for(l=status.header_offset;l<length;l+=size) {
-	printf("\r%2u%%  ",(long)(100.0/((float)length/l)));
-	msg.idx.offset=l;
-	if((i=smb_lockmsghdr(msg,10))!=0) {
-		printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-		continue; }
-	if((i=smb_getmsghdr(&msg))!=0) {
-		smb_unlockmsghdr(msg);
-		printf("\n(%06lX) smb_getmsghdr returned %d\n",l,i);
-		size=SHD_BLOCK_LEN;
-		continue; }
-	smb_unlockmsghdr(msg);
-	printf("#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
-	if(!(msg.hdr.attr&MSG_DELETE)) {   /* Don't index deleted messages */
-		msg.offset=n-1;
-		msg.hdr.number=n;
-		msg.idx.number=n;
-		msg.idx.attr=msg.hdr.attr;
-		msg.idx.time=msg.hdr.when_imported.time;
-		strcpy(str,msg.subj);
-		strlwr(str);
-		remove_re(str);
-		msg.idx.subj=crc16(str);
-		if(status.attr&SMB_EMAIL) {
-			if(msg.to_ext)
-				msg.idx.to=atoi(msg.to_ext);
-			else
-				msg.idx.to=0;
-			if(msg.from_ext)
-				msg.idx.from=atoi(msg.from_ext);
-			else
-				msg.idx.from=0; }
-		else {
-			strcpy(str,msg.to);
-			strlwr(str);
-			msg.idx.to=crc16(str);
-			strcpy(str,msg.from);
-			strlwr(str);
-			msg.idx.from=crc16(str); }
-		if((i=smb_putmsg(msg))!=0) {
-			printf("\nsmb_putmsg returned %d\n",i);
-			continue; }
-		n++; }
-	else
-		printf("Not indexing deleted message\n");
-	size=smb_getmsghdrlen(msg);
-	while(size%SHD_BLOCK_LEN)
-		size++;
-
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		/**************************/
-		/* Allocate header blocks */
-		/**************************/
-		fseek(sha_fp,(l-status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-		if(msg.hdr.attr&MSG_DELETE) c=0;		/* mark as free */
-		else c=1;								/* or allocated */
-
-		for(i=0;i<size/SHD_BLOCK_LEN;i++)
-			fputc(c,sha_fp);
-
-		/************************/
-		/* Allocate data blocks */
-		/************************/
-
-		if(!(msg.hdr.attr&MSG_DELETE))
-			smb_incdat(msg.hdr.offset,smb_getmsgdatlen(msg),1);
-		}
-
-	smb_freemsgmem(msg); }
-printf("\nDone.\n");
-status.total_msgs=status.last_msg=n-1;
-if((i=smb_putstatus(status))!=0)
-	printf("\nsmb_putstatus returned %d\n",i);
-smb_unlocksmbhdr();
-smb_close();
-return(0);
-}
diff --git a/src/sbbs2/smb/121a/fixsmb.mak b/src/sbbs2/smb/121a/fixsmb.mak
deleted file mode 100644
index cdb9fbc2842a15dc746e5f89dc5512f80ae0c77a..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/fixsmb.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-###############################
-# Makefile for FIXSMB	      #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-MAIN	= fixsmb.exe
-OBJS	= $(MODEL)\fixsmb.obj $(MODEL)\smblib.obj $(MODEL)\smbvars.obj
-HEADERS = smblib.h smbdefs.h crc32.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(MODEL) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) 
-+ $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-$(MODEL)\fixsmb.obj:	$(HEADERS)
-$(MODEL)\smbvars.obj:    $(HEADERS)
-$(MODEL)\smblib.obj:     $(HEADERS)
diff --git a/src/sbbs2/smb/121a/inet2smb.c b/src/sbbs2/smb/121a/inet2smb.c
deleted file mode 100644
index beb692af1ed9347cff0bda4a9a6c60fb08d2ca58..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/inet2smb.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* Converts RFC #822 Internet Text Messages to SMB format */
-
-#include <dos.h>
-#include "smblib.h"
-
-/******************************************************************************
- Chops off the ":" and all spaces and tabs after it for the message headers
-******************************************************************************/
-char *header(char *instr)
-{
-	char str[256],*p;
-	int i=0;
-
-	p=strstr(instr,":");
-	++p;
-	while(*p==SP || *p==TAB)
-		++p;
-	while(i<strlen(p)) {
-		if(p[i]==LF || p[i]==CR) {
-			p[i]=0;
-			break; }
-		++i; }
-	return p;
-}
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/******************************************************************************
- Converts ASCII time in RFC 822 or RFC 1036 format to SMB when_t format
-******************************************************************************/
-when_t imsgtime(char *str)
-{
-	char month[25],zone[25],*p;
-	struct date date;
-	struct time t;
-	when_t when;
-
-when.zone=0;	/* Default to UT */
-
-if(isdigit(str[1])) {	/* Regular format: "01 Jan 86 0234 GMT" */
-	date.da_day=atoi(str);
-	sprintf(month,"%3.3s",str+3);
-	if(!stricmp(month,"jan"))
-		date.da_mon=1;
-	else if(!stricmp(month,"feb"))
-		date.da_mon=2;
-	else if(!stricmp(month,"mar"))
-		date.da_mon=3;
-	else if(!stricmp(month,"apr"))
-		date.da_mon=4;
-	else if(!stricmp(month,"may"))
-		date.da_mon=5;
-	else if(!stricmp(month,"jun"))
-		date.da_mon=6;
-	else if(!stricmp(month,"jul"))
-		date.da_mon=7;
-	else if(!stricmp(month,"aug"))
-		date.da_mon=8;
-	else if(!stricmp(month,"sep"))
-		date.da_mon=9;
-	else if(!stricmp(month,"oct"))
-		date.da_mon=10;
-	else if(!stricmp(month,"nov"))
-		date.da_mon=11;
-	else
-		date.da_mon=12;
-	date.da_year=1900+atoi(str+7);
-	t.ti_hour=atoi(str+10);
-	t.ti_min=atoi(str+12);
-	t.ti_sec=0;
-	p=str+13; }
-
-else {					/* USENET format: "Mon,  1 Jan 86 02:34:00 GMT" */
-	date.da_day=atoi(str+5);
-	sprintf(month,"%3.3s",str+8);
-	if(!stricmp(month,"jan"))
-		date.da_mon=1;
-	else if(!stricmp(month,"feb"))
-		date.da_mon=2;
-	else if(!stricmp(month,"mar"))
-		date.da_mon=3;
-	else if(!stricmp(month,"apr"))
-		date.da_mon=4;
-	else if(!stricmp(month,"may"))
-		date.da_mon=5;
-	else if(!stricmp(month,"jun"))
-		date.da_mon=6;
-	else if(!stricmp(month,"jul"))
-		date.da_mon=7;
-	else if(!stricmp(month,"aug"))
-		date.da_mon=8;
-	else if(!stricmp(month,"sep"))
-		date.da_mon=9;
-	else if(!stricmp(month,"oct"))
-		date.da_mon=10;
-	else if(!stricmp(month,"nov"))
-		date.da_mon=11;
-	else
-		date.da_mon=12;
-	date.da_year=atoi(str+12);
-	if(date.da_year<100)
-		date.da_year+=1900;
-    p=str+12;
-	while(*p!=SP) p++;	/* skip the year */
-	while(*p==SP) p++;	/* and white space */
-	t.ti_hour=atoi(p);
-	t.ti_min=atoi(p+3);
-	t.ti_sec=atoi(p+6);
-	p=str+22; }
-
-when.time=dostounix(&date,&t);
-
-while(*p!=SP) p++;	/* skip the time */
-while(*p==SP) p++;	/* and white space */
-
-sprintf(zone,"%-.5s",p);
-
-/* Get the zone */
-if(!strcmpi(zone,"GMT") || !strcmpi(zone,"UT"))
-	when.zone=0;
-else if(!strcmpi(zone,"EST"))
-	when.zone=EST;
-else if(!strcmpi(zone,"EDT"))
-	when.zone=EDT;
-else if(!strcmpi(zone,"MST"))
-	when.zone=MST;
-else if(!strcmpi(zone,"MDT"))
-	when.zone=MDT;
-else if(!strcmpi(zone,"CST"))
-	when.zone=CST;
-else if(!strcmpi(zone,"CDT"))
-	when.zone=CDT;
-else if(!strcmpi(zone,"PST"))
-	when.zone=PST;
-else if(!strcmpi(zone,"PDT"))
-	when.zone=PDT;
-
-else if(isalpha(zone[0]) && !zone[1]) { /* Military single character zone */
-	zone[0]&=0xdf;	/* convert to upper case */
-	if(zone[0]>='A' && zone[0]<='I')
-		when.zone='@'-zone[0];
-	else if(zone[0]>='K' && zone[0]<='M')   /* J is not used */
-		when.zone='A'-zone[0];
-	else if(zone[0]>='N' && zone[0]<='Y')
-		when.zone=zone[0]-'M'; }
-
-else if((zone[0]=='+' || zone[0]=='-') && isdigit(zone[1])) { /* Literal */
-	when.zone=(((zone[1]&0xf)*10)+(zone[2]&0xf))*60;	/* Hours */
-	when.zone+=atoi(zone+3);							/* Minutes */
-	if(zone[0]=='-')                                    /* Negative? */
-		when.zone=-when.zone; }
-
-return(when);
-}
-
-void main(int argc, char **argv)
-{
-	FILE *stream;
-	char str[256]={NULL},filespec[256],file[256],*p,*abuf;
-	ushort i,xlat,net;
-	ulong l,length,datlen;
-	struct ffblk ff;
-	smbmsg_t	msg;
-    smbstatus_t status;
-
-	if(argc<2) {
-		printf("Usage: INET2SMB <file_spec> <smb_name>\r\n");
-		exit(1); }
-
-	strcpy(filespec,argv[1]);
-	strcpy(smb_file,argv[2]);
-	strupr(smb_file);
-
-	smb_open(10);
-	if(!filelength(fileno(shd_fp)))
-		smb_create(2000,2000,0,0,10);
-
-	i=findfirst(filespec,&ff,0);
-	while(!i) {
-		sprintf(file,"%s",ff.ff_name);
-		if((stream=fopen(file,"rb"))==NULL) {
-			printf("Error opening %s\r\n",file);
-			break; }
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=SMB_VERSION;
-		msg.hdr.when_imported.time=time(NULL);
-		msg.hdr.when_imported.zone=PST;  /* set to local time zone */
-
-		while(str[0]!=CR && str[0]!=LF) {
-			fgets(str,81,stream);
-			if(!strnicmp(str,"Resent-",6)) {
-				p=strstr(str,"Resent-");
-				sprintf(str,"%s",p); }
-			if(!strnicmp(str,"Return-Path",11)
-				|| !strnicmp(str,"Path",4)) {
-				strcpy(str,header(str));
-				smb_hfield(&msg,REPLYTO,strlen(str),str); }
-			else if(!strnicmp(str,"Date",4)) {
-				strcpy(str,header(str));
-				msg.hdr.when_written=imsgtime(str); }
-			else if(!strnicmp(str,"From",4) || !strnicmp(str,"Sender",6)) {
-				strcpy(str,header(str));
-				p=strstr(str," (");
-				if(p) {
-					*p=0;
-					*(p+1)=0;
-					p+=2;
-					smb_hfield(&msg,SENDERNETADDR,strlen(str),str);
-					sprintf(str,"%s",p);
-					p=strstr(str,")");
-					*p=0; }
-				smb_hfield(&msg,SENDER,strlen(str),str);
-				strlwr(str);
-				msg.idx.from=crc16(str); }
-			else if(!strnicmp(str,"Subject",7)) {
-				strcpy(str,header(str));
-				smb_hfield(&msg,SUBJECT,strlen(str),str);
-				strlwr(str);
-				msg.idx.subj=crc16(str); }
-			else if(!strnicmp(str,"To",2)) {
-				strcpy(str,header(str));
-				smb_hfield(&msg,RECIPIENT,strlen(str),str);
-				strlwr(str);
-				msg.idx.to=crc16(str); }
-
-			/* Following are optional fields */
-
-			else if(!strnicmp(str,"Message-ID",10)) {
-				strcpy(str,header(str));
-				smb_hfield(&msg,RFC822MSGID,strlen(str),str); }
-			else if(!strnicmp(str,"In-Reply-To",11)) {
-				strcpy(str,header(str));
-				smb_hfield(&msg,RFC822REPLYID,strlen(str),str); }
-
-			/* User defined extension field */
-
-			else if(!strnicmp(str,"X-",2)) {
-				if(strstr(str,"To")) {
-					strcpy(str,header(str));
-					smb_hfield(&msg,RECIPIENT,strlen(str),str);
-					strlwr(str);
-					msg.idx.to=crc16(str); }
-				else
-					smb_hfield(&msg,RFC822HEADER,strlen(str),str); }
-			else
-				smb_hfield(&msg,RFC822HEADER,strlen(str),str); }
-
-		l=ftell(stream);
-		fseek(stream,0L,SEEK_END);
-		length=ftell(stream)-l;
-		fseek(stream,l,SEEK_SET);
-
-		if((abuf=(char *)MALLOC(length))==NULL) {
-			printf("alloc error\n");
-			exit(1); }
-		fread(abuf,length,1,stream);
-		fclose(stream);
-
-		net=NET_INTERNET;
-		smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
-
-		if(smb_open_da(10)) {
-			printf("error opening %s.SDA\n",smb_file);
-			exit(1); }
-		msg.hdr.offset=smb_fallocdat(length+2,1);
-		fclose(sda_fp);
-		if(msg.hdr.offset && msg.hdr.offset<1L) {
-			printf("error %ld allocating records\r\n",msg.hdr.offset);
-			exit(1); }
-		fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,sdt_fp);
-		fwrite(abuf,SDT_BLOCK_LEN,smb_datblocks(length),sdt_fp);
-		FREE(abuf);
-		fflush(sdt_fp);
-
-		smb_dfield(&msg,TEXT_BODY,length+2);
-
-		smb_addmsghdr(&msg,&status,1,10);
-		smb_freemsgmem(msg);
-		i=findnext(&ff); }
-}
diff --git a/src/sbbs2/smb/121a/inet2smb.mak b/src/sbbs2/smb/121a/inet2smb.mak
deleted file mode 100644
index 682933f6361aaaa3a6faa28b52d098a7adc6922d..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/inet2smb.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-###############################
-# Makefile for INET2SMB       #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= s
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-MAIN	= inet2smb.exe
-OBJS	= inet2smb.obj smblib.obj smbvars.obj
-HEADERS = smblib.h smbdefs.h crc32.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) 
-+ $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-inet2smb.obj:	$(HEADERS)
-smbvars.obj:    $(HEADERS)
-smblib.obj:     $(HEADERS)
diff --git a/src/sbbs2/smb/121a/lzh.c b/src/sbbs2/smb/121a/lzh.c
deleted file mode 100644
index 2d21e4d55f31cdbac167a0d9f772f5d0d7d7ddbe..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/lzh.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/* LZH.C */
-
-/* Digital Dynamics conversion of 1988 LZH (LHarc) encoding functions	*/
-/* Based on Japanese version 29-NOV-1988								*/
-/* LZSS coded by Haruhiko Okumura										*/
-/* Adaptive Huffman Coding coded by Haruyasu Yoshizaki					*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifndef __WATCOMC__
-	#include <alloc.h>
-#endif
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-	#if defined(__TURBOC__)
-		#define REALLOC(x,y) farrealloc(x,y)
-		#define LMALLOC(x) farmalloc(x)
-		#define MALLOC(x) farmalloc(x)
-		#define LFREE(x) farfree(x)
-		#define FREE(x) farfree(x)
-	#elif defined(__WATCOMC__)
-		#define REALLOC realloc
-		#define LMALLOC(x) halloc(x,1)	/* far heap, but slow */
-		#define MALLOC malloc			/* far heap, but 64k max */
-		#define LFREE hfree
-		#define FREE free
-	#else	/* Other 16-bit Compiler */
-		#define REALLOC realloc
-		#define LMALLOC malloc
-		#define MALLOC malloc
-		#define LFREE free
-		#define FREE free
-	#endif
-#else		/* 32-bit Compiler or Small Memory Model */
-	#define REALLOC realloc
-	#define LMALLOC malloc
-	#define MALLOC malloc
-	#define LFREE free
-	#define FREE free
-#endif
-
-
-
-typedef unsigned char uchar;
-
-/* LZSS Parameters */
-
-#define LZH_N			4096	/* Size of string buffer */
-#define LZH_F			60		/* Size of look-ahead buffer */
-#define LZH_THRESHOLD	2
-#define LZH_NIL 		LZH_N	/* End of tree's node  */
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned char *lzh_text_buf;
-short int	lzh_match_position, lzh_match_length,
-	  *lzh_lson, *lzh_rson, *lzh_dad;
-
-#else
-
-unsigned char lzh_text_buf[LZH_N + LZH_F - 1];
-short int	  lzh_match_position, lzh_match_length,
-		lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
-
-#endif
-
-
-void lzh_init_tree(void)  /* Initializing tree */
-{
-	short int  i;
-
-	for (i = LZH_N + 1; i <= LZH_N + 256; i++)
-		lzh_rson[i] = LZH_NIL;			/* root */
-	for (i = 0; i < LZH_N; i++)
-		lzh_dad[i] = LZH_NIL;			/* node */
-}
-
-/******************************/
-/* Inserting node to the tree */
-/* Only used during encoding  */
-/******************************/
-void lzh_insert_node(short int r)
-{
-	short int  i, p, cmp;
-	unsigned char  *key;
-	unsigned c;
-
-	cmp = 1;
-	key = lzh_text_buf+r;
-	p = LZH_N + 1 + key[0];
-	lzh_rson[r] = lzh_lson[r] = LZH_NIL;
-	lzh_match_length = 0;
-	for ( ; ; ) {
-		if (cmp >= 0) {
-			if (lzh_rson[p] != LZH_NIL)
-				p = lzh_rson[p];
-			else {
-				lzh_rson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		} else {
-			if (lzh_lson[p] != LZH_NIL)
-				p = lzh_lson[p];
-			else {
-				lzh_lson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		}
-		for (i = 1; i < LZH_F; i++)
-			if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
-				break;
-		if (i > LZH_THRESHOLD) {
-			if (i > lzh_match_length) {
-				lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
-				if ((lzh_match_length = i) >= LZH_F)
-					break;
-			}
-			if (i == lzh_match_length) {
-				if ((c = ((r - p) & (LZH_N - 1)) - 1) < lzh_match_position) {
-					lzh_match_position = c;
-				}
-			}
-		}
-	}
-	lzh_dad[r] = lzh_dad[p];
-	lzh_lson[r] = lzh_lson[p];
-	lzh_rson[r] = lzh_rson[p];
-	lzh_dad[lzh_lson[p]] = r;
-	lzh_dad[lzh_rson[p]] = r;
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = r;
-	else
-		lzh_lson[lzh_dad[p]] = r;
-	lzh_dad[p] = LZH_NIL;  /* remove p */
-}
-
-void lzh_delete_node(short int p)  /* Deleting node from the tree */
-{
-	short int  q;
-
-	if (lzh_dad[p] == LZH_NIL)
-		return;			/* unregistered */
-	if (lzh_rson[p] == LZH_NIL)
-		q = lzh_lson[p];
-	else
-	if (lzh_lson[p] == LZH_NIL)
-		q = lzh_rson[p];
-	else {
-		q = lzh_lson[p];
-		if (lzh_rson[q] != LZH_NIL) {
-			do {
-				q = lzh_rson[q];
-			} while (lzh_rson[q] != LZH_NIL);
-			lzh_rson[lzh_dad[q]] = lzh_lson[q];
-			lzh_dad[lzh_lson[q]] = lzh_dad[q];
-			lzh_lson[q] = lzh_lson[p];
-			lzh_dad[lzh_lson[p]] = q;
-		}
-		lzh_rson[q] = lzh_rson[p];
-		lzh_dad[lzh_rson[p]] = q;
-	}
-	lzh_dad[q] = lzh_dad[p];
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = q;
-	else
-		lzh_lson[lzh_dad[p]] = q;
-	lzh_dad[p] = LZH_NIL;
-}
-
-/* Huffman coding parameters */
-
-#define LZH_N_CHAR		(256 - LZH_THRESHOLD + LZH_F)
-					/* character code (= 0..LZH_N_CHAR-1) */
-#define LZH_T		(LZH_N_CHAR * 2 - 1)	/* Size of table */
-#define LZH_R		(LZH_T - 1) 		/* root position */
-#define MAX_FREQ	0x8000
-					/* update when cumulative frequency */
-					/* reaches to this value */
-
-/*
- * Tables for encoding/decoding upper 6 bits of
- * sliding dictionary pointer
- */
-/* encoder table */
-uchar lzh_p_len[64] = {
-	0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-uchar lzh_p_code[64] = {
-	0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
-	0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
-	0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
-	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
-	0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
-	0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
-	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
-};
-
-/* decoder table */
-uchar lzh_d_code[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
-	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
-	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
-	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
-	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
-	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
-	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
-	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
-	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
-	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
-	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
-	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
-	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
-	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
-};
-
-uchar lzh_d_len[256] = {
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-};
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned short *lzh_freq=NULL;	 /* cumulative freq table */
-
-/*
- * pointing parent nodes.
- * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
- */
-short int *lzh_prnt=NULL;
-
-/* pointing children nodes (son[], son[] + 1)*/
-short int *lzh_son=NULL;
-
-#else	/* STATIC */
-
-unsigned short lzh_freq[LZH_T + 1];   /* cumulative freq table */
-short int lzh_prnt[LZH_T + LZH_N_CHAR];
-short int lzh_son[LZH_T + 1];		  /* bug fixed by Digital Dynamics */
-
-#endif
-
-
-unsigned short lzh_getbuf = 0;		/* Was just "unsigned" fixed 04/12/95 */
-uchar lzh_getlen = 0;
-
-int lzh_getbit(uchar *inbuf, long *incnt, long inlen)    /* get one bit */
-{
-	short int i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 1;
-	lzh_getlen--;
-	return (i < 0);
-}
-
-short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen)   /* get a byte */
-{
-	unsigned short i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 8;
-	lzh_getlen -= 8;
-	return i >> 8;
-}
-
-unsigned lzh_putbuf = 0;
-uchar lzh_putlen = 0;
-
-/* output c bits */
-void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen)
-{
-	lzh_putbuf |= c >> lzh_putlen;
-	if ((lzh_putlen += l) >= 8) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-		if ((lzh_putlen -= 8) >= 8) {
-			outbuf[(*outlen)++]=lzh_putbuf;
-			lzh_putlen -= 8;
-			lzh_putbuf = c << (l - lzh_putlen);
-		} else {
-			lzh_putbuf <<= 8;
-		}
-	}
-}
-
-
-/* initialize freq tree */
-
-void lzh_start_huff()
-{
-	short int i, j;
-
-lzh_getbuf = 0; 	/* Added by Digital Dynamics for repeating operations */
-lzh_getlen = 0;
-lzh_putbuf = 0;
-lzh_putlen = 0;
-
-	for (i = 0; i < LZH_N_CHAR; i++) {
-		lzh_freq[i] = 1;
-		lzh_son[i] = i + LZH_T;
-		lzh_prnt[i + LZH_T] = i;
-	}
-	i = 0; j = LZH_N_CHAR;
-	while (j <= LZH_R) {
-		lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
-		lzh_son[j] = i;
-		lzh_prnt[i] = lzh_prnt[i + 1] = j;
-		i += 2; j++;
-	}
-	lzh_freq[LZH_T] = 0xffff;
-    lzh_prnt[LZH_R] = 0;
-}
-
-
-/* reconstruct freq tree */
-
-void lzh_reconst()
-{
-	short int i, j, k;
-	unsigned short f, l;
-
-	/* halven cumulative freq for leaf nodes */
-	j = 0;
-	for (i = 0; i < LZH_T; i++) {
-		if (lzh_son[i] >= LZH_T) {
-			lzh_freq[j] = (lzh_freq[i] + 1) / 2;
-			lzh_son[j] = lzh_son[i];
-			j++;
-		}
-	}
-	/* make a tree : first, connect children nodes */
-	for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
-		k = i + 1;
-		f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
-		for (k = j - 1; f < lzh_freq[k]; k--);
-		k++;
-		l = (j - k) * 2;
-		
-		/* movmem() is Turbo-C dependent
-		   rewritten to memmove() by Kenji */
-		
-		/* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
-		(void)memmove(lzh_freq+k+1,lzh_freq+k, l);
-		lzh_freq[k] = f;
-		/* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
-		(void)memmove(lzh_son+k+1,lzh_son+k, l);
-		lzh_son[k] = i;
-	}
-	/* connect parent nodes */
-	for (i = 0; i < LZH_T; i++) {
-		if ((k = lzh_son[i]) >= LZH_T) {
-			lzh_prnt[k] = i;
-		} else {
-			lzh_prnt[k] = lzh_prnt[k + 1] = i;
-		}
-	}
-}
-
-/* update freq tree */
-
-void lzh_update(short int c)
-{
-	short int i, j, k, l;
-
-	if (lzh_freq[LZH_R] == MAX_FREQ) {
-		lzh_reconst();
-	}
-	c = lzh_prnt[c + LZH_T];
-	do {
-		k = ++lzh_freq[c];
-
-		/* swap nodes to keep the tree freq-ordered */
-		if (k > lzh_freq[l = c + 1]) {
-			while (k > lzh_freq[++l]);
-			l--;
-			lzh_freq[c] = lzh_freq[l];
-			lzh_freq[l] = k;
-
-			i = lzh_son[c];
-			lzh_prnt[i] = l;
-			if (i < LZH_T) lzh_prnt[i + 1] = l;
-
-			j = lzh_son[l];
-			lzh_son[l] = i;
-
-			lzh_prnt[j] = c;
-			if (j < LZH_T) lzh_prnt[j + 1] = c;
-			lzh_son[c] = j;
-
-			c = l;
-		}
-	} while ((c = lzh_prnt[c]) != 0);	/* do it until reaching the root */
-}
-
-unsigned short lzh_code, lzh_len;
-
-void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-	short int j, k;
-
-	i = 0;
-	j = 0;
-	k = lzh_prnt[c + LZH_T];
-
-	/* search connections from leaf node to the root */
-	do {
-		i >>= 1;
-
-		/*
-		if node's address is odd, output 1
-		else output 0
-		*/
-		if (k & 1) i += 0x8000;
-
-		j++;
-	} while ((k = lzh_prnt[k]) != LZH_R);
-	lzh_putcode(j, i, outbuf, outlen);
-	lzh_code = i;
-	lzh_len = j;
-	lzh_update(c);
-}
-
-void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-
-	/* output upper 6 bits with encoding */
-	i = c >> 6;
-	lzh_putcode(lzh_p_len[i], (unsigned)lzh_p_code[i] << 8, outbuf, outlen);
-
-	/* output lower 6 bits directly */
-	lzh_putcode(6, (c & 0x3f) << 10, outbuf, outlen);
-}
-
-void lzh_encode_end(uchar *outbuf, long *outlen)
-{
-	if (lzh_putlen) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-	}
-}
-
-short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short c;
-
-	c = lzh_son[LZH_R];
-
-	/*
-	 * start searching tree from the root to leaves.
-	 * choose node #(lzh_son[]) if input bit == 0
-	 * else choose #(lzh_son[]+1) (input bit == 1)
-	 */
-	while (c < LZH_T) {
-		c += lzh_getbit(inbuf,incnt,inlen);
-		c = lzh_son[c];
-	}
-	c -= LZH_T;
-	lzh_update(c);
-	return c;
-}
-
-short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short i, j, c;
-
-	/* decode upper 6 bits from given table */
-	i = lzh_getbyte(inbuf,incnt,inlen);
-	c = (unsigned)lzh_d_code[i] << 6;
-	j = lzh_d_len[i];
-
-	/* input lower 6 bits directly */
-	j -= 2;
-	while (j--) {
-		i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
-	}
-	return c | i & 0x3f;
-}
-
-/* Compression */
-
-/* Encoding/Compressing */
-/* Returns length of outbuf */
-long lzh_encode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, c, len, r, s, last_match_length;
-	long incnt,outlen; /* textsize=0; */
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		return(-1); }
-	if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		FREE(lzh_lson);
-		return(-1); }
-	if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-		FREE(lzh_rson);
-		return(-1); }
-#endif
-
-	incnt=0;
-	memcpy(outbuf,&inlen,sizeof(inlen));
-	outlen=sizeof(inlen);
-	if(!inlen) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-        FREE(lzh_rson);
-		FREE(lzh_dad);
-#endif
-		return(outlen); }
-	lzh_start_huff();
-	lzh_init_tree();
-	s = 0;
-	r = LZH_N - LZH_F;
-	for (i = s; i < r; i++)
-		lzh_text_buf[i] = ' ';
-	for (len = 0; len < LZH_F && incnt<inlen; len++)
-		lzh_text_buf[r + len] = inbuf[incnt++];
-	/* textsize = len; */
-	for (i = 1; i <= LZH_F; i++)
-		lzh_insert_node(r - i);
-	lzh_insert_node(r);
-	do {
-		if (lzh_match_length > len)
-			lzh_match_length = len;
-		if (lzh_match_length <= LZH_THRESHOLD) {
-			lzh_match_length = 1;
-			lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
-		} else {
-			lzh_encode_char(255 - LZH_THRESHOLD + lzh_match_length
-				,outbuf,&outlen);
-			lzh_encode_position(lzh_match_position
-				,outbuf,&outlen);
-		}
-		last_match_length = lzh_match_length;
-		for (i = 0; i < last_match_length && incnt<inlen; i++) {
-			lzh_delete_node(s);
-			c=inbuf[incnt++];
-			lzh_text_buf[s] = c;
-			if (s < LZH_F - 1)
-				lzh_text_buf[s + LZH_N] = c;
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			lzh_insert_node(r);
-		}
-/***
-		if ((textsize += i) > printcount) {
-			printf("%12ld\r", textsize);
-			printcount += 1024;
-		}
-***/
-		while (i++ < last_match_length) {
-			lzh_delete_node(s);
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			if (--len) lzh_insert_node(r);
-		}
-	} while (len > 0);
-	lzh_encode_end(outbuf,&outlen);
-/*
-	printf("input: %ld (%ld) bytes\n", inlen,textsize);
-	printf("output: %ld bytes\n", outlen);
-	printf("output/input: %.3f\n", (double)outlen / inlen);
-*/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-	FREE(lzh_lson);
-	FREE(lzh_rson);
-	FREE(lzh_dad);
-#endif
-
-	return(outlen);
-}
-
-/* Decoding/Uncompressing */
-/* Returns length of outbuf */
-long lzh_decode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, j, k, r, c;
-	unsigned long int  count;
-	long incnt,textsize;
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short)))
-		==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-
-#endif
-
-	incnt=0;
-	memcpy(&textsize,inbuf,sizeof(textsize));
-	incnt+=sizeof(textsize);
-	if (textsize == 0) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-#endif
-		return(textsize); }
-	lzh_start_huff();
-	for (i = 0; i < LZH_N - LZH_F; i++)
-		*(lzh_text_buf+i) = ' ';
-	r = LZH_N - LZH_F;
-    for (count = 0; count < textsize; ) {
-		c = lzh_decode_char(inbuf,&incnt,inlen);
-		if (c < 256) {
-			outbuf[count]=c;
-#if 0
-			if(r>(LZH_N + LZH_F - 1) || r<0) {
-				printf("Overflow! (%d)\n",r);
-				getch();
-				exit(-1); }
-#endif
-			*(lzh_text_buf+r) = c;
-			r++;
-			r &= (LZH_N - 1);
-			count++;
-		} else {
-			i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
-				& (LZH_N - 1);
-			j = c - 255 + LZH_THRESHOLD;
-			for (k = 0; k < j && count<textsize; k++) {
-				c = lzh_text_buf[(i + k) & (LZH_N - 1)];
-				outbuf[count]=c;
-#if 0
-				if(r>(LZH_N + LZH_F - 1) || r<0) {
-					printf("Overflow! (%d)\n",r);
-					exit(-1); }
-#endif
-				*(lzh_text_buf+r) = c;
-				r++;
-				r &= (LZH_N - 1);
-				count++;
-			}
-		}
-	}
-/***
-	printf("%12ld\n", count);
-***/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-#endif
-
-return(count);
-}
-
-
diff --git a/src/sbbs2/smb/121a/lzh.h b/src/sbbs2/smb/121a/lzh.h
deleted file mode 100644
index 68a71dd90c338ec888128735e99829fefdb02856..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/lzh.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* LZH.H */
-
-long lzh_encode(uchar *inbuf, long inlen, uchar *outbuf);
-long lzh_decode(uchar *inbuf, long inlen, uchar *outbuf);
-
diff --git a/src/sbbs2/smb/121a/qwk2smb.c b/src/sbbs2/smb/121a/qwk2smb.c
deleted file mode 100644
index acf65074c7ddb92dfe6dfe7e89fb8aa1643535cc..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/qwk2smb.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* QWK2SMB.C */
-
-/* Converts QWK packet to to SMB formatted message bases */
-
-/* The intention of this source code is an example of how to use the SMBLIB */
-/* library functions to access an SMB format message base.					*/
-
-/* This program and source code are freeware. May be used in part or whole	*/
-/* for any purpose without consent or notification of Digital Dynamics. 	*/
-
-/* Digital Dynamics does request that developers that release products that */
-/* support the SMB format notify Digital Dynamics so the implementation 	*/
-/* and contact chapters in the technical specification may be updated.		*/
-
-#include "smblib.h"
-#include "crc32.h"
-#include <dos.h>
-
-char sbbs[128];
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=' ') c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(f.ff_fsize);
-return(-1L);
-}
-
-/****************************************************************************/
-/* Returns the FidoNet address kept in str as ASCII.                        */
-/****************************************************************************/
-fidoaddr_t atofaddr(char *str)
-{
-    char *p;
-	fidoaddr_t addr;
-
-addr.zone=addr.net=addr.node=addr.point=0;
-if((p=strchr(str,':'))!=NULL) {
-	addr.zone=atoi(str);
-	addr.net=atoi(p+1); }
-else {
-	addr.zone=1;
-	addr.net=atoi(str); }
-if(!addr.zone)				/* no such thing as zone 0 */
-	addr.zone=1;
-if((p=strchr(str,'/'))!=NULL)
-    addr.node=atoi(p+1);
-else {
-	addr.net=1;
-	addr.node=atoi(str); }
-if((p=strchr(str,'.'))!=NULL)
-    addr.point=atoi(p+1);
-return(addr);
-}
-
-
-int main(int argc, char **argv)
-{
-	uchar	*p,str[128],from[128],to[128],subj[128],block[128],*buf;
-	ushort	xlat;
-	ushort	i,j,k,msgs,total;
-	ulong	l,m,length,size,crc;
-	FILE	*qwk;
-	struct	date date;
-	struct	time curtime;
-	smbmsg_t	msg;
-	smbstatus_t status;
-
-if(argc<2) {
-	printf("usage: qwk2smb <qwk_dir>\r\n");
-	exit(1); }
-
-sprintf(str,"%s\\MESSAGES.DAT",argv[1]);
-if((qwk=fopen(str,"rb"))==NULL) {
-	printf("error opening %s\n",str);
-	exit(1); }
-
-size=filelength(fileno(qwk));
-smb_file[0]=0;
-
-for(l=128,i=1,msgs=total=1;l<size;l+=i*128) {
-	fseek(qwk,l,SEEK_SET);
-	if(!fread(block,1,128,qwk))
-		break;
-	i=atoi(block+116);	/* i = number of 128 byte records */
-	if(i<2) {
-		i=1;
-		continue; }
-
-	j=(ushort)block[123]|(((ushort)block[124])<<8);  /* conference number */
-
-	if(strcmp(smb_file,itoa(j,str,10))) {		 /* changed conference */
-		fclose(sdt_fp);
-		fclose(shd_fp);
-		fclose(sid_fp);
-		strcpy(smb_file,str);
-		printf("\nConference #%s\n",str);
-		msgs=1;
-		k=smb_open(10);
-		if(k) {
-			printf("smb_open returned %d\n",k);
-			exit(1); }
-		if(!filelength(fileno(shd_fp))) 		/* new conference */
-			smb_create(2000,2000,0,0,10); }
-
-	smb_getstatus(&status); 	  // Initialized for first call to smb_addcrc()
-
-	printf("%u (total=%u)\r",msgs,total);
-
-	/*****************************/
-	/* Initialize the SMB header */
-	/*****************************/
-
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=SMB_VERSION;
-
-	/**************************/
-	/* Convert the QWK header */
-	/**************************/
-
-	if(block[0]=='*' || block[0]=='+')
-		msg.idx.attr|=MSG_PRIVATE;
-	if(block[0]=='*' || block[0]=='-' || block[0]=='`')
-		msg.idx.attr|=MSG_READ;
-    msg.hdr.attr=msg.idx.attr;
-
-	date.da_mon=((block[8]&0xf)*10)+(block[9]&0xf);
-	date.da_day=((block[11]&0xf)*10)+(block[12]&0xf);
-	date.da_year=((block[14]&0xf)*10)+(block[15]&0xf)+1900;
-	curtime.ti_hour=((block[16]&0xf)*10)+(block[17]&0xf);
-	curtime.ti_min=((block[19]&0xf)*10)+(block[20]&0xf);
-	curtime.ti_sec=0;
-	msg.hdr.when_written.time=dostounix(&date,&curtime);
-	msg.hdr.when_written.zone=PST;		 /* set to local time zone */
-	msg.hdr.when_imported.time=time(NULL);
-	msg.hdr.when_imported.zone=PST; 	 /* set to local time zone */
-
-	sprintf(to,"%25.25s",block+21);     /* To user */
-    truncsp(to);
-    smb_hfield(&msg,RECIPIENT,strlen(to),to);
-    strlwr(to);
-    msg.idx.to=crc16(to);
-
-	sprintf(from,"%25.25s",block+46);   /* From user */
-    truncsp(from);
-    smb_hfield(&msg,SENDER,strlen(from),from);
-    strlwr(from);
-    msg.idx.from=crc16(from);
-
-	sprintf(subj,"%25.25s",block+71);   /* Subject */
-	truncsp(subj);
-	smb_hfield(&msg,SUBJECT,strlen(subj),subj);
-	strlwr(subj);
-    msg.idx.subj=crc16(subj);
-
-	/********************************/
-	/* Convert the QWK message text */
-	/********************************/
-
-	length=0;
-	if((buf=MALLOC((i-1)*128*2))==NULL) {
-		printf("memory allocation error\n");
-		exit(1); }
-	for(j=1;j<i;j++) {
-		if(!fread(block,1,128,qwk))
-			break;
-		for(k=0;k<128;k++) {
-			if(block[k]==0)
-				continue;
-			if(block[k]==0xE3) {	   /* expand 0xe3 to crlf */
-				buf[length++]=CR;
-				buf[length++]=LF;
-				continue; }
-			buf[length++]=block[k]; } }
-
-	while(length && buf[length-1]<=SP) length--; /* remove trailing garbage */
-
-	/*****************/
-	/* Calculate CRC */
-	/*****************/
-
-	crc=0xffffffffUL;
-	for(m=0;m<length;m++)
-		crc=ucrc32(buf[m],crc);
-	crc=~crc;
-
-	/*******************/
-	/* Check for dupes */
-	/*******************/
-
-	j=smb_addcrc(status.max_crcs,crc,10);
-    if(j) {
-        if(j==1) {
-            printf("\nDuplicate message\n");
-            smb_freemsgmem(msg);
-			FREE(buf);
-            continue; }
-        printf("smb_addcrc returned %d\n",j);
-        exit(1); }
-
-	/*************************************/
-	/* Write SMB message header and text */
-	/*************************************/
-
-	length+=2;	/* for translation string */
-
-	if(smb_open_da(10)) {
-		printf("error opening %s.SDA\n",smb_file);
-		exit(1); }
-	msg.hdr.offset=smb_fallocdat(length,1);
-	fclose(sda_fp);
-	if(msg.hdr.offset && msg.hdr.offset<1L) {
-		printf("error %ld allocating blocks\r\n",msg.hdr.offset);
-		exit(1); }
-	fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
-    xlat=XLAT_NONE;
-    fwrite(&xlat,2,1,sdt_fp);
-	fwrite(buf,length,1,sdt_fp);
-	fflush(sdt_fp);
-
-	smb_dfield(&msg,TEXT_BODY,length);
-
-	k=smb_addmsghdr(&msg,&status,1,10);
-	if(k) {
-		printf("smb_addmsghdr returned %d\n",k);
-		exit(1); }
-	smb_freemsgmem(msg);
-	FREE(buf);
-	msgs++;
-	total++; }
-
-return(0);
-}
-
diff --git a/src/sbbs2/smb/121a/qwk2smb.mak b/src/sbbs2/smb/121a/qwk2smb.mak
deleted file mode 100644
index 242f1111d2042eb65834fa8886c5b0444d5abdd5..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/qwk2smb.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-###############################
-# Makefile for QWK2SMB	      #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= s
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS	= -n -c
-MAIN	= qwk2smb.exe
-OBJS	= qwk2smb.obj smblib.obj smbvars.obj
-HEADERS = smblib.h smbdefs.h crc32.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) 
-+ $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-qwk2smb.obj:	$(HEADERS)
-smbvars.obj:    $(HEADERS)
-smblib.obj:     $(HEADERS)
diff --git a/src/sbbs2/smb/121a/smb.hst b/src/sbbs2/smb/121a/smb.hst
deleted file mode 100644
index 24472860e60c0574d9ce59113ec89eff99d2c421..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smb.hst
+++ /dev/null
@@ -1,303 +0,0 @@
-Synchronet Message Base Specification Modification History
-==========================================================
-
-******************************
-01/20/94 Initial Release v1.00
-******************************
-
-Quite a few spelling errors in SMB.TXT corrected.
-
-Estimated maximum number of messages (in Introduction of SMB.TXT) formula
-corrected (1500 rounded to nearest 256 is 1536, not 2048).
-
-Pages 32 and 38 (SENDEREXT and RECIPIENTEXT header field types) incorrectly
-stated the index record contains CRC-32s, when in fact the index contains
-CRC-16s of the agent names or extensions.
-
-FORWARDTO header field types incorrectly stated they were for replies, rather
-than forwarding instructions.
-
-Trigger header field types incorrectly stated they were "attachments" rather
-than triggers.
-
-Bug fixed in smb_open() function in smblib.c: was allocating buffer via
-setvbuf for wrong file pointer when opening header file. Caused loss of 
-memory (2k) everytime smb_open() was called.
-
-Bug fixed in smb_getmsghdr() function in smblib.c: msg->from_agent,to_agent,
-and replyto_agent were not initialized properly.
-
-Added from_ext, to_ext, and replyto_ext fields to msg struct. Initialized
-with call to smb_getmsghdr() function. These are convenience pointers for
-the to, from, and replyto agent extensions (user numbers, usually).
-
-Fixed a nasty bug in the smb_freemsgdat() function, causing odd values in the
-SDA file and cross-linked messages when fast allocation mode was not used for
-new messages.
-
-smb_putmsghdr() function replaced by smb_putmsg() and it calls smb_putmsghdr()
-and smb_putmsgidx() - previously smb_putmsghdr() actually wrote the header
-and the index. So you must change any occurances of smb_putmsghdr() to
-smb_putmsg() if you intend to write to both the index and header records.
-
-smb_open() now takes a "retry_time" parameter (number of seconds) to lock
-and read the message base header and verify the "id" and "version". Added
-new error codes: -1 indicates failure to lock message base header, -2 indicates
-id mismatch, and -3 indicates incompatible message base version.
-
-rewind() and clearerr() calls added to library functions to eliminate the
-problem of "sticky" error flags when using fread() and fwrite(). Reordered
-the use of chsize() to force seeking (with fseek()) before using the file
-descriptor operation (chsize()) would would fail under some circumstances.
-
-smb_getmsgidx() function now uses "fast" message number look-up algorythm.
-
-Added smb_getlastidx() function to retrieve the last index in the message
-base.
-
-Allocation strategy for hfield and dfield elements of the smbmsg_t structure
-were changed to require less memory. Rather than an array of pointers (pointer
-to a pointer) of type hfield_t or dfield_t, they are simply an array (pointer)
-of type hfield_t or dfield_t. The only change you need to make are any
-references to "smbmsg_t.hfield[x]->etc" to "smbmsg_t.hfield[x].etc".
-
-Added several new error codes to smb_getmsghdr(). -7 indicates missing one
-of the three mandatory header fields (sender, recipient, or subject). -8
-indicates that total_dfields element of smbhdr_t is incorrect (extends beyond
-smbhdr_t.length). -9 indicates incompatible header version.
-
-New error code to smb_addcrc(), -4 indicates error getting length of file.
-
-smb_putmsghdr() returns -2 on failure write header, -3 on failure to write
-dfield, -4 on failure to write hfield (fixed), -5 on failure to write hfield
-(data), and -6 on failure to pad record with NULLs.
-
-Bugs fixed in sample conversion source code and SMBUTIL: Overwriting first
-two bytes of next record when using self-packing storage, SBBSFIDO would
-crash on blank kludge lines, SEEN-BYs weren't converted properly by SBBSFIDO,
-and more.
-
-*** IMPORTANT ***
-Index format changed, added message time field to idxrec_t for fast pointer
-manipulation by (import) date/time stamp. This is SMB format v1.10 and is
-not compatible with the v1.00 format. A conversion program (100TO110.EXE)
-is included with source code for converted any existing message bases.
-
-CHKSMB, a utility for checking message bases for corruption, included with
-SMBLIB.
-
-SMBUTIL and CHKSMB both accept wildcard arguments for processing multiple
-message bases.
-
-idxrec_t.to and idxrec_t.from may contain USER NUMBER instead of CRC of user
-names. This implementation is currently specific to E-mail boxes on Synchronet
-BBS. E-mail from non-local users are stored with a "from" field of 0.
-
-**********************
-03/28/94 Release v1.10
-**********************
-
-Forgot to include this file (oops).
-
-***********************
-03/28/94 Release v1.10a
-***********************
-
-Fixed problem with buffered fread() routine attempting to read into a locked
-regions.
-
-Added smb_stack() function for saving (pushing) currently open message base
-and ability to pop it off later.
-
-Added fix for keeping original sender information in smbmsg_t structure when
-a message has been forwarded.
-
-CHKSMB now correctly support multiple destination messages (without reporting
-missallocated active data blocks) and now reports packable bytes available.
-
-SMBUTIL can now conditionally compress a message base, only if so many K are
-compressable.
-
-Fixed problem with incorrect UTC value.
-
-Added NET_WWIV network type.
-
-**********************
-06/02/94 Release v1.11
-**********************
-
-Created Watcom compatible MAKEFILE for DOS, 32-bit DOS, and 32-bit OS/2
-versions of SMBUTIL.
-
-Enhanced macro definitions in SMBDEFS.H for MALLOC, FREE, and REALLOC to
-support Watcom and other compilers other than Borland. Also added LMALLOC
-and LFREE macros for large allocation (>64k) operations.
-
-Fixed problem with multiple calls to setvbuf() when using Watcom C libraries.
-Memory allocated by setvbuf() would never be released. To work around this
-Watcom C bug, a static buffer, shd_buf[], is now used instead.
-
-Fixed bug in smb_getmsghdr() that would cause it to return -6 when attempting
-to allocate 0 length header fields.
-
-Added LZH.C to SMBLIB for message data compression/decompression.
-
-Removed the 16-bit CRC functions from SMBUTIL and put them in CRC16.C (now part
-of SMBLIB) for easier integration into other applications.
-
-Added Hyper Allocation storage method to specification: smbstatus_t.reserved
-changed to smbstatus_t.attr and SMB_HYPERALLOC bit is set when Hyper Allocation
-storage is used for a message base. This is the only change between v1.10 and 
-v1.20 of the message base format. No other bits in smbstatus_t.attr are 
-currently defined. See the specification for definition of the Hyper Allocation
-storage method.
-
-Changed SMB Storage and Retrieval Protocol chapters in the specification to
-Pseudo-code examples.
-
-Added SMBLIB Storage and Retrieval C example chapters to the specification.
-
-Added field descriptions for message base header record fields and Status Info
-(base header #1) record fields to the specification.
-
-Changed SMBLIB smb_addmsghdr() 'fast' argument to 'storage' to specify the
-storage method to use (either SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC).
-Previous usage (0 for self-pack, 1 for fast) still compatible.
-
-Added smb_hallocdat() and smb_hallochdr() to SMBLIB functions for the Hyper
-Allocation storage method.
-
-Added SMB_STACK_XCHNG operation to smb_stack() function, to exchange the top
-of the stack with the currently open message base.
-
-**********************
-02/14/95 Release v1.20
-**********************
-
-smb_close() was modified in the following ways:
-	Only attempts to close non-NULL file pointers
-	If shd_fp is currently open, calls smb_unlocksmbhdr() before closing
-		(just in case it was left locked by application)
-
-smb_open() was modified in the following ways:
-	Initializes all file pointers to NULL
-	calls smb_close() if any of the files couldn't be opened
-
-smb_locksmbhdr() was modified in the following ways:
-	If lock fails, attempts to unlock the header before next lock
-		attempt (just incase application attempts to lock a locked
-		header without first unlocking it)
-
-smb_lockmsghdr() was modified in the following ways:
-	If lock fails, attempts to unlock the header before next lock
-		attempt (same reason stated above)
-
-CHKSMB (1.21) was modified in the following ways:
-	Tests for valid translations strings in the .SDT files
-	Displays totals for bytes used by header and data blocks, bytes used
-		by deleted messages, and bytes saved by LZH compression
-
-SMBUTIL (1.21) underwent some minor cosmetic changes.
-
-***********************
-03/18/95 Release v1.20a
-***********************
-
-SMBUTIL (1.22) now compiles correctly under Watcom, using correct time zone
-information. SMBUTIL maint() will no longer delete messages if max_age is
-specified in the SMB header and the when_imported time for a message is in the
-future.
-
-Fixed problem in LZH.C that would cause lzh_decode() to generate exception
-errors when compiled with a 32-bit compiler.
-
-CHKSMB (1.22) now supports /E command line switch to display extended
-information about corrupted messages. CHKSMB.C is now Watcom compatible.
-
-Added fflush() calls to all smblib functions that write to the SDT, SHA, or SDA
-files. This eliminates the problem of duplicate data offsets (data blocks for
-multiple messages pointing to the same location) causing corrupted SDT files
-(unsupported translation types reported by CHKSMB).
-
-Added fflush() call after writing to SDT file in SMB_PUT example in SMB.TXT.
-
-Fixed example *2SMB.C files to be compatible with SMBLIB v1.20 smb_create()
-function.
-
-Fixed smb_hallocdat() function prototype to stop redeclaration warnings.
-
-Minor typos in specification fixed.
-
-***********************
-04/24/95 Release v1.20b
-***********************
-
-Added SMB_EMAIL (1<<0) attribute definition for the message base status header
-to specify a local e-mail message base where index "to" and "from" fields are
-stored as user numbers, not CRC-16s (this is the only change between v1.20
-and v1.21 of the SMB format).
-
-Version 1.21 of FIXSMB no longer needs the "/M" switch to correctly fix a
-Synchronet e-mail message base (as long as the SMB_EMAIL status attr is set).
-
-Version 1.23 of SMBUTIL can now import text into a Synchronet e-mail message
-base (as long as the SMB_EMAIL status attr has been set). It will ask for the
-sender and recipient user numbers. Fixed an apparently nasty bug that would
-cause damage to message bases when (I)mporting (check for SMB_HYPERALLOC
-attribute was backwards). Excess baggage in the SMBUTIL source code was also
-removed (no longer supports /L, /F, and /D command line switches). Only
-supports self-packing and hyper-allocated message bases (it will not damage
-fast allocated bases, however). "SMBUTIL M" now correctly handles message bases
-that contain messages that have been pre-flagged for deletion (MSG_DELETE attr
-set).
-
-Changed smb_open(int retry_count) function: if retry_count is 0, then a "fast
-open" method is used which doesn't lock and read the status header to check
-for compatibility and validity of message base.
-
-Added SMBLIB_VERSION definition (string constant) to contain the current
-version and revision (if applicable) of the SMB library. This version number
-may not always be the same as SMB_VERSION (version of the SMB format) or the
-current version of the specification. It may be helpful to include a display
-of this version number somewhere in your application (i.e. printf("SMBLIB v%s"
-,SMBLIB_VERSION);).
-
-Changed smb_stack() example in the Performance Issues chapter to keep two
-message bases always open using SMB_STACK_XCHNG.
-
-Fixed bug in SMBUTIL that would cause an infinite loop when analysing an
-extrememly corrupted HyperAllocated message base.
-
-Fixed bug in smb_stack() function when using SMB_STACK_XCHNG operation. Would
-previously set current message base to an undefined message base, rather than
-the message base on top of the stack (last pushed or exchanged).
-
-CHKSMB v1.22 compiled in the 1.20b release did not support wildcards (wasn't
-linked with WILDARGS.OBJ) - this has been fixed and is the only change in
-CHKSMB v1.23.
-
-**********************
-05/31/95 Release v1.21
-**********************
-
-Add uchar forwarded element to smbmsg_t structure. This variable is initialized
-by the smb_getmsghdr() function. If the message has been forwarded, it will
-be set to non-zero.
-
-Fixed bug in LZH.C which caused lzh_decode() to produce incorrect results
-(usually t's and spaces) when compiled with a 32-bit compiler.
-
-Added HUGE16 and FAR16 macros to SMBDEFS.H for huge and far pointers for
-16-bit compilers only (default pointer type for 32-bit compilers).
-
-Fixed bug in FIXSMB.C that would initialize the SDA file to the wrong length.
-
-Added net type NET_MHS for MHS gateways.
-
-SMBUTIL (1.24) will no longer free deleted headers when maintaining a message
-base if the /A (no analysis) command line switch is used. This speeds up the
-message base maintenance/pack operation significantly by using: SMBUTIL /A MP
-
-***********************
-08/31/95 Release v1.21a
-***********************
diff --git a/src/sbbs2/smb/121a/smb.prn b/src/sbbs2/smb/121a/smb.prn
deleted file mode 100644
index 904897ea1eea04ff4d58ef80d1495c853b730dee..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smb.prn
+++ /dev/null
@@ -1,5661 +0,0 @@
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	
-	                     Synchronet Message Base Specification
-	                                 Version 1.21
-	                               Updated 08/31/95
-	
-	                        Copyright 1995 Digital Dynamics
-	
-	                                  PO Box 501
-	                             Yorba Linda, CA 92686
-	
-	                 Voice: 714-529-6328   BBS: 714-529-9525 V.32/V.32bis
-	                   FAX: 714-529-9721        714-529-9547 V.FC
-	                  Fido: 1:103/705      ftp: netcom.com /pub/sb/sbbs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	Table of Contents
-	=================
-	
-	Introduction.............................................................3
-	Implementation Levels....................................................8
-	Definitions.............................................................10
-	        Acronyms........................................................12
-	        Data Types......................................................13
-	File Formats............................................................18
-	        Index.....................(*.SID)...............................18
-	        Header....................(*.SHD)...............................20
-	        Header Allocation.........(*.SHA)...............................30
-	        Data......................(*.SDT)...............................31
-	        Data Allocation...........(*.SDA)...............................32
-	        CRC History...............(*.SCH)...............................33
-	Header Field Types......................................................34
-	Data Field Types........................................................58
-	Messsage Attributes.....................................................60
-	Translation Types.......................................................61
-	Agent Types.............................................................62
-	Network Types...........................................................63
-	Media Types.............................................................64
-	Message Storage Pseudo Code.............................................67
-	Message Retrieval Pseudo Code...........................................69
-	SMBUTIL.................................................................70
-	CHKSMB..................................................................71
-	FIXSMB..................................................................72
-	SMBLIB (C library)......................................................73
-	        Data Types and Constants..(SMBDEFS.H)...........................74
-	        Global Variables..........(SMBVARS.C)...........................75
-	        Function Prototypes.......(SMBLIB.H)............................76
-	        Library Functions.........(SMBLIB.C)............................77
-	        Miscellaneous.............(CRC*.* and LZH.*)....................84
-	SMBLIB Storage Example..................................................86
-	SMBLIB Retrieval Example................................................89
-	SMBLIB Performance Issues...............................................91
-	Bibliography............................................................95
-	Implementations.........................................................96
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            2                                Contents
-
-
-	Introduction
-	============
-	
-	Q. What is SMB?
-	
-	A. SMB (Synchronet Message Base) is a technical specification for the storage
-	   format of electronic mail messages. These e-mail messages may all be
-	   contained in one database, or, more commonly, separated into catagorized
-	   databases. These message databases (or message bases) are also referred to
-	   as "sub-boards", "forums", "conferences", and "SIGs". The messages may be
-	   directed to an individual person, sent to a group of individuals, or sent
-	   to everyone who can read messages in that message base. Messages may be
-	   created and read soley at one physical location, or imported from and
-	   exported to a message network that may span continents. Message bases that
-	   are connected to a message network are often called "echoes".
-	
-	
-	Q. Why SMB?
-	
-	A. The Synchronet Message Base is designed to store high volumes of messages
-	   while maintaining optimum search, retrieval, and creation performance.
-	   These messages are not limited to mere text. In addition to text, SMB
-	   defines the storage of digitized sound, MIDI, graphics, fonts, animation,
-	   as well as other multimedia data and triggers for localized multimedia.
-	   SMB thrives on a multi-user environment where messages are being created,
-	   read, modified, and deleted by multiple tasks simultaneously. With the
-	   large message networks of today being the rule, rather than the exception,
-	   and high volumes of messages being imported on a daily, sometimes hourly
-	   basis, creation and deletion speed is of the utmost importance. This is
-	   where SMB really shines. Being extensible enough to handle message formats
-	   from networks of today and tomorrow, and fast enough to import more messages
-	   that humanly readable, the SMB format will more than meet your message
-	   storage needs.
-	
-	
-	Q. Why a specification?
-	
-	A. Message bases are often accessed and modified by a number of different
-	   programs. Often these programs are developed by individuals or companies
-	   other than the original designer of the message base format. This
-	   specification is an attempt to aid developers in creating programs that
-	   access or modify a message base stored in the SMB format.
-	
-	
-	Q. Who can use this specification?
-	
-	A. Anyone that has interest in the Synchronet Message Base format at either
-	   an educational or professional level. Specifically, software developers
-	   interested or currently involved in the development of message readers,
-	   editors, echomail (toss/scan) programs, message transfer agents (MTAs),
-	   network gateways, and bulletin board systems. Much of the information in
-	   this specification is intended for those with preexisting programming
-	   knowledge, so those with little or no programming experience may find it
-	   hard to comprehend.
-
-	_______________________________________________________________________________
-	Synchronet                            3                            Introduction
-
-
-	
-	
-	Q. What does the SMB specification include?
-	
-	A. The text you are reading is part of the SMB specification: a single text
-	   document that defines the storage format of each of the six files of an
-	   SMB format message base and how they are related to each other.
-	
-	   Included with this specification is C source code to be used as an example
-	   to programmers of how to access an SMB format message base and public domain
-	   library functions (SMBLIB) that can be compiled and linked into programs
-	   that access an SMB format message base developed by third parties. An SMB
-	   utility program (SMBUTIL) is also included with C source code as an example
-	   of how to use the SMBLIB functions.
-	
-	
-	Q. Where did the SMB specification come from?
-	
-	A. Digital Dynamics (southern California based software development company)
-	   released "Synchronet Multinode BBS Software Version 1a" in June of 1992 as
-	   one of the first BBS packages to be designed from the ground-up to operate
-	   in a multinode environment with incredible speed and reliability, with a
-	   large suite of multinode specific features and design innovations.
-	
-	   The original message base format was designed with localized messaging and
-	   low volume message networks in mind. By January of 1993, it was clear that
-	   high volume message networks (FidoNet, RelayNet, Usenet, etc.) were the
-	   preference of most BBS users and a new message base format was required to
-	   allow for high volume message storage, improved storage, retrieval, and
-	   maintenance performance, as well as lower storage space requirements.
-	
-	   Rather than introduce another new message format, Digital Dynamics sought
-	   to implement an existing public specification for a format that would meet
-	   current and future message storage needs. More than a few specifications
-	   were seriously considered at one time or another, but after careful
-	   examination, design flaws and lack of extensibility eliminated them from the
-	   long term plans of Digital Dynamics and Synchronet BBS Software. Thus began
-	   the design of the "Synchronet Message Base" (SMB) format.
-	
-	   At the request of many message related program developers, Digital Dynamics
-	   created and released the SMB specification before the release of "Synchronet
-	   Version 2.00" to allow lead-time on developing support programs for the new
-	   format.
-	
-	   Digital Dynamics strongly encourages developers of message related programs
-	   (including software that directly competes with Synchronet or other Digital
-	   Dynamics products) to implement support for SMB. Though this is a public
-	   specification and Digital Dynamics encourages developer suggestions, it will
-	   remain under the sole control of Digital Dynamics unless specifically stated
-	   otherwise in a future revision of this specification.
-	
-	   Digital Dynamics requests that any organizations that wish to adopt or
-	   ratify this specification, in part or whole, notify Digital Dynamics through
-	   any of the contact methods listed at the beginning of this document.
-
-	_______________________________________________________________________________
-	Synchronet                            4                            Introduction
-
-
-	
-	
-	Q. How does SMB store messages?
-	
-	A. Each message base is stored in a set of binary files. This set consists
-	   of between three and six files depending the storage method used. The base
-	   filename (maximum of eight characters under DOS) is the same for all six
-	   files of the same message base and unique amoung the filenames of other
-	   message bases in the same directory. The six files each have a different
-	   three character extension. The first character of the extension is always
-	   the letter 'S' (for SMB), while the second and third characters define the
-	   contents of the file.
-	
-	   Two of the six files associated with each message base are not recreatable
-	   and therefore are the most important when considering data integrity. These
-	   two files are the data file (with a .SDT extension) and header file (.SHD
-	   extension). Both of these files use 256 byte blocks and have associated
-	   block allocation tables (stored in .SDA and .SHA respectively) so that
-	   deleted message blocks may be used by new messages without creating odd
-	   sized unused 'holes' in the files. The block allocation table files (.SDA
-	   and .SHA) can be recreated with the information stored in the header (.SHD)
-	   file. When using Hyper Allocation storage method, the allocation files (.SDA
-	   and .SHA) are not used.
-	
-	   For fast indexing, there is a small fixed length index file (with a .SID
-	   extension). This file allows for the immediate location of message header
-	   records based on sender's name or user number, recipient's name or user
-	   number, subject, message number, or message attributes. This file can be
-	   recreated with the data stored in the header (.SHD) file.
-	
-	   The last file is an optional CRC history (.SCH) file. It contains 32-bit
-	   CRCs of a configurable number of messages imported or created locally. This
-	   is to help eliminate duplicate messages created by user or program error.
-	   The CRC history file can be recreated with the combination of information
-	   stored in the data (.SDT) and header (.SHD) files.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            5                            Introduction
-
-
-	Q. How fast do messages import into an SMB message base?
-	
-	A. This is a very important question for systems for that import large volumes
-	   of messages. Of course, the answer depends on the storage format which you
-	   are importing from, the average length of messages, the design of the
-	   program which is peforming the import process, as well as the hardware and
-	   system software being used. What's important is that SMB will allow the
-	   fastest import process possible with any given combination of the above
-	   factors.
-	
-	   Since system storage capacity is rarely infinite, neither is the number
-	   of messages which can be stored in a message base. System operators must
-	   define the maximum number of messages to be stored in a message base, the
-	   maximum age of the messages in that message base, or a combination of both.
-	   When using the Self-packing storage method (defined later in this document),
-	   the smaller the number of messages stored in a message base, the faster the
-	   import process. The SMB format is flexible enough to support multiple levels
-	   of import performance based on optimizations for storage space or speed.
-	   Most system operators will almost invariably choose speed over space, but
-	   which choices are available is determined by the importing program. This
-	   specification defines three storage methods, from slowest to fastest:
-	   Self-packing, Fast Allocation, and Hyper Allocation. Other options defined
-	   in this specification may affect storage performance, including duplicate
-	   message checking and message compression/encryption.
-	
-	
-	Q. How much storage is required for an SMB message base?
-	
-	A. The biggest factor in determining storage requirements for a message base
-	   is the maximum number of messages to be stored in the base (defined by the
-	   system operator) and the average size of each message. The minimum required
-	   storage for a message base is 32 bytes plus 532 bytes per message (plus four
-	   bytes per message if duplicate message checking is used and three bytes
-	   per message if Self-packing or Fast Allocation storage methods are used).
-	
-	   The SMB format was originally designed to be "self-packing", meaning purged
-	   (deleted) message header and data blocks will be used automatically by new
-	   messages. Relying solely on self-packing, an SMB format message base will
-	   never "shrink" in size. This is not to say that it will continually "grow"
-	   in size, but that without specific packing procedures, deleted message
-	   blocks may remain unused for extended periods of time, meanwhile using some
-	   amount of storage space that could be recovered using specific packing
-	   procedures. The Fast Allocation and Hyper Allocation storage methods do not
-	   use deleted message blocks for new messages so specific packing procedures
-	   must be used if any messages are deleted and that storage space is to ever
-	   be recovered.
-	
-	   Limiting the maximum age of messages in an SMB message base is another way
-	   to control the storage requirements. While maximum message age definition is
-	   optional, the definition of the maximum number of messages is not.
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            6                            Introduction
-
-
-	Q. How many messages can be stored per SMB message base?
-	
-	A. Without considering storage limitations or message data lengths greater than
-	   256, the theoretical maximum number of messages that can be stored in a
-	   single SMB message base is 16.7 million. Considering the variable length
-	   nature of message and header data, it is suggested that the system operator
-	   allow no more than 1 million messages per base.
-	
-	   To determine an estimated maximum number of messages for a message base
-	   using the average message data length as a factor, use the following
-	   formula:
-	
-	   4.2 billion divided by the average message length rounded up to be evenly
-	   divisible by 256.
-	
-	   If the average message data length is 1500 bytes, the estimated maximum
-	   number of messages would be 2,734,375 (4.2 billion divided by 1536).
-	
-	   Implementations of this format may be further limited by available system
-	   memory.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            7                            Introduction
-
-
-	Implementation Levels
-	=====================
-	The SMB format can be implemented to varying degrees between programs without
-	creating compatibilty issues. Rather than have developers specifically state
-	which features they have and have not implemented, we have defined seven levels
-	of implementation (represented by Roman numerals I through VII). For a program
-	or software package to meet an implementation level, it must have all of the
-	features listed for that level and all of those for each level below it. The
-	minimum suggested imlementation is level I. The SMBUTIL program included with
-	this specification is an example of a level I implementation with features
-	from some of the higher implementation levels.
-	
-	Level I
-	-------
-	The minimum suggested level of implementation. Messages contain merely ASCII
-	text displayable on an ANSI terminal. Messages can be added to the message
-	base and if the maximum number of messages is exceeded, messages are removed
-	or marked for deletion.
-	
-	Level II
-	--------
-	The addition of file attachments, multiple index/header entries per message
-	(multiple destinations), multiple text bodies for the separation of message
-	text and tag/origin lines (for example), forwarding, threading, and specific
-	FidoNet kludge header field support makes this level of implementation more
-	realistic for bulletin board system and EchoMail software implementation.
-	
-	Synchronet Multinode BBS Software v2.00 has a level II implementation of this
-	specification.
-	
-	Level III
-	---------
-	This implementation adds support for translation strings defined later in this
-	document for data compression, encryption, escaping, and encoding. This level
-	is still limited to basic ASCII text and ANSI escape sequence entry and
-	retrieval.
-	
-	Synchronet Multinode BBS Software v2.10 has a level III implementation of this
-	specification.
-	
-	Level IV
-	--------
-	The storage and retrieval of embedded and attached images is added in this
-	level of implementation. Supported images are limited to single binary or text
-	data blocks that can be displayed or transferred to the user (automatically,
-	or by request) if their display and translation protocols define specific
-	support for the image type.
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            8                   Implementation Levels
-
-
-	Level V
-	-------
-	This level of implementation adds support for embedded and attached sound data.
-	This includes digitized sound and MIDI data. Supported sounds are limited to
-	single binary or text data blocks that can be played or transferred to the user
-	(automatically or by request) if their presentation and translation protocols
-	define specific support for the sound type.
-	
-	Level VI
-	--------
-	Localized sound and image data can be triggered by messages stored and
-	retrieved in an implementation of this level.
-	
-	Level VII
-	---------
-	Complete multimedia support is reached in this implementation level with
-	support for embedded and attached animation, sound, and video data.
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                            9                   Implementation Levels
-
-
-	Definitions
-	===========
-	
-	Control Characters
-	------------------
-	When specifying control characters (ASCII 1 through 31), the caret symbol "^"
-	or the abreviation "ctrl-" followed by a character will be used to indicate the
-	value. ^A is equivalent to ASCII 1, ^B ASCII 2, etc. The case of the control
-	character is not significant (i.e. ^z and ^Z are equivalent). The control
-	character ^@ (ASCII 0) will be specified as NULL or 0.
-	
-	
-	Hexadecimal
-	-----------
-	Base sixteen numbering system which includes the digits 0-9 and A-F.
-	Hexadecimal numbers are represented in this document with a prefix of "0x" or
-	"\x" or a suffix of "h". Hexadecimal letter digits are not case sensitive
-	(i.e. the number 0xff is the same as 0xFF).
-	
-	
-	File dump
-	---------
-	When example file dumps are displayed, the format is similar to that of the
-	output from the DOS DEBUG program. With the exception of the ASCII characters,
-	all numbers are in hexadecimal.
-	
-	Offset    Byte values                                          ASCII characters
-	
-	000000    53 4D 42 1A 10 01 20 00   F4 01 00 00 F4 01 00 00    SMB... .�...�...
-	000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-	
-	
-	Bit values
-	----------
-	Bit (or flag) values are represented in C notation as (1<<x) where x is the bit
-	number. (i.e. bit number 7 (1<<7) is the same as 0x80).
-	
-	
-	Word storage
-	------------
-	All words (16-bit) and double words (32-bit) are stored in Intel 80x86 (little
-	endian) format with bytes stored from low to high (reverse of the Motorola
-	680x0 word storage format).
-	
-	A 16-bit word with the value 1234h is stored as 34h 12h.
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           10                             Definitions
-
-
-	Translation strings
-	-------------------
-	Translation strings (xlat variables) are arrays of words (16-bit) in the order
-	of the original storage translation. The last translation type is followed by a
-	16-bit zero (defined later as XLAT_NONE). If there are no translations, then
-	the first and only element of the array is XLAT_NONE.
-	
-	If multiple translations are used, the translation order must be reversed
-	upon retrieval to obtain the proper data.
-	
-	
-	Local e-mail
-	------------
-	When referring to the local e-mail message base of a Synchronet BBS, we are
-	referring specifically the message base with the name "MAIL" stored in the
-	"DATA" directory (e.g. \SBBS\DATA\MAIL).
-	
-	Messages stored in this message base are different in the following respects:
-	
-	    The SMB_EMAIL status header attribute is set ON
-	    Hyper Allocation storage method is not supported
-	    The "To" and and "From" fields of the message indexes do NOT contain CRCs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           11                             Definitions
-
-
-	Acronyms:
-	========
-	
-	ANSI            American National Standards Institute
-	ASCII           American Standard Code for Information Interchange
-	BBS             Bulletin Board System
-	C               The C programming language as defined by ANSI X3.159-1989
-	CR              Carriage Return character (ASCII 13)
-	CRC             Cyclic Redundancy Check
-	CRC-16          Standard 16-bit CRC using 1021h polynomial (seed 0)
-	CRC-32          Standard 32-bit CRC using EDB88320h polynomial (seed -1)
-	CRLF            Carriage Return character followed by a Line Feed character
-	FSC             FidoNet Standards Commitee (FTS proposal)
-	FTN             FidoNet Technology Network
-	FTS             FidoNet Technical Standard
-	LF              Line Feed character (ASCII 10)
-	QWK             Compressed message packet format for message reading/networking
-	RFC             Request for Comments
-	SMB             Synchronet Message Base
-	UT              Universal Time (formerly called "Greenwhich Mean Time")
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           12                  Definition of Acronyms
-
-
-	Data types
-	==========
-	
-	uchar           Unsigned 8-bit value (0 through 255).
-	                C example:
-	
-	                #define uchar unsigned char
-	
-	
-	short           Signed 16-bit value (-32768 through 32767).
-	                "short" is a C keyword indicating "short int".
-	
-	
-	ushort          Unsigned 16-bit value (0 through 65535).
-	                C example:
-	
-	                #define ushort unsigned short
-	
-	
-	ulong           Unsigned 32-bit value (0 through 4294967295).
-	                C example:
-	
-	                #define ulong unsigned long
-	
-	
-	time_t          Unsigned 32-bit value.
-	                Seconds since 00:00 Jan 01 1970 (Unix format).
-	                Used for all time/date storage in SMB as part of the when_t
-	                data type. This time format will support dates through the year
-	                2105.
-	                time_t is defined by ANSI C as a long (signed) which can
-	                limit its date support to the year 2038 depending on the
-	                library routines used.
-	
-	
-	ASCII           String (aka character array) of 8-bit ASCII characters.
-	                Characters with the bit 7 set (80h through FFh) represent
-	                the IBM PC extended ASCII character set. When data or header
-	                fields of this type are stored in the header, a NULL
-	                terminator may or may not be present.
-	                C example:
-	
-	                uchar str[80];
-	
-	
-	ASCIIZ          ASCII string with (non-optional) NULL terminator.
-	                C example:
-	
-	                uchar str[81];
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           13                Definition of Data Types
-
-
-	nulstr          ASCII string immediately terminated by NULL.
-	                C example:
-	
-	                uchar *nulstr="";
-	
-	
-	undef           Data buffer with undefined contents.
-	                C example:
-	
-	                uchar buf[BUF_LEN];
-	
-	when_t          Date/Time stamp including time-zone adjustment information.
-	                C example:
-	
-	                typedef struct {
-	
-	                    time_t  time;   // Time stamp (in local time)
-	                    short   zone;   // Zone constant or Minutes (+/-) from UT
-	
-	                    } when_t;
-	
-	                time:
-	
-	                A time value of 0 is invalid and indicates an uninitialized
-	                time stamp.
-	
-	                Time stamps are always stored in universal time. i.e.
-	                Regardless of what the local time zone is, Jan 1st 1994 00:00
-	                will always be stored as 2D24BD00h.
-	
-	                zone:
-	
-	                If the zone is in the range -720 to +720, it represents the
-	                number of minutes east or west of UT. Values in this range
-	                should only be used for time zones not otherwise represented
-	                here.
-	
-	                If the zone is greater than 720 or less than -720, then the
-	                following bits have special meaning:
-	
-	                (1<<12)         // Non-US time zone     (east of UT)
-	                (1<<13)         // Non-US time zone     (west of UT)
-	                (1<<14)         // U.S. time zone
-	                (1<<15)         // Daylight savings
-	
-	                The lower 12 bits (0 through 11) contain the number of minutes
-	                east or west of UT (not accounting for daylight savings).
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           14                Definition of Data Types
-
-
-	                If the time zone is one specified in the U.S. Uniform Time Act,
-	                the following values represent the zone:
-	
-	                AST 0x40F0      // Atlantic             (-04:00)
-	                EST 0x412C      // Eastern              (-05:00)
-	                CST 0x4168      // Central              (-06:00)
-	                MST 0x41A4      // Mountain             (-07:00)
-	                PST 0x41E0      // Pacific              (-08:00)
-	                YST 0x421C      // Yukon                (-09:00)
-	                HST 0x4258      // Hawaii/Alaska        (-10:00)
-	                BST 0x4294      // Bering               (-11:00)
-	
-	                With bit 15 set, the following values represent the same zone
-	                with the presence of daylight savings:
-	
-	                ADT 0xC0F0      // Atlantic             (-03:00)
-	                EDT 0xC12C      // Eastern              (-04:00)
-	                CDT 0xC168      // Central              (-05:00)
-	                MDT 0xC1A4      // Mountain             (-06:00)
-	                PDT 0xC1E0      // Pacific              (-07:00)
-	                YDT 0xC21C      // Yukon                (-08:00)
-	                HDT 0xC258      // Hawaii/Alaska        (-09:00)
-	                BDT 0xC294      // Bering               (-10:00)
-	
-	                The following non-standard time zone specifications may also be
-	                used:
-	
-	                MID 0x2294      // Midway               (-11:00)
-	                VAN 0x21E0      // Vancouver            (-08:00)
-	                EDM 0x21A4      // Edmonton             (-07:00)
-	                WIN 0x2168      // Winnipeg             (-06:00)
-	                BOG 0x212C      // Bogota               (-05:00)
-	                CAR 0x20F0      // Caracas              (-04:00)
-	                RIO 0x20B4      // Rio de Janeiro       (-03:00)
-	                FER 0x2078      // Fernando de Noronha  (-02:00)
-	                AZO 0x203C      // Azores               (-01:00)
-	                LON 0x1000      // London               (+00:00)
-	                BER 0x103C      // Berlin               (+01:00)
-	                ATH 0x1078      // Athens               (+02:00)
-	                MOS 0x10B4      // Moscow               (+03:00)
-	                DUB 0x10F0      // Dubai                (+04:00)
-	                KAB 0x110E      // Kabul                (+04:30)
-	                KAR 0x112C      // Karachi              (+05:00)
-	                BOM 0x114A      // Bombay               (+05:30)
-	                KAT 0x1159      // Kathmandu            (+05:45)
-	                DHA 0x1168      // Dhaka                (+06:00)
-	                BAN 0x11A4      // Bangkok              (+07:00)
-	                HON 0x11E0      // Hong Kong            (+08:00)
-	                TOK 0x121C      // Tokyo                (+09:00)
-	                SYD 0x1258      // Sydney               (+10:00)
-	                NOU 0x1294      // Noumea               (+11:00)
-	                WEL 0x12D0      // Wellington           (+12:00)
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           15                Definition of Data Types
-
-
-	fidoaddr_t      FidoNet address stored as four ushorts that represent the zone,
-	                network, node, and point (in that order).
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort zone,
-	                           net,
-	                           node,
-	                           point;
-	
-	                    } fidoaddr_t;
-	
-	
-	typestr_t       ASCIIZ string with ushort type prefix.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // Specifier for type of 'str'
-	                    uchar   str[];  // ASCIIZ filename or other string data
-	
-	                    } typestr_t;
-	
-	
-	mattach_t       File attachment information with type prefix, translation
-	                string, and filename.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // Attachment type
-	                    ushort  xlat[]; // Translations of data in attachment
-	                    uchar   str[];  // ASCIIZ filename
-	
-	                    } mattach_t;
-	
-	vattach_t       Video file attachment information with type, compression,
-	                translation string, and filename.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // Attachment type
-	                    ushort  comp;   // Compression method
-	                    ushort  xlat[]; // Translations of data in attachment
-	                    uchar   str[];  // ASCIIZ filename
-	
-	                    } vattach_t;
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           16                Definition of Data Types
-
-
-	mtext_t         Message text with translation string prefix.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  xlat[]; // Translations of text
-	                    uchar   text[]; // Actual text data
-	
-	                    } mtext_t;
-	
-	
-	ftext_t         Formatted message text with translation string prefix and
-	                format type.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // See Image Types for valid types
-	                    ushort  xlat[]; // Translations of data
-	                    uchar   data[]; // Actual formatted text data
-	
-	                    } ftext_t;
-	
-	
-	membed_t        Embedded data with type prefix, translation string, and ASCIIZ
-	                description.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // Specifier for type of 'dat'
-	                    ushort  xlat[]; // Translations of embedded data
-	                    uchar   name[]; // ASCIIZ char description of embedded data
-	                    uchar   dat[];  // Binary data
-	
-	                    } membed_t;
-	
-	vembed_t        Embedded video data with type, compression method, translation
-	                string, and ASCIIZ description.
-	                C example:
-	
-	                typedef struct {
-	
-	                    ushort  type;   // Specifier for type of 'dat'
-	                    ushort  comp;   // Compression method
-	                    ushort  xlat[]; // Translations of embedded data
-	                    uchar   name[]; // ASCIIZ char description of embedded data
-	                    uchar   dat[];  // Binary data
-	
-	                    } vembed_t;
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           17                Definition of Data Types
-
-
-	File formats
-	============
-	
-	Index File (*.SID)
-	------------------
-	The index file for each message base contains one record per message in the
-	base. Each record is fixed length using the following format:
-	
-	Index Record:
-	------------
-	C example:
-	
-	typedef struct {
-	
-	    ushort  to;     // 16-bit CRC of recipient name (lower case) or user number
-	    ushort  from;   // 16-bit CRC of sender name (lower case) or user number
-	    ushort  subj;   // 16-bit CRC of title/subject (lower case)
-	    ushort  attr;   // attributes (MSG_PRIVATE, MSG_READ, etc. flags)
-	    ulong   offset; // byte offset of message header in header file
-	    ulong   number; // message serial number (1 based)
-	    time_t  time;   // import date/time stamp (Unix format)
-	
-	    } idxrec_t;
-	
-	
-	Example file dump (16 messages starting with message number 15):
-	---------------------------------------------------------------
-	000000    36 4F 13 07 2A 77 00 00   20 00 00 00 0F 00 00 00    6O..*w.. .......
-	000010    BE 62 76 2C 36 4F 46 0A   7F B2 00 00 20 01 00 00    �bv,6OF.�.. ...
-	000020    10 00 00 00 C7 29 78 2C   36 4F 70 6F 46 FF 00 00    ....�)x,6OpoF�..
-	000030    20 02 00 00 11 00 00 00   AD D3 7A 2C 70 6F 13 07     .......��z,po..
-	000040    46 FF 00 00 20 03 00 00   12 00 00 00 D6 F8 7F 2C    F�.. .......��,
-	000050    36 4F E1 EA E7 E9 00 00   20 04 00 00 13 00 00 00    6O����.. .......
-	000060    1E 7B 85 2C 37 0D 2E DF   4D 79 00 00 20 05 00 00    .{�,7..�My.. ...
-	000070    14 00 00 00 5C E1 A1 2C   90 54 2D 5A 86 62 00 00    ....\�,�T-Z�b..
-	000080    20 06 00 00 15 00 00 00   39 2E A2 2C 70 6F 1A 8B     .......9.�,po.�
-	000090    46 FF 00 00 20 07 00 00   16 00 00 00 D0 7B A8 2C    F�.. .......�{�,
-	0000A0    2E DF 1A 8B 4D 79 00 00   20 08 00 00 17 00 00 00    .�.�My.. .......
-	0000B0    FF 7B A8 2C B4 D9 35 7C   23 B1 00 00 20 09 00 00    �{�,��5|#�.. ...
-	0000C0    18 00 00 00 CE D4 BA 2C   36 4F BC D8 B2 E7 00 00    ....�Ժ,6O�ز�..
-	0000D0    20 0A 00 00 19 00 00 00   14 5F C3 2C BA A8 4E B0     ........_�,��N�
-	0000E0    67 76 00 00 20 0B 00 00   1A 00 00 00 6F 89 C3 2C    gv.. .......o��,
-	0000F0    36 4F 0C 01 19 9C 00 00   20 0C 00 00 1B 00 00 00    6O...�.. .......
-	000100    F8 30 C6 2C 36 4F FA 48   0E 55 00 00 20 0D 00 00    �0�,6O�H.U.. ...
-	000110    1C 00 00 00 6A 94 D3 2C   36 4F F1 CE CF A2 00 00    ....j��,6O��Ϣ..
-	000120    20 0E 00 00 1D 00 00 00   53 DB D5 2C 8D A6 21 CE     .......S��,��!�
-	000130    F7 AB 00 00 20 0F 00 00   1E 00 00 00 31 29 DC 2C    ��.. .......1)�,
-	
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           18               Index (*.SID) File Format
-
-
-	Field descriptions:
-	------------------
-	To:
-	The 'To' field is the CRC-16 of the name of the intended recipient agent of
-	this message or the intended recipient's user number. If the CRC is stored, the
-	text must be converted to lower case (A-Z changed to a-z) before the CRC is
-	calculated. If the message is forwarded to another agent, the original or new
-	index record must be changed to contain the CRC-16 of the new recipient name or
-	user number. This field must always contain the recipient user number for local
-	e-mail on a Synchronet BBS. Outbound netmail stored in the Synchronet local
-	e-mail message base will contain 0 in this field.
-	
-	From:
-	This field, similar to the 'To' field, contains the CRC-16 of the name of the
-	sending agent of this message or the sender's user number. If the CRC is
-	stored, the text must be converted to lower case (A-Z changed to a-z) before
-	the CRC is calculated. If the message is forwarded to another agent, the
-	original or new index record must be changed to contain the CRC-16 of the new
-	sender name or user number. If the message was imported into the local e-mail
-	message base on a Synchronet BBS via netmail, this field will contain 0.
-	
-	Subj:
-	The 'Subj' field contains the CRC-16 of the message's subject. The subject
-	must be converted to lower case (A-Z changed to a-z) and all preceeding
-	"re: "'s and "re:"'s removed before calculating the CRC-16.
-	
-	Attr:
-	This ushort is a bit field of the specific attributes for this message.
-	It is a clone of the 'attr' element of the msghdr_t structure.
-	
-	Offset:
-	This ulong is the offset (in bytes) in the header file for this message's
-	header record.
-	
-	Number:
-	This ulong is the serial number of this message. Valid values are 1 through
-	0xffffffff. No two index records in the same message base may have the same
-	message number. All index records must have sequential, but not necessarily
-	consequetive, message numbers.
-	
-	Time:
-	This field is the date/time stamp the message was imported to or posted in
-	the message base. It is a clone of the 'when_imported.time' element of the
-	msghdr_t structure.
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           19               Index (*.SID) File Format
-
-
-	Header File (*.SHD)
-	===================
-	
-	Each SMB header file is made up of two distinct sections: base header records
-	and message header records (usually the bulk of the file).
-	
-	Base Header Records:
-	-------------------
-	Base header records are blocks of data that apply to the entire message base
-	and are of variable length. This specification defines only one base header
-	record, the "Status info" (smbstatus_t) record. This status info record must be
-	the first base header record in the file and must be modified if additional
-	base header records are added.
-	
-	Additional header records allow other developers to store configuration and
-	status information particular to their application needs. It also allows for
-	future header record definitions as part of this specification without causing
-	backward compatibility issues.
-	
-	Each base header record contains a fixed length portion (smbhdr_t) and an
-	optional variable length portion.
-	
-	Whenever a base header record is read or updated (written), it must first
-	be successfully locked and subsequently unlocked.
-	
-	The first base header record (Status Info) is used as a semaphore when writing
-	to the message index (.SID) file and, when using the Hyper Allocation storage
-	method, writing to the message data (.SDT) file. This record must be
-	succesfully locked before writing and subsequently unlocked. This is to insure
-	that multiple applications simultaneously writing to the same message base
-	does result in corrrupted data.
-	
-	
-	Message Header Records:
-	----------------------
-	Following the last base header record is the first message header record. Each
-	header record is stored in one or more 256 byte blocks. There must be exactly
-	one active message header record for every index record in the index file.
-	(Note: This does not include deleted message headers that have not been
-	overwritten by a new message header).
-	
-	Each message header record contains a fixed length portion (msghdr_t), a list
-	of zero or more fixed length data fields (dfield_t), and a list of three or
-	more variable length header fields (hfield_t).
-	
-	The value of the data stored in the zero or more unused bytes of the last
-	header record block have an undefined value, though whenever possible
-	developers should initialize to binary zero for human readability.
-	
-	Whenever a message header record is read or updated (written), it must first
-	be successfully locked and subsequently unlocked.
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           20              Header File (*.SHD) Format
-
-
-	Base Header Record (Fixed Portion):
-	----------------------------------
-	C example:
-	
-	typedef struct {
-	
-	    uchar   id[4];          // text or binary unique hdr ID
-	    ushort  version;        // version number (initially 100h for 1.00)
-	    ushort  length;         // length including this struct
-	
-	    } smbhdr_t;
-	
-	
-	Base Header Record Field Descriptions:
-	-------------------------------------
-	Id:
-	This is a four byte unique ID identifying the type of the base header record.
-	The bytes may contain any value, but printable ASCII characters are preferred.
-	The only ID defined in this specification is "SMB^Z" used by the Status Info
-	base header record.
-	
-	Version:
-	This is a version number of the base header record type. Base header records
-	of different versions may have different formats or contain different
-	information. This is to aid the application in determining if the record
-	is pertinent and if so, to what degree. The Status Info base header record
-	uses this version field to define the version of the format for the entire
-	message base (currently 0x121 for version 1.21).
-	
-	Length:
-	This is entire length in bytes of this header record (including both fixed
-	and variable portions).
-	
-	
-	Base Header #1 (Status info) Record (Variable Portion):
-	------------------------------------------------------
-	C example:
-	
-	typedef struct {
-	
-	    ulong   last_msg;       // last message number posted or imported
-	    ulong   total_msgs;     // total messages currently in message base
-	    ulong   header_offset;  // byte offset to first header record
-	    ulong   max_crcs;       // Maximum number of CRCs to keep in history
-	    ulong   max_msgs;       // Maximum number of messages to keep in base
-	    ushort  max_age;        // Maximum age of messages (days) to keep in base
-	    ushort  attr;           // Attribute bits
-	
-	    } smbstatus_t;
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           21              Header File (*.SHD) Format
-
-
-	Base Header #1 (Status Info) Record (Variable Portion) Field Descriptions:
-	-------------------------------------------------------------------------
-	Last_msg:
-	This is the serial number of the last message imported or posted into this
-	message base. The index, header, and data records for this message may possibly
-	not exist (due to deletion). This field is used for determining the message
-	number to give to a new message being imported or posted into this message
-	base. This field must be updated for every message added to the message base.
-	
-	Total_msgs:
-	This is the total number of active messages currently in the message base.
-	This number should match the number of records in the index (.SID) file
-	and active header records in the header (.SHD) file. This field must be
-	updated whenever a message is added to or removed from the message base.
-	
-	Header_offset:
-	This is the byte offset to the first message header record. It is useful
-	for skipping all the base header records and going directly to the first
-	message header record.
-	
-	Max_crcs:
-	This is the maximum number of message CRCs to store in the CRC history (.SCH)
-	file for duplicate message checking. If this field contains 0, then duplicate
-	message checking is disabled.
-	
-	Max_msgs:
-	This is the preferred maximum number of messages to keep in this message
-	base as specified by the system operator. It is used by maintenance programs
-	that trim the message base down by removing old messages. This field should
-	be ignored by applications importing or posting messages allowing them to
-	exceed this maximum at will.
-	
-	Max_age:
-	This field is the maximum age (in days) of messages to keep in the message
-	base. It is used by maintenance programs to purge out-dated messages from
-	the message base.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           22              Header File (*.SHD) Format
-
-
-	Attr:
-	This is a bit field containing specific attributes (or flags) that may define
-	the way messages are stored or retrieved from the this message base. The
-	following attributes are defined:
-	
-	    SMB_EMAIL       (1<<0)
-	
-	    Indicates the message base is specifically for messages to or from local
-	    users. When this bit is set, the idxrec.to and idxrec.from fields will
-	    contain the user numbers (or 0 for non-user destination/source) instead of
-	    the CRC-16 of the agent name.
-	
-	    SMB_HYPERALLOC  (1<<1)
-	
-	    Indicates the message base uses the Hyper Allocation storage method. This
-	    bit should not be cleared by an application without first deleting all the
-	    messages in the message base. This is due to the fact the Hyper Allocation
-	    is not downward compatible with the Self-packing and Fast Allocation
-	    storage methods.
-	
-	When used with Synchronet BBS software, a message base must NOT have both of
-	the above attributes set. The only message base that should have the SMB_EMAIL
-	attribute set is the DATA\MAIL message base.
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           23              Header File (*.SHD) Format
-
-
-	Base Header #1 (Status info) Record Contents:
-	--------------------------------------------
-	smbhdr.id="SMB\x1a";        // SMB^Z
-	smbhdr.version=0x121;       // v1.21
-	smbhdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); smbstatus_t status;
-	
-	
-	Additional Base Headers:
-	-----------------------
-	Additional headers from developers must have initial 8 bytes in smbhdr_t
-	format, length must include size of smbhdr_t, and header_offset of smbstatus_t
-	must be changed to include the size of the additional header(s).
-	
-	
-	Example file dump (base header portion only):
-	--------------------------------------------
-	000000    53 4D 42 1A 20 01 20 00   F4 01 00 00 F4 01 00 00    SMB. . .�...�...
-	000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           24              Header File (*.SHD) Format
-
-
-	Message Header Record (Fixed portion):
-	-------------------------------------
-	C example:
-	
-	typedef struct {
-	
-	    uchar   id[4];          // SHD^Z (same for all types and versions)
-	    ushort  type;           // Message type (this is the definition of type 0)
-	    ushort  version;        // Version of type (initially 100h for 1.00)
-	    ushort  length;         // Total length of fixed portion + all fields
-	    ushort  attr;           // Attributes (bit field) (duplicated in SID)
-	    ulong   auxattr;        // Auxillary attributes (bit field)
-	    ulong   netattr;        // Network attributes (bit field)
-	    when_t  when_written;   // Date/Time message was originally created
-	    when_t  when_imported;  // Date/Time message was imported (locally)
-	    ulong   number;         // Message number (unique, not necessarily seq.)
-	    ulong   thread_orig;    // Original message number in thread
-	    ulong   thread_next;    // Next message in thread
-	    ulong   thread_first;   // Number of first reply to this message
-	    uchar   reserved[16];   // 16 reserved bytes for future use
-	    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-	    ushort  total_dfields;  // Total number of data fields
-	
-	    } msghdr_t;
-	
-	typedef struct {
-	
-	    ushort  type;           // See "Data Field Types" values
-	    ulong   offset;         // Offset into buffer 
-	    ulong   length;         // Length of data field in buffer
-	
-	    } dfield_t;
-	
-	typedef struct {
-	
-	    ushort  type;           // See "Header Field Types" for values
-	    ushort  length;         // Length of buffer
-	    uchar   dat[length];
-	
-	    } hfield_t;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           25              Header File (*.SHD) Format
-
-
-	Example file dump (one header record, both fixed and variable length portions):
-	------------------------------------------------------------------------------
-	000020    53 48 44 1A 00 00 20 01   F5 00 00 00 00 00 00 00    SHD... .�.......
-	000030    00 00 00 00 46 DB F7 2C   00 00 7D D7 29 2D 00 00    ....F��,..}�)-..
-	000040    01 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-	000050    00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-	000060    00 00 00 00 02 00 00 00   00 00 00 00 4A 01 00 00    ............J...
-	000070    02 00 4A 01 00 00 53 00   00 00 00 00 13 00 4D 61    ..J...S.......Ma
-	000080    72 69 61 6E 6E 65 20 4D   6F 6E 74 67 6F 6D 65 72    rianne Montgomer
-	000090    79 30 00 0C 00 43 61 72   6F 6C 20 47 61 69 73 65    y0...Carol Gaise
-	0000A0    72 60 00 07 00 46 61 72   6E 68 61 6D A4 00 14 00    r`...Farnham�...
-	0000B0    31 3A 31 33 38 2F 31 30   32 2E 30 20 32 63 66 38    1:138/102.0 2cf8
-	0000C0    30 35 37 36 A5 00 14 00   31 3A 33 34 33 2F 31 30    0576�...1:343/10
-	0000D0    30 2E 30 20 32 63 66 33   62 39 30 61 A3 00 23 00    0.0 2cf3b90a�.#.
-	0000E0    31 33 38 2F 31 30 32 20   31 20 32 37 30 2F 31 30    138/102 1 270/10
-	0000F0    31 20 32 30 39 2F 32 30   39 20 31 30 33 2F 30 20    1 209/209 103/0 
-	000100    33 35 35 02 00 02 00 02   00 03 00 08 00 01 00 8A    355............�
-	000110    00 66 00 00 00 00 00 00   00 00 00 00 00 00 00 00    .f..............
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           26              Header File (*.SHD) Format
-
-
-	Contents of example header:
-	--------------------------
-	id                   SHD^Z
-	type                 0000h
-	version              0120h
-	length               245
-	attr                 0000h
-	auxattr              00000000h
-	netattr              00000000h
-	when_written         Sat Nov 27 17:57:10 1993
-	when_imported        Tue Jan 04 15:54:21 1994
-	number               1
-	thread_orig          0
-	thread_next          0
-	thread_first         0
-	reserved[16]         
-	offset               0
-	total_dfields        2
-	
-	dfield[0].type       00h
-	dfield[0].offset     0
-	dfield[0].length     330
-	dfield[1].type       02h
-	dfield[1].offset     330
-	dfield[1].length     83
-	
-	hfield[0].type       00h
-	hfield[0].length     19
-	hfield[0]_dat        Marianne Montgomery
-	hfield[1].type       30h
-	hfield[1].length     12
-	hfield[1]_dat        Carol Gaiser
-	hfield[2].type       60h
-	hfield[2].length     7
-	hfield[2]_dat        Farnham
-	hfield[3].type       A4h
-	hfield[3].length     20
-	hfield[3]_dat        1:138/102.0 2cf80576
-	hfield[4].type       A5h
-	hfield[4].length     20
-	hfield[4]_dat        1:343/100.0 2cf3b90a
-	hfield[5].type       A3h
-	hfield[5].length     35
-	hfield[5]_dat        138/102 1 270/101 209/209 103/0 355
-	hfield[6].type       02h
-	hfield[6].length     2
-	hfield[6]_dat        02 00
-	hfield[7].type       03h
-	hfield[7].length     8
-	hfield[7]_dat        01 00 8A 00 66 00 00 00
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           27              Header File (*.SHD) Format
-
-
-	Fixed Portion Field descriptions:
-	--------------------------------
-	Id:
-	This field (regardless of the header type or version) must always contain the
-	the string "SHD^Z". This is to aid in the restoration of a corrupted header
-	file and give a visual indication of the beginning of a new header record when
-	viewing dumps of the header file.
-	
-	Type:
-	This is the message header type. Only one type is currently defined by this
-	specification (type 0). Any and all future header types will have the first
-	4 fields (10 bytes) in the same format of type 0. This allows other types
-	(with different lengths) to be skipped because the 4th field (length) will
-	always be in the same position.
-	
-	Version:
-	This is the version of this header type. This specification defines version
-	1.21 of message header type 0 (stored as 121h).
-	
-	Length:
-	This is the total length of this message header record (including both fixed
-	and variable length portions, but NOT including unused block space).
-	
-	Attr:
-	This is a bit field (16-bit) containing basic message attributes (flags) for
-	this message. An exact duplicate of this field is stored in the index file as
-	well. They must always match.
-	
-	Auxattr:
-	This is a bit field (32-bit) containing the auxillary attributes (flags) for
-	this message. The attributes stored in this variable are more specific in
-	nature and less critical than those in the Attr field.
-	
-	Netattr:
-	This is a bit field (32-bit) containing the network attributes (flags) for this
-	message. The attributes stored in this variable are related solely to message
-	networking.
-	
-	When_written:
-	This is the date and time when the message was originally created.
-	
-	When_imported:
-	This is the date and time when the message was posted on or imported into the
-	local message system.
-	
-	Number:
-	This is the message's unique serial number (from 1 to FFFFFFFFh). This field
-	is duplicated in the index file. They must always match.
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           28              Header File (*.SHD) Format
-
-
-	Thread_orig:
-	If this message is a reply, then this field contains the number of the original
-	message that was replied to. If this message was not a reply, this field will
-	contain the value 0.
-	
-	Thread_next:
-	If this message is a reply, and there are later replies to that message
-	(the message number contained in the Thread_orig field), then this field will
-	contain the number of the next reply in the chain. If this message is the only
-	reply to the orignal message, this field will contain the value 0.
-	
-	Thread_first:
-	If there are any replies to this message (after it has been posted), this field
-	will contain the number of the first reply to this message. If there are no
-	replies to this message, this field will contain the value 0.
-	
-	Reserved:
-	Unused bytes, reserved for future definition in the message header type 0
-	specification.
-	
-	Offset:
-	The byte offset into the data file, specifying the start of the buffer for
-	all data associated with this message. This value must be either 0 or modula
-	256. When retrieving the actual data portion of data fields, the physical
-	offset into the file will be the offset of the message data buffer (this field)
-	plus the offset of the individual data field (msghdr_t.offset+dfield_t.offset).
-	
-	Total_dfields:
-	This field contains the total number of data fields associated with this
-	message. The value of this field must match the actual number of data fields
-	stored in the header (dfield_t data types following the fixed portion of the
-	message header).
-	
-	
-	Variable Portion Field descriptions:
-	-----------------------------------
-	See the Header Field Type and Data Field Type sections for the descriptions
-	of the values contained in these fields.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           29              Header File (*.SHD) Format
-
-
-	Message Header Block Allocation (*.SHA)
-	=======================================
-	
-	If this message base uses the Hyper Allocation storage method (the
-	SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-	not created or used.
-	
-	This file contains no header or signature data. Each byte (uchar) in the file
-	specifies the allocation state of the corresponding 256 byte block in the
-	header (*.SHD) file. A value of 0 indicates a free header block, and a value of
-	1 indicates an allocated block. Other non-zero values are undefined.
-	
-	This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           30   Header Allocation File (*.SHA) Format
-
-
-	Message Data (*.SDT)
-	====================
-	
-	This file contains no header or signature data. It contains the text and other
-	embedded data for the messages in a single message base. The data for each
-	message always begins on a 256 byte block boundary. The data in the unused
-	portion of a data block is undefined, but should be initialized to NULL
-	whenever possible.
-	
-	This file must always be opened DENY NONE (shareable).
-	
-	Data fields of type TEXT_BODY and TEXT_TAIL must have all trailing white space
-	and control characters removed (i.e. the last character of the data record
-	must be in the range 21h to FFh). The only exception to this rule, is if the
-	TEXT_BODY is terminated with multiple contiguous CRLFs, only the last CRLF
-	should be removed. A CRLF should always be appended to the text data when it is
-	displayed.
-	
-	When reading from this file, it is a good idea to make sure the message header
-	for the data being read is currently locked (though no single message header
-	should be locked for extended durations of time). This will insure that no
-	other application will write to this portion of the file while it's being
-	read (read from disk, not displayed).
-	
-	When using the Hyper Allocation storage method, the Status Info message base
-	header must be successfully locked before writing to this file and subsequently
-	unlocked.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           31                Data File (*.SDT) Format
-
-
-	Message Data Block Allocation (*.SDA)
-	=====================================
-	
-	If this message base uses the Hyper Allocation storage method (the
-	SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-	not created or used.
-	
-	This file contains no header or signature data. Each word (ushort) in the file
-	specifies the allocation state of the corresponding 256 byte block in the data
-	(*.SDT) file. A value of 0 indicates a free block, and a non-zero value
-	indicates the number of message header records associated with this message
-	data (most often 1). Each block can be used by up to 65,535 header records.
-	
-	This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           32     Data Allocation File (*.SDA) Format
-
-
-	CRC history for duplicate message checking (*.SCH)
-	==================================================
-	
-	This file is optional and contains no header or signature data. Each long word
-	(ulong) in the file contains a CRC-32 of previously posted/imported messages.
-	These CRCs can be used to check a candidate message for posting/import to be
-	sure the message isn't a duplicate created by human or program error. The
-	maximum number of CRCs to store is defined in the first message base header
-	record (smbstatus_t.max_crcs).
-	
-	The CRC is calculated on the first TEXT_BODY data field before any translations
-	are applied (e.g. encoding, compression, encryption).
-	
-	This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           33         CRC History File (*.SCH) Format
-
-
-	Header Field Types:
-	==================
-	
-	These are the defined valid values for hfield_t.type:
-	
-	Name     : SENDER
-	Value    : 00h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : Yes
-	Summary  : Name of agent that sent this message
-	
-	If blank (0 length or nulstr), assumed "Anonymous". If multiple SENDER fields
-	exist, then the message has been forwarded and the order of the fields in the
-	record must match the forwarding order (chronologically). When forwarding a
-	message, the original SENDER field should be left intact and new SENDER,
-	FORWARDED, and RECIPIENT fields added to the end of the record.
-	
-	
-	Name     : SENDERAGENT
-	Value    : 01h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : AGENT_PERSON or previous SENDERAGENT if exists
-	Summary  : Type of agent that sent this message
-	
-	If multiple SENDER fields exist, then the message has been forwarded. If any of the
-	forwarding agents is of a type other than AGENT_PERSON, then this field must
-	follow that SENDER field to specify the agent type.
-	
-	Name     : SENDERNETTYPE
-	Value    : 02h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : NET_NONE or previous SENDERNETTYPE if exists
-	Summary  : Type of network message was sent from
-	
-	If multiple SENDERNETADDR fields are included, a SENDERNETTYPE field should be
-	included before each to determine what data type the address is stored in.
-	
-	Name     : SENDERNETADDR
-	Value    : 03h
-	Data     : undef
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous SENDERNETADDR if exists
-	Summary  : Network address for agent that sent this message
-	
-	The SENDERNETTYPE field indicates the data type of this field. If the
-	SENDERNETTYPE is of type NET_INTERNET, the local-part of the Internet
-	address is optional. If the local-part separator character ('@') is omitted,
-	the SENDER field is assumed to be the local-part of the address.
-
-	_______________________________________________________________________________
-	Synchronet                           34                      Header Field Types
-
-
-	
-	Name     : SENDEREXT
-	Value    : 04h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous SENDEREXT if exists
-	Summary  : Extension of sending agent
-	
-	This field is useful for storing the sending agent's extension, when the
-	agent's extension binds more tightly than the agent's name.
-	
-	For example, Synchronet Multinode BBS Software stores local e-mail with the
-	sending and receiving agent's user numbers stored as their respective
-	extensions. This is done so that if a user name changes for some reason,
-	messages will not "disappear" from the user's mail box.
-	
-	If the SMB_EMAIL status header attribute is set, then the "From" field in the
-	index must contain the binary value of this field rather than the CRC-16 of the
-	SENDER (name) field.
-	
-	Name     : SENDERPOS
-	Value    : 05h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous SENDERPOS if exists
-	Summary  : Position of sending agent
-	
-	Primarily for documentary purposes, this field contains the position of the
-	sending agent (i.e. President, Sysop, C.E.O., MIS Director, etc).
-	
-	It can also be useful for getting a message or reply to the intended
-	recipient when the agent name is not located or is unknown, but the position
-	of the agent is known and specified.
-	
-	Name     : SENDERORG
-	Value    : 06h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous SENDERORG if exists
-	Summary  : Organization name of sending agent
-	
-	Primarily for documentary purposes, this field contains the organization to
-	which the sending agent belongs (i.e. Microsoft, Joe's BBS, SoCal User's Group,
-	etc).
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           35                      Header Field Types
-
-
-	Name     : AUTHOR
-	Value    : 10h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Default  : First SENDER
-	Summary  : Name of agent that created this message
-	
-	This field can only be added by the process that originally creates the
-	message. It should not be included if same as first SENDER field. If multiple
-	AUTHOR fields exist, then the message was created by multiple agents and is
-	considered valid. The order of multiple AUTHOR fields in the record is not
-	significant.
-	
-	Name     : AUTHORAGENT
-	Value    : 11h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDERAGENT or previous AUTHORAGENT if exists
-	Summary  : Type of agent that created this message
-	
-	This field can only be added by the process that originally creates the
-	message. It should not be included if same as first SENDERAGENT field. If
-	multiple AUTHOR fields exist, then the message was created by multiple agents
-	and if the agent type for any of the authors is other than AGENT_PERSON, an
-	AUTHORAGENT field must follow to specify the agent type.
-	
-	Name     : AUTHORNETTYPE
-	Value    : 12h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDERNETTYPE or previous AUTHORNETTYPE if exists
-	Summary  : Type of network this author is member of
-	
-	Name     : AUTHORNETADDR
-	Value    : 13h
-	Data     : undef
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDERNETADDR or previous AUTHORNETADDR if exists
-	Summary  : Network address of this author
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           36                      Header Field Types
-
-
-	Name     : AUTHOREXT
-	Value    : 14h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDEREXT or previous AUTHOREXT if exists
-	Summary  : Extension of this author
-	
-	Name     : AUTHORPOS
-	Value    : 15h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDERPOS or previous AUTHORPOS if exists
-	Summary  : Position of this author
-	
-	Name     : AUTHORORG
-	Value    : 16h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : SENDERORG or previous AUTHORORG if exists
-	Summary  : Organization this author belongs to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           37                      Header Field Types
-
-
-	Name     : REPLYTO
-	Value    : 20h
-	Data     : ASCII
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDER
-	Summary  : Name of agent that replies should go to
-	
-	Name     : REPLYTOAGENT
-	Value    : 21h
-	Data     : ushort
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDERAGENT
-	Summary  : Type of agent that replies should go to
-	
-	Name     : REPLYTONETTYPE
-	Value    : 22h
-	Data     : ushort
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDERNETTYPE
-	Summary  : Type of network that replies should go to
-	
-	Name     : REPLYTONETADDR
-	Value    : 23h
-	Data     : undef
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDERNETADDR
-	Summary  : Network address that replies should go to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           38                      Header Field Types
-
-
-	Name     : REPLYTOEXT
-	Value    : 24h
-	Data     : ASCII
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDEREXT
-	Summary  : Extension of agent that replies should go to
-	
-	Name     : REPLYTOPOS
-	Value    : 25h
-	Data     : ASCII
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDERPOS
-	Summary  : Position of agent that replies should go to
-	
-	Name     : REPLYTOORG
-	Value    : 26h
-	Data     : ASCII
-	Multiple : Yes, but only last is valid
-	Required : No
-	Default  : SENDERORG
-	Summary  : Organization of agent that replies should go to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           39                      Header Field Types
-
-
-	Name     : RECIPIENT
-	Value    : 30h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : Yes
-	Default  : "All"
-	Summary  : Name of agent to receive this message
-	
-	If multiple RECIPIENT fields exist, the message has been forwarded and for each
-	additional RECIPIENT field (after the initial RECIPIENT), there should be a
-	FORWARDED field. The order of the RECIPIENT fields in the record must match the
-	order in which the message was sent and forwarded (chronologically).
-	
-	Name     : RECIPIENTAGENT
-	Value    : 31h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : AGENT_PERSON or previous RECIPIENTAGENT if exists
-	Summary  : Type of agent to receive this message
-	
-	If multiple RECIPIENT fields exist, the message has been forwarded. If any of
-	the recipient agents are of a type other than AGENT_PERSON, this field must
-	follow the RECIPIENT field to specify the agent type.
-	
-	Name     : RECIPIENTNETTYPE
-	Value    : 32h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : NET_NONE or previous RECIPIENTNETTYPE if exists
-	Summary  : Type of network to receive this message
-	
-	Name     : RECIPIENTNETADDR
-	Value    : 33h
-	Data     : undef
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous RECIPIENTNETADDR if exists
-	Summary  : Address of network to receive this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           40                      Header Field Types
-
-
-	Name     : RECIPIENTEXT
-	Value    : 34h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous RECIPIENTEXT if exists
-	Summary  : Extension of agent to receive this message
-	
-	If SMB_EMAIL status header attribute is set, then the "To" field in the index
-	must contain the binary value of this field rather than the CRC-16 of the
-	RECIPIENT (name) field. This is the case specifically with the local e-mail
-	message base on a Synchronet BBS.
-	
-	Name     : RECIPIENTPOS
-	Value    : 35h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous RECIPIENTPOS if exists
-	Summary  : Position of agent to receive this message
-	
-	Name     : RECIPIENTORG
-	Value    : 36h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : Previous RECIPIENTORG if exists
-	Summary  : Type of agent to receive this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           41                      Header Field Types
-
-
-	Name     : FORWARDTO
-	Value    : 40h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Name of agent this message is to be forwarded to
-	
-	Name     : FORWARDTOAGENT
-	Value    : 41h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTAGENT or previous FORWARDTOAGENT if exists
-	Summary  : Type of agent this message is to be forwarded to
-	
-	Name     : FORWARDTONETTYPE
-	Value    : 42h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTNETTYPE or previous FORWARDTONETTYPE if exists
-	Summary  : Type of network this message is to be forwarded to
-	
-	Name     : FORWARDTONETADDR
-	Value    : 43h
-	Data     : undef
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTNETADDR or previous FORWARDTONETADDR if exists
-	Summary  : Network address this message is to be forwarded to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           42                      Header Field Types
-
-
-	Name     : FORWARDTOEXT
-	Value    : 44h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTEXT or previous FORWARDTOEXT if exists
-	Summary  : Extension of agent this message is to be forwarded to
-	
-	Name     : FORWARDTOPOS
-	Value    : 45h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTPOS or previous FORWARDTOPOS if exists
-	Summary  : Position of agent this message is to be forwarded to
-	
-	Name     : FORWARDTOORG
-	Value    : 46h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTORG or previous FORWARDTOORG if exists
-	Summary  : Organization of agent this message is to be forwarded to
-	
-	Name     : FORWARDED
-	Value    : 48h
-	Data     : when_t
-	Multiple : Yes, order significant
-	Required : Yes, if forwarded
-	Summary  : Date/Time this message was forwarded to another agent
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           43                      Header Field Types
-
-
-	Name     : RECEIVEDBY
-	Value    : 50h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : Yes, if receiving agent is other than RECIPIENT
-	Summary  : Name of agent that received this message
-	
-	Name     : RECEIVEDBYAGENT
-	Value    : 51h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTAGENT or previous RECEIVEDBYAGENT if exists
-	Summary  : Type of agent that received this message
-	
-	Name     : RECEIVEDBYNETTYPE
-	Value    : 52h
-	Data     : ushort
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTNETTYPE or previous RECEIVEDBYNETTYPE if exists
-	Summary  : Type of network that received this message
-	
-	Name     : RECEIVEDBYNETADDR
-	Value    : 53h
-	Data     : undef
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTNETADDR or previous RECEIVEDBYNETADDR if exists
-	Summary  : Network address that received this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           44                      Header Field Types
-
-
-	Name     : RECEIVEDBYEXT
-	Value    : 54h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTEXT or previous RECEIVEDBYEXT if exists
-	Summary  : Extension of agent that received this message
-	
-	Name     : RECEIVEDBYPOS
-	Value    : 55h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTPOS or previous RECEIVEDBYPOS if exists
-	Summary  : Position of agent that received this message
-	
-	Name     : RECEIVEDBYORG
-	Value    : 56h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Default  : RECIPIENTORG or previous RECEIVEDBYORG if exists
-	Summary  : Organization of agent that received this message
-	
-	Name     : RECEIVED
-	Value    : 58h
-	Data     : when_t
-	Multiple : Yes, order significant
-	Required : Yes, if received
-	Default  : NULL
-	Summary  : Date/Time this message was received
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           45                      Header Field Types
-
-
-	Name     : SUBJECT
-	Value    : 60h
-	Data     : ASCII
-	Multiple : No
-	Required : Yes, but may be blank (0 length or nulstr)
-	Summary  : Subject/title of message
-	
-	Name     : SUMMARY
-	Value    : 61h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Summary  : Summary of message contents, created by AUTHOR
-	
-	Name     : COMMENT
-	Value    : 62h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Comment about this message, created by SENDER
-	
-	This field is useful for adding notes to a message when forwarding to a new
-	recipient.
-	
-	Name     : CARBONCOPY
-	Value    : 63h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : List of agents this message was also sent to
-	
-	This field is optional and only for the use of notifying the recipient of who
-	else received the message.
-	
-	Name     : GROUP
-	Value    : 64h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Name of group of users to receive message on recipient system
-	
-	This field is used when sending to a group name across a network, where the
-	group can be expanded into multiple header records for each agent on the
-	destination system.
-	
-	Name     : EXPIRATION
-	Value    : 65h
-	Data     : when_t
-	Multiple : No
-	Required : No
-	Summary  : Date/Time that this message will expire
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           46                      Header Field Types
-
-
-	Name     : PRIORITY
-	Value    : 66h
-	Data     : ulong
-	Multiple : No
-	Required : No
-	Default  : 0
-	Summary  : Message priority (0 is lowest, FFFFFFFFh is highest)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           47                      Header Field Types
-
-
-	Name     : FILEATTACH
-	Value    : 70h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Name/file specification of attached file(s)
-	
-	Name of attached file(s). Wildcards allowed. MSG_FILEATTACH attribute must be
-	set. If the MSG_FILEATTACH attribute is set but this field is not included,
-	the SUBJECT field is assumed to be the filename(s).
-	
-	Name     : DESTFILE
-	Value    : 71h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Destination name for attached file(s)
-	
-	Wildcards allowed. FILEATTACH field must also be included.
-	
-	Name     : FILEATTACHLIST
-	Value    : 72h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Name of ASCII list of attached filenames
-	
-	Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-	MSG_FILEATTACH attribute must be set.
-	
-	Name     : DESTFILELIST
-	Value    : 73h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Name of ASCII list of destination filenames
-	
-	Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-	
-	Name     : FILEREQUEST
-	Value    : 74h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Name of requested file
-	
-	Wildcards allowed. MSG_FILEREQUEST attribute must be set
-	
-	Name     : FILEPASSWORD
-	Value    : 75h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Password for FILEREQUEST
-
-	_______________________________________________________________________________
-	Synchronet                           48                      Header Field Types
-
-
-	
-	Name     : FILEREQUESTLIST
-	Value    : 76h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Name of ASCII list of filenames to request
-	
-	Wildcards allowed.
-	
-	Name     : FILEPASSWORDLIST
-	Value    : 77h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Name of ASCII list of passwords for FILEREQUESTLIST
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           49                      Header Field Types
-
-
-	Name     : IMAGEATTACH
-	Value    : 80h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached image file for display
-	
-	MSG_FILEATTACH attribute must be set. See Image Types for valid
-	mattach_t.type values.
-	
-	Name     : ANIMATTACH
-	Value    : 81h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached graphical animation file for display
-	
-	MSG_FILEATTACH attribute must be set. See Animation Types for valid
-	mattach_t.type values.
-	
-	Name     : FONTATTACH
-	Value    : 82h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached font definition file
-	
-	MSG_FILEATTACH attribute must be set. See Font Types for valid mattach_t.type
-	values.
-	
-	Name     : SOUNDATTACH
-	Value    : 83h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached sound file for playback
-	
-	MSG_FILEATTACH attribute must be set. See Sound Types for valid mattach_t.type
-	values.
-	
-	Name     : PRESENTATTACH
-	Value    : 84h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached presentation definition file
-	
-	MSG_FILEATTACH attribute must be set. See Present Types for valid
-	mattach_t.type values.
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           50                      Header Field Types
-
-
-	Name     : VIDEOATTACH
-	Value    : 85h
-	Data     : vattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of attached interleaved video/sound file
-	
-	MSG_FILEATTACH attribute must be set. See Video Types for valid
-	vattach_t.type values and Video Compression Types for valid vattach_t.comp
-	values.
-	
-	Name     : APPDATAATTACH
-	Value    : 86h
-	Data     : mattach_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Name of attached application data file for process/display
-	
-	MSG_FILEATTACH attribute must be set. See Application Data Types for valid
-	mattach_t.type values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           51                      Header Field Types
-
-
-	Name     : IMAGETRIGGER
-	Value    : 90h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of image file to trigger for display
-	
-	See Image Types for valid typestr_t.type values.
-	
-	Name     : ANIMTRIGGER
-	Value    : 91h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of animation file to trigger for display
-	
-	See Animation Types for valid typestr_t.type values.
-	
-	Name     : FONTTRIGGER
-	Value    : 92h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of font definition file to trigger
-	
-	See Font Types for valid typestr_t.type values.
-	
-	Name     : SOUNDTRIGGER
-	Value    : 93h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of sound file to trigger for playback
-	
-	See Sound Types for valid typestr_t.type values.
-	
-	Name     : PRESENTTRIGGER
-	Value    : 94h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of presentation definition file to trigger
-	
-	See Present Types for valid typestr_t.type values.
-	
-	Name     : VIDEOTRIGGER
-	Value    : 95h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of interleaved video/sound file to trigger
-	
-	See Video Types for valid typestr_t.type values.
-	
-
-	_______________________________________________________________________________
-	Synchronet                           52                      Header Field Types
-
-
-	Name     : APPDATATRIGGER
-	Value    : 96h
-	Data     : typestr_t
-	Multiple : Yes, order significant
-	Required : No
-	Summary  : Type and filename of application data file to trigger
-	
-	See Application Data Types for valid typestr_t.type values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           53                      Header Field Types
-
-
-	Name     : FIDOCTRL
-	Value    : A0h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Format   : keyword ":" [" "] appdata
-	Summary  : FTS/FSC-compliant control information line
-	
-	Any FidoNet FTS/FSC-compliant control information ("kludge") line that
-	does not have an equivalent representation here. All data not unique to the
-	actual control line, including leading and trailing white space, Ctrl-A (01h)
-	character and terminating CR must be ommited. Defined in FTS-0001.
-	
-	Name     : FIDOAREA
-	Value    : A1h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Summary  : FTN EchoMail conference name.
-	
-	Defined in FTS-0004.
-	
-	Name     : FIDOSEENBY
-	Value    : A2h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Format   : net"/"node [" "[net"/"]node] [...]
-	Summary  : Used to store two-dimensional (net/node) SEEN-BY information
-	
-	Often used in FTN EchoMail environments. Only the actual SEEN-BY data is stored
-	and SEEN-BY: is stripped along with any leading and trailing white space
-	characters. Defined in FTS-0004.
-	
-	Name     : FIDOPATH
-	Value    : A3h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Format   : net"/"node [" "[net"/"]node] [...]
-	Summary  : Used to store two-dimensional (net/node)
-	
-	Defined in FTS-0004. ^aPATH: is stripped along with any leading and trailing
-	white space characters.
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           54                      Header Field Types
-
-
-	Name     : FIDOMSGID
-	Value    : A4h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Format   : origaddr " " serialno
-	Summary  : MSGID field as specified in FTS-0009.
-	
-	Name     : FIDOREPLYID
-	Value    : A5h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Format   : origaddr " " serialno
-	Summary  : REPLY field as specified in FTS-0009.
-	
-	Name     : FIDOPID
-	Value    : A6h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Format   : pID " " version [" "serialno]
-	Summary  : Indentification string of program that created this message
-	
-	Defined FSC-0046. "^aPID:" and any white space is not included.
-	
-	Name     : FIDOFLAGS
-	Value    : A7h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Used to store the FTN FLAGS kludge information
-	
-	Note that all FLAG options that have binary representation in the message
-	header must be removed from the FLAGS string prior to storing it. Only the
-	actual flags option string is stored and ^aFLAGS is stripped along with any
-	leading and trailing white space characters. Defined in FSC-0053.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           55                      Header Field Types
-
-
-	Name     : RFC822HEADER
-	Value    : B0h
-	Data     : ASCII
-	Multiple : Yes, order significant
-	Required : No
-	Format   : field-name ":" [field-body] [CRLF]
-	Summary  : Undefined RFC-822 header field
-	
-	Internet Message storage format, that does not have an equivalent
-	representation here. Folded header fields are allowed. Terminating CRLF may be
-	ommited.
-	
-	Name     : RFC822MSGID
-	Value    : B1h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Format   : "<" addr-spec ">"
-	Summary  : Message-ID field as specified in RFC-822.
-	
-	Name     : RFC822REPLYID
-	Value    : B2h
-	Data     : ASCII
-	Multiple : No
-	Required : No
-	Format   : "<" addr-spec ">"
-	Summary  : In-Reply-To field as specified in RFC-822.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           56                      Header Field Types
-
-
-	Name     : UNKNOWN
-	Value    : F0h
-	Data     : undef
-	Multiple : Yes
-	Required : No
-	Summary  : Undefined header field of undefined type
-	
-	This field is useful for retaining binary header fields (that do not have an
-	equivalent representation here) between message storage formats.
-	
-	Name     : UNKNOWNASCII
-	Value    : F1h
-	Data     : ASCII
-	Multiple : Yes
-	Required : No
-	Summary  : Undefined header field of type ASCII
-	
-	This field is useful for retaining ASCII header fields (that do not have an
-	equivalent representation here) between message storage formats.
-	
-	Name     : UNUSED
-	Value    : FFh
-	Data     : undef
-	Multiple : Yes
-	Required : No
-	Summary  : Unused (deleted) header field
-	
-	The data contained in this header field is of an unknown type and should not be
-	processed.
-	
-	
-	Note:
-	----
-	Specifically, not defined are the values F000h through FFFFh. These values
-	are to be used for user or system defined header fields. Digital Dynamics
-	requests that any developers or organizations that wish to have additional
-	header fields added to this specification notify Digital Dynamics through any
-	of the contact methods listed at the beginning of this document.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           57                      Header Field Types
-
-
-	Data Field Types:
-	================
-	
-	These are the defined valid values for dfield_t.type:
-	
-	
-	Val Name                Data        Description
-	--- ----                ----        -----------
-	00h TEXT_BODY           mtext_t     Displayable text (body of message).
-	                                    Included in duplicate message checking.
-	                                    All terminating white space and control
-	                                    characters are to be truncated from data
-	                                    (except when multiple contiguous CRLFs
-	                                    terminate the text, only the last CRLF
-	                                    is removed).
-	
-	01h TEXT_SOUL           mtext_t     Non-displayed text.
-	                                    Not normally displayed. Not necessarily
-	                                    displayable.
-	                                    Included in duplicate message checking.
-	
-	02h TEXT_TAIL           mtext_t     Displayable text (tag/tear/origin lines,
-	                                    etc).
-	                                    Not included in duplicate message checking.
-	                                    All terminating white space and control
-	                                    characters are to be truncated from data.
-	
-	03h TEXT_WING           mtext_t     Non-displayed text.
-	                                    Not normally displayed. Not necessarily
-	                                    displayable.
-	                                    Not included in duplicate message checking.
-	
-	10h FTEXT_BODY          ftext_t     Formatted equivalent of TEXT_BODY to be
-	                                    displayed in place of TEXT_BODY if format
-	                                    is supported. See Image Types for valid
-	                                    values of ftext_t.type.
-	
-	12h FTEXT_TAIL          ftext_t     Formatted equivalent of TEXT_TAIL to be
-	                                    displayed in place of TEXT_TAIL if format
-	                                    is supported. See Image Types for valid
-	                                    values of ftext_t.type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           58                        Data Field Types
-
-
-	20h IMAGEEMBED          membed_t    Type and data of embedded raster image file
-	                                    for display.
-	                                    See Image Types for valid membed.type
-	                                    values.
-	
-	21h ANIMEMBED           membed_t    Type and data of embedded graphical
-	                                    animation file for display.
-	                                    See Animation Types for valid membed.type
-	                                    values.
-	
-	22h FONTEMBED           membed_t    Type and data of embedded font definition
-	                                    file. See Font Types for valid
-	                                    membed_t.type values.
-	
-	23h SOUNDEMBED          membed_t    Type and data of embedded sound file for
-	                                    playback.
-	                                    See Sound Types for valid membed_t.type
-	                                    values.
-	
-	24h PRESENTEMBED        membed_t    Type and data of embedded presentation
-	                                    definition file.
-	                                    See Present Types for valid membed_t.type
-	                                    values.
-	
-	25h VIDEOEMBED          vembed_t    Type and data of embedded video/sound file
-	                                    for playback.
-	                                    See Video Types for valid vembed_t.type
-	                                    values.
-	                                    See Video Compression Types for valid
-	                                    vembed_t.comp values.
-	
-	26h APPDATAEMBED        membed_t    Type and data of embedded application data
-	                                    file for process/display.
-	                                    See Application Data Types for valid
-	                                    membed_t.type values.
-	
-	FFh UNUSED              undef       Space allocated for future update/expansion
-	
-	
-	Specifically, not defined are the values F000h through FFFFh. These values
-	are to be used for user or system defined data fields. Digital Dynamics
-	requests that any developers or organizations that wish to have additional
-	data fields added to this specification notify Digital Dynamics through any
-	of the contact methods listed at the beginning of this document.
-	
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           59                        Data Field Types
-
-
-	Message Attributes:
-	------------------
-	
-	These are the bit values for idxrec_t.attr and msghdr_t.attr:
-	
-	MSG_PRIVATE         (1<<0)  // Private
-	MSG_READ            (1<<1)  // Read by addressee
-	MSG_PERMANENT       (1<<2)  // Permanent
-	MSG_LOCKED          (1<<3)  // Msg is locked, no editing possible
-	MSG_DELETE          (1<<4)  // Msg is marked for deletion
-	MSG_ANONYMOUS       (1<<5)  // Anonymous author
-	MSG_KILLREAD        (1<<6)  // Delete message after it has been read
-	MSG_MODERATED       (1<<7)  // This message must be validated before export
-	MSG_VALIDATED       (1<<8)  // This message has been validated by a moderator
-	
-	
-	Auxillary Attributes:
-	--------------------
-	These are the bit values for msghdr_t.auxattr:
-	
-	MSG_FILEREQUEST     (1<<0)  // File request
-	MSG_FILEATTACH      (1<<1)  // File(s) attached to Msg
-	MSG_TRUNCFILE       (1<<2)  // Truncate file(s) when sent
-	MSG_KILLFILE        (1<<3)  // Delete file(s) when sent
-	MSG_RECEIPTREQ      (1<<4)  // Return receipt requested
-	MSG_CONFIRMREQ      (1<<5)  // Confirmation receipt requested
-	MSG_NODISP          (1<<6)  // Msg may not be displayed to user
-	
-	
-	Network Attributes:
-	------------------
-	These are the bit values for msghdr_t.netattr:
-	
-	MSG_LOCAL           (1<<0)  // Msg created locally
-	MSG_INTRANSIT       (1<<1)  // Msg is in-transit
-	MSG_SENT            (1<<2)  // Sent to remote
-	MSG_KILLSENT        (1<<3)  // Kill when sent
-	MSG_ARCHIVESENT     (1<<4)  // Archive when sent
-	MSG_HOLD            (1<<5)  // Hold for pick-up
-	MSG_CRASH           (1<<6)  // Crash
-	MSG_IMMEDIATE       (1<<7)  // Send Msg now, ignore restrictions
-	MSG_DIRECT          (1<<8)  // Send directly to destination
-	MSG_GATE            (1<<9)  // Send via gateway
-	MSG_ORPHAN          (1<<10) // Unknown destination
-	MSG_FPU             (1<<11) // Force pickup
-	MSG_TYPELOCAL       (1<<12) // Msg is for local use only
-	MSG_TYPEECHO        (1<<13) // Msg is for conference distribution
-	MSG_TYPENET         (1<<14) // Msg is direct network mail
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           60                      Message Attributes
-
-
-	Translation Types:
-	-----------------
-	
-	Definition for values of *.xlat[x]:
-	
-	XLAT_NONE           0       // No translation/End of translation list
-	XLAT_LF2CRLF        1       // Expand sole LF to CRLF
-	XLAT_ESCAPED        2       // 7-bit ASCII escaping for ctrl and 8-bit data
-	XLAT_HUFFMAN        3       // Static and adaptive Huffman coding compression
-	XLAT_LZW            4       // LZW (Lempel-Ziv-Welch) encoding for compression
-	                            // Terry Welch, IEEE Computer Vol 17, No 6
-	                            // June 1984, pp 8-19
-	XLAT_LZC            5       // LZC (modified LZW) encoding for compression
-	                            // Unix compress program
-	XLAT_RLE            6       // Run length encoding compression
-	XLAT_IMPLODE        7       // Implode compression (PKZIP v1.x)
-	XLAT_SHRINK         8       // Shrink compression (PKZIP v1.x)
-	XLAT_LZH            9       // LZH dynamic Huffman coding
-	                            // Haruyasu Yoshizaki, LHarc
-	                            // November, 1988
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           61                       Translation Types
-
-
-	Agent Types:
-	-----------
-	
-	AGENT_PERSON        0       // To or from person
-	AGENT_PROCESS       1       // Unknown process, identified by agent name
-	
-	Agent types E000h through EFFFh are reserved for Synchronet process types
-	(defined specifically by Digital Dynamics).
-	
-	Note:
-	----
-	Specifically not defined are agent types F000h through FFFFh. These values
-	are to be used for user or system defined agent types. Digital Dynamics
-	requests that any developers or organizations that wish to have additional
-	agent types added to this specification notify Digital Dynamics through any
-	of the contact methods listed at the beginning of this document.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           62                             Agent Types
-
-
-	Network Types:
-	-------------
-	
-	                            // Net Type             Address Format
-	                            // -----------------------------------
-	NET_NONE            0       // Locally created      none
-	NET_UNKNOWN         1       // Unknown              undef
-	NET_FIDO            2       // FTN network          fidoaddr_t
-	NET_POSTLINK        3       // PostLink network     none
-	NET_QWK             4       // QWK based network    ASCII
-	NET_INTERNET        5       // The Internet         ASCII
-	NET_WWIV            6       // WWIV based network   ulong
-	NET_MHS             7       // MHS network          ASCII
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           63                           Network Types
-
-
-	Media Types:
-	===========
-	
-	Image Types:
-	-----------
-	
-	IMAGE_UNKNOWN       0x00    // Use image signature header to determine format
-	IMAGE_ASC           0x01    // ASCII text/IBM extended ASCII graphics
-	IMAGE_ANS           0x02    // ANSI X3.64 terminal escape sequences
-	IMAGE_AVT           0x03    // AVATAR terminal escape sequences
-	IMAGE_LVI           0x04    // LVI terminal escape sequences
-	IMAGE_GIF           0x05    // Compuserve Graphics Interchange Format (GIF)
-	IMAGE_TIF           0x06    // Tagged Image Format (AKA TIFF)
-	IMAGE_JPG           0x07    // Joint Photographers Electronics Group (JPEG)
-	IMAGE_T16           0x08    // TrueVision 16-bit bitmap (TGA)
-	IMAGE_T24           0x09    // TrueVision 24-bit bitmap (TGA)
-	IMAGE_T32           0x0a    // TrueVision 32-bit bitmpa (TGA)
-	IMAGE_PCX           0x0b    // ZSoft PaintBrush graphics
-	IMAGE_BMP           0x0c    // Windows bitmap
-	IMAGE_RLE           0x0d    // Windows bitmap (compressed)
-	IMAGE_DIB           0x0e    // Display independant bitmap
-	IMAGE_PCD           0x0f    // Kodak PhotoCD
-	IMAGE_G3F           0x10    // Group 3 FAX
-	IMAGE_EPS           0x11    // Ecapsulated PostScript
-	IMAGE_RTF           0x12    // Rich text format
-	IMAGE_RIP           0x13    // Remote Imaging Protocol Script (RIPscrip)
-	IMAGE_NAP           0x14    // NAPLPS
-	IMAGE_CDR           0x15    // Corel Draw!
-	IMAGE_CGM           0x16    // Computer graphics metafile
-	IMAGE_WMF           0x17    // Windows metafile
-	IMAGE_DFX           0x18    // Autodesk AutoCAD
-	IMAGE_IFF           0x19    // Amiga Interchange File Format
-	
-	
-	Animation Types:
-	---------------
-	
-	ANIM_UNKNOWN        0       // Use file signature header to determine format
-	ANIM_FLI            1       // Autodesk animator
-	ANIM_FLC            2       // Autodesk
-	ANIM_GL             3       // Grasprt
-	ANIM_IFF            4       // Amiga Interchange File Format
-	
-	
-	Video Types:
-	-----------
-	
-	VIDEO_UNKNOWN       0       // Use file signature header to determine format
-	VIDEO_QTIME         1       // Apple Quick-time
-	VIDEO_FQTIME        2       // Apple Flattened Quick-time
-	VIDEO_AVI           3       // Windows Auto/Video Interleave
-	VIDEO_ULT           4       // OS/2 Ultimotion
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           64                             Media Types
-
-
-	Video Compression Types:
-	-----------------------
-	
-	VCOMP_UNKNOWN       0       // Use file signature header to determine codec
-	VCOMP_RLE           1       // Apple animation
-	VCOMP_SMC           2       // Apple graphics
-	VCOMP_RPZA          3       // Apple video
-	VCOMP_KLIC          4       // Captain crunch
-	VCOMP_CVID          5       // CinePak
-	VCOMP_RT21          6       // Intel indeo R2
-	VCOMP_IV31          7       // Intel indeo R3
-	VCOMP_YVU9          8       // Intel YVU9
-	VCOMP_JPEG          9       // JPEG
-	VCOMP_MRLE          10      // Microsoft RLE
-	VCOMP_MSVC          11      // Microsoft video 1
-	
-	
-	Font Types:
-	----------
-	
-	FONT_UNKNOWN        0       // Use file signature header to determine format
-	FONT_TTF            1       // Windows TrueType
-	FONT_PFB            2       // PostScript Type 1 Font Binary
-	FONT_PFM            3       // PostScript Type 1 Font Metric
-	FONT_AMIGA          4       // Amiga Bitmapped
-	FONT_AGFA           5       // CompuGraphic Fonts
-	
-	
-	Sound Types:
-	-----------
-	
-	SOUND_UNKNOWN       0       // Use file signature header to determine format
-	SOUND_MOD           1       // MOD format
-	SOUND_VOC           2       // Sound Blaster VOC format
-	SOUND_WAV           3       // Windows 3.1 WAV RIFF format
-	SOUND_MID           4       // MIDI format
-	SOUND_GMID          5       // General MIDI format (standardized patches)
-	SOUND_SMP           6       // Turtle Beach SampleVision format
-	SOUND_SF            7       // IRCAM format
-	SOUND_AU            8       // Sun Microsystems AU format
-	SOUND_IFF           9       // Amiga Interchange File Format
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           65                             Media Types
-
-
-	Application Data Types:
-	----------------------
-	
-	APPDATA_UNKNOWN     0       // Use file signature header to determine format
-	APPDATA_WORDPERFECT 1       // WordPerfect Document
-	APPDATA_WKS         2       // Lotus 123 Worksheet (?)
-	APPDATA_WK1         3       // Lotus 123 Worksheet rev 1
-	APPDATA_WK2         4       // Lotus 123 Worksheet rev 2
-	APPDATA_WK3         5       // Lotus 123 Worksheet rev 3
-	APPDATA_DBF         6       // dBase III data file
-	APPDATA_PDX         7       // Paradox data file
-	APPDATA_EXCEL       8       // Excel data file
-	APPDATA_QUATRO      9       // Borland Quatro Pro file
-	APPDATA_WORD        10      // Microsoft Word
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           66                             Media Types
-
-
-	Message Storage Pseudo Code
-	===========================
-	
-	The following is a "C like" pseudo code listing example of adding a message to
-	an SMB message base. SMBLIB contains C functions to do most of the following
-	operations. We are supplying this pseudo code as a general definition of the
-	order of required operations in writing to the message base. Many details have
-	been left out to simplify the code and to demonstrate only the basic
-	principles.
-	
-	shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-	sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-	sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-	
-	lock ( shd , smbhdr )
-	read ( shd , smbstatus )
-	
-	if ( smbstatus.attr & SMB_HYPERALLOC )
-	    msg.hdr.offset = filelength ( sdt )
-	
-	else {
-	    number_of_blocks = length_of_message_data / SDT_BLOCK_LEN
-	    if ( length_of_message_data % SDT_BLOCK_LEN )   /* unevenly divisible */
-	        number_of_blocks = number_of_blocks + 1
-	
-	    sda = open ( MSGBASE.SDA , READ/WRITE/DENY_ALL )
-	
-	    if ( fast_allocation_mode )
-	        seek ( sda , END_OF_FILE )
-	
-	    else {
-	        seek ( sda , BEGINNING_OF_FILE )
-	        while ( not end_of_file ( sda ) ) {
-	            read ( sda , allocated , number_of_blocks * 2 )
-	            if ( allocated = 0 ) {
-	                seek_backwards ( sda , number_of_blocks * 2 )
-	                break
-	            }
-	        }
-	    }
-	
-	    msg.hdr.offset = ( current_position ( sda ) / 2 ) * SDT_BLOCK_LEN
-	
-	    allocated = 1
-	
-	    write ( sda , allocated , number_of_blocks * 2 )
-	
-	    close ( sda )
-	}
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           67             Message Storage Pseudo Code
-
-
-	seek ( sdt , msg.hdr.offset )
-	
-	write ( sdt , message_data )
-	
-	if ( smbstatus.attr & SMB_HYPERALLOC )
-	    msg.idx.offset = filelength ( shd )
-	
-	else {
-	    number_of_blocks = length_of_message_header / SHD_BLOCK_LEN
-	    if ( length_of_message_header % SHD_BLOCK_LEN )   /* unevenly divisible */
-	        number_of_blocks = number_of_blocks + 1
-	
-	    sha = open ( MSGBASE.SHA , READ/WRITE/DENY_ALL )
-	
-	    if ( fast_allocation_mode )
-	        seek ( sha , END_OF_FILE )
-	
-	    else {
-	        seek ( sha , BEGINNING_OF_FILE )
-	        while ( not end_of_file ( sha ) ) {
-	            read ( sha , allocated , number_of_blocks )
-	            if ( allocated = 0 ) {
-	                seek_backwards ( sha , number_of_blocks )
-	                break
-	            }
-	        }
-	    }
-	
-	    msg.idx.offset = ( current_position ( sha ) * SHD_BLOCK_LEN )
-	    msg.idx.offset = msg.idx.offset + smbstatus.header_offset
-	
-	    allocated = 1
-	
-	    write ( sha , allocated , number_of_blocks )
-	
-	    close ( sha )
-	}
-	
-	seek ( shd , msg.idx.offset )
-	
-	msg.hdr.number = smbstatus.last_msg+1
-	
-	write ( shd , msg.hdr )
-	
-	smbstatus.total_msgs = smbstatus.total_msgs + 1
-	smbstatus.last_msg = msg.hdr.number
-	
-	write ( shd , smbstatus )
-	
-	write ( sid , msg.idx )
-	
-	unlock ( shd , smbstatus )
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           68             Message Storage Pseudo Code
-
-
-	Message Retrieval Pseudo Code
-	=============================
-	
-	shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-	sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-	sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-	
-	read ( sid , msg.idx )
-	
-	seek ( shd , msg.idx.offset )
-	
-	lock ( shd , msg.hdr )
-	
-	read ( shd , msg.hdr )
-	
-	seek ( sdt , msg.hdr.offset )
-	
-	read ( sdt , msg.hdr.data_length )
-	
-	unlock ( shd , msg.hdr )
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           69           Message Retrieval Pseudo Code
-
-
-	SMBUTIL
-	=======
-	
-	SMBUTIL is a utility that can perform various functions on an SMB message base.
-	The primary purpose of SMBUTIL is as an example to C programmers of how to use
-	the SMBLIB functions to access and modify an SMB message base. The complete C
-	source code for SMBUTIL is included and functions from it can be used or
-	modified by developers at their own discretion. The following files make up
-	SMBUTIL:
-	
-	SMBUTIL.EXE     Compiled and linked for 16-bit DOS (ready to run)
-	SMBUTIL.C       C functions
-	SMBUTIL.H       C definitions and variable prototypes
-	SMBUTIL.WAT     Makefile for Watcom C/C++ (type wmake -f smbutil.wat)
-	SMBUTIL.BOR     Makefile for Borland C/C++ (type make -f smbutil.bor)
-	
-	The usage syntax is as follows:
-	
-	SMBUTIL [/opts] cmd smb_filespec.shd
-	
-	where cmd is one or more of the following:
-	
-	       l[n] = list msgs starting at number n
-	       r[n] = read msgs starting at number n
-	       v[n] = view msg headers starting at number n
-	       k[n] = kill (delete) n msgs
-	       i<f> = import from text file f
-	       s    = display msg base status
-	       c    = change msg base status
-	       m    = maintain msg base - delete old msgs and msgs over max
-	       p[k] = pack msg base (k specifies minimum packable Kbytes)
-	
-	where opts is one or more of the following:
-	
-	       a    = always (force) packing
-	       z<n> = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)
-	
-	and smb_filespec is the base filename or file specification (wildcards) for the
-	message base. If wildcards are used, the ".SHD" extension must be specified.
-	
-	An example command line:
-	
-	SMBUTIL MP C:\SBBS\DATA\SUBS\*.SHD
-	
-	would maintain and pack all the message bases found in the C:\SBBS\DATA\SUBS
-	directory.
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           70                                 SMBUTIL
-
-
-	CHKSMB
-	======
-	
-	CHKSMB is a utility that performs a comprehensive analysis of a message base
-	to find any possible errors and calculate the number of packable bytes. It does
-	not "fix" a message base if any errors are found, it only reports the specific
-	errors (and exits with a non-zero error level). If any errors are reported,
-	packing the message base with SMBUTIL may rebuild the damaged files. If that
-	doesn't work, then use FIXSMB as a last resort.
-	
-	C source code for CHKSMB is also included as an example to programmers of how
-	to use SMBLIB functions.
-	
-	The usage syntax is as follows:
-	
-	CHKSMB [/opts] smb_filespec.shd
-	
-	where opts is one or more of the following:
-	
-	        q   = quiet mode (no beeps)
-	        s   = stop after an errored message base (for use with wildcards)
-	        p   = pause after an errored message base (wait for key press)
-	        t   = don't check for unsupported translation strings (faster)
-	        e   = display extended information on corrupted messages
-	
-	An example command line:
-	
-	CHKSMB /QP C:\SBBS\DATA\SUBS\*.SHD
-	
-	would check all the message bases in the C:\SBBS\DATA\SUBS directory, without
-	beeping on errors, and pausing after an errored message base.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           71                                  CHKSMB
-
-
-	FIXSMB
-	======
-	
-	FIXSMB is a utility that will rebuild the index and allocation files for a
-	message base. Since the message headers are not necessarily stored
-	sequentially, the order of the messages in the index may be changed when the
-	index is rebuilt. Messages are also re-numbered, so only use this program if
-	the index is corrupted and the messages are extremely important.
-	
-	C source code for FIXSMB is also included as an example to programmers of how
-	to use SMBLIB functions.
-	
-	The usage syntax is as follows:
-	
-	FIXSMB [/M] smb_file
-	
-	An example command line:
-	
-	FIXSMB \SBBS\DATA\MAIL
-	
-	Only use the "/M" command line switch if fixing an older Synchronet e-mail
-	message base (created with SBBS v2.1 or earlier). Once the SMB_EMAIL status
-	attr is set ("SMBUTIL S" will report a status attr of 1), the "/M" is not
-	required.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           72                                  FIXSMB
-
-
-	SMBLIB
-	======
-	
-	SMBLIB is a library of C functions for accessing and storing messages in an
-	SMB format message base. It can eliminate much of the development time for
-	developers that wish to use the library in whole or in part, or use the
-	functions as examples for their own message base function library. The library
-	consists of the following files:
-	
-	SMBDEFS.H       Constant definitions, macros, and data types
-	SMBLIB.H        Library constants and function prototypes
-	SMBLIB.C        Function definitions
-	SMBVARS.C       Global variable definitions (doubles as declaration file)
-	
-	For developers to use this library with their program, they must include the
-	"SMBLIB.H" header file at the top of each C file that uses any of the library
-	functions, global variables, data types, macros, and constants. This can be
-	done by simply adding the following line to each .C file:
-	
-	#include "smblib.h"
-	
-	If SMBLIB.H is included, there is no need to include SMBDEFS.H or SMBVARS.C.
-	
-	To link the library functions and variables with a main program, the files
-	SMBVARS.OBJ and SMBLIB.OBJ must be linked with the main program .OBJ files.
-	If the operating system is DOS, be sure that all .OBJ files are compiled for
-	the same memory model.
-	
-	Example MAKEFILEs for compiling and linking SMBUTIL with Borland C/C++
-	(SMBUTIL.BOR) and Watcom C/C++ (SMBUTIL.WAT) are included.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           73                                  SMBLIB
-
-
-	SMBDEFS.H
-	=========
-	
-	The SMBDEFS.H file contains important constant definitions and data types (also
-	defined in this document). If ever this document and SMBDEFS.H are inconsistent
-	with each other, then SMBDEFS.H is to be considered correct and this document
-	in error. If such a discrepency is found, please notifiy Digital Dynamics so it
-	can be corrected in a future revision of the specification.
-	
-	Most notable of the data types is a structure called smbmsg_t (not defined
-	in this document). It contains the fixed and variable portions of a message's
-	header record as well as convenience pointers to the sender's name
-	(smbmsg_t.to), recipient's name (smbmsg_t.from), network addresses, and more.
-	If multiple SENDER header fields are included (for example), then smbmsg_t.to
-	will point to the last SENDER header field in the header record. Convenience
-	pointers for other data items work in the same fasion if multiple header fields
-	of the same type exist in the header record.
-	
-	Variables of the smbmsg_t data type (and pointers to variables of smbmsg_t
-	type) are used as arguments to many of the SMBLIB functions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           74                               SMBDEFS.H
-
-
-	SMBVARS.C
-	=========
-	
-	The SMBVARS.C file contains definitions of the global variables used by the
-	SMBLIB functions. It is a fairly small file since their are a small number of
-	global variables (by design). This file is used for both definitions and
-	declarations, so no "extern" declarations need to be made in developers source
-	code as long as SMBVARS.C or (preferably) SMBLIB.H is included in the source
-	code.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           75                               SMBVARS.C
-
-
-	SMBLIB.H
-	=======
-	
-	The SMBLIB.H file contains prototypes of all the functions in the SMBLIB.C
-	file. It is necessary to include this file in C source code if any of the
-	SMBLIB functions are used. The following C source line will include this file:
-	
-	#include "smblib.h"
-	
-	and should be placed near the top of all C source files that use SMBLIB
-	functions, variables, constants, or data types.
-	
-	Function prototypes are necessary for compilers to know the correct calling
-	syntax of a function and detect incorrect usage. Prototypes are also useful
-	as a quick reference for programmers as to the correct calling syntax of a
-	specific function.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           76                                SMBLIB.H
-
-
-	SMBLIB.C
-	=======
-	
-	The SMBLIB.C file contains the actual SMBLIB library functions. This source
-	file is not a stand alone program, but instead must be compiled and linked
-	with a main source file to create the executable program.
-	
-	The functions in this file are organized in a logical order, but their order
-	is actually irrelevant to the compiling, linking, and execution of the
-	resulting program.
-	
-	A comment block preceeds each function, explaining what the function does,
-	how the passed parameters are used, and what the return code (if any)
-	indicates. A more detailed explanation of each function is included here:
-	
-	int smb_open(int retry_time)
-	----------------------------
-	The smb_open() function must be called before the message base is accessed
-	(read from or written to). The parameter, retry_time, is the maximum number
-	of seconds to wait while retrying to lock the message base header. If
-	retry_time is 0, then the message base header is not locked or read (this is
-	called "Fast Open" and should only be used when speed is more important than
-	checking for compatibility and validity upon opening). The global variable
-	smb_file must be initialized with the path and base filename of the message
-	base. This function returns 0 on success, 1 if the .SDT file could not be
-	opened, 2 if the .SHD file could not be opened, and 3 if the .SID file could
-	not be opened. If the message base header could not be locked, this function
-	returns -1. If the message base ID is incorrect, it returns -2. And if the
-	message base is of an incompatible version, it returns -3.
-	
-	The errno global variable (standard of most C libraries) will most likely
-	contain the error code for open failure.
-	
-	int smb_open_da(int retry_time)
-	-------------------------------
-	The smb_open_da() function is used to open the data block allocation file for
-	writing messages to a message base. The parameter, retry_time, is the maximum
-	number of seconds to wait while retrying to open the file. This function
-	returns 0 on success. -1 is returned if an open error other than "Access
-	Denied" is returned from the operating system, and the global variable errno
-	will contain the error code. -2 is returned if the retry_time has been
-	reached, and -3 is returned if the file descriptor could not be converted to
-	a stream by the fdopen() function.
-	
-	fclose(sda_fp) should be called immediately after all necessary file access
-	has been completed.
-	
-	This function is not used with the Hyper Allocation storage method.
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           77                                SMBLIB.C
-
-
-	int smb_open_ha(int retry_time)
-	-------------------------------
-	The smb_open_ha() function is used to open the header block allocation file for
-	writing messages to a message base. The parameter, retry_time, is the maximum
-	number of seconds to wait while retrying to open the file. This function
-	returns 0 on success. -1 is returned if an open error other than "Access
-	Denied" is returned from the operating system, and the global variable errno
-	will contain the error code. -2 is returned if the retry_time has been
-	reached, and -3 is returned if the file descriptor could not be converted to
-	a stream by the fdopen() function.
-	
-	fclose(sha_fp) should be called immediately after all necessary file access
-	has been completed.
-	
-	This function is not used with the Hyper Allocation storage method.
-	
-	int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-	    ,int retry_time)
-	--------------------------------------------------------------------------
-	The smb_create() function is used to create a new message base or reset an
-	existing message base. The parameters max_crcs, max_msgs, max_age, and attr
-	are used to set the initial status of the message base status header. The
-	parameter, retry_time is the maximum number of seconds to wait while retrying
-	to lock the message base header. This functions returns 0 on success or 1 if
-	the message base header could not be locked.
-	
-	int smb_trunchdr(int retry_time)
-	--------------------------------
-	The smb_trunchdr() function is used to truncate the header file when packing
-	the message base and writing the new header information back to the header
-	file. The parameter, retry_time is the maximum number of seconds to wait while
-	retrying to truncate the header file. Returns 0 on success, -1 if error was
-	other than "Access Denied", or -2 if retry_time reached.
-	
-	int smb_locksmbhdr(int retry_time)
-	----------------------------------
-	The smb_locksmbhdr() function is used to lock the first message base (status)
-	header. The parameter, retry_time is the number of seconds to wait while
-	retrying to lock the header. The smb_unlocksmbhdr() function should always be
-	used to unlock the header after accessing the message base header (usually
-	with smb_getstatus() and/or smb_putstatus()). Returns 0 if successful, -1 if
-	unsuccessful.
-	
-	int smb_unlocksmbhdr()
-	----------------------
-	The smb_unlocksmbhdr() function is used to unlock a previously locked message
-	base header (using smb_lockmsghdr()). Returns 0 on success, non-zero on
-	failure.
-	
-	int smb_getstatus(smbstatus_t *hdr)
-	-----------------------------------
-	The smb_getstatus() function is used to read the status message base header
-	into the hdr structure. Returns 0 on success, 1 on failure.
-
-
-	_______________________________________________________________________________
-	Synchronet                           78                                SMBLIB.C
-
-
-	int smb_putstatus(smbstatus_t hdr)
-	----------------------------------
-	The smb_putstatus() function is used to write the status information to the
-	first message base header. The parameter hdr, contains the status information
-	to be written. Returns 0 on success, 1 on failure.
-	
-	int smb_getmsgidx(smbmsg_t *msg)
-	--------------------------------
-	The smb_getmsgidx() function is used to get the byte offset for a specific
-	message header in the message header file based on the message base index.
-	
-	If msg->hdr.number is non-zero when this function is called, then the index
-	will be searched for this message number. If the message number is found in
-	the index, the msg->idx.offset is set to the byte offset of the message header
-	record in the header file and msg->offset is set to the record offset of the
-	index record in the index file, and the function returns 0. If the message
-	number is not found in the index, the function returns 1.
-	
-	If msg->hdr.number is zero, msg->idx.offset and msg->idx.number are obtained
-	from the index record at record offset msg->offset. If msg->offset is an
-	invalid record offset when this function is called, the function returns 1.
-	Otherwise, the function returns 0.
-	
-	int smb_getlastidx(idxrec_t *idx)
-	---------------------------------
-	Reads the last index record of the currently open message base into the
-	idxrec_t structure pointed to by idx. Returns 0 if successful, -1 if the index
-	is empty or unopened, or -2 if the record can't be read.
-	
-	int smb_getmsghdrlen(smbmsg_t msg)
-	----------------------------------
-	The smb_getmsghdrlen() function is used to calculate the total length of
-	message header msg including both fixed and variable length portions. This
-	function returns the length of the header record in bytes.
-	
-	long smb_getmsgdatlen(smbmsg_t msg)
-	-----------------------------------
-	The smb_getmsgdatlen() function is used to calculate the total length of the
-	data for message msg. This function returns the length of all data fields
-	combined.
-	
-	int smb_lockmsghdr(smbmsg_t msg, int retry_time)
-	------------------------------------------------
-	The smb_lockmsghdr() function is used to lock the header record for message
-	msg. The parameter retry_time is the maximum number of seconds to wait while
-	retrying to lock the header. Returns 0 on success, -1 on failure. The function
-	smb_unlockmsghdr() should immediately be called after accessing the message
-	header (usually with smb_getmsghdr() or smb_putmsghdr()).
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           79                                SMBLIB.C
-
-
-	int smb_getmsghdr(smbmsg_t *msg)
-	--------------------------------
-	The function smb_getmsghdr() is used to read the header record for message
-	msg. msg->idx.offset must be initialized to the byte offset of the header
-	record in the header file before this function is called. The function
-	smb_freemsgmem() must be called to free the memory allocated by this function
-	for the header and data felds. This function returns 0 on success, -1 if
-	the fixed portion of the message header record could not be read, -2 if the
-	message header ID was incorrect, -3 if memory could not be allocated, -4
-	if a data field could not be read, -5 if the fixed length portion of a header
-	field could not be read, -6 if the variable length portion of a header field
-	could not be read, -7 if one or more of the mandatory header fields (SENDER,
-	RECIPIENT, or SUBJECT) are missing, -8 if total_dfields extends beyond the
-	end of the header record, or -9 if incompatible header version.
-	
-	Several convenience pointers in the msg structure are initialized by this
-	function to point to the last occurance of the SENDER (msg->from), RECIPIENT
-	(msg->to), SUBJECT (msg->subj), etc.
-	
-	int smb_unlockmsghdr(smbmsg_t msg)
-	----------------------------------
-	The smb_unlockmsghdr() function is used to unlock a previously locked message
-	header (with smb_lockmsghdr()). This function returns 0 on success, non-zero
-	on failure.
-	
-	int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
-	---------------------------------------------------------
-	The smb_addcrc() function is used to add a CRC-32 to the CRC history file
-	for a message base, automatically checking for duplicates. The parameter
-	max_crcs should be the max_crcs defined in the status header of the message
-	base. The parameter crc, is the CRC-32 of the TEXT_BODY and TEXT_SOUL data
-	fields for the message. The parameter retry_time is the maximum number of
-	seconds to wait when retrying to open the CRC history file.
-	
-	This function returns -1 if there was an open error, -2 if the retry_time
-	was reached, -3 if there was a memory allocation error, 1 if the CRC already
-	exists in the CRC history file (indicating a duplicate message), or 0 on
-	success (and no duplicate).
-	
-	int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
-	---------------------------------------------------------------------
-	The smb_hfield() function is used to add a header field to the structure msg.
-	The parameters type, length, and data, must be specified according to the
-	header field values listed in this specification. This function returns 0
-	on success, non-zero on memory allocation error. The function smb_freemsgmem()
-	must be called to free the memory allocated by this function.
-	
-	int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
-	--------------------------------------------------------
-	The smb_dfield() function is used to add a data field to the structure msg.
-	The parameters type and length must be specified according to the data field
-	values listed in this specification. This function returns 0 on success,
-	non-zero on memory allocation error. The function smb_freemsgmem() must be
-	called to free the memory allocated by this function.
-
-	_______________________________________________________________________________
-	Synchronet                           80                                SMBLIB.C
-
-
-	int smb_addmsghdr(smbmsg_t *msg,smbstatus_t *status,int storage,int retry_time)
-	-------------------------------------------------------------------------------
-	The smb_addmsghdr() function is used to add a new message header to the message
-	header file and update the index file. The msg and status structures are
-	updated to reflect the new total messages, last message number, etc. The
-	storage parameter is used to indicate the storage method to use (either
-	SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC). If the storage type is
-	SMB_SELFPACK, the header block allocation file will be searched for unused
-	block(s) to store this header. If the storage type is SMB_FASTALLOC or
-	SMB_HYPERALLOC, the header is stored at the end of the header file. Returns 0
-	on success, non-zero on failure. The parameter retry_time is the maximum number
-	of seconds to wait while retrying to lock and open files.
-	
-	int smb_putmsg(smbmsg_t msg)
-	----------------------------
-	The smb_putmsg() function calls both the smb_putmsghdr() and smb_putmsgidx()
-	functions to write the header and index elements of a message to the
-	appropriate files. Returns 0 on success, non-zero on failure.
-	
-	int smb_putmsgidx(smbmsg_t msg)
-	-------------------------------
-	The smb_putmsgidx() function is used to store a message index in the message
-	index file. The message index can be for a new message or an existing
-	message. Returns 0 on success, non-zero on failure.
-	
-	int smb_putmsghdr(smbmsg_t msg)
-	-------------------------------
-	The smb_putmsghdr() function is used to store a message header in the message
-	header file. The message header can be for a new message or an existing
-	message. Returns 0 on success, non-zero on failure.
-	
-	void smb_freemsgmem(smbmsg_t msg)
-	---------------------------------
-	Frees allocated memory for the header and data fields in the msg structure.
-	This function must be called to free the memory allocated by the functions
-	smb_hfield(), smb_dfield(), and smb_getmsghdr().
-	
-	long smb_hdrblocks(ulong length)
-	--------------------------------
-	The smb_hdrblocks() function is used to calculate the number of blocks
-	required to store a message header of length size (in bytes). This function
-	returns the number of blocks required.
-	
-	long smb_datblocks(ulong length)
-	--------------------------------
-	The smb_datblocks() function is used to calculate the number of blocks
-	required to store message data of length size (in byte). This function returns
-	the number of blocks required.
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           81                                SMBLIB.C
-
-
-	long smb_allochdr(ulong length)
-	-------------------------------
-	The smb_allochdr() function is used to search for free blocks to store a
-	message header of length bytes and mark the free blocks as allocated in the
-	header allocation file. This function returns the byte offset to the header
-	record or a negative number on error. The function smb_open_ha() should be
-	called prior to calling this function and fclose(sha_fp) should be called
-	after. The function is called from smb_addmsghdr(), so you probably have no
-	need to call this function directly.
-	
-	long smb_fallochdr(ulong length)
-	--------------------------------
-	The smb_fallochdr() function works exactly the same as the smb_allochdr()
-	function except it is much faster because the header allocation file is not
-	searched for free blocks. The function is called from smb_addmsghdr(), so you
-	probably have no need to call this function directly.
-	
-	long smb_hallochdr(ulong header_offset)
-	---------------------------------------
-	This smb_hallochdr() functions works exactly the same as the smb_fallochdr()
-	function except the status.header_offset is passed as the argument and the
-	header allocation (.SHA) file is not updated so smb_open_ha() need not be
-	called. The function is called from smb_addmsghdr(), so you probably have no
-	need to call this function directly.
-	
-	long smb_allocdat(ulong length, ushort headers)
-	-----------------------------------------------
-	The smb_allocdat() function is used to search for free blocks to store length
-	amount of data for a message. The parameter headers, indicates the number of
-	message headers that are associated with this data. Normally, the headers
-	parameter will be 1, unless this message is part of a mass mailing. The offset
-	to the allocated data blocks is returned, or a negative value on error. The
-	function smb_open_da() should be called prior to calling this function and
-	fclose(sda_fp) should be called after.
-	
-	long smb_fallocdat(ulong length, ushort headers)
-	------------------------------------------------
-	The smb_fallocdat() function works exactly the same as the smb_allocdat()
-	function except it is much faster because the data allocation file is not
-	searched for free blocks.
-	
-	long smb_hallocdat()
-	--------------------
-	The smb_hallocdat() function works exactly the same as the smb_hallocdat()
-	function except no argument is passed and the data allocation file (.SDA) is
-	not updated so smb_open_da() need not be called.
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           82                                SMBLIB.C
-
-
-	int smb_incdat(ulong offset, ulong length, ushort headers)
-	----------------------------------------------------------
-	The smb_incdat() function is used to increment the header counter in the data
-	allocation file for the data starting at the byte offset and length size in
-	bytes. The parameter headers, indicates the number of headers to add to the
-	current allocation value in the data allocation file. Returns 0 on success,
-	non-zero on failure.
-	
-	int smb_freemsg(smbmsg_t msg, smbstatus_t status)
-	-------------------------------------------------
-	The smb_freemsg() function is used to free the disk space allocated for the
-	header and data fields of the message msg. Returns 0 on success, non-zero on
-	failure. The parameter, status, must be the current status from the message
-	base header for this message base.
-	
-	int smb_freemsgdat(ulong offset, ulong length, ushort headers)
-	--------------------------------------------------------------
-	The smb_freemsgdat() function is used to decrement the data block allocation
-	records in the data allocation file associated with the data in the data file
-	by the value of the headers parameter (normally 1). The parameter offset
-	indicates the byte offset to the beginning of the message data in the data
-	file and the parameter length is the total length of the message data.
-	Returns 0 on success, non-zero on failure.
-	
-	int smb_freemsghdr(ulong offset, ulong length)
-	----------------------------------------------
-	The smb_freemsghdr() function is used to set the header block allocation
-	records in the header allocation file to 0 (indicated non-allocated block).
-	The parameter offset indicates the byte offset to the beginning of the header
-	record being freed and the parameter length indicates the total length of the
-	header record. Returns 0 on success, non-zero on failure.
-	
-	int smb_stack(int op)
-	---------------------
-	The smb_stack() function is used to save and restore message base information
-	so that multiple message bases can be open simultaneously. The stack can
-	save up to 4 message bases (allowing 5 simultaneously open message bases).
-	The stack is a "last in, first out" storage area for open message bases.
-	If the op parameter is SMB_STACK_PUSH, smb_stack() will save (push) the current
-	message base onto the stack. Calling smb_stack(SMB_STACK_POP) will restore
-	(pop) the most recently pushed message base off the stack. Calling
-	smb_stack(SMB_STACK_XCHNG) will exchange the most recently pushed message base
-	and the current message base (replacing the top of the stack with the current
-	message base).
-	
-	void smb_close()
-	----------------
-	Closes the header, data, and index files for the currently open message base.
-	
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           83                                SMBLIB.C
-
-
-	Miscellaneous SMBLIB Files
-	==========================
-	
-	CRC32.H         C header file for CRC-32 calculations
-	-----------------------------------------------------
-	This file contains a static 32-bit CRC table (crc32tbl[]) and a macro (ucrc32)
-	that uses this table to calculate 32-bit CRCs one byte at a time.
-	
-	Example:
-	
-	    ulong crc=0xffffffff;
-	
-	for(i=0;i<length;i++)
-	    crc=ucrc32(buf[i],crc);
-	crc=~crc;
-	
-	
-	CRC16.C         C functions for 16-bit CRC calculations
-	-------------------------------------------------------
-	This file contains a function (ucrc16), to calculate 16-bit CRCs one byte at a
-	time and a function (crc16) that uses the ucrc16() function to calculate the
-	16-bit CRC of an ASCIIZ character string.
-	
-	Example:
-	
-	    ushort crc;
-	
-	crc=crc16("Text");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           84              Miscellaneous SMBLIB Files
-
-
-	LZH.H           Function prototypes for LZH.C
-	---------------------------------------------
-	This file contains function prototypes for the two most important functions
-	in LZH.C, lzh_encode() and lzh_decode().
-	
-	Example:
-	
-	    uchar str[256],lzh[512];
-	    long length;
-	
-	strcpy(str,"This is a string of text");
-	length=lzh_encode(str,strlen(str),lzh);
-	lzh_decode(lzh,length,str);
-	
-	
-	LZH.C           C functions for LZH encoding (compression/decompression)
-	------------------------------------------------------------------------
-	This file contains the functions for encoding and decoding LZH compressed
-	data. If the macro LZH_DYNAMIC_BUF is defined when this file is compiled,
-	temporary buffers will be dynamically allocated as opposed to static. This
-	may be slower than the static buffer method, but frees the allocated memory
-	after encoding or decoding. If free memory for your application is an issue,
-	then define this macro when compiling this file.
-	
-	Example (Borland C):
-	
-	bcc -c -DLZH_DYNAMIC_BUF lzh
-	
-	Example (Watcom C):
-	
-	wcc -dLZH_DYNAMIC_BUF lzh
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           85              Miscellaneous SMBLIB Files
-
-
-	SMBLIB Storage Example
-	======================
-	
-	#include "smblib.h"
-	#include "crc16.c"
-	
-	int main(void)
-	{
-	    char    str[256]                        // General purpose string
-	           ,*msg_text="Hello, world!"       // Message text
-	           ,nul_buf[SDT_BLOCK_LEN]={0}      // NULL initialized buffer
-	           ;
-	    int     i                               // General purpose integer
-	           ,storage=SMB_SELFPACK            // Default storage method
-	           ,retry=10                        // Retry for opening/locking files
-	           ;
-	    ushort  max_age=0                       // Default maximum age of messages
-	           ,xlat=XLAT_NONE                  // Translation string
-	           ,tzone=PST                       // Time zone
-	           ,copies=1                        // Number of copies of this msg
-	           ;
-	    ulong   max_msgs=500                    // Default max number of msgs
-	           ,max_crcs=0                      // Default max crcs
-	           ,length                          // Length of msg text
-	           ,offset                          // Offset to msg text in data file
-	           ;
-	    smbmsg_t    msg;                        // Message structure
-	    smbstatus_t status;                     // Message base status record
-	
-	strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-	if((i=smb_open(retry))!=0) {                // Can't open!?!
-	    printf("smb_open returned %d\n",i);
-	    return(1); }
-	
-	if(!filelength(fileno(shd_fp)))             // Message base not created yet
-	    smb_create(max_crcs                     // Create with default settings
-	              ,max_msgs
-	              ,max_age
-	              ,storage==SMB_HYPERALLOC
-	                    ? SMB_HYPERALLOC : 0    // SMB_EMAIL if this was e-mail
-	              ,retry
-	              );
-	
-	if((i=smb_locksmbhdr(retry))!=0) {          // Can't lock status base header
-	    printf("smb_locksmbhdr returned %d\n",i);
-	    smb_close();
-	    return(1); }
-	
-	if((i=smb_getstatus(&status))!=0) {         // Can't read status base header
-	    smb_unlocksmbhdr();
-	    smb_close();
-	    printf("smb_getstatus returned %d\n",i);
-	    return(1); }
-
-
-	_______________________________________________________________________________
-	Synchronet                           86                  SMBLIB Storage Example
-
-
-	if(status.attr&SMB_HYPERALLOC)
-	    storage=SMB_HYPERALLOC;
-	else
-	    storage=SMB_SELFPACK;
-	
-	length=strlen(msg_text);                    // Get length of message
-	length+=sizeof(xlat);                       // Add length of xlat string
-	
-	if(storage==SMB_HYPERALLOC)                 // Allocate space for message text
-	    offset=smb_hallocdat();
-	else {
-	    if((i=smb_open_da(retry))!=0) {
-	        smb_unlocksmbhdr();
-	        printf("smb_open_da returned %d\n",i);
-	        smb_close();
-	        return(1); }
-	    if(storage==SMB_FASTALLOC)
-	        offset=smb_fallocdat(length,copies);
-	    else
-	        offset=smb_allocdat(length,copies);
-	    fclose(sda_fp); }
-	
-	fseek(sdt_fp,offset,SEEK_SET);              // Seek to beginning of data block
-	fwrite(&xlat,sizeof(xlat),1,sdt_fp);        // Write xlat string
-	fwrite(msg_text,strlen(msg_text),1,sdt_fp); // Write message text
-	fwrite(nul_buf,SDT_BLOCK_LEN-length         // Write NULLs out to end of block
-	    ,1,sdt_fp);
-	fflush(sdt_fp);                             // Flush output buffer
-	smb_unlocksmbhdr();                         // Unlock status base header
-	
-	memset(&msg,0,sizeof(smbmsg_t));            // Initialize header to NULL
-	memcpy(msg.hdr.id,"SHD\x1a",4);             // Always set to SHD^Z
-	msg.hdr.version=SMB_VERSION;
-	msg.hdr.when_written.time=time(NULL);
-	msg.hdr.when_written.zone=tzone;
-	msg.hdr.when_imported.time=time(NULL);
-	msg.hdr.when_imported.zone=tzone;
-	msg.hdr.offset=offset;
-	
-	strcpy(str,"All");                          // Send message to "All"
-	if((i=smb_hfield(&msg,RECIPIENT,strlen(str),str))!=0) {
-	    printf("smb_hfield returned %d\n",i);
-	    smb_freemsgdat(offset,length,copies);
-	    smb_close();
-	    return(1); }
-	strlwr(str);                                // If this were e-mail, idx.to
-	msg.idx.to=crc16(str);                      // would be the "to" user number
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           87                  SMBLIB Storage Example
-
-
-	strcpy(str,"Sysop");                        // Send message from "Sysop"
-	if((i=smb_hfield(&msg,SENDER,strlen(str),str))!=0) {
-	    printf("smb_hfield returned %d\n",i);
-	    smb_freemsgdat(offset,length,copies);
-	    smb_freemsgmem(msg);
-	    smb_close();
-	    return(1); }
-	strlwr(str);                                // If this were e-mail, idx.from
-	msg.idx.from=crc16(str);                    // would be the "from" user number
-	
-	strcpy(str,"This is a test");               // Set the message subject/title
-	if((i=smb_hfield(&msg,SUBJECT,strlen(str),str))!=0) {
-	    printf("smb_hfield returned %d\n",i);
-	    smb_freemsgdat(offset,length,copies);
-	    smb_freemsgmem(msg);
-	    smb_close();
-	    return(1); }
-	strlwr(str);
-	msg.idx.subj=crc16(str);
-	
-	if((i=smb_dfield(&msg,TEXT_BODY,length))!=0) {
-	    printf("smb_dfield returned %d\n",i);
-	    smb_freemsgdat(offset,length,copies);
-	    smb_freemsgmem(msg);
-	    smb_close();
-	    return(1); }
-	
-	if((i=smb_addmsghdr(&msg,&status,storage,retry))!=0) {
-	    printf("smb_addmsghdr returned %d\n",i);
-	    smb_freemsgdat(offset,length,copies);
-	    smb_freemsgmem(msg);
-	    smb_close();
-	    return(1); }
-	
-	smb_freemsgmem(msg);                        // Unnecessary if exiting main()
-	smb_close();                                // Unnecessary if exiting main()
-	return(0);
-	}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           88                  SMBLIB Storage Example
-
-
-	SMBLIB Retrieval Example
-	========================
-	
-	#include "smblib.h"
-	
-	int main(void)
-	{
-	    char        ch;                         // General purpose character
-	    int         i,                          // General purpose integer
-	                retry=10;                   // Retry for opening/locking files
-	    ushort      xlat;                       // Translation string
-	    ulong       l;                          // General purpose long integer
-	    smbmsg_t    msg;                        // Message structure
-	
-	strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-	if((i=smb_open(retry))!=0) {                // Can't open!?!
-	    printf("smb_open returned %d\n",i);
-	    return(1); }
-	
-	if(!filelength(fileno(shd_fp))) {           // Message base not created yet
-	    printf("Empty\n");
-	    smb_close();
-	    return(0); }
-	
-	for(msg.offset=0;!ferror(sid_fp);msg.offset++) {
-	
-	    fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-	    if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-	        break;
-	
-	    if((i=smb_lockmsghdr(msg,retry))!=0) {
-	        printf("smb_lockmsghdr returned %d\n",i);
-	        break; }
-	    if((i=smb_getmsghdr(&msg))!=0) {
-	        smb_unlockmsghdr(msg);
-	        printf("smb_getmsghdr returned %d\n",i);
-	        break; }
-	    if((i=smb_unlockmsghdr(msg))!=0) {
-	        smb_freemsgmem(msg);
-	        printf("smb_unlockmsghdr returned %d\n",i);
-	        break; }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           89                SMBLIB Retrieval Example
-
-
-	    printf("Subj : %s\n",msg.subj);
-	    printf("To   : %s\n",msg.to);
-	    printf("From : %s\n",msg.from);
-	    printf("Date : %s\n",ctime((time_t *)&msg.hdr.when_written.time));
-	
-	    for(i=0;i<msg.hdr.total_dfields;i++)
-	        switch(msg.dfield[i].type) {
-	            case TEXT_BODY:             // Only show BODY and TAIL data fields
-	            case TEXT_TAIL:
-	                fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-	                    ,SEEK_SET);
-	                fread(&xlat,sizeof(xlat),1,sdt_fp);
-	                if(xlat!=XLAT_NONE)     // No translations supported
-	                    continue;
-	                for(l=sizeof(xlat);l<msg.dfield[i].length;l++) {
-	                    ch=fgetc(sdt_fp);
-	                    if(ch)
-	                        putchar(ch); }
-	                printf("\n");
-	                break; }
-	    printf("\n");
-	
-	    smb_freemsgmem(msg); }          // Free memory allocated by smb_getmsghdr()
-	
-	smb_close();
-	return(0);
-	}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           90                SMBLIB Retrieval Example
-
-
-	SMBLIB Performance Issues
-	=========================
-	
-	Since importing messages is the usually the most time consuming task likely
-	undertaken by an SMB application, it is also the most susceptable to design
-	issues that effect performance.
-	
-	Opening and Closing
-	-------------------
-	When importing multiple messages for a single message base, it appears logical
-	to open the message base, import all the messages, then close it. This indeed
-	is preferred over opening and closing the message base for each message.
-	
-	When importing multiple messages for possibly non-consecutive message bases,
-	developers may eaily make the mistake of opening and closing the message base
-	for each message. This is not necessary and can considerably hinder the
-	import performance. The easiest solution is to only close the message base and
-	open a new one if the next message to be imported is not for the same message
-	base as the previously imported message. Example:
-	
-	smb_file[0]=0;
-	for(i=0;i<total_messages_to_be_imported;i++) {
-	    if(stricmp(get_messagebase_for_this_message(i),smb_file)) {
-	        if(smb_file[0])     /* We've already opened one */
-	            smb_close();
-	        strcpy(smb_file,get_messagebase_for_this_message(i));
-	        smb_open(10); }
-	    /* Import this message */
-	    }
-	if(smb_file[0])
-	    smb_close();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           91               SMBLIB Performance Issues
-
-
-	A more advanced method is to keep multiple message bases open at the same time.
-	Due to the likely limitation of total file handles on the system, it is
-	suggested to keep the number of simultaneously open message bases at or below
-	3. SMBLIB includes the function smb_stack() to easily "push" and "pop" message
-	bases without closing them (push is the equivalent to "save" and pop is the
-	equivalent to "restore"). The downside of this function is that you cannot
-	access message bases on the stack without actually popping them off (in reverse
-	of the order they were pushed). You can however "exchange" the current message
-	base with the message base on the top of the stack (most recently pushed).
-	To intelligently juggle more than two open message bases, the developer should
-	create their own equivalent of the smb_stack() function so they can access the
-	message bases on the stack without popping them off. An example of keeping a
-	maximum of two message bases open using smb_stack():
-	
-	    char last_messagebase[128],new_messagebase[128];
-	
-	smb_file[0]=0;
-	last_messagebase[0]=0;
-	for(i=0;i<total_messages_to_be_imported;i++) {
-	    strcpy(new_messagebase,get_messagebase_for_this_message(i));
-	    if(stricmp(new_messagebase,smb_file)) {     /* Not current message base */
-	        if(smb_file[0]) {                       /* We've already opened one */
-	            if(!stricmp(new_messagebase,last_messagebase)) { /* Same as last */
-	                strcpy(last_messagebase,smb_file);
-	                smb_stack(SMB_STACK_XCHNG); }       /* Retore previous base */
-	            else {
-	                if(last_messagebase[0]) {
-	                    smb_stack(SMB_STACK_XCHNG);
-	                    smb_close();
-	                    strcpy(last_messagebase,new_messagebase); }
-	                else {
-	                    strcpy(last_messagebase,smb_file);
-	                    smb_stack(SMB_STACK_PUSH); }    /* Save current base */
-	                strcpy(smb_file,new_messagebase);
-	                smb_open(10); } }
-	        else {
-	            strcpy(smb_file,new_messagebase);
-	            smb_open(10); } }
-	    /* Import this message */
-	    }
-	if(smb_file[0])
-	    smb_close();
-	if(last_messagebase[0]) {
-	    smb_stack(SMB_STACK_POP);
-	    smb_close(); }
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           92               SMBLIB Performance Issues
-
-
-	The second example would be of negligible performance gain over the first
-	example (6 open operations versus 7) if the messages to import were in the
-	following order:
-	
-	msg[0] --> msgbase[0]       // 0 opened
-	msg[1] --> msgbase[1]       // 0 pushed 1 opened
-	msg[2] --> msgbase[1]
-	msg[3] --> msgbase[2]       // 1 closed 0 popped 0 closed 2 opened
-	msg[4] --> msgbase[0]       // 2 pushed 0 opened
-	msg[5] --> msgbase[2]       // 0 pushed 2 popped (exchanged)
-	msg[6] --> msgbase[3]       // 2 closed 0 popped 0 closed 3 opened
-	msg[7] --> msgbase[0]       // 3 pushed 0 opened
-	
-	The second example would be of significant performance gain over the first
-	example (4 open operations versus 8) if the messages to import were in the
-	following order:
-	
-	msg[0] --> msgbase[0]       // 0 opened
-	msg[1] --> msgbase[1]       // 0 pushed 1 opened
-	msg[2] --> msgbase[0]       // 1 pushed 0 popped (exchanged)
-	msg[3] --> msgbase[1]       // 0 pushed 1 popped (exchanged)
-	msg[4] --> msgbase[0]       // 1 pushed 0 popped (exchanged)
-	msg[5] --> msgbase[2]       // 0 pushed 1 popped (exchanged) 1 closed 2 opened
-	msg[6] --> msgbase[3]       // 2 pushed 0 popped (exchanged) 0 closed 3 opened
-	msg[7] --> msgbase[2]       // 3 pushed 2 popped (exchanged)
-	
-	More advanced use of "stack-like" message base file handle storage can easily
-	reduce the number of open operations, therefore increasing import performance
-	under more adverse message base ordering conditions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           93               SMBLIB Performance Issues
-
-
-	Compression
-	-----------
-	If any message data compression features are offered by the application, it
-	is important the the application not unnecessarily compress data that will
-	not save any storage space. While this may seem an obvious statement, please
-	review the following pseudo-code example:
-	
-	if ( message_data_length < SDT_BLOCK_LEN )
-	    // Store uncompressed data
-	else {
-	    // Compress data
-	    if ( ( compressed_data_length / SDT_BLOCK_LEN )
-	        < ( message_data_length / SDT_BLOCK_LEN ) ) // Saves a block or more
-	        // Store compressed data
-	    else
-	        // Store uncompressed data
-	    }
-	
-	Since the SMB format stores message data in fixed length blocks, there is no
-	point in storing a message in compressed format if it requires the same number
-	of blocks as the uncompressed format (i.e. a message that is two blocks in
-	length in uncompressed format and only a block and a half in length when
-	compressed should not be stored in compressed format since it still requires
-	two full blocks of storage). It is important to note that in the above example,
-	the length of the data translation string was not taken into account in
-	determining the number of required blocks. Also, the smb_datblocks() function
-	is normally used in determing the number of required blocks to store a given
-	data length and it is a little more involved than simply dividing the length of
-	the data by SDT_BLOCK_LEN.
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           94               SMBLIB Performance Issues
-
-
-	Bibliography
-	============
-	
-	Title     : The C Programming Language
-	Publisher : Prentice Hall
-	Author    : Brian W. Kernighan and Dennis M. Ritchie
-	
-	Document  : ARPANET Request for Comments (RFC) #822
-	Title     : Standard for the Format of ARPA Internet text messages
-	Publisher : SRI International
-	Author    : David H. Crocker, University of Delaware
-	
-	Document  : FTS-0001
-	Publisher : FSC
-	Author    : Randy Bush, Pacific Systems Group
-	
-	Document  : FTS-0004
-	Title     : EchoMail Specification
-	Publisher : FSC
-	Author    : Bob Hartman
-	
-	Document  : FTS-0009
-	Title     : A standard for unique message identifiers and reply chain linkage
-	Publisher : FSC
-	Author    : Jim Nutt
-	
-	Document  : FSC-00046
-	Title     : A Product Idenfifier for FidoNet Message Handlers
-	Publisher : FSC
-	Author    : Joaquim H. Homrighausen
-	
-	Document  : FSC-00053
-	Title     : Specifications for the ^aFLAGS field
-	Publisher : FSC
-	Author    : Joaquim H. Homrighausen
-	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           95                            Bibliography
-
-
-	Implementations
-	===============
-	
-	Product   : Synchronet Multinode BBS Software
-	Developer : Digital Dynamics
-	Level     : III
-	Version   : 2.20
-	
-	Product   : Synchronet/FidoNet Import/Export Utility (SBBSFIDO)
-	Developer : Digital Dynamics
-	Level     : III
-	Version   : 2.23
-	
-	Product   : Synchronet UTI (Universal Text Interface) Driver
-	Developer : Digital Dynamics
-	Level     : III
-	Version   : 2.23
-	
-	Product   : SBBSecho FidoNet Packet Tosser for Synchronet
-	Developer : Digital Dynamics
-	Level     : III
-	Version   : 1.11
-	
-	Product   : NetXpress Internet UUCP for Synchronet
-	Developer : Merlin Systems
-	Level     : II
-	Version   : 1.50
-	
-	Product   : InterEcho FidoNet Packet Tosser
-	Developer : InterMail Sales Inc
-	Level     : II
-	Version   : 1.11
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-	_______________________________________________________________________________
-	Synchronet                           96                                   Index
-
-
diff --git a/src/sbbs2/smb/121a/smb.txt b/src/sbbs2/smb/121a/smb.txt
deleted file mode 100644
index 96c50c01ac86ec8914703c4d3a00761a58555a05..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smb.txt
+++ /dev/null
@@ -1,5661 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-                     Synchronet Message Base Specification
-                                 Version 1.21
-                               Updated 08/31/95
-
-                        Copyright 1995 Digital Dynamics
-
-                                  PO Box 501
-                             Yorba Linda, CA 92686
-
-                 Voice: 714-529-6328   BBS: 714-529-9525 V.32/V.32bis
-                   FAX: 714-529-9721        714-529-9547 V.FC
-                  Fido: 1:103/705      ftp: netcom.com /pub/sb/sbbs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Table of Contents
-=================
-
-Introduction.............................................................3
-Implementation Levels....................................................8
-Definitions.............................................................10
-        Acronyms........................................................12
-        Data Types......................................................13
-File Formats............................................................18
-        Index.....................(*.SID)...............................18
-        Header....................(*.SHD)...............................20
-        Header Allocation.........(*.SHA)...............................30
-        Data......................(*.SDT)...............................31
-        Data Allocation...........(*.SDA)...............................32
-        CRC History...............(*.SCH)...............................33
-Header Field Types......................................................34
-Data Field Types........................................................58
-Messsage Attributes.....................................................60
-Translation Types.......................................................61
-Agent Types.............................................................62
-Network Types...........................................................63
-Media Types.............................................................64
-Message Storage Pseudo Code.............................................67
-Message Retrieval Pseudo Code...........................................69
-SMBUTIL.................................................................70
-CHKSMB..................................................................71
-FIXSMB..................................................................72
-SMBLIB (C library)......................................................73
-        Data Types and Constants..(SMBDEFS.H)...........................74
-        Global Variables..........(SMBVARS.C)...........................75
-        Function Prototypes.......(SMBLIB.H)............................76
-        Library Functions.........(SMBLIB.C)............................77
-        Miscellaneous.............(CRC*.* and LZH.*)....................84
-SMBLIB Storage Example..................................................86
-SMBLIB Retrieval Example................................................89
-SMBLIB Performance Issues...............................................91
-Bibliography............................................................95
-Implementations.........................................................96
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            2                                Contents
-
-
-Introduction
-============
-
-Q. What is SMB?
-
-A. SMB (Synchronet Message Base) is a technical specification for the storage
-   format of electronic mail messages. These e-mail messages may all be
-   contained in one database, or, more commonly, separated into catagorized
-   databases. These message databases (or message bases) are also referred to
-   as "sub-boards", "forums", "conferences", and "SIGs". The messages may be
-   directed to an individual person, sent to a group of individuals, or sent
-   to everyone who can read messages in that message base. Messages may be
-   created and read soley at one physical location, or imported from and
-   exported to a message network that may span continents. Message bases that
-   are connected to a message network are often called "echoes".
-
-
-Q. Why SMB?
-
-A. The Synchronet Message Base is designed to store high volumes of messages
-   while maintaining optimum search, retrieval, and creation performance.
-   These messages are not limited to mere text. In addition to text, SMB
-   defines the storage of digitized sound, MIDI, graphics, fonts, animation,
-   as well as other multimedia data and triggers for localized multimedia.
-   SMB thrives on a multi-user environment where messages are being created,
-   read, modified, and deleted by multiple tasks simultaneously. With the
-   large message networks of today being the rule, rather than the exception,
-   and high volumes of messages being imported on a daily, sometimes hourly
-   basis, creation and deletion speed is of the utmost importance. This is
-   where SMB really shines. Being extensible enough to handle message formats
-   from networks of today and tomorrow, and fast enough to import more messages
-   that humanly readable, the SMB format will more than meet your message
-   storage needs.
-
-
-Q. Why a specification?
-
-A. Message bases are often accessed and modified by a number of different
-   programs. Often these programs are developed by individuals or companies
-   other than the original designer of the message base format. This
-   specification is an attempt to aid developers in creating programs that
-   access or modify a message base stored in the SMB format.
-
-
-Q. Who can use this specification?
-
-A. Anyone that has interest in the Synchronet Message Base format at either
-   an educational or professional level. Specifically, software developers
-   interested or currently involved in the development of message readers,
-   editors, echomail (toss/scan) programs, message transfer agents (MTAs),
-   network gateways, and bulletin board systems. Much of the information in
-   this specification is intended for those with preexisting programming
-   knowledge, so those with little or no programming experience may find it
-   hard to comprehend.
-
-_______________________________________________________________________________
-Synchronet                            3                            Introduction
-
-
-
-
-Q. What does the SMB specification include?
-
-A. The text you are reading is part of the SMB specification: a single text
-   document that defines the storage format of each of the six files of an
-   SMB format message base and how they are related to each other.
-
-   Included with this specification is C source code to be used as an example
-   to programmers of how to access an SMB format message base and public domain
-   library functions (SMBLIB) that can be compiled and linked into programs
-   that access an SMB format message base developed by third parties. An SMB
-   utility program (SMBUTIL) is also included with C source code as an example
-   of how to use the SMBLIB functions.
-
-
-Q. Where did the SMB specification come from?
-
-A. Digital Dynamics (southern California based software development company)
-   released "Synchronet Multinode BBS Software Version 1a" in June of 1992 as
-   one of the first BBS packages to be designed from the ground-up to operate
-   in a multinode environment with incredible speed and reliability, with a
-   large suite of multinode specific features and design innovations.
-
-   The original message base format was designed with localized messaging and
-   low volume message networks in mind. By January of 1993, it was clear that
-   high volume message networks (FidoNet, RelayNet, Usenet, etc.) were the
-   preference of most BBS users and a new message base format was required to
-   allow for high volume message storage, improved storage, retrieval, and
-   maintenance performance, as well as lower storage space requirements.
-
-   Rather than introduce another new message format, Digital Dynamics sought
-   to implement an existing public specification for a format that would meet
-   current and future message storage needs. More than a few specifications
-   were seriously considered at one time or another, but after careful
-   examination, design flaws and lack of extensibility eliminated them from the
-   long term plans of Digital Dynamics and Synchronet BBS Software. Thus began
-   the design of the "Synchronet Message Base" (SMB) format.
-
-   At the request of many message related program developers, Digital Dynamics
-   created and released the SMB specification before the release of "Synchronet
-   Version 2.00" to allow lead-time on developing support programs for the new
-   format.
-
-   Digital Dynamics strongly encourages developers of message related programs
-   (including software that directly competes with Synchronet or other Digital
-   Dynamics products) to implement support for SMB. Though this is a public
-   specification and Digital Dynamics encourages developer suggestions, it will
-   remain under the sole control of Digital Dynamics unless specifically stated
-   otherwise in a future revision of this specification.
-
-   Digital Dynamics requests that any organizations that wish to adopt or
-   ratify this specification, in part or whole, notify Digital Dynamics through
-   any of the contact methods listed at the beginning of this document.
-
-_______________________________________________________________________________
-Synchronet                            4                            Introduction
-
-
-
-
-Q. How does SMB store messages?
-
-A. Each message base is stored in a set of binary files. This set consists
-   of between three and six files depending the storage method used. The base
-   filename (maximum of eight characters under DOS) is the same for all six
-   files of the same message base and unique amoung the filenames of other
-   message bases in the same directory. The six files each have a different
-   three character extension. The first character of the extension is always
-   the letter 'S' (for SMB), while the second and third characters define the
-   contents of the file.
-
-   Two of the six files associated with each message base are not recreatable
-   and therefore are the most important when considering data integrity. These
-   two files are the data file (with a .SDT extension) and header file (.SHD
-   extension). Both of these files use 256 byte blocks and have associated
-   block allocation tables (stored in .SDA and .SHA respectively) so that
-   deleted message blocks may be used by new messages without creating odd
-   sized unused 'holes' in the files. The block allocation table files (.SDA
-   and .SHA) can be recreated with the information stored in the header (.SHD)
-   file. When using Hyper Allocation storage method, the allocation files (.SDA
-   and .SHA) are not used.
-
-   For fast indexing, there is a small fixed length index file (with a .SID
-   extension). This file allows for the immediate location of message header
-   records based on sender's name or user number, recipient's name or user
-   number, subject, message number, or message attributes. This file can be
-   recreated with the data stored in the header (.SHD) file.
-
-   The last file is an optional CRC history (.SCH) file. It contains 32-bit
-   CRCs of a configurable number of messages imported or created locally. This
-   is to help eliminate duplicate messages created by user or program error.
-   The CRC history file can be recreated with the combination of information
-   stored in the data (.SDT) and header (.SHD) files.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            5                            Introduction
-
-
-Q. How fast do messages import into an SMB message base?
-
-A. This is a very important question for systems for that import large volumes
-   of messages. Of course, the answer depends on the storage format which you
-   are importing from, the average length of messages, the design of the
-   program which is peforming the import process, as well as the hardware and
-   system software being used. What's important is that SMB will allow the
-   fastest import process possible with any given combination of the above
-   factors.
-
-   Since system storage capacity is rarely infinite, neither is the number
-   of messages which can be stored in a message base. System operators must
-   define the maximum number of messages to be stored in a message base, the
-   maximum age of the messages in that message base, or a combination of both.
-   When using the Self-packing storage method (defined later in this document),
-   the smaller the number of messages stored in a message base, the faster the
-   import process. The SMB format is flexible enough to support multiple levels
-   of import performance based on optimizations for storage space or speed.
-   Most system operators will almost invariably choose speed over space, but
-   which choices are available is determined by the importing program. This
-   specification defines three storage methods, from slowest to fastest:
-   Self-packing, Fast Allocation, and Hyper Allocation. Other options defined
-   in this specification may affect storage performance, including duplicate
-   message checking and message compression/encryption.
-
-
-Q. How much storage is required for an SMB message base?
-
-A. The biggest factor in determining storage requirements for a message base
-   is the maximum number of messages to be stored in the base (defined by the
-   system operator) and the average size of each message. The minimum required
-   storage for a message base is 32 bytes plus 532 bytes per message (plus four
-   bytes per message if duplicate message checking is used and three bytes
-   per message if Self-packing or Fast Allocation storage methods are used).
-
-   The SMB format was originally designed to be "self-packing", meaning purged
-   (deleted) message header and data blocks will be used automatically by new
-   messages. Relying solely on self-packing, an SMB format message base will
-   never "shrink" in size. This is not to say that it will continually "grow"
-   in size, but that without specific packing procedures, deleted message
-   blocks may remain unused for extended periods of time, meanwhile using some
-   amount of storage space that could be recovered using specific packing
-   procedures. The Fast Allocation and Hyper Allocation storage methods do not
-   use deleted message blocks for new messages so specific packing procedures
-   must be used if any messages are deleted and that storage space is to ever
-   be recovered.
-
-   Limiting the maximum age of messages in an SMB message base is another way
-   to control the storage requirements. While maximum message age definition is
-   optional, the definition of the maximum number of messages is not.
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            6                            Introduction
-
-
-Q. How many messages can be stored per SMB message base?
-
-A. Without considering storage limitations or message data lengths greater than
-   256, the theoretical maximum number of messages that can be stored in a
-   single SMB message base is 16.7 million. Considering the variable length
-   nature of message and header data, it is suggested that the system operator
-   allow no more than 1 million messages per base.
-
-   To determine an estimated maximum number of messages for a message base
-   using the average message data length as a factor, use the following
-   formula:
-
-   4.2 billion divided by the average message length rounded up to be evenly
-   divisible by 256.
-
-   If the average message data length is 1500 bytes, the estimated maximum
-   number of messages would be 2,734,375 (4.2 billion divided by 1536).
-
-   Implementations of this format may be further limited by available system
-   memory.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            7                            Introduction
-
-
-Implementation Levels
-=====================
-The SMB format can be implemented to varying degrees between programs without
-creating compatibilty issues. Rather than have developers specifically state
-which features they have and have not implemented, we have defined seven levels
-of implementation (represented by Roman numerals I through VII). For a program
-or software package to meet an implementation level, it must have all of the
-features listed for that level and all of those for each level below it. The
-minimum suggested imlementation is level I. The SMBUTIL program included with
-this specification is an example of a level I implementation with features
-from some of the higher implementation levels.
-
-Level I
--------
-The minimum suggested level of implementation. Messages contain merely ASCII
-text displayable on an ANSI terminal. Messages can be added to the message
-base and if the maximum number of messages is exceeded, messages are removed
-or marked for deletion.
-
-Level II
---------
-The addition of file attachments, multiple index/header entries per message
-(multiple destinations), multiple text bodies for the separation of message
-text and tag/origin lines (for example), forwarding, threading, and specific
-FidoNet kludge header field support makes this level of implementation more
-realistic for bulletin board system and EchoMail software implementation.
-
-Synchronet Multinode BBS Software v2.00 has a level II implementation of this
-specification.
-
-Level III
----------
-This implementation adds support for translation strings defined later in this
-document for data compression, encryption, escaping, and encoding. This level
-is still limited to basic ASCII text and ANSI escape sequence entry and
-retrieval.
-
-Synchronet Multinode BBS Software v2.10 has a level III implementation of this
-specification.
-
-Level IV
---------
-The storage and retrieval of embedded and attached images is added in this
-level of implementation. Supported images are limited to single binary or text
-data blocks that can be displayed or transferred to the user (automatically,
-or by request) if their display and translation protocols define specific
-support for the image type.
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            8                   Implementation Levels
-
-
-Level V
--------
-This level of implementation adds support for embedded and attached sound data.
-This includes digitized sound and MIDI data. Supported sounds are limited to
-single binary or text data blocks that can be played or transferred to the user
-(automatically or by request) if their presentation and translation protocols
-define specific support for the sound type.
-
-Level VI
---------
-Localized sound and image data can be triggered by messages stored and
-retrieved in an implementation of this level.
-
-Level VII
----------
-Complete multimedia support is reached in this implementation level with
-support for embedded and attached animation, sound, and video data.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                            9                   Implementation Levels
-
-
-Definitions
-===========
-
-Control Characters
-------------------
-When specifying control characters (ASCII 1 through 31), the caret symbol "^"
-or the abreviation "ctrl-" followed by a character will be used to indicate the
-value. ^A is equivalent to ASCII 1, ^B ASCII 2, etc. The case of the control
-character is not significant (i.e. ^z and ^Z are equivalent). The control
-character ^@ (ASCII 0) will be specified as NULL or 0.
-
-
-Hexadecimal
------------
-Base sixteen numbering system which includes the digits 0-9 and A-F.
-Hexadecimal numbers are represented in this document with a prefix of "0x" or
-"\x" or a suffix of "h". Hexadecimal letter digits are not case sensitive
-(i.e. the number 0xff is the same as 0xFF).
-
-
-File dump
----------
-When example file dumps are displayed, the format is similar to that of the
-output from the DOS DEBUG program. With the exception of the ASCII characters,
-all numbers are in hexadecimal.
-
-Offset    Byte values                                          ASCII characters
-
-000000    53 4D 42 1A 10 01 20 00   F4 01 00 00 F4 01 00 00    SMB... .�...�...
-000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-
-
-Bit values
-----------
-Bit (or flag) values are represented in C notation as (1<<x) where x is the bit
-number. (i.e. bit number 7 (1<<7) is the same as 0x80).
-
-
-Word storage
-------------
-All words (16-bit) and double words (32-bit) are stored in Intel 80x86 (little
-endian) format with bytes stored from low to high (reverse of the Motorola
-680x0 word storage format).
-
-A 16-bit word with the value 1234h is stored as 34h 12h.
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           10                             Definitions
-
-
-Translation strings
--------------------
-Translation strings (xlat variables) are arrays of words (16-bit) in the order
-of the original storage translation. The last translation type is followed by a
-16-bit zero (defined later as XLAT_NONE). If there are no translations, then
-the first and only element of the array is XLAT_NONE.
-
-If multiple translations are used, the translation order must be reversed
-upon retrieval to obtain the proper data.
-
-
-Local e-mail
-------------
-When referring to the local e-mail message base of a Synchronet BBS, we are
-referring specifically the message base with the name "MAIL" stored in the
-"DATA" directory (e.g. \SBBS\DATA\MAIL).
-
-Messages stored in this message base are different in the following respects:
-
-    The SMB_EMAIL status header attribute is set ON
-    Hyper Allocation storage method is not supported
-    The "To" and and "From" fields of the message indexes do NOT contain CRCs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           11                             Definitions
-
-
-Acronyms:
-========
-
-ANSI            American National Standards Institute
-ASCII           American Standard Code for Information Interchange
-BBS             Bulletin Board System
-C               The C programming language as defined by ANSI X3.159-1989
-CR              Carriage Return character (ASCII 13)
-CRC             Cyclic Redundancy Check
-CRC-16          Standard 16-bit CRC using 1021h polynomial (seed 0)
-CRC-32          Standard 32-bit CRC using EDB88320h polynomial (seed -1)
-CRLF            Carriage Return character followed by a Line Feed character
-FSC             FidoNet Standards Commitee (FTS proposal)
-FTN             FidoNet Technology Network
-FTS             FidoNet Technical Standard
-LF              Line Feed character (ASCII 10)
-QWK             Compressed message packet format for message reading/networking
-RFC             Request for Comments
-SMB             Synchronet Message Base
-UT              Universal Time (formerly called "Greenwhich Mean Time")
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           12                  Definition of Acronyms
-
-
-Data types
-==========
-
-uchar           Unsigned 8-bit value (0 through 255).
-                C example:
-
-                #define uchar unsigned char
-
-
-short           Signed 16-bit value (-32768 through 32767).
-                "short" is a C keyword indicating "short int".
-
-
-ushort          Unsigned 16-bit value (0 through 65535).
-                C example:
-
-                #define ushort unsigned short
-
-
-ulong           Unsigned 32-bit value (0 through 4294967295).
-                C example:
-
-                #define ulong unsigned long
-
-
-time_t          Unsigned 32-bit value.
-                Seconds since 00:00 Jan 01 1970 (Unix format).
-                Used for all time/date storage in SMB as part of the when_t
-                data type. This time format will support dates through the year
-                2105.
-                time_t is defined by ANSI C as a long (signed) which can
-                limit its date support to the year 2038 depending on the
-                library routines used.
-
-
-ASCII           String (aka character array) of 8-bit ASCII characters.
-                Characters with the bit 7 set (80h through FFh) represent
-                the IBM PC extended ASCII character set. When data or header
-                fields of this type are stored in the header, a NULL
-                terminator may or may not be present.
-                C example:
-
-                uchar str[80];
-
-
-ASCIIZ          ASCII string with (non-optional) NULL terminator.
-                C example:
-
-                uchar str[81];
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           13                Definition of Data Types
-
-
-nulstr          ASCII string immediately terminated by NULL.
-                C example:
-
-                uchar *nulstr="";
-
-
-undef           Data buffer with undefined contents.
-                C example:
-
-                uchar buf[BUF_LEN];
-
-when_t          Date/Time stamp including time-zone adjustment information.
-                C example:
-
-                typedef struct {
-
-                    time_t  time;   // Time stamp (in local time)
-                    short   zone;   // Zone constant or Minutes (+/-) from UT
-
-                    } when_t;
-
-                time:
-
-                A time value of 0 is invalid and indicates an uninitialized
-                time stamp.
-
-                Time stamps are always stored in universal time. i.e.
-                Regardless of what the local time zone is, Jan 1st 1994 00:00
-                will always be stored as 2D24BD00h.
-
-                zone:
-
-                If the zone is in the range -720 to +720, it represents the
-                number of minutes east or west of UT. Values in this range
-                should only be used for time zones not otherwise represented
-                here.
-
-                If the zone is greater than 720 or less than -720, then the
-                following bits have special meaning:
-
-                (1<<12)         // Non-US time zone     (east of UT)
-                (1<<13)         // Non-US time zone     (west of UT)
-                (1<<14)         // U.S. time zone
-                (1<<15)         // Daylight savings
-
-                The lower 12 bits (0 through 11) contain the number of minutes
-                east or west of UT (not accounting for daylight savings).
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           14                Definition of Data Types
-
-
-                If the time zone is one specified in the U.S. Uniform Time Act,
-                the following values represent the zone:
-
-                AST 0x40F0      // Atlantic             (-04:00)
-                EST 0x412C      // Eastern              (-05:00)
-                CST 0x4168      // Central              (-06:00)
-                MST 0x41A4      // Mountain             (-07:00)
-                PST 0x41E0      // Pacific              (-08:00)
-                YST 0x421C      // Yukon                (-09:00)
-                HST 0x4258      // Hawaii/Alaska        (-10:00)
-                BST 0x4294      // Bering               (-11:00)
-
-                With bit 15 set, the following values represent the same zone
-                with the presence of daylight savings:
-
-                ADT 0xC0F0      // Atlantic             (-03:00)
-                EDT 0xC12C      // Eastern              (-04:00)
-                CDT 0xC168      // Central              (-05:00)
-                MDT 0xC1A4      // Mountain             (-06:00)
-                PDT 0xC1E0      // Pacific              (-07:00)
-                YDT 0xC21C      // Yukon                (-08:00)
-                HDT 0xC258      // Hawaii/Alaska        (-09:00)
-                BDT 0xC294      // Bering               (-10:00)
-
-                The following non-standard time zone specifications may also be
-                used:
-
-                MID 0x2294      // Midway               (-11:00)
-                VAN 0x21E0      // Vancouver            (-08:00)
-                EDM 0x21A4      // Edmonton             (-07:00)
-                WIN 0x2168      // Winnipeg             (-06:00)
-                BOG 0x212C      // Bogota               (-05:00)
-                CAR 0x20F0      // Caracas              (-04:00)
-                RIO 0x20B4      // Rio de Janeiro       (-03:00)
-                FER 0x2078      // Fernando de Noronha  (-02:00)
-                AZO 0x203C      // Azores               (-01:00)
-                LON 0x1000      // London               (+00:00)
-                BER 0x103C      // Berlin               (+01:00)
-                ATH 0x1078      // Athens               (+02:00)
-                MOS 0x10B4      // Moscow               (+03:00)
-                DUB 0x10F0      // Dubai                (+04:00)
-                KAB 0x110E      // Kabul                (+04:30)
-                KAR 0x112C      // Karachi              (+05:00)
-                BOM 0x114A      // Bombay               (+05:30)
-                KAT 0x1159      // Kathmandu            (+05:45)
-                DHA 0x1168      // Dhaka                (+06:00)
-                BAN 0x11A4      // Bangkok              (+07:00)
-                HON 0x11E0      // Hong Kong            (+08:00)
-                TOK 0x121C      // Tokyo                (+09:00)
-                SYD 0x1258      // Sydney               (+10:00)
-                NOU 0x1294      // Noumea               (+11:00)
-                WEL 0x12D0      // Wellington           (+12:00)
-
-
-
-_______________________________________________________________________________
-Synchronet                           15                Definition of Data Types
-
-
-fidoaddr_t      FidoNet address stored as four ushorts that represent the zone,
-                network, node, and point (in that order).
-                C example:
-
-                typedef struct {
-
-                    ushort zone,
-                           net,
-                           node,
-                           point;
-
-                    } fidoaddr_t;
-
-
-typestr_t       ASCIIZ string with ushort type prefix.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'str'
-                    uchar   str[];  // ASCIIZ filename or other string data
-
-                    } typestr_t;
-
-
-mattach_t       File attachment information with type prefix, translation
-                string, and filename.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Attachment type
-                    ushort  xlat[]; // Translations of data in attachment
-                    uchar   str[];  // ASCIIZ filename
-
-                    } mattach_t;
-
-vattach_t       Video file attachment information with type, compression,
-                translation string, and filename.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Attachment type
-                    ushort  comp;   // Compression method
-                    ushort  xlat[]; // Translations of data in attachment
-                    uchar   str[];  // ASCIIZ filename
-
-                    } vattach_t;
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           16                Definition of Data Types
-
-
-mtext_t         Message text with translation string prefix.
-                C example:
-
-                typedef struct {
-
-                    ushort  xlat[]; // Translations of text
-                    uchar   text[]; // Actual text data
-
-                    } mtext_t;
-
-
-ftext_t         Formatted message text with translation string prefix and
-                format type.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // See Image Types for valid types
-                    ushort  xlat[]; // Translations of data
-                    uchar   data[]; // Actual formatted text data
-
-                    } ftext_t;
-
-
-membed_t        Embedded data with type prefix, translation string, and ASCIIZ
-                description.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'dat'
-                    ushort  xlat[]; // Translations of embedded data
-                    uchar   name[]; // ASCIIZ char description of embedded data
-                    uchar   dat[];  // Binary data
-
-                    } membed_t;
-
-vembed_t        Embedded video data with type, compression method, translation
-                string, and ASCIIZ description.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'dat'
-                    ushort  comp;   // Compression method
-                    ushort  xlat[]; // Translations of embedded data
-                    uchar   name[]; // ASCIIZ char description of embedded data
-                    uchar   dat[];  // Binary data
-
-                    } vembed_t;
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           17                Definition of Data Types
-
-
-File formats
-============
-
-Index File (*.SID)
-------------------
-The index file for each message base contains one record per message in the
-base. Each record is fixed length using the following format:
-
-Index Record:
-------------
-C example:
-
-typedef struct {
-
-    ushort  to;     // 16-bit CRC of recipient name (lower case) or user number
-    ushort  from;   // 16-bit CRC of sender name (lower case) or user number
-    ushort  subj;   // 16-bit CRC of title/subject (lower case)
-    ushort  attr;   // attributes (MSG_PRIVATE, MSG_READ, etc. flags)
-    ulong   offset; // byte offset of message header in header file
-    ulong   number; // message serial number (1 based)
-    time_t  time;   // import date/time stamp (Unix format)
-
-    } idxrec_t;
-
-
-Example file dump (16 messages starting with message number 15):
----------------------------------------------------------------
-000000    36 4F 13 07 2A 77 00 00   20 00 00 00 0F 00 00 00    6O..*w.. .......
-000010    BE 62 76 2C 36 4F 46 0A   7F B2 00 00 20 01 00 00    �bv,6OF.�.. ...
-000020    10 00 00 00 C7 29 78 2C   36 4F 70 6F 46 FF 00 00    ....�)x,6OpoF�..
-000030    20 02 00 00 11 00 00 00   AD D3 7A 2C 70 6F 13 07     .......��z,po..
-000040    46 FF 00 00 20 03 00 00   12 00 00 00 D6 F8 7F 2C    F�.. .......��,
-000050    36 4F E1 EA E7 E9 00 00   20 04 00 00 13 00 00 00    6O����.. .......
-000060    1E 7B 85 2C 37 0D 2E DF   4D 79 00 00 20 05 00 00    .{�,7..�My.. ...
-000070    14 00 00 00 5C E1 A1 2C   90 54 2D 5A 86 62 00 00    ....\�,�T-Z�b..
-000080    20 06 00 00 15 00 00 00   39 2E A2 2C 70 6F 1A 8B     .......9.�,po.�
-000090    46 FF 00 00 20 07 00 00   16 00 00 00 D0 7B A8 2C    F�.. .......�{�,
-0000A0    2E DF 1A 8B 4D 79 00 00   20 08 00 00 17 00 00 00    .�.�My.. .......
-0000B0    FF 7B A8 2C B4 D9 35 7C   23 B1 00 00 20 09 00 00    �{�,��5|#�.. ...
-0000C0    18 00 00 00 CE D4 BA 2C   36 4F BC D8 B2 E7 00 00    ....�Ժ,6O�ز�..
-0000D0    20 0A 00 00 19 00 00 00   14 5F C3 2C BA A8 4E B0     ........_�,��N�
-0000E0    67 76 00 00 20 0B 00 00   1A 00 00 00 6F 89 C3 2C    gv.. .......o��,
-0000F0    36 4F 0C 01 19 9C 00 00   20 0C 00 00 1B 00 00 00    6O...�.. .......
-000100    F8 30 C6 2C 36 4F FA 48   0E 55 00 00 20 0D 00 00    �0�,6O�H.U.. ...
-000110    1C 00 00 00 6A 94 D3 2C   36 4F F1 CE CF A2 00 00    ....j��,6O��Ϣ..
-000120    20 0E 00 00 1D 00 00 00   53 DB D5 2C 8D A6 21 CE     .......S��,��!�
-000130    F7 AB 00 00 20 0F 00 00   1E 00 00 00 31 29 DC 2C    ��.. .......1)�,
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           18               Index (*.SID) File Format
-
-
-Field descriptions:
-------------------
-To:
-The 'To' field is the CRC-16 of the name of the intended recipient agent of
-this message or the intended recipient's user number. If the CRC is stored, the
-text must be converted to lower case (A-Z changed to a-z) before the CRC is
-calculated. If the message is forwarded to another agent, the original or new
-index record must be changed to contain the CRC-16 of the new recipient name or
-user number. This field must always contain the recipient user number for local
-e-mail on a Synchronet BBS. Outbound netmail stored in the Synchronet local
-e-mail message base will contain 0 in this field.
-
-From:
-This field, similar to the 'To' field, contains the CRC-16 of the name of the
-sending agent of this message or the sender's user number. If the CRC is
-stored, the text must be converted to lower case (A-Z changed to a-z) before
-the CRC is calculated. If the message is forwarded to another agent, the
-original or new index record must be changed to contain the CRC-16 of the new
-sender name or user number. If the message was imported into the local e-mail
-message base on a Synchronet BBS via netmail, this field will contain 0.
-
-Subj:
-The 'Subj' field contains the CRC-16 of the message's subject. The subject
-must be converted to lower case (A-Z changed to a-z) and all preceeding
-"re: "'s and "re:"'s removed before calculating the CRC-16.
-
-Attr:
-This ushort is a bit field of the specific attributes for this message.
-It is a clone of the 'attr' element of the msghdr_t structure.
-
-Offset:
-This ulong is the offset (in bytes) in the header file for this message's
-header record.
-
-Number:
-This ulong is the serial number of this message. Valid values are 1 through
-0xffffffff. No two index records in the same message base may have the same
-message number. All index records must have sequential, but not necessarily
-consequetive, message numbers.
-
-Time:
-This field is the date/time stamp the message was imported to or posted in
-the message base. It is a clone of the 'when_imported.time' element of the
-msghdr_t structure.
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           19               Index (*.SID) File Format
-
-
-Header File (*.SHD)
-===================
-
-Each SMB header file is made up of two distinct sections: base header records
-and message header records (usually the bulk of the file).
-
-Base Header Records:
--------------------
-Base header records are blocks of data that apply to the entire message base
-and are of variable length. This specification defines only one base header
-record, the "Status info" (smbstatus_t) record. This status info record must be
-the first base header record in the file and must be modified if additional
-base header records are added.
-
-Additional header records allow other developers to store configuration and
-status information particular to their application needs. It also allows for
-future header record definitions as part of this specification without causing
-backward compatibility issues.
-
-Each base header record contains a fixed length portion (smbhdr_t) and an
-optional variable length portion.
-
-Whenever a base header record is read or updated (written), it must first
-be successfully locked and subsequently unlocked.
-
-The first base header record (Status Info) is used as a semaphore when writing
-to the message index (.SID) file and, when using the Hyper Allocation storage
-method, writing to the message data (.SDT) file. This record must be
-succesfully locked before writing and subsequently unlocked. This is to insure
-that multiple applications simultaneously writing to the same message base
-does result in corrrupted data.
-
-
-Message Header Records:
-----------------------
-Following the last base header record is the first message header record. Each
-header record is stored in one or more 256 byte blocks. There must be exactly
-one active message header record for every index record in the index file.
-(Note: This does not include deleted message headers that have not been
-overwritten by a new message header).
-
-Each message header record contains a fixed length portion (msghdr_t), a list
-of zero or more fixed length data fields (dfield_t), and a list of three or
-more variable length header fields (hfield_t).
-
-The value of the data stored in the zero or more unused bytes of the last
-header record block have an undefined value, though whenever possible
-developers should initialize to binary zero for human readability.
-
-Whenever a message header record is read or updated (written), it must first
-be successfully locked and subsequently unlocked.
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           20              Header File (*.SHD) Format
-
-
-Base Header Record (Fixed Portion):
-----------------------------------
-C example:
-
-typedef struct {
-
-    uchar   id[4];          // text or binary unique hdr ID
-    ushort  version;        // version number (initially 100h for 1.00)
-    ushort  length;         // length including this struct
-
-    } smbhdr_t;
-
-
-Base Header Record Field Descriptions:
--------------------------------------
-Id:
-This is a four byte unique ID identifying the type of the base header record.
-The bytes may contain any value, but printable ASCII characters are preferred.
-The only ID defined in this specification is "SMB^Z" used by the Status Info
-base header record.
-
-Version:
-This is a version number of the base header record type. Base header records
-of different versions may have different formats or contain different
-information. This is to aid the application in determining if the record
-is pertinent and if so, to what degree. The Status Info base header record
-uses this version field to define the version of the format for the entire
-message base (currently 0x121 for version 1.21).
-
-Length:
-This is entire length in bytes of this header record (including both fixed
-and variable portions).
-
-
-Base Header #1 (Status info) Record (Variable Portion):
-------------------------------------------------------
-C example:
-
-typedef struct {
-
-    ulong   last_msg;       // last message number posted or imported
-    ulong   total_msgs;     // total messages currently in message base
-    ulong   header_offset;  // byte offset to first header record
-    ulong   max_crcs;       // Maximum number of CRCs to keep in history
-    ulong   max_msgs;       // Maximum number of messages to keep in base
-    ushort  max_age;        // Maximum age of messages (days) to keep in base
-    ushort  attr;           // Attribute bits
-
-    } smbstatus_t;
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           21              Header File (*.SHD) Format
-
-
-Base Header #1 (Status Info) Record (Variable Portion) Field Descriptions:
--------------------------------------------------------------------------
-Last_msg:
-This is the serial number of the last message imported or posted into this
-message base. The index, header, and data records for this message may possibly
-not exist (due to deletion). This field is used for determining the message
-number to give to a new message being imported or posted into this message
-base. This field must be updated for every message added to the message base.
-
-Total_msgs:
-This is the total number of active messages currently in the message base.
-This number should match the number of records in the index (.SID) file
-and active header records in the header (.SHD) file. This field must be
-updated whenever a message is added to or removed from the message base.
-
-Header_offset:
-This is the byte offset to the first message header record. It is useful
-for skipping all the base header records and going directly to the first
-message header record.
-
-Max_crcs:
-This is the maximum number of message CRCs to store in the CRC history (.SCH)
-file for duplicate message checking. If this field contains 0, then duplicate
-message checking is disabled.
-
-Max_msgs:
-This is the preferred maximum number of messages to keep in this message
-base as specified by the system operator. It is used by maintenance programs
-that trim the message base down by removing old messages. This field should
-be ignored by applications importing or posting messages allowing them to
-exceed this maximum at will.
-
-Max_age:
-This field is the maximum age (in days) of messages to keep in the message
-base. It is used by maintenance programs to purge out-dated messages from
-the message base.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           22              Header File (*.SHD) Format
-
-
-Attr:
-This is a bit field containing specific attributes (or flags) that may define
-the way messages are stored or retrieved from the this message base. The
-following attributes are defined:
-
-    SMB_EMAIL       (1<<0)
-
-    Indicates the message base is specifically for messages to or from local
-    users. When this bit is set, the idxrec.to and idxrec.from fields will
-    contain the user numbers (or 0 for non-user destination/source) instead of
-    the CRC-16 of the agent name.
-
-    SMB_HYPERALLOC  (1<<1)
-
-    Indicates the message base uses the Hyper Allocation storage method. This
-    bit should not be cleared by an application without first deleting all the
-    messages in the message base. This is due to the fact the Hyper Allocation
-    is not downward compatible with the Self-packing and Fast Allocation
-    storage methods.
-
-When used with Synchronet BBS software, a message base must NOT have both of
-the above attributes set. The only message base that should have the SMB_EMAIL
-attribute set is the DATA\MAIL message base.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           23              Header File (*.SHD) Format
-
-
-Base Header #1 (Status info) Record Contents:
---------------------------------------------
-smbhdr.id="SMB\x1a";        // SMB^Z
-smbhdr.version=0x121;       // v1.21
-smbhdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); smbstatus_t status;
-
-
-Additional Base Headers:
------------------------
-Additional headers from developers must have initial 8 bytes in smbhdr_t
-format, length must include size of smbhdr_t, and header_offset of smbstatus_t
-must be changed to include the size of the additional header(s).
-
-
-Example file dump (base header portion only):
---------------------------------------------
-000000    53 4D 42 1A 20 01 20 00   F4 01 00 00 F4 01 00 00    SMB. . .�...�...
-000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           24              Header File (*.SHD) Format
-
-
-Message Header Record (Fixed portion):
--------------------------------------
-C example:
-
-typedef struct {
-
-    uchar   id[4];          // SHD^Z (same for all types and versions)
-    ushort  type;           // Message type (this is the definition of type 0)
-    ushort  version;        // Version of type (initially 100h for 1.00)
-    ushort  length;         // Total length of fixed portion + all fields
-    ushort  attr;           // Attributes (bit field) (duplicated in SID)
-    ulong   auxattr;        // Auxillary attributes (bit field)
-    ulong   netattr;        // Network attributes (bit field)
-    when_t  when_written;   // Date/Time message was originally created
-    when_t  when_imported;  // Date/Time message was imported (locally)
-    ulong   number;         // Message number (unique, not necessarily seq.)
-    ulong   thread_orig;    // Original message number in thread
-    ulong   thread_next;    // Next message in thread
-    ulong   thread_first;   // Number of first reply to this message
-    uchar   reserved[16];   // 16 reserved bytes for future use
-    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-    ushort  total_dfields;  // Total number of data fields
-
-    } msghdr_t;
-
-typedef struct {
-
-    ushort  type;           // See "Data Field Types" values
-    ulong   offset;         // Offset into buffer 
-    ulong   length;         // Length of data field in buffer
-
-    } dfield_t;
-
-typedef struct {
-
-    ushort  type;           // See "Header Field Types" for values
-    ushort  length;         // Length of buffer
-    uchar   dat[length];
-
-    } hfield_t;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           25              Header File (*.SHD) Format
-
-
-Example file dump (one header record, both fixed and variable length portions):
-------------------------------------------------------------------------------
-000020    53 48 44 1A 00 00 20 01   F5 00 00 00 00 00 00 00    SHD... .�.......
-000030    00 00 00 00 46 DB F7 2C   00 00 7D D7 29 2D 00 00    ....F��,..}�)-..
-000040    01 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-000050    00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-000060    00 00 00 00 02 00 00 00   00 00 00 00 4A 01 00 00    ............J...
-000070    02 00 4A 01 00 00 53 00   00 00 00 00 13 00 4D 61    ..J...S.......Ma
-000080    72 69 61 6E 6E 65 20 4D   6F 6E 74 67 6F 6D 65 72    rianne Montgomer
-000090    79 30 00 0C 00 43 61 72   6F 6C 20 47 61 69 73 65    y0...Carol Gaise
-0000A0    72 60 00 07 00 46 61 72   6E 68 61 6D A4 00 14 00    r`...Farnham�...
-0000B0    31 3A 31 33 38 2F 31 30   32 2E 30 20 32 63 66 38    1:138/102.0 2cf8
-0000C0    30 35 37 36 A5 00 14 00   31 3A 33 34 33 2F 31 30    0576�...1:343/10
-0000D0    30 2E 30 20 32 63 66 33   62 39 30 61 A3 00 23 00    0.0 2cf3b90a�.#.
-0000E0    31 33 38 2F 31 30 32 20   31 20 32 37 30 2F 31 30    138/102 1 270/10
-0000F0    31 20 32 30 39 2F 32 30   39 20 31 30 33 2F 30 20    1 209/209 103/0 
-000100    33 35 35 02 00 02 00 02   00 03 00 08 00 01 00 8A    355............�
-000110    00 66 00 00 00 00 00 00   00 00 00 00 00 00 00 00    .f..............
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           26              Header File (*.SHD) Format
-
-
-Contents of example header:
---------------------------
-id                   SHD^Z
-type                 0000h
-version              0120h
-length               245
-attr                 0000h
-auxattr              00000000h
-netattr              00000000h
-when_written         Sat Nov 27 17:57:10 1993
-when_imported        Tue Jan 04 15:54:21 1994
-number               1
-thread_orig          0
-thread_next          0
-thread_first         0
-reserved[16]         
-offset               0
-total_dfields        2
-
-dfield[0].type       00h
-dfield[0].offset     0
-dfield[0].length     330
-dfield[1].type       02h
-dfield[1].offset     330
-dfield[1].length     83
-
-hfield[0].type       00h
-hfield[0].length     19
-hfield[0]_dat        Marianne Montgomery
-hfield[1].type       30h
-hfield[1].length     12
-hfield[1]_dat        Carol Gaiser
-hfield[2].type       60h
-hfield[2].length     7
-hfield[2]_dat        Farnham
-hfield[3].type       A4h
-hfield[3].length     20
-hfield[3]_dat        1:138/102.0 2cf80576
-hfield[4].type       A5h
-hfield[4].length     20
-hfield[4]_dat        1:343/100.0 2cf3b90a
-hfield[5].type       A3h
-hfield[5].length     35
-hfield[5]_dat        138/102 1 270/101 209/209 103/0 355
-hfield[6].type       02h
-hfield[6].length     2
-hfield[6]_dat        02 00
-hfield[7].type       03h
-hfield[7].length     8
-hfield[7]_dat        01 00 8A 00 66 00 00 00
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           27              Header File (*.SHD) Format
-
-
-Fixed Portion Field descriptions:
---------------------------------
-Id:
-This field (regardless of the header type or version) must always contain the
-the string "SHD^Z". This is to aid in the restoration of a corrupted header
-file and give a visual indication of the beginning of a new header record when
-viewing dumps of the header file.
-
-Type:
-This is the message header type. Only one type is currently defined by this
-specification (type 0). Any and all future header types will have the first
-4 fields (10 bytes) in the same format of type 0. This allows other types
-(with different lengths) to be skipped because the 4th field (length) will
-always be in the same position.
-
-Version:
-This is the version of this header type. This specification defines version
-1.21 of message header type 0 (stored as 121h).
-
-Length:
-This is the total length of this message header record (including both fixed
-and variable length portions, but NOT including unused block space).
-
-Attr:
-This is a bit field (16-bit) containing basic message attributes (flags) for
-this message. An exact duplicate of this field is stored in the index file as
-well. They must always match.
-
-Auxattr:
-This is a bit field (32-bit) containing the auxillary attributes (flags) for
-this message. The attributes stored in this variable are more specific in
-nature and less critical than those in the Attr field.
-
-Netattr:
-This is a bit field (32-bit) containing the network attributes (flags) for this
-message. The attributes stored in this variable are related solely to message
-networking.
-
-When_written:
-This is the date and time when the message was originally created.
-
-When_imported:
-This is the date and time when the message was posted on or imported into the
-local message system.
-
-Number:
-This is the message's unique serial number (from 1 to FFFFFFFFh). This field
-is duplicated in the index file. They must always match.
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           28              Header File (*.SHD) Format
-
-
-Thread_orig:
-If this message is a reply, then this field contains the number of the original
-message that was replied to. If this message was not a reply, this field will
-contain the value 0.
-
-Thread_next:
-If this message is a reply, and there are later replies to that message
-(the message number contained in the Thread_orig field), then this field will
-contain the number of the next reply in the chain. If this message is the only
-reply to the orignal message, this field will contain the value 0.
-
-Thread_first:
-If there are any replies to this message (after it has been posted), this field
-will contain the number of the first reply to this message. If there are no
-replies to this message, this field will contain the value 0.
-
-Reserved:
-Unused bytes, reserved for future definition in the message header type 0
-specification.
-
-Offset:
-The byte offset into the data file, specifying the start of the buffer for
-all data associated with this message. This value must be either 0 or modula
-256. When retrieving the actual data portion of data fields, the physical
-offset into the file will be the offset of the message data buffer (this field)
-plus the offset of the individual data field (msghdr_t.offset+dfield_t.offset).
-
-Total_dfields:
-This field contains the total number of data fields associated with this
-message. The value of this field must match the actual number of data fields
-stored in the header (dfield_t data types following the fixed portion of the
-message header).
-
-
-Variable Portion Field descriptions:
------------------------------------
-See the Header Field Type and Data Field Type sections for the descriptions
-of the values contained in these fields.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           29              Header File (*.SHD) Format
-
-
-Message Header Block Allocation (*.SHA)
-=======================================
-
-If this message base uses the Hyper Allocation storage method (the
-SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-not created or used.
-
-This file contains no header or signature data. Each byte (uchar) in the file
-specifies the allocation state of the corresponding 256 byte block in the
-header (*.SHD) file. A value of 0 indicates a free header block, and a value of
-1 indicates an allocated block. Other non-zero values are undefined.
-
-This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           30   Header Allocation File (*.SHA) Format
-
-
-Message Data (*.SDT)
-====================
-
-This file contains no header or signature data. It contains the text and other
-embedded data for the messages in a single message base. The data for each
-message always begins on a 256 byte block boundary. The data in the unused
-portion of a data block is undefined, but should be initialized to NULL
-whenever possible.
-
-This file must always be opened DENY NONE (shareable).
-
-Data fields of type TEXT_BODY and TEXT_TAIL must have all trailing white space
-and control characters removed (i.e. the last character of the data record
-must be in the range 21h to FFh). The only exception to this rule, is if the
-TEXT_BODY is terminated with multiple contiguous CRLFs, only the last CRLF
-should be removed. A CRLF should always be appended to the text data when it is
-displayed.
-
-When reading from this file, it is a good idea to make sure the message header
-for the data being read is currently locked (though no single message header
-should be locked for extended durations of time). This will insure that no
-other application will write to this portion of the file while it's being
-read (read from disk, not displayed).
-
-When using the Hyper Allocation storage method, the Status Info message base
-header must be successfully locked before writing to this file and subsequently
-unlocked.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           31                Data File (*.SDT) Format
-
-
-Message Data Block Allocation (*.SDA)
-=====================================
-
-If this message base uses the Hyper Allocation storage method (the
-SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-not created or used.
-
-This file contains no header or signature data. Each word (ushort) in the file
-specifies the allocation state of the corresponding 256 byte block in the data
-(*.SDT) file. A value of 0 indicates a free block, and a non-zero value
-indicates the number of message header records associated with this message
-data (most often 1). Each block can be used by up to 65,535 header records.
-
-This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           32     Data Allocation File (*.SDA) Format
-
-
-CRC history for duplicate message checking (*.SCH)
-==================================================
-
-This file is optional and contains no header or signature data. Each long word
-(ulong) in the file contains a CRC-32 of previously posted/imported messages.
-These CRCs can be used to check a candidate message for posting/import to be
-sure the message isn't a duplicate created by human or program error. The
-maximum number of CRCs to store is defined in the first message base header
-record (smbstatus_t.max_crcs).
-
-The CRC is calculated on the first TEXT_BODY data field before any translations
-are applied (e.g. encoding, compression, encryption).
-
-This file must always be opened DENY ALL (non-shareable).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           33         CRC History File (*.SCH) Format
-
-
-Header Field Types:
-==================
-
-These are the defined valid values for hfield_t.type:
-
-Name     : SENDER
-Value    : 00h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes
-Summary  : Name of agent that sent this message
-
-If blank (0 length or nulstr), assumed "Anonymous". If multiple SENDER fields
-exist, then the message has been forwarded and the order of the fields in the
-record must match the forwarding order (chronologically). When forwarding a
-message, the original SENDER field should be left intact and new SENDER,
-FORWARDED, and RECIPIENT fields added to the end of the record.
-
-
-Name     : SENDERAGENT
-Value    : 01h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : AGENT_PERSON or previous SENDERAGENT if exists
-Summary  : Type of agent that sent this message
-
-If multiple SENDER fields exist, then the message has been forwarded. If any of the
-forwarding agents is of a type other than AGENT_PERSON, then this field must
-follow that SENDER field to specify the agent type.
-
-Name     : SENDERNETTYPE
-Value    : 02h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : NET_NONE or previous SENDERNETTYPE if exists
-Summary  : Type of network message was sent from
-
-If multiple SENDERNETADDR fields are included, a SENDERNETTYPE field should be
-included before each to determine what data type the address is stored in.
-
-Name     : SENDERNETADDR
-Value    : 03h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERNETADDR if exists
-Summary  : Network address for agent that sent this message
-
-The SENDERNETTYPE field indicates the data type of this field. If the
-SENDERNETTYPE is of type NET_INTERNET, the local-part of the Internet
-address is optional. If the local-part separator character ('@') is omitted,
-the SENDER field is assumed to be the local-part of the address.
-
-_______________________________________________________________________________
-Synchronet                           34                      Header Field Types
-
-
-
-Name     : SENDEREXT
-Value    : 04h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDEREXT if exists
-Summary  : Extension of sending agent
-
-This field is useful for storing the sending agent's extension, when the
-agent's extension binds more tightly than the agent's name.
-
-For example, Synchronet Multinode BBS Software stores local e-mail with the
-sending and receiving agent's user numbers stored as their respective
-extensions. This is done so that if a user name changes for some reason,
-messages will not "disappear" from the user's mail box.
-
-If the SMB_EMAIL status header attribute is set, then the "From" field in the
-index must contain the binary value of this field rather than the CRC-16 of the
-SENDER (name) field.
-
-Name     : SENDERPOS
-Value    : 05h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERPOS if exists
-Summary  : Position of sending agent
-
-Primarily for documentary purposes, this field contains the position of the
-sending agent (i.e. President, Sysop, C.E.O., MIS Director, etc).
-
-It can also be useful for getting a message or reply to the intended
-recipient when the agent name is not located or is unknown, but the position
-of the agent is known and specified.
-
-Name     : SENDERORG
-Value    : 06h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERORG if exists
-Summary  : Organization name of sending agent
-
-Primarily for documentary purposes, this field contains the organization to
-which the sending agent belongs (i.e. Microsoft, Joe's BBS, SoCal User's Group,
-etc).
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           35                      Header Field Types
-
-
-Name     : AUTHOR
-Value    : 10h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Default  : First SENDER
-Summary  : Name of agent that created this message
-
-This field can only be added by the process that originally creates the
-message. It should not be included if same as first SENDER field. If multiple
-AUTHOR fields exist, then the message was created by multiple agents and is
-considered valid. The order of multiple AUTHOR fields in the record is not
-significant.
-
-Name     : AUTHORAGENT
-Value    : 11h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERAGENT or previous AUTHORAGENT if exists
-Summary  : Type of agent that created this message
-
-This field can only be added by the process that originally creates the
-message. It should not be included if same as first SENDERAGENT field. If
-multiple AUTHOR fields exist, then the message was created by multiple agents
-and if the agent type for any of the authors is other than AGENT_PERSON, an
-AUTHORAGENT field must follow to specify the agent type.
-
-Name     : AUTHORNETTYPE
-Value    : 12h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERNETTYPE or previous AUTHORNETTYPE if exists
-Summary  : Type of network this author is member of
-
-Name     : AUTHORNETADDR
-Value    : 13h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERNETADDR or previous AUTHORNETADDR if exists
-Summary  : Network address of this author
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           36                      Header Field Types
-
-
-Name     : AUTHOREXT
-Value    : 14h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDEREXT or previous AUTHOREXT if exists
-Summary  : Extension of this author
-
-Name     : AUTHORPOS
-Value    : 15h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERPOS or previous AUTHORPOS if exists
-Summary  : Position of this author
-
-Name     : AUTHORORG
-Value    : 16h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERORG or previous AUTHORORG if exists
-Summary  : Organization this author belongs to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           37                      Header Field Types
-
-
-Name     : REPLYTO
-Value    : 20h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDER
-Summary  : Name of agent that replies should go to
-
-Name     : REPLYTOAGENT
-Value    : 21h
-Data     : ushort
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERAGENT
-Summary  : Type of agent that replies should go to
-
-Name     : REPLYTONETTYPE
-Value    : 22h
-Data     : ushort
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERNETTYPE
-Summary  : Type of network that replies should go to
-
-Name     : REPLYTONETADDR
-Value    : 23h
-Data     : undef
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERNETADDR
-Summary  : Network address that replies should go to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           38                      Header Field Types
-
-
-Name     : REPLYTOEXT
-Value    : 24h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDEREXT
-Summary  : Extension of agent that replies should go to
-
-Name     : REPLYTOPOS
-Value    : 25h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERPOS
-Summary  : Position of agent that replies should go to
-
-Name     : REPLYTOORG
-Value    : 26h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERORG
-Summary  : Organization of agent that replies should go to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           39                      Header Field Types
-
-
-Name     : RECIPIENT
-Value    : 30h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes
-Default  : "All"
-Summary  : Name of agent to receive this message
-
-If multiple RECIPIENT fields exist, the message has been forwarded and for each
-additional RECIPIENT field (after the initial RECIPIENT), there should be a
-FORWARDED field. The order of the RECIPIENT fields in the record must match the
-order in which the message was sent and forwarded (chronologically).
-
-Name     : RECIPIENTAGENT
-Value    : 31h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : AGENT_PERSON or previous RECIPIENTAGENT if exists
-Summary  : Type of agent to receive this message
-
-If multiple RECIPIENT fields exist, the message has been forwarded. If any of
-the recipient agents are of a type other than AGENT_PERSON, this field must
-follow the RECIPIENT field to specify the agent type.
-
-Name     : RECIPIENTNETTYPE
-Value    : 32h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : NET_NONE or previous RECIPIENTNETTYPE if exists
-Summary  : Type of network to receive this message
-
-Name     : RECIPIENTNETADDR
-Value    : 33h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTNETADDR if exists
-Summary  : Address of network to receive this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           40                      Header Field Types
-
-
-Name     : RECIPIENTEXT
-Value    : 34h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTEXT if exists
-Summary  : Extension of agent to receive this message
-
-If SMB_EMAIL status header attribute is set, then the "To" field in the index
-must contain the binary value of this field rather than the CRC-16 of the
-RECIPIENT (name) field. This is the case specifically with the local e-mail
-message base on a Synchronet BBS.
-
-Name     : RECIPIENTPOS
-Value    : 35h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTPOS if exists
-Summary  : Position of agent to receive this message
-
-Name     : RECIPIENTORG
-Value    : 36h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTORG if exists
-Summary  : Type of agent to receive this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           41                      Header Field Types
-
-
-Name     : FORWARDTO
-Value    : 40h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of agent this message is to be forwarded to
-
-Name     : FORWARDTOAGENT
-Value    : 41h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTAGENT or previous FORWARDTOAGENT if exists
-Summary  : Type of agent this message is to be forwarded to
-
-Name     : FORWARDTONETTYPE
-Value    : 42h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETTYPE or previous FORWARDTONETTYPE if exists
-Summary  : Type of network this message is to be forwarded to
-
-Name     : FORWARDTONETADDR
-Value    : 43h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETADDR or previous FORWARDTONETADDR if exists
-Summary  : Network address this message is to be forwarded to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           42                      Header Field Types
-
-
-Name     : FORWARDTOEXT
-Value    : 44h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTEXT or previous FORWARDTOEXT if exists
-Summary  : Extension of agent this message is to be forwarded to
-
-Name     : FORWARDTOPOS
-Value    : 45h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTPOS or previous FORWARDTOPOS if exists
-Summary  : Position of agent this message is to be forwarded to
-
-Name     : FORWARDTOORG
-Value    : 46h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTORG or previous FORWARDTOORG if exists
-Summary  : Organization of agent this message is to be forwarded to
-
-Name     : FORWARDED
-Value    : 48h
-Data     : when_t
-Multiple : Yes, order significant
-Required : Yes, if forwarded
-Summary  : Date/Time this message was forwarded to another agent
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           43                      Header Field Types
-
-
-Name     : RECEIVEDBY
-Value    : 50h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes, if receiving agent is other than RECIPIENT
-Summary  : Name of agent that received this message
-
-Name     : RECEIVEDBYAGENT
-Value    : 51h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTAGENT or previous RECEIVEDBYAGENT if exists
-Summary  : Type of agent that received this message
-
-Name     : RECEIVEDBYNETTYPE
-Value    : 52h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETTYPE or previous RECEIVEDBYNETTYPE if exists
-Summary  : Type of network that received this message
-
-Name     : RECEIVEDBYNETADDR
-Value    : 53h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETADDR or previous RECEIVEDBYNETADDR if exists
-Summary  : Network address that received this message
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           44                      Header Field Types
-
-
-Name     : RECEIVEDBYEXT
-Value    : 54h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTEXT or previous RECEIVEDBYEXT if exists
-Summary  : Extension of agent that received this message
-
-Name     : RECEIVEDBYPOS
-Value    : 55h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTPOS or previous RECEIVEDBYPOS if exists
-Summary  : Position of agent that received this message
-
-Name     : RECEIVEDBYORG
-Value    : 56h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTORG or previous RECEIVEDBYORG if exists
-Summary  : Organization of agent that received this message
-
-Name     : RECEIVED
-Value    : 58h
-Data     : when_t
-Multiple : Yes, order significant
-Required : Yes, if received
-Default  : NULL
-Summary  : Date/Time this message was received
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           45                      Header Field Types
-
-
-Name     : SUBJECT
-Value    : 60h
-Data     : ASCII
-Multiple : No
-Required : Yes, but may be blank (0 length or nulstr)
-Summary  : Subject/title of message
-
-Name     : SUMMARY
-Value    : 61h
-Data     : ASCII
-Multiple : No
-Required : No
-Summary  : Summary of message contents, created by AUTHOR
-
-Name     : COMMENT
-Value    : 62h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Comment about this message, created by SENDER
-
-This field is useful for adding notes to a message when forwarding to a new
-recipient.
-
-Name     : CARBONCOPY
-Value    : 63h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : List of agents this message was also sent to
-
-This field is optional and only for the use of notifying the recipient of who
-else received the message.
-
-Name     : GROUP
-Value    : 64h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of group of users to receive message on recipient system
-
-This field is used when sending to a group name across a network, where the
-group can be expanded into multiple header records for each agent on the
-destination system.
-
-Name     : EXPIRATION
-Value    : 65h
-Data     : when_t
-Multiple : No
-Required : No
-Summary  : Date/Time that this message will expire
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           46                      Header Field Types
-
-
-Name     : PRIORITY
-Value    : 66h
-Data     : ulong
-Multiple : No
-Required : No
-Default  : 0
-Summary  : Message priority (0 is lowest, FFFFFFFFh is highest)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           47                      Header Field Types
-
-
-Name     : FILEATTACH
-Value    : 70h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name/file specification of attached file(s)
-
-Name of attached file(s). Wildcards allowed. MSG_FILEATTACH attribute must be
-set. If the MSG_FILEATTACH attribute is set but this field is not included,
-the SUBJECT field is assumed to be the filename(s).
-
-Name     : DESTFILE
-Value    : 71h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Destination name for attached file(s)
-
-Wildcards allowed. FILEATTACH field must also be included.
-
-Name     : FILEATTACHLIST
-Value    : 72h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of ASCII list of attached filenames
-
-Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-MSG_FILEATTACH attribute must be set.
-
-Name     : DESTFILELIST
-Value    : 73h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of ASCII list of destination filenames
-
-Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-
-Name     : FILEREQUEST
-Value    : 74h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of requested file
-
-Wildcards allowed. MSG_FILEREQUEST attribute must be set
-
-Name     : FILEPASSWORD
-Value    : 75h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Password for FILEREQUEST
-
-_______________________________________________________________________________
-Synchronet                           48                      Header Field Types
-
-
-
-Name     : FILEREQUESTLIST
-Value    : 76h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of ASCII list of filenames to request
-
-Wildcards allowed.
-
-Name     : FILEPASSWORDLIST
-Value    : 77h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of ASCII list of passwords for FILEREQUESTLIST
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           49                      Header Field Types
-
-
-Name     : IMAGEATTACH
-Value    : 80h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached image file for display
-
-MSG_FILEATTACH attribute must be set. See Image Types for valid
-mattach_t.type values.
-
-Name     : ANIMATTACH
-Value    : 81h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached graphical animation file for display
-
-MSG_FILEATTACH attribute must be set. See Animation Types for valid
-mattach_t.type values.
-
-Name     : FONTATTACH
-Value    : 82h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached font definition file
-
-MSG_FILEATTACH attribute must be set. See Font Types for valid mattach_t.type
-values.
-
-Name     : SOUNDATTACH
-Value    : 83h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached sound file for playback
-
-MSG_FILEATTACH attribute must be set. See Sound Types for valid mattach_t.type
-values.
-
-Name     : PRESENTATTACH
-Value    : 84h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached presentation definition file
-
-MSG_FILEATTACH attribute must be set. See Present Types for valid
-mattach_t.type values.
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           50                      Header Field Types
-
-
-Name     : VIDEOATTACH
-Value    : 85h
-Data     : vattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached interleaved video/sound file
-
-MSG_FILEATTACH attribute must be set. See Video Types for valid
-vattach_t.type values and Video Compression Types for valid vattach_t.comp
-values.
-
-Name     : APPDATAATTACH
-Value    : 86h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of attached application data file for process/display
-
-MSG_FILEATTACH attribute must be set. See Application Data Types for valid
-mattach_t.type values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           51                      Header Field Types
-
-
-Name     : IMAGETRIGGER
-Value    : 90h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of image file to trigger for display
-
-See Image Types for valid typestr_t.type values.
-
-Name     : ANIMTRIGGER
-Value    : 91h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of animation file to trigger for display
-
-See Animation Types for valid typestr_t.type values.
-
-Name     : FONTTRIGGER
-Value    : 92h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of font definition file to trigger
-
-See Font Types for valid typestr_t.type values.
-
-Name     : SOUNDTRIGGER
-Value    : 93h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of sound file to trigger for playback
-
-See Sound Types for valid typestr_t.type values.
-
-Name     : PRESENTTRIGGER
-Value    : 94h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of presentation definition file to trigger
-
-See Present Types for valid typestr_t.type values.
-
-Name     : VIDEOTRIGGER
-Value    : 95h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of interleaved video/sound file to trigger
-
-See Video Types for valid typestr_t.type values.
-
-
-_______________________________________________________________________________
-Synchronet                           52                      Header Field Types
-
-
-Name     : APPDATATRIGGER
-Value    : 96h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of application data file to trigger
-
-See Application Data Types for valid typestr_t.type values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           53                      Header Field Types
-
-
-Name     : FIDOCTRL
-Value    : A0h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : keyword ":" [" "] appdata
-Summary  : FTS/FSC-compliant control information line
-
-Any FidoNet FTS/FSC-compliant control information ("kludge") line that
-does not have an equivalent representation here. All data not unique to the
-actual control line, including leading and trailing white space, Ctrl-A (01h)
-character and terminating CR must be ommited. Defined in FTS-0001.
-
-Name     : FIDOAREA
-Value    : A1h
-Data     : ASCII
-Multiple : No
-Required : No
-Summary  : FTN EchoMail conference name.
-
-Defined in FTS-0004.
-
-Name     : FIDOSEENBY
-Value    : A2h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : net"/"node [" "[net"/"]node] [...]
-Summary  : Used to store two-dimensional (net/node) SEEN-BY information
-
-Often used in FTN EchoMail environments. Only the actual SEEN-BY data is stored
-and SEEN-BY: is stripped along with any leading and trailing white space
-characters. Defined in FTS-0004.
-
-Name     : FIDOPATH
-Value    : A3h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : net"/"node [" "[net"/"]node] [...]
-Summary  : Used to store two-dimensional (net/node)
-
-Defined in FTS-0004. ^aPATH: is stripped along with any leading and trailing
-white space characters.
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           54                      Header Field Types
-
-
-Name     : FIDOMSGID
-Value    : A4h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : origaddr " " serialno
-Summary  : MSGID field as specified in FTS-0009.
-
-Name     : FIDOREPLYID
-Value    : A5h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : origaddr " " serialno
-Summary  : REPLY field as specified in FTS-0009.
-
-Name     : FIDOPID
-Value    : A6h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : pID " " version [" "serialno]
-Summary  : Indentification string of program that created this message
-
-Defined FSC-0046. "^aPID:" and any white space is not included.
-
-Name     : FIDOFLAGS
-Value    : A7h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Used to store the FTN FLAGS kludge information
-
-Note that all FLAG options that have binary representation in the message
-header must be removed from the FLAGS string prior to storing it. Only the
-actual flags option string is stored and ^aFLAGS is stripped along with any
-leading and trailing white space characters. Defined in FSC-0053.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           55                      Header Field Types
-
-
-Name     : RFC822HEADER
-Value    : B0h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : field-name ":" [field-body] [CRLF]
-Summary  : Undefined RFC-822 header field
-
-Internet Message storage format, that does not have an equivalent
-representation here. Folded header fields are allowed. Terminating CRLF may be
-ommited.
-
-Name     : RFC822MSGID
-Value    : B1h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : "<" addr-spec ">"
-Summary  : Message-ID field as specified in RFC-822.
-
-Name     : RFC822REPLYID
-Value    : B2h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : "<" addr-spec ">"
-Summary  : In-Reply-To field as specified in RFC-822.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           56                      Header Field Types
-
-
-Name     : UNKNOWN
-Value    : F0h
-Data     : undef
-Multiple : Yes
-Required : No
-Summary  : Undefined header field of undefined type
-
-This field is useful for retaining binary header fields (that do not have an
-equivalent representation here) between message storage formats.
-
-Name     : UNKNOWNASCII
-Value    : F1h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Undefined header field of type ASCII
-
-This field is useful for retaining ASCII header fields (that do not have an
-equivalent representation here) between message storage formats.
-
-Name     : UNUSED
-Value    : FFh
-Data     : undef
-Multiple : Yes
-Required : No
-Summary  : Unused (deleted) header field
-
-The data contained in this header field is of an unknown type and should not be
-processed.
-
-
-Note:
-----
-Specifically, not defined are the values F000h through FFFFh. These values
-are to be used for user or system defined header fields. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-header fields added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           57                      Header Field Types
-
-
-Data Field Types:
-================
-
-These are the defined valid values for dfield_t.type:
-
-
-Val Name                Data        Description
---- ----                ----        -----------
-00h TEXT_BODY           mtext_t     Displayable text (body of message).
-                                    Included in duplicate message checking.
-                                    All terminating white space and control
-                                    characters are to be truncated from data
-                                    (except when multiple contiguous CRLFs
-                                    terminate the text, only the last CRLF
-                                    is removed).
-
-01h TEXT_SOUL           mtext_t     Non-displayed text.
-                                    Not normally displayed. Not necessarily
-                                    displayable.
-                                    Included in duplicate message checking.
-
-02h TEXT_TAIL           mtext_t     Displayable text (tag/tear/origin lines,
-                                    etc).
-                                    Not included in duplicate message checking.
-                                    All terminating white space and control
-                                    characters are to be truncated from data.
-
-03h TEXT_WING           mtext_t     Non-displayed text.
-                                    Not normally displayed. Not necessarily
-                                    displayable.
-                                    Not included in duplicate message checking.
-
-10h FTEXT_BODY          ftext_t     Formatted equivalent of TEXT_BODY to be
-                                    displayed in place of TEXT_BODY if format
-                                    is supported. See Image Types for valid
-                                    values of ftext_t.type.
-
-12h FTEXT_TAIL          ftext_t     Formatted equivalent of TEXT_TAIL to be
-                                    displayed in place of TEXT_TAIL if format
-                                    is supported. See Image Types for valid
-                                    values of ftext_t.type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           58                        Data Field Types
-
-
-20h IMAGEEMBED          membed_t    Type and data of embedded raster image file
-                                    for display.
-                                    See Image Types for valid membed.type
-                                    values.
-
-21h ANIMEMBED           membed_t    Type and data of embedded graphical
-                                    animation file for display.
-                                    See Animation Types for valid membed.type
-                                    values.
-
-22h FONTEMBED           membed_t    Type and data of embedded font definition
-                                    file. See Font Types for valid
-                                    membed_t.type values.
-
-23h SOUNDEMBED          membed_t    Type and data of embedded sound file for
-                                    playback.
-                                    See Sound Types for valid membed_t.type
-                                    values.
-
-24h PRESENTEMBED        membed_t    Type and data of embedded presentation
-                                    definition file.
-                                    See Present Types for valid membed_t.type
-                                    values.
-
-25h VIDEOEMBED          vembed_t    Type and data of embedded video/sound file
-                                    for playback.
-                                    See Video Types for valid vembed_t.type
-                                    values.
-                                    See Video Compression Types for valid
-                                    vembed_t.comp values.
-
-26h APPDATAEMBED        membed_t    Type and data of embedded application data
-                                    file for process/display.
-                                    See Application Data Types for valid
-                                    membed_t.type values.
-
-FFh UNUSED              undef       Space allocated for future update/expansion
-
-
-Specifically, not defined are the values F000h through FFFFh. These values
-are to be used for user or system defined data fields. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-data fields added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           59                        Data Field Types
-
-
-Message Attributes:
-------------------
-
-These are the bit values for idxrec_t.attr and msghdr_t.attr:
-
-MSG_PRIVATE         (1<<0)  // Private
-MSG_READ            (1<<1)  // Read by addressee
-MSG_PERMANENT       (1<<2)  // Permanent
-MSG_LOCKED          (1<<3)  // Msg is locked, no editing possible
-MSG_DELETE          (1<<4)  // Msg is marked for deletion
-MSG_ANONYMOUS       (1<<5)  // Anonymous author
-MSG_KILLREAD        (1<<6)  // Delete message after it has been read
-MSG_MODERATED       (1<<7)  // This message must be validated before export
-MSG_VALIDATED       (1<<8)  // This message has been validated by a moderator
-
-
-Auxillary Attributes:
---------------------
-These are the bit values for msghdr_t.auxattr:
-
-MSG_FILEREQUEST     (1<<0)  // File request
-MSG_FILEATTACH      (1<<1)  // File(s) attached to Msg
-MSG_TRUNCFILE       (1<<2)  // Truncate file(s) when sent
-MSG_KILLFILE        (1<<3)  // Delete file(s) when sent
-MSG_RECEIPTREQ      (1<<4)  // Return receipt requested
-MSG_CONFIRMREQ      (1<<5)  // Confirmation receipt requested
-MSG_NODISP          (1<<6)  // Msg may not be displayed to user
-
-
-Network Attributes:
-------------------
-These are the bit values for msghdr_t.netattr:
-
-MSG_LOCAL           (1<<0)  // Msg created locally
-MSG_INTRANSIT       (1<<1)  // Msg is in-transit
-MSG_SENT            (1<<2)  // Sent to remote
-MSG_KILLSENT        (1<<3)  // Kill when sent
-MSG_ARCHIVESENT     (1<<4)  // Archive when sent
-MSG_HOLD            (1<<5)  // Hold for pick-up
-MSG_CRASH           (1<<6)  // Crash
-MSG_IMMEDIATE       (1<<7)  // Send Msg now, ignore restrictions
-MSG_DIRECT          (1<<8)  // Send directly to destination
-MSG_GATE            (1<<9)  // Send via gateway
-MSG_ORPHAN          (1<<10) // Unknown destination
-MSG_FPU             (1<<11) // Force pickup
-MSG_TYPELOCAL       (1<<12) // Msg is for local use only
-MSG_TYPEECHO        (1<<13) // Msg is for conference distribution
-MSG_TYPENET         (1<<14) // Msg is direct network mail
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           60                      Message Attributes
-
-
-Translation Types:
------------------
-
-Definition for values of *.xlat[x]:
-
-XLAT_NONE           0       // No translation/End of translation list
-XLAT_LF2CRLF        1       // Expand sole LF to CRLF
-XLAT_ESCAPED        2       // 7-bit ASCII escaping for ctrl and 8-bit data
-XLAT_HUFFMAN        3       // Static and adaptive Huffman coding compression
-XLAT_LZW            4       // LZW (Lempel-Ziv-Welch) encoding for compression
-                            // Terry Welch, IEEE Computer Vol 17, No 6
-                            // June 1984, pp 8-19
-XLAT_LZC            5       // LZC (modified LZW) encoding for compression
-                            // Unix compress program
-XLAT_RLE            6       // Run length encoding compression
-XLAT_IMPLODE        7       // Implode compression (PKZIP v1.x)
-XLAT_SHRINK         8       // Shrink compression (PKZIP v1.x)
-XLAT_LZH            9       // LZH dynamic Huffman coding
-                            // Haruyasu Yoshizaki, LHarc
-                            // November, 1988
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           61                       Translation Types
-
-
-Agent Types:
------------
-
-AGENT_PERSON        0       // To or from person
-AGENT_PROCESS       1       // Unknown process, identified by agent name
-
-Agent types E000h through EFFFh are reserved for Synchronet process types
-(defined specifically by Digital Dynamics).
-
-Note:
-----
-Specifically not defined are agent types F000h through FFFFh. These values
-are to be used for user or system defined agent types. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-agent types added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           62                             Agent Types
-
-
-Network Types:
--------------
-
-                            // Net Type             Address Format
-                            // -----------------------------------
-NET_NONE            0       // Locally created      none
-NET_UNKNOWN         1       // Unknown              undef
-NET_FIDO            2       // FTN network          fidoaddr_t
-NET_POSTLINK        3       // PostLink network     none
-NET_QWK             4       // QWK based network    ASCII
-NET_INTERNET        5       // The Internet         ASCII
-NET_WWIV            6       // WWIV based network   ulong
-NET_MHS             7       // MHS network          ASCII
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           63                           Network Types
-
-
-Media Types:
-===========
-
-Image Types:
------------
-
-IMAGE_UNKNOWN       0x00    // Use image signature header to determine format
-IMAGE_ASC           0x01    // ASCII text/IBM extended ASCII graphics
-IMAGE_ANS           0x02    // ANSI X3.64 terminal escape sequences
-IMAGE_AVT           0x03    // AVATAR terminal escape sequences
-IMAGE_LVI           0x04    // LVI terminal escape sequences
-IMAGE_GIF           0x05    // Compuserve Graphics Interchange Format (GIF)
-IMAGE_TIF           0x06    // Tagged Image Format (AKA TIFF)
-IMAGE_JPG           0x07    // Joint Photographers Electronics Group (JPEG)
-IMAGE_T16           0x08    // TrueVision 16-bit bitmap (TGA)
-IMAGE_T24           0x09    // TrueVision 24-bit bitmap (TGA)
-IMAGE_T32           0x0a    // TrueVision 32-bit bitmpa (TGA)
-IMAGE_PCX           0x0b    // ZSoft PaintBrush graphics
-IMAGE_BMP           0x0c    // Windows bitmap
-IMAGE_RLE           0x0d    // Windows bitmap (compressed)
-IMAGE_DIB           0x0e    // Display independant bitmap
-IMAGE_PCD           0x0f    // Kodak PhotoCD
-IMAGE_G3F           0x10    // Group 3 FAX
-IMAGE_EPS           0x11    // Ecapsulated PostScript
-IMAGE_RTF           0x12    // Rich text format
-IMAGE_RIP           0x13    // Remote Imaging Protocol Script (RIPscrip)
-IMAGE_NAP           0x14    // NAPLPS
-IMAGE_CDR           0x15    // Corel Draw!
-IMAGE_CGM           0x16    // Computer graphics metafile
-IMAGE_WMF           0x17    // Windows metafile
-IMAGE_DFX           0x18    // Autodesk AutoCAD
-IMAGE_IFF           0x19    // Amiga Interchange File Format
-
-
-Animation Types:
----------------
-
-ANIM_UNKNOWN        0       // Use file signature header to determine format
-ANIM_FLI            1       // Autodesk animator
-ANIM_FLC            2       // Autodesk
-ANIM_GL             3       // Grasprt
-ANIM_IFF            4       // Amiga Interchange File Format
-
-
-Video Types:
------------
-
-VIDEO_UNKNOWN       0       // Use file signature header to determine format
-VIDEO_QTIME         1       // Apple Quick-time
-VIDEO_FQTIME        2       // Apple Flattened Quick-time
-VIDEO_AVI           3       // Windows Auto/Video Interleave
-VIDEO_ULT           4       // OS/2 Ultimotion
-
-
-
-_______________________________________________________________________________
-Synchronet                           64                             Media Types
-
-
-Video Compression Types:
------------------------
-
-VCOMP_UNKNOWN       0       // Use file signature header to determine codec
-VCOMP_RLE           1       // Apple animation
-VCOMP_SMC           2       // Apple graphics
-VCOMP_RPZA          3       // Apple video
-VCOMP_KLIC          4       // Captain crunch
-VCOMP_CVID          5       // CinePak
-VCOMP_RT21          6       // Intel indeo R2
-VCOMP_IV31          7       // Intel indeo R3
-VCOMP_YVU9          8       // Intel YVU9
-VCOMP_JPEG          9       // JPEG
-VCOMP_MRLE          10      // Microsoft RLE
-VCOMP_MSVC          11      // Microsoft video 1
-
-
-Font Types:
-----------
-
-FONT_UNKNOWN        0       // Use file signature header to determine format
-FONT_TTF            1       // Windows TrueType
-FONT_PFB            2       // PostScript Type 1 Font Binary
-FONT_PFM            3       // PostScript Type 1 Font Metric
-FONT_AMIGA          4       // Amiga Bitmapped
-FONT_AGFA           5       // CompuGraphic Fonts
-
-
-Sound Types:
------------
-
-SOUND_UNKNOWN       0       // Use file signature header to determine format
-SOUND_MOD           1       // MOD format
-SOUND_VOC           2       // Sound Blaster VOC format
-SOUND_WAV           3       // Windows 3.1 WAV RIFF format
-SOUND_MID           4       // MIDI format
-SOUND_GMID          5       // General MIDI format (standardized patches)
-SOUND_SMP           6       // Turtle Beach SampleVision format
-SOUND_SF            7       // IRCAM format
-SOUND_AU            8       // Sun Microsystems AU format
-SOUND_IFF           9       // Amiga Interchange File Format
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           65                             Media Types
-
-
-Application Data Types:
-----------------------
-
-APPDATA_UNKNOWN     0       // Use file signature header to determine format
-APPDATA_WORDPERFECT 1       // WordPerfect Document
-APPDATA_WKS         2       // Lotus 123 Worksheet (?)
-APPDATA_WK1         3       // Lotus 123 Worksheet rev 1
-APPDATA_WK2         4       // Lotus 123 Worksheet rev 2
-APPDATA_WK3         5       // Lotus 123 Worksheet rev 3
-APPDATA_DBF         6       // dBase III data file
-APPDATA_PDX         7       // Paradox data file
-APPDATA_EXCEL       8       // Excel data file
-APPDATA_QUATRO      9       // Borland Quatro Pro file
-APPDATA_WORD        10      // Microsoft Word
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           66                             Media Types
-
-
-Message Storage Pseudo Code
-===========================
-
-The following is a "C like" pseudo code listing example of adding a message to
-an SMB message base. SMBLIB contains C functions to do most of the following
-operations. We are supplying this pseudo code as a general definition of the
-order of required operations in writing to the message base. Many details have
-been left out to simplify the code and to demonstrate only the basic
-principles.
-
-shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-
-lock ( shd , smbhdr )
-read ( shd , smbstatus )
-
-if ( smbstatus.attr & SMB_HYPERALLOC )
-    msg.hdr.offset = filelength ( sdt )
-
-else {
-    number_of_blocks = length_of_message_data / SDT_BLOCK_LEN
-    if ( length_of_message_data % SDT_BLOCK_LEN )   /* unevenly divisible */
-        number_of_blocks = number_of_blocks + 1
-
-    sda = open ( MSGBASE.SDA , READ/WRITE/DENY_ALL )
-
-    if ( fast_allocation_mode )
-        seek ( sda , END_OF_FILE )
-
-    else {
-        seek ( sda , BEGINNING_OF_FILE )
-        while ( not end_of_file ( sda ) ) {
-            read ( sda , allocated , number_of_blocks * 2 )
-            if ( allocated = 0 ) {
-                seek_backwards ( sda , number_of_blocks * 2 )
-                break
-            }
-        }
-    }
-
-    msg.hdr.offset = ( current_position ( sda ) / 2 ) * SDT_BLOCK_LEN
-
-    allocated = 1
-
-    write ( sda , allocated , number_of_blocks * 2 )
-
-    close ( sda )
-}
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           67             Message Storage Pseudo Code
-
-
-seek ( sdt , msg.hdr.offset )
-
-write ( sdt , message_data )
-
-if ( smbstatus.attr & SMB_HYPERALLOC )
-    msg.idx.offset = filelength ( shd )
-
-else {
-    number_of_blocks = length_of_message_header / SHD_BLOCK_LEN
-    if ( length_of_message_header % SHD_BLOCK_LEN )   /* unevenly divisible */
-        number_of_blocks = number_of_blocks + 1
-
-    sha = open ( MSGBASE.SHA , READ/WRITE/DENY_ALL )
-
-    if ( fast_allocation_mode )
-        seek ( sha , END_OF_FILE )
-
-    else {
-        seek ( sha , BEGINNING_OF_FILE )
-        while ( not end_of_file ( sha ) ) {
-            read ( sha , allocated , number_of_blocks )
-            if ( allocated = 0 ) {
-                seek_backwards ( sha , number_of_blocks )
-                break
-            }
-        }
-    }
-
-    msg.idx.offset = ( current_position ( sha ) * SHD_BLOCK_LEN )
-    msg.idx.offset = msg.idx.offset + smbstatus.header_offset
-
-    allocated = 1
-
-    write ( sha , allocated , number_of_blocks )
-
-    close ( sha )
-}
-
-seek ( shd , msg.idx.offset )
-
-msg.hdr.number = smbstatus.last_msg+1
-
-write ( shd , msg.hdr )
-
-smbstatus.total_msgs = smbstatus.total_msgs + 1
-smbstatus.last_msg = msg.hdr.number
-
-write ( shd , smbstatus )
-
-write ( sid , msg.idx )
-
-unlock ( shd , smbstatus )
-
-
-
-_______________________________________________________________________________
-Synchronet                           68             Message Storage Pseudo Code
-
-
-Message Retrieval Pseudo Code
-=============================
-
-shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-
-read ( sid , msg.idx )
-
-seek ( shd , msg.idx.offset )
-
-lock ( shd , msg.hdr )
-
-read ( shd , msg.hdr )
-
-seek ( sdt , msg.hdr.offset )
-
-read ( sdt , msg.hdr.data_length )
-
-unlock ( shd , msg.hdr )
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           69           Message Retrieval Pseudo Code
-
-
-SMBUTIL
-=======
-
-SMBUTIL is a utility that can perform various functions on an SMB message base.
-The primary purpose of SMBUTIL is as an example to C programmers of how to use
-the SMBLIB functions to access and modify an SMB message base. The complete C
-source code for SMBUTIL is included and functions from it can be used or
-modified by developers at their own discretion. The following files make up
-SMBUTIL:
-
-SMBUTIL.EXE     Compiled and linked for 16-bit DOS (ready to run)
-SMBUTIL.C       C functions
-SMBUTIL.H       C definitions and variable prototypes
-SMBUTIL.WAT     Makefile for Watcom C/C++ (type wmake -f smbutil.wat)
-SMBUTIL.BOR     Makefile for Borland C/C++ (type make -f smbutil.bor)
-
-The usage syntax is as follows:
-
-SMBUTIL [/opts] cmd smb_filespec.shd
-
-where cmd is one or more of the following:
-
-       l[n] = list msgs starting at number n
-       r[n] = read msgs starting at number n
-       v[n] = view msg headers starting at number n
-       k[n] = kill (delete) n msgs
-       i<f> = import from text file f
-       s    = display msg base status
-       c    = change msg base status
-       m    = maintain msg base - delete old msgs and msgs over max
-       p[k] = pack msg base (k specifies minimum packable Kbytes)
-
-where opts is one or more of the following:
-
-       a    = always (force) packing
-       z<n> = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)
-
-and smb_filespec is the base filename or file specification (wildcards) for the
-message base. If wildcards are used, the ".SHD" extension must be specified.
-
-An example command line:
-
-SMBUTIL MP C:\SBBS\DATA\SUBS\*.SHD
-
-would maintain and pack all the message bases found in the C:\SBBS\DATA\SUBS
-directory.
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           70                                 SMBUTIL
-
-
-CHKSMB
-======
-
-CHKSMB is a utility that performs a comprehensive analysis of a message base
-to find any possible errors and calculate the number of packable bytes. It does
-not "fix" a message base if any errors are found, it only reports the specific
-errors (and exits with a non-zero error level). If any errors are reported,
-packing the message base with SMBUTIL may rebuild the damaged files. If that
-doesn't work, then use FIXSMB as a last resort.
-
-C source code for CHKSMB is also included as an example to programmers of how
-to use SMBLIB functions.
-
-The usage syntax is as follows:
-
-CHKSMB [/opts] smb_filespec.shd
-
-where opts is one or more of the following:
-
-        q   = quiet mode (no beeps)
-        s   = stop after an errored message base (for use with wildcards)
-        p   = pause after an errored message base (wait for key press)
-        t   = don't check for unsupported translation strings (faster)
-        e   = display extended information on corrupted messages
-
-An example command line:
-
-CHKSMB /QP C:\SBBS\DATA\SUBS\*.SHD
-
-would check all the message bases in the C:\SBBS\DATA\SUBS directory, without
-beeping on errors, and pausing after an errored message base.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           71                                  CHKSMB
-
-
-FIXSMB
-======
-
-FIXSMB is a utility that will rebuild the index and allocation files for a
-message base. Since the message headers are not necessarily stored
-sequentially, the order of the messages in the index may be changed when the
-index is rebuilt. Messages are also re-numbered, so only use this program if
-the index is corrupted and the messages are extremely important.
-
-C source code for FIXSMB is also included as an example to programmers of how
-to use SMBLIB functions.
-
-The usage syntax is as follows:
-
-FIXSMB [/M] smb_file
-
-An example command line:
-
-FIXSMB \SBBS\DATA\MAIL
-
-Only use the "/M" command line switch if fixing an older Synchronet e-mail
-message base (created with SBBS v2.1 or earlier). Once the SMB_EMAIL status
-attr is set ("SMBUTIL S" will report a status attr of 1), the "/M" is not
-required.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           72                                  FIXSMB
-
-
-SMBLIB
-======
-
-SMBLIB is a library of C functions for accessing and storing messages in an
-SMB format message base. It can eliminate much of the development time for
-developers that wish to use the library in whole or in part, or use the
-functions as examples for their own message base function library. The library
-consists of the following files:
-
-SMBDEFS.H       Constant definitions, macros, and data types
-SMBLIB.H        Library constants and function prototypes
-SMBLIB.C        Function definitions
-SMBVARS.C       Global variable definitions (doubles as declaration file)
-
-For developers to use this library with their program, they must include the
-"SMBLIB.H" header file at the top of each C file that uses any of the library
-functions, global variables, data types, macros, and constants. This can be
-done by simply adding the following line to each .C file:
-
-#include "smblib.h"
-
-If SMBLIB.H is included, there is no need to include SMBDEFS.H or SMBVARS.C.
-
-To link the library functions and variables with a main program, the files
-SMBVARS.OBJ and SMBLIB.OBJ must be linked with the main program .OBJ files.
-If the operating system is DOS, be sure that all .OBJ files are compiled for
-the same memory model.
-
-Example MAKEFILEs for compiling and linking SMBUTIL with Borland C/C++
-(SMBUTIL.BOR) and Watcom C/C++ (SMBUTIL.WAT) are included.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           73                                  SMBLIB
-
-
-SMBDEFS.H
-=========
-
-The SMBDEFS.H file contains important constant definitions and data types (also
-defined in this document). If ever this document and SMBDEFS.H are inconsistent
-with each other, then SMBDEFS.H is to be considered correct and this document
-in error. If such a discrepency is found, please notifiy Digital Dynamics so it
-can be corrected in a future revision of the specification.
-
-Most notable of the data types is a structure called smbmsg_t (not defined
-in this document). It contains the fixed and variable portions of a message's
-header record as well as convenience pointers to the sender's name
-(smbmsg_t.to), recipient's name (smbmsg_t.from), network addresses, and more.
-If multiple SENDER header fields are included (for example), then smbmsg_t.to
-will point to the last SENDER header field in the header record. Convenience
-pointers for other data items work in the same fasion if multiple header fields
-of the same type exist in the header record.
-
-Variables of the smbmsg_t data type (and pointers to variables of smbmsg_t
-type) are used as arguments to many of the SMBLIB functions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           74                               SMBDEFS.H
-
-
-SMBVARS.C
-=========
-
-The SMBVARS.C file contains definitions of the global variables used by the
-SMBLIB functions. It is a fairly small file since their are a small number of
-global variables (by design). This file is used for both definitions and
-declarations, so no "extern" declarations need to be made in developers source
-code as long as SMBVARS.C or (preferably) SMBLIB.H is included in the source
-code.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           75                               SMBVARS.C
-
-
-SMBLIB.H
-=======
-
-The SMBLIB.H file contains prototypes of all the functions in the SMBLIB.C
-file. It is necessary to include this file in C source code if any of the
-SMBLIB functions are used. The following C source line will include this file:
-
-#include "smblib.h"
-
-and should be placed near the top of all C source files that use SMBLIB
-functions, variables, constants, or data types.
-
-Function prototypes are necessary for compilers to know the correct calling
-syntax of a function and detect incorrect usage. Prototypes are also useful
-as a quick reference for programmers as to the correct calling syntax of a
-specific function.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           76                                SMBLIB.H
-
-
-SMBLIB.C
-=======
-
-The SMBLIB.C file contains the actual SMBLIB library functions. This source
-file is not a stand alone program, but instead must be compiled and linked
-with a main source file to create the executable program.
-
-The functions in this file are organized in a logical order, but their order
-is actually irrelevant to the compiling, linking, and execution of the
-resulting program.
-
-A comment block preceeds each function, explaining what the function does,
-how the passed parameters are used, and what the return code (if any)
-indicates. A more detailed explanation of each function is included here:
-
-int smb_open(int retry_time)
-----------------------------
-The smb_open() function must be called before the message base is accessed
-(read from or written to). The parameter, retry_time, is the maximum number
-of seconds to wait while retrying to lock the message base header. If
-retry_time is 0, then the message base header is not locked or read (this is
-called "Fast Open" and should only be used when speed is more important than
-checking for compatibility and validity upon opening). The global variable
-smb_file must be initialized with the path and base filename of the message
-base. This function returns 0 on success, 1 if the .SDT file could not be
-opened, 2 if the .SHD file could not be opened, and 3 if the .SID file could
-not be opened. If the message base header could not be locked, this function
-returns -1. If the message base ID is incorrect, it returns -2. And if the
-message base is of an incompatible version, it returns -3.
-
-The errno global variable (standard of most C libraries) will most likely
-contain the error code for open failure.
-
-int smb_open_da(int retry_time)
--------------------------------
-The smb_open_da() function is used to open the data block allocation file for
-writing messages to a message base. The parameter, retry_time, is the maximum
-number of seconds to wait while retrying to open the file. This function
-returns 0 on success. -1 is returned if an open error other than "Access
-Denied" is returned from the operating system, and the global variable errno
-will contain the error code. -2 is returned if the retry_time has been
-reached, and -3 is returned if the file descriptor could not be converted to
-a stream by the fdopen() function.
-
-fclose(sda_fp) should be called immediately after all necessary file access
-has been completed.
-
-This function is not used with the Hyper Allocation storage method.
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           77                                SMBLIB.C
-
-
-int smb_open_ha(int retry_time)
--------------------------------
-The smb_open_ha() function is used to open the header block allocation file for
-writing messages to a message base. The parameter, retry_time, is the maximum
-number of seconds to wait while retrying to open the file. This function
-returns 0 on success. -1 is returned if an open error other than "Access
-Denied" is returned from the operating system, and the global variable errno
-will contain the error code. -2 is returned if the retry_time has been
-reached, and -3 is returned if the file descriptor could not be converted to
-a stream by the fdopen() function.
-
-fclose(sha_fp) should be called immediately after all necessary file access
-has been completed.
-
-This function is not used with the Hyper Allocation storage method.
-
-int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-    ,int retry_time)
---------------------------------------------------------------------------
-The smb_create() function is used to create a new message base or reset an
-existing message base. The parameters max_crcs, max_msgs, max_age, and attr
-are used to set the initial status of the message base status header. The
-parameter, retry_time is the maximum number of seconds to wait while retrying
-to lock the message base header. This functions returns 0 on success or 1 if
-the message base header could not be locked.
-
-int smb_trunchdr(int retry_time)
---------------------------------
-The smb_trunchdr() function is used to truncate the header file when packing
-the message base and writing the new header information back to the header
-file. The parameter, retry_time is the maximum number of seconds to wait while
-retrying to truncate the header file. Returns 0 on success, -1 if error was
-other than "Access Denied", or -2 if retry_time reached.
-
-int smb_locksmbhdr(int retry_time)
-----------------------------------
-The smb_locksmbhdr() function is used to lock the first message base (status)
-header. The parameter, retry_time is the number of seconds to wait while
-retrying to lock the header. The smb_unlocksmbhdr() function should always be
-used to unlock the header after accessing the message base header (usually
-with smb_getstatus() and/or smb_putstatus()). Returns 0 if successful, -1 if
-unsuccessful.
-
-int smb_unlocksmbhdr()
-----------------------
-The smb_unlocksmbhdr() function is used to unlock a previously locked message
-base header (using smb_lockmsghdr()). Returns 0 on success, non-zero on
-failure.
-
-int smb_getstatus(smbstatus_t *hdr)
------------------------------------
-The smb_getstatus() function is used to read the status message base header
-into the hdr structure. Returns 0 on success, 1 on failure.
-
-
-_______________________________________________________________________________
-Synchronet                           78                                SMBLIB.C
-
-
-int smb_putstatus(smbstatus_t hdr)
-----------------------------------
-The smb_putstatus() function is used to write the status information to the
-first message base header. The parameter hdr, contains the status information
-to be written. Returns 0 on success, 1 on failure.
-
-int smb_getmsgidx(smbmsg_t *msg)
---------------------------------
-The smb_getmsgidx() function is used to get the byte offset for a specific
-message header in the message header file based on the message base index.
-
-If msg->hdr.number is non-zero when this function is called, then the index
-will be searched for this message number. If the message number is found in
-the index, the msg->idx.offset is set to the byte offset of the message header
-record in the header file and msg->offset is set to the record offset of the
-index record in the index file, and the function returns 0. If the message
-number is not found in the index, the function returns 1.
-
-If msg->hdr.number is zero, msg->idx.offset and msg->idx.number are obtained
-from the index record at record offset msg->offset. If msg->offset is an
-invalid record offset when this function is called, the function returns 1.
-Otherwise, the function returns 0.
-
-int smb_getlastidx(idxrec_t *idx)
----------------------------------
-Reads the last index record of the currently open message base into the
-idxrec_t structure pointed to by idx. Returns 0 if successful, -1 if the index
-is empty or unopened, or -2 if the record can't be read.
-
-int smb_getmsghdrlen(smbmsg_t msg)
-----------------------------------
-The smb_getmsghdrlen() function is used to calculate the total length of
-message header msg including both fixed and variable length portions. This
-function returns the length of the header record in bytes.
-
-long smb_getmsgdatlen(smbmsg_t msg)
------------------------------------
-The smb_getmsgdatlen() function is used to calculate the total length of the
-data for message msg. This function returns the length of all data fields
-combined.
-
-int smb_lockmsghdr(smbmsg_t msg, int retry_time)
-------------------------------------------------
-The smb_lockmsghdr() function is used to lock the header record for message
-msg. The parameter retry_time is the maximum number of seconds to wait while
-retrying to lock the header. Returns 0 on success, -1 on failure. The function
-smb_unlockmsghdr() should immediately be called after accessing the message
-header (usually with smb_getmsghdr() or smb_putmsghdr()).
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           79                                SMBLIB.C
-
-
-int smb_getmsghdr(smbmsg_t *msg)
---------------------------------
-The function smb_getmsghdr() is used to read the header record for message
-msg. msg->idx.offset must be initialized to the byte offset of the header
-record in the header file before this function is called. The function
-smb_freemsgmem() must be called to free the memory allocated by this function
-for the header and data felds. This function returns 0 on success, -1 if
-the fixed portion of the message header record could not be read, -2 if the
-message header ID was incorrect, -3 if memory could not be allocated, -4
-if a data field could not be read, -5 if the fixed length portion of a header
-field could not be read, -6 if the variable length portion of a header field
-could not be read, -7 if one or more of the mandatory header fields (SENDER,
-RECIPIENT, or SUBJECT) are missing, -8 if total_dfields extends beyond the
-end of the header record, or -9 if incompatible header version.
-
-Several convenience pointers in the msg structure are initialized by this
-function to point to the last occurance of the SENDER (msg->from), RECIPIENT
-(msg->to), SUBJECT (msg->subj), etc.
-
-int smb_unlockmsghdr(smbmsg_t msg)
-----------------------------------
-The smb_unlockmsghdr() function is used to unlock a previously locked message
-header (with smb_lockmsghdr()). This function returns 0 on success, non-zero
-on failure.
-
-int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
----------------------------------------------------------
-The smb_addcrc() function is used to add a CRC-32 to the CRC history file
-for a message base, automatically checking for duplicates. The parameter
-max_crcs should be the max_crcs defined in the status header of the message
-base. The parameter crc, is the CRC-32 of the TEXT_BODY and TEXT_SOUL data
-fields for the message. The parameter retry_time is the maximum number of
-seconds to wait when retrying to open the CRC history file.
-
-This function returns -1 if there was an open error, -2 if the retry_time
-was reached, -3 if there was a memory allocation error, 1 if the CRC already
-exists in the CRC history file (indicating a duplicate message), or 0 on
-success (and no duplicate).
-
-int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
----------------------------------------------------------------------
-The smb_hfield() function is used to add a header field to the structure msg.
-The parameters type, length, and data, must be specified according to the
-header field values listed in this specification. This function returns 0
-on success, non-zero on memory allocation error. The function smb_freemsgmem()
-must be called to free the memory allocated by this function.
-
-int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
---------------------------------------------------------
-The smb_dfield() function is used to add a data field to the structure msg.
-The parameters type and length must be specified according to the data field
-values listed in this specification. This function returns 0 on success,
-non-zero on memory allocation error. The function smb_freemsgmem() must be
-called to free the memory allocated by this function.
-
-_______________________________________________________________________________
-Synchronet                           80                                SMBLIB.C
-
-
-int smb_addmsghdr(smbmsg_t *msg,smbstatus_t *status,int storage,int retry_time)
--------------------------------------------------------------------------------
-The smb_addmsghdr() function is used to add a new message header to the message
-header file and update the index file. The msg and status structures are
-updated to reflect the new total messages, last message number, etc. The
-storage parameter is used to indicate the storage method to use (either
-SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC). If the storage type is
-SMB_SELFPACK, the header block allocation file will be searched for unused
-block(s) to store this header. If the storage type is SMB_FASTALLOC or
-SMB_HYPERALLOC, the header is stored at the end of the header file. Returns 0
-on success, non-zero on failure. The parameter retry_time is the maximum number
-of seconds to wait while retrying to lock and open files.
-
-int smb_putmsg(smbmsg_t msg)
-----------------------------
-The smb_putmsg() function calls both the smb_putmsghdr() and smb_putmsgidx()
-functions to write the header and index elements of a message to the
-appropriate files. Returns 0 on success, non-zero on failure.
-
-int smb_putmsgidx(smbmsg_t msg)
--------------------------------
-The smb_putmsgidx() function is used to store a message index in the message
-index file. The message index can be for a new message or an existing
-message. Returns 0 on success, non-zero on failure.
-
-int smb_putmsghdr(smbmsg_t msg)
--------------------------------
-The smb_putmsghdr() function is used to store a message header in the message
-header file. The message header can be for a new message or an existing
-message. Returns 0 on success, non-zero on failure.
-
-void smb_freemsgmem(smbmsg_t msg)
----------------------------------
-Frees allocated memory for the header and data fields in the msg structure.
-This function must be called to free the memory allocated by the functions
-smb_hfield(), smb_dfield(), and smb_getmsghdr().
-
-long smb_hdrblocks(ulong length)
---------------------------------
-The smb_hdrblocks() function is used to calculate the number of blocks
-required to store a message header of length size (in bytes). This function
-returns the number of blocks required.
-
-long smb_datblocks(ulong length)
---------------------------------
-The smb_datblocks() function is used to calculate the number of blocks
-required to store message data of length size (in byte). This function returns
-the number of blocks required.
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           81                                SMBLIB.C
-
-
-long smb_allochdr(ulong length)
--------------------------------
-The smb_allochdr() function is used to search for free blocks to store a
-message header of length bytes and mark the free blocks as allocated in the
-header allocation file. This function returns the byte offset to the header
-record or a negative number on error. The function smb_open_ha() should be
-called prior to calling this function and fclose(sha_fp) should be called
-after. The function is called from smb_addmsghdr(), so you probably have no
-need to call this function directly.
-
-long smb_fallochdr(ulong length)
---------------------------------
-The smb_fallochdr() function works exactly the same as the smb_allochdr()
-function except it is much faster because the header allocation file is not
-searched for free blocks. The function is called from smb_addmsghdr(), so you
-probably have no need to call this function directly.
-
-long smb_hallochdr(ulong header_offset)
----------------------------------------
-This smb_hallochdr() functions works exactly the same as the smb_fallochdr()
-function except the status.header_offset is passed as the argument and the
-header allocation (.SHA) file is not updated so smb_open_ha() need not be
-called. The function is called from smb_addmsghdr(), so you probably have no
-need to call this function directly.
-
-long smb_allocdat(ulong length, ushort headers)
------------------------------------------------
-The smb_allocdat() function is used to search for free blocks to store length
-amount of data for a message. The parameter headers, indicates the number of
-message headers that are associated with this data. Normally, the headers
-parameter will be 1, unless this message is part of a mass mailing. The offset
-to the allocated data blocks is returned, or a negative value on error. The
-function smb_open_da() should be called prior to calling this function and
-fclose(sda_fp) should be called after.
-
-long smb_fallocdat(ulong length, ushort headers)
-------------------------------------------------
-The smb_fallocdat() function works exactly the same as the smb_allocdat()
-function except it is much faster because the data allocation file is not
-searched for free blocks.
-
-long smb_hallocdat()
---------------------
-The smb_hallocdat() function works exactly the same as the smb_hallocdat()
-function except no argument is passed and the data allocation file (.SDA) is
-not updated so smb_open_da() need not be called.
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           82                                SMBLIB.C
-
-
-int smb_incdat(ulong offset, ulong length, ushort headers)
-----------------------------------------------------------
-The smb_incdat() function is used to increment the header counter in the data
-allocation file for the data starting at the byte offset and length size in
-bytes. The parameter headers, indicates the number of headers to add to the
-current allocation value in the data allocation file. Returns 0 on success,
-non-zero on failure.
-
-int smb_freemsg(smbmsg_t msg, smbstatus_t status)
--------------------------------------------------
-The smb_freemsg() function is used to free the disk space allocated for the
-header and data fields of the message msg. Returns 0 on success, non-zero on
-failure. The parameter, status, must be the current status from the message
-base header for this message base.
-
-int smb_freemsgdat(ulong offset, ulong length, ushort headers)
---------------------------------------------------------------
-The smb_freemsgdat() function is used to decrement the data block allocation
-records in the data allocation file associated with the data in the data file
-by the value of the headers parameter (normally 1). The parameter offset
-indicates the byte offset to the beginning of the message data in the data
-file and the parameter length is the total length of the message data.
-Returns 0 on success, non-zero on failure.
-
-int smb_freemsghdr(ulong offset, ulong length)
-----------------------------------------------
-The smb_freemsghdr() function is used to set the header block allocation
-records in the header allocation file to 0 (indicated non-allocated block).
-The parameter offset indicates the byte offset to the beginning of the header
-record being freed and the parameter length indicates the total length of the
-header record. Returns 0 on success, non-zero on failure.
-
-int smb_stack(int op)
----------------------
-The smb_stack() function is used to save and restore message base information
-so that multiple message bases can be open simultaneously. The stack can
-save up to 4 message bases (allowing 5 simultaneously open message bases).
-The stack is a "last in, first out" storage area for open message bases.
-If the op parameter is SMB_STACK_PUSH, smb_stack() will save (push) the current
-message base onto the stack. Calling smb_stack(SMB_STACK_POP) will restore
-(pop) the most recently pushed message base off the stack. Calling
-smb_stack(SMB_STACK_XCHNG) will exchange the most recently pushed message base
-and the current message base (replacing the top of the stack with the current
-message base).
-
-void smb_close()
-----------------
-Closes the header, data, and index files for the currently open message base.
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           83                                SMBLIB.C
-
-
-Miscellaneous SMBLIB Files
-==========================
-
-CRC32.H         C header file for CRC-32 calculations
------------------------------------------------------
-This file contains a static 32-bit CRC table (crc32tbl[]) and a macro (ucrc32)
-that uses this table to calculate 32-bit CRCs one byte at a time.
-
-Example:
-
-    ulong crc=0xffffffff;
-
-for(i=0;i<length;i++)
-    crc=ucrc32(buf[i],crc);
-crc=~crc;
-
-
-CRC16.C         C functions for 16-bit CRC calculations
--------------------------------------------------------
-This file contains a function (ucrc16), to calculate 16-bit CRCs one byte at a
-time and a function (crc16) that uses the ucrc16() function to calculate the
-16-bit CRC of an ASCIIZ character string.
-
-Example:
-
-    ushort crc;
-
-crc=crc16("Text");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           84              Miscellaneous SMBLIB Files
-
-
-LZH.H           Function prototypes for LZH.C
----------------------------------------------
-This file contains function prototypes for the two most important functions
-in LZH.C, lzh_encode() and lzh_decode().
-
-Example:
-
-    uchar str[256],lzh[512];
-    long length;
-
-strcpy(str,"This is a string of text");
-length=lzh_encode(str,strlen(str),lzh);
-lzh_decode(lzh,length,str);
-
-
-LZH.C           C functions for LZH encoding (compression/decompression)
-------------------------------------------------------------------------
-This file contains the functions for encoding and decoding LZH compressed
-data. If the macro LZH_DYNAMIC_BUF is defined when this file is compiled,
-temporary buffers will be dynamically allocated as opposed to static. This
-may be slower than the static buffer method, but frees the allocated memory
-after encoding or decoding. If free memory for your application is an issue,
-then define this macro when compiling this file.
-
-Example (Borland C):
-
-bcc -c -DLZH_DYNAMIC_BUF lzh
-
-Example (Watcom C):
-
-wcc -dLZH_DYNAMIC_BUF lzh
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           85              Miscellaneous SMBLIB Files
-
-
-SMBLIB Storage Example
-======================
-
-#include "smblib.h"
-#include "crc16.c"
-
-int main(void)
-{
-    char    str[256]                        // General purpose string
-           ,*msg_text="Hello, world!"       // Message text
-           ,nul_buf[SDT_BLOCK_LEN]={0}      // NULL initialized buffer
-           ;
-    int     i                               // General purpose integer
-           ,storage=SMB_SELFPACK            // Default storage method
-           ,retry=10                        // Retry for opening/locking files
-           ;
-    ushort  max_age=0                       // Default maximum age of messages
-           ,xlat=XLAT_NONE                  // Translation string
-           ,tzone=PST                       // Time zone
-           ,copies=1                        // Number of copies of this msg
-           ;
-    ulong   max_msgs=500                    // Default max number of msgs
-           ,max_crcs=0                      // Default max crcs
-           ,length                          // Length of msg text
-           ,offset                          // Offset to msg text in data file
-           ;
-    smbmsg_t    msg;                        // Message structure
-    smbstatus_t status;                     // Message base status record
-
-strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-if((i=smb_open(retry))!=0) {                // Can't open!?!
-    printf("smb_open returned %d\n",i);
-    return(1); }
-
-if(!filelength(fileno(shd_fp)))             // Message base not created yet
-    smb_create(max_crcs                     // Create with default settings
-              ,max_msgs
-              ,max_age
-              ,storage==SMB_HYPERALLOC
-                    ? SMB_HYPERALLOC : 0    // SMB_EMAIL if this was e-mail
-              ,retry
-              );
-
-if((i=smb_locksmbhdr(retry))!=0) {          // Can't lock status base header
-    printf("smb_locksmbhdr returned %d\n",i);
-    smb_close();
-    return(1); }
-
-if((i=smb_getstatus(&status))!=0) {         // Can't read status base header
-    smb_unlocksmbhdr();
-    smb_close();
-    printf("smb_getstatus returned %d\n",i);
-    return(1); }
-
-
-_______________________________________________________________________________
-Synchronet                           86                  SMBLIB Storage Example
-
-
-if(status.attr&SMB_HYPERALLOC)
-    storage=SMB_HYPERALLOC;
-else
-    storage=SMB_SELFPACK;
-
-length=strlen(msg_text);                    // Get length of message
-length+=sizeof(xlat);                       // Add length of xlat string
-
-if(storage==SMB_HYPERALLOC)                 // Allocate space for message text
-    offset=smb_hallocdat();
-else {
-    if((i=smb_open_da(retry))!=0) {
-        smb_unlocksmbhdr();
-        printf("smb_open_da returned %d\n",i);
-        smb_close();
-        return(1); }
-    if(storage==SMB_FASTALLOC)
-        offset=smb_fallocdat(length,copies);
-    else
-        offset=smb_allocdat(length,copies);
-    fclose(sda_fp); }
-
-fseek(sdt_fp,offset,SEEK_SET);              // Seek to beginning of data block
-fwrite(&xlat,sizeof(xlat),1,sdt_fp);        // Write xlat string
-fwrite(msg_text,strlen(msg_text),1,sdt_fp); // Write message text
-fwrite(nul_buf,SDT_BLOCK_LEN-length         // Write NULLs out to end of block
-    ,1,sdt_fp);
-fflush(sdt_fp);                             // Flush output buffer
-smb_unlocksmbhdr();                         // Unlock status base header
-
-memset(&msg,0,sizeof(smbmsg_t));            // Initialize header to NULL
-memcpy(msg.hdr.id,"SHD\x1a",4);             // Always set to SHD^Z
-msg.hdr.version=SMB_VERSION;
-msg.hdr.when_written.time=time(NULL);
-msg.hdr.when_written.zone=tzone;
-msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_imported.zone=tzone;
-msg.hdr.offset=offset;
-
-strcpy(str,"All");                          // Send message to "All"
-if((i=smb_hfield(&msg,RECIPIENT,strlen(str),str))!=0) {
-    printf("smb_hfield returned %d\n",i);
-    smb_freemsgdat(offset,length,copies);
-    smb_close();
-    return(1); }
-strlwr(str);                                // If this were e-mail, idx.to
-msg.idx.to=crc16(str);                      // would be the "to" user number
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           87                  SMBLIB Storage Example
-
-
-strcpy(str,"Sysop");                        // Send message from "Sysop"
-if((i=smb_hfield(&msg,SENDER,strlen(str),str))!=0) {
-    printf("smb_hfield returned %d\n",i);
-    smb_freemsgdat(offset,length,copies);
-    smb_freemsgmem(msg);
-    smb_close();
-    return(1); }
-strlwr(str);                                // If this were e-mail, idx.from
-msg.idx.from=crc16(str);                    // would be the "from" user number
-
-strcpy(str,"This is a test");               // Set the message subject/title
-if((i=smb_hfield(&msg,SUBJECT,strlen(str),str))!=0) {
-    printf("smb_hfield returned %d\n",i);
-    smb_freemsgdat(offset,length,copies);
-    smb_freemsgmem(msg);
-    smb_close();
-    return(1); }
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-if((i=smb_dfield(&msg,TEXT_BODY,length))!=0) {
-    printf("smb_dfield returned %d\n",i);
-    smb_freemsgdat(offset,length,copies);
-    smb_freemsgmem(msg);
-    smb_close();
-    return(1); }
-
-if((i=smb_addmsghdr(&msg,&status,storage,retry))!=0) {
-    printf("smb_addmsghdr returned %d\n",i);
-    smb_freemsgdat(offset,length,copies);
-    smb_freemsgmem(msg);
-    smb_close();
-    return(1); }
-
-smb_freemsgmem(msg);                        // Unnecessary if exiting main()
-smb_close();                                // Unnecessary if exiting main()
-return(0);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           88                  SMBLIB Storage Example
-
-
-SMBLIB Retrieval Example
-========================
-
-#include "smblib.h"
-
-int main(void)
-{
-    char        ch;                         // General purpose character
-    int         i,                          // General purpose integer
-                retry=10;                   // Retry for opening/locking files
-    ushort      xlat;                       // Translation string
-    ulong       l;                          // General purpose long integer
-    smbmsg_t    msg;                        // Message structure
-
-strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-if((i=smb_open(retry))!=0) {                // Can't open!?!
-    printf("smb_open returned %d\n",i);
-    return(1); }
-
-if(!filelength(fileno(shd_fp))) {           // Message base not created yet
-    printf("Empty\n");
-    smb_close();
-    return(0); }
-
-for(msg.offset=0;!ferror(sid_fp);msg.offset++) {
-
-    fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-    if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-        break;
-
-    if((i=smb_lockmsghdr(msg,retry))!=0) {
-        printf("smb_lockmsghdr returned %d\n",i);
-        break; }
-    if((i=smb_getmsghdr(&msg))!=0) {
-        smb_unlockmsghdr(msg);
-        printf("smb_getmsghdr returned %d\n",i);
-        break; }
-    if((i=smb_unlockmsghdr(msg))!=0) {
-        smb_freemsgmem(msg);
-        printf("smb_unlockmsghdr returned %d\n",i);
-        break; }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           89                SMBLIB Retrieval Example
-
-
-    printf("Subj : %s\n",msg.subj);
-    printf("To   : %s\n",msg.to);
-    printf("From : %s\n",msg.from);
-    printf("Date : %s\n",ctime((time_t *)&msg.hdr.when_written.time));
-
-    for(i=0;i<msg.hdr.total_dfields;i++)
-        switch(msg.dfield[i].type) {
-            case TEXT_BODY:             // Only show BODY and TAIL data fields
-            case TEXT_TAIL:
-                fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-                    ,SEEK_SET);
-                fread(&xlat,sizeof(xlat),1,sdt_fp);
-                if(xlat!=XLAT_NONE)     // No translations supported
-                    continue;
-                for(l=sizeof(xlat);l<msg.dfield[i].length;l++) {
-                    ch=fgetc(sdt_fp);
-                    if(ch)
-                        putchar(ch); }
-                printf("\n");
-                break; }
-    printf("\n");
-
-    smb_freemsgmem(msg); }          // Free memory allocated by smb_getmsghdr()
-
-smb_close();
-return(0);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           90                SMBLIB Retrieval Example
-
-
-SMBLIB Performance Issues
-=========================
-
-Since importing messages is the usually the most time consuming task likely
-undertaken by an SMB application, it is also the most susceptable to design
-issues that effect performance.
-
-Opening and Closing
--------------------
-When importing multiple messages for a single message base, it appears logical
-to open the message base, import all the messages, then close it. This indeed
-is preferred over opening and closing the message base for each message.
-
-When importing multiple messages for possibly non-consecutive message bases,
-developers may eaily make the mistake of opening and closing the message base
-for each message. This is not necessary and can considerably hinder the
-import performance. The easiest solution is to only close the message base and
-open a new one if the next message to be imported is not for the same message
-base as the previously imported message. Example:
-
-smb_file[0]=0;
-for(i=0;i<total_messages_to_be_imported;i++) {
-    if(stricmp(get_messagebase_for_this_message(i),smb_file)) {
-        if(smb_file[0])     /* We've already opened one */
-            smb_close();
-        strcpy(smb_file,get_messagebase_for_this_message(i));
-        smb_open(10); }
-    /* Import this message */
-    }
-if(smb_file[0])
-    smb_close();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           91               SMBLIB Performance Issues
-
-
-A more advanced method is to keep multiple message bases open at the same time.
-Due to the likely limitation of total file handles on the system, it is
-suggested to keep the number of simultaneously open message bases at or below
-3. SMBLIB includes the function smb_stack() to easily "push" and "pop" message
-bases without closing them (push is the equivalent to "save" and pop is the
-equivalent to "restore"). The downside of this function is that you cannot
-access message bases on the stack without actually popping them off (in reverse
-of the order they were pushed). You can however "exchange" the current message
-base with the message base on the top of the stack (most recently pushed).
-To intelligently juggle more than two open message bases, the developer should
-create their own equivalent of the smb_stack() function so they can access the
-message bases on the stack without popping them off. An example of keeping a
-maximum of two message bases open using smb_stack():
-
-    char last_messagebase[128],new_messagebase[128];
-
-smb_file[0]=0;
-last_messagebase[0]=0;
-for(i=0;i<total_messages_to_be_imported;i++) {
-    strcpy(new_messagebase,get_messagebase_for_this_message(i));
-    if(stricmp(new_messagebase,smb_file)) {     /* Not current message base */
-        if(smb_file[0]) {                       /* We've already opened one */
-            if(!stricmp(new_messagebase,last_messagebase)) { /* Same as last */
-                strcpy(last_messagebase,smb_file);
-                smb_stack(SMB_STACK_XCHNG); }       /* Retore previous base */
-            else {
-                if(last_messagebase[0]) {
-                    smb_stack(SMB_STACK_XCHNG);
-                    smb_close();
-                    strcpy(last_messagebase,new_messagebase); }
-                else {
-                    strcpy(last_messagebase,smb_file);
-                    smb_stack(SMB_STACK_PUSH); }    /* Save current base */
-                strcpy(smb_file,new_messagebase);
-                smb_open(10); } }
-        else {
-            strcpy(smb_file,new_messagebase);
-            smb_open(10); } }
-    /* Import this message */
-    }
-if(smb_file[0])
-    smb_close();
-if(last_messagebase[0]) {
-    smb_stack(SMB_STACK_POP);
-    smb_close(); }
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           92               SMBLIB Performance Issues
-
-
-The second example would be of negligible performance gain over the first
-example (6 open operations versus 7) if the messages to import were in the
-following order:
-
-msg[0] --> msgbase[0]       // 0 opened
-msg[1] --> msgbase[1]       // 0 pushed 1 opened
-msg[2] --> msgbase[1]
-msg[3] --> msgbase[2]       // 1 closed 0 popped 0 closed 2 opened
-msg[4] --> msgbase[0]       // 2 pushed 0 opened
-msg[5] --> msgbase[2]       // 0 pushed 2 popped (exchanged)
-msg[6] --> msgbase[3]       // 2 closed 0 popped 0 closed 3 opened
-msg[7] --> msgbase[0]       // 3 pushed 0 opened
-
-The second example would be of significant performance gain over the first
-example (4 open operations versus 8) if the messages to import were in the
-following order:
-
-msg[0] --> msgbase[0]       // 0 opened
-msg[1] --> msgbase[1]       // 0 pushed 1 opened
-msg[2] --> msgbase[0]       // 1 pushed 0 popped (exchanged)
-msg[3] --> msgbase[1]       // 0 pushed 1 popped (exchanged)
-msg[4] --> msgbase[0]       // 1 pushed 0 popped (exchanged)
-msg[5] --> msgbase[2]       // 0 pushed 1 popped (exchanged) 1 closed 2 opened
-msg[6] --> msgbase[3]       // 2 pushed 0 popped (exchanged) 0 closed 3 opened
-msg[7] --> msgbase[2]       // 3 pushed 2 popped (exchanged)
-
-More advanced use of "stack-like" message base file handle storage can easily
-reduce the number of open operations, therefore increasing import performance
-under more adverse message base ordering conditions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           93               SMBLIB Performance Issues
-
-
-Compression
------------
-If any message data compression features are offered by the application, it
-is important the the application not unnecessarily compress data that will
-not save any storage space. While this may seem an obvious statement, please
-review the following pseudo-code example:
-
-if ( message_data_length < SDT_BLOCK_LEN )
-    // Store uncompressed data
-else {
-    // Compress data
-    if ( ( compressed_data_length / SDT_BLOCK_LEN )
-        < ( message_data_length / SDT_BLOCK_LEN ) ) // Saves a block or more
-        // Store compressed data
-    else
-        // Store uncompressed data
-    }
-
-Since the SMB format stores message data in fixed length blocks, there is no
-point in storing a message in compressed format if it requires the same number
-of blocks as the uncompressed format (i.e. a message that is two blocks in
-length in uncompressed format and only a block and a half in length when
-compressed should not be stored in compressed format since it still requires
-two full blocks of storage). It is important to note that in the above example,
-the length of the data translation string was not taken into account in
-determining the number of required blocks. Also, the smb_datblocks() function
-is normally used in determing the number of required blocks to store a given
-data length and it is a little more involved than simply dividing the length of
-the data by SDT_BLOCK_LEN.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           94               SMBLIB Performance Issues
-
-
-Bibliography
-============
-
-Title     : The C Programming Language
-Publisher : Prentice Hall
-Author    : Brian W. Kernighan and Dennis M. Ritchie
-
-Document  : ARPANET Request for Comments (RFC) #822
-Title     : Standard for the Format of ARPA Internet text messages
-Publisher : SRI International
-Author    : David H. Crocker, University of Delaware
-
-Document  : FTS-0001
-Publisher : FSC
-Author    : Randy Bush, Pacific Systems Group
-
-Document  : FTS-0004
-Title     : EchoMail Specification
-Publisher : FSC
-Author    : Bob Hartman
-
-Document  : FTS-0009
-Title     : A standard for unique message identifiers and reply chain linkage
-Publisher : FSC
-Author    : Jim Nutt
-
-Document  : FSC-00046
-Title     : A Product Idenfifier for FidoNet Message Handlers
-Publisher : FSC
-Author    : Joaquim H. Homrighausen
-
-Document  : FSC-00053
-Title     : Specifications for the ^aFLAGS field
-Publisher : FSC
-Author    : Joaquim H. Homrighausen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           95                            Bibliography
-
-
-Implementations
-===============
-
-Product   : Synchronet Multinode BBS Software
-Developer : Digital Dynamics
-Level     : III
-Version   : 2.20
-
-Product   : Synchronet/FidoNet Import/Export Utility (SBBSFIDO)
-Developer : Digital Dynamics
-Level     : III
-Version   : 2.23
-
-Product   : Synchronet UTI (Universal Text Interface) Driver
-Developer : Digital Dynamics
-Level     : III
-Version   : 2.23
-
-Product   : SBBSecho FidoNet Packet Tosser for Synchronet
-Developer : Digital Dynamics
-Level     : III
-Version   : 1.11
-
-Product   : NetXpress Internet UUCP for Synchronet
-Developer : Merlin Systems
-Level     : II
-Version   : 1.50
-
-Product   : InterEcho FidoNet Packet Tosser
-Developer : InterMail Sales Inc
-Level     : II
-Version   : 1.11
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-_______________________________________________________________________________
-Synchronet                           96                                   Index
-
-
diff --git a/src/sbbs2/smb/121a/smb_read.me b/src/sbbs2/smb/121a/smb_read.me
deleted file mode 100644
index b1c1ec64d76330dbfb0c1d6a9486dd86b016d0c9..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smb_read.me
+++ /dev/null
@@ -1,65 +0,0 @@
-Synchronet Message Base (SMB) Specification v1.21 - READ.ME -
-=============================================================
-
-Files:
-
-        Miscellaneous
-        -------------
-        SMB_READ.ME     This file
-        FILE_ID.DIZ     Description of archive
-        SMB.HST         History of changes made since v1.00
-
-	Technical Specification
-        -----------------------
-        SMB.PRN         Paginated, to be printed at 12cpi (!)
-        SMB.TXT         Not paginated, for online viewing
-
-        Message Base C Library
-        ----------------------
-        SMBDEFS.H       C data types and constants
-        SMBVARS.C       C global variables
-        SMBLIB.H        C function prototypes
-        SMBLIB.C        C library functions
-	CRC32.H 	C header file for 32-bit CRC calculations
-        CRC16.C         C source file for 16-bit CRC calculations
-        LZH.H           C header file for LZH compression functions
-        LZH.C           C source file for LZH compression functions
-
-        Message Base Utility
-        --------------------
-        SMBUTIL.H       C header file
-        SMBUTIL.C       C source file
-        SMBUTIL.BOR     C makefile (for Borland C: make -f smbutil.bor)
-	SMBUTIL.WAT     C makefile (for Watcom C: wmake -f smbutil.wat
-                                      32-bit OS2: wmake -f smbutil.wat OS=OS2
-				      32-bit DOS: wmake -f smbutil.wat OS=DOSX)
-        SMBUTIL.EXE     Compiled and linked for 16-bit DOS
-
-        Check Message Base for Corruption
-        ---------------------------------
-        CHKSMB.C        C source file
-        CHKSMB.MAK      C makefile (for Borland C: make -f chksmb)
-        CHKSMB.EXE      Compiled and linked for 16-bit DOS
-
-	Rebuild Message Base Index and Allocation Files
-	-----------------------------------------------
-	FIXSMB.C	C source file
-	FIXSMB.MAK	C makefile (for Borland C: make -f fixsmb)
-	FIXSMB.EXE	Compiled and linked for 16-bit DOS
-
-        Convert from FidoNet (FTSC-1) to SMB
-        ------------------------------------
-        FIDO2SMB.C      C source file
-        FIDO2SMB.MAK    C makefile (for Borland C: make -f fido2smb)
-
-        Convert from Internet (RFC-822) to SMB
-        --------------------------------------
-        INET2SMB.C      C source file
-        INET2SMB.MAK    C makefile (for Borland C: make -f inet2smb)
-
-        Convert from QWK to SMB
-        -----------------------
-        QWK2SMB.C       C source file
-        QWK2SMB.MAK     C makefile (for Borland C: make -f qwk2smb)
-
-/* END of SMB_READ.ME */
diff --git a/src/sbbs2/smb/121a/smbdefs.h b/src/sbbs2/smb/121a/smbdefs.h
deleted file mode 100644
index 71791e69524fa58b43bf4ecbe9f495c6d237407e..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbdefs.h
+++ /dev/null
@@ -1,449 +0,0 @@
-/* SMBDEFS.H */
-
-#ifndef _SMBDEFS_H
-#define _SMBDEFS_H
-
-/**********/
-/* Macros */
-/**********/
-
-#define SMB_VERSION 		0x0121		/* SMB format version */
-										/* High byte major, low byte minor */
-#define SMBLIB_VERSION		"1.21a"     /* SMB library version */
-
-										/* Control characters */
-#define TAB 				0x09		/* Horizontal tabulation	^I */
-#define LF					0x0a		/* Line feed				^J */
-#define FF					0x0c		/* Form feed				^L */
-#define CR					0x0d		/* Carriage return			^M */
-#define ESC 				0x1b		/* Escape					^[ */
-#define SP					0x20		/* Space					   */
-
-#define ulong				unsigned long
-#define ushort				unsigned short
-#define uchar				unsigned char
-#define uint				unsigned int
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-#	define HUGE16 huge
-#	define FAR16 far
-#	if defined(__TURBOC__)
-#		define REALLOC(x,y) farrealloc(x,y)
-#		define LMALLOC(x) farmalloc(x)
-#		define MALLOC(x) farmalloc(x)
-#		define LFREE(x) farfree(x)
-#		define FREE(x) farfree(x)
-#	elif defined(__WATCOMC__)
-#		define REALLOC realloc
-#		define LMALLOC(x) halloc(x,1)  /* far heap, but slow */
-#		define MALLOC malloc		   /* far heap, but 64k max */
-#		define LFREE hfree
-#		define FREE free
-#	else	/* Other 16-bit Compiler */
-#		define REALLOC realloc
-#		define LMALLOC malloc
-#		define MALLOC malloc
-#		define LFREE free
-#		define FREE free
-#	endif
-#else		/* 32-bit Compiler or Small Memory Model */
-#	define HUGE16
-#	define FAR16
-#	define REALLOC realloc
-#	define LMALLOC malloc
-#	define MALLOC malloc
-#	define LFREE free
-#	define FREE free
-#endif
-
-
-#define SDT_BLOCK_LEN		256 		/* Size of data blocks */
-#define SHD_BLOCK_LEN		256 		/* Size of header blocks */
-
-#define SMB_SELFPACK		0			/* Self-packing storage allocation */
-#define SMB_FASTALLOC		1			/* Fast allocation */
-#define SMB_HYPERALLOC		2			/* No allocation */
-
-#define SMB_EMAIL			1			/* User numbers stored in Indexes */
-
-										/* Time zone macros for when_t.zone */
-#define DAYLIGHT			0x8000		/* Daylight savings is active */
-#define US_ZONE 			0x4000		/* U.S. time zone */
-#define WESTERN_ZONE		0x2000		/* Non-standard zone west of UT */
-#define EASTERN_ZONE		0x1000		/* Non-standard zone east of UT */
-
-										/* US Time Zones (standard) */
-#define AST 				0x40F0		// Atlantic 			(-04:00)
-#define EST 				0x412C		// Eastern				(-05:00)
-#define CST 				0x4168		// Central				(-06:00)
-#define MST 				0x41A4		// Mountain 			(-07:00)
-#define PST 				0x41E0		// Pacific				(-08:00)
-#define YST 				0x421C		// Yukon				(-09:00)
-#define HST 				0x4258		// Hawaii/Alaska		(-10:00)
-#define BST 				0x4294		// Bering				(-11:00)
-
-										/* US Time Zones (daylight) */
-#define ADT 				0xC0F0		// Atlantic 			(-03:00)
-#define EDT 				0xC12C		// Eastern				(-04:00)
-#define CDT 				0xC168		// Central				(-05:00)
-#define MDT 				0xC1A4		// Mountain 			(-06:00)
-#define PDT 				0xC1E0		// Pacific				(-07:00)
-#define YDT 				0xC21C		// Yukon				(-08:00)
-#define HDT 				0xC258		// Hawaii/Alaska		(-09:00)
-#define BDT 				0xC294		// Bering				(-10:00)
-
-										/* Non-standard Time Zones */
-#define MID 				0x2294		// Midway				(-11:00)
-#define VAN 				0x21E0		// Vancouver			(-08:00)
-#define EDM 				0x21A4		// Edmonton 			(-07:00)
-#define WIN 				0x2168		// Winnipeg 			(-06:00)
-#define BOG 				0x212C		// Bogota				(-05:00)
-#define CAR 				0x20F0		// Caracas				(-04:00)
-#define RIO 				0x20B4		// Rio de Janeiro		(-03:00)
-#define FER 				0x2078		// Fernando de Noronha	(-02:00)
-#define AZO 				0x203C		// Azores				(-01:00)
-#define LON 				0x1000		// London				(+00:00)
-#define BER 				0x103C		// Berlin				(+01:00)
-#define ATH 				0x1078		// Athens				(+02:00)
-#define MOS 				0x10B4		// Moscow				(+03:00)
-#define DUB 				0x10F0		// Dubai				(+04:00)
-#define KAB 				0x110E		// Kabul				(+04:30)
-#define KAR 				0x112C		// Karachi				(+05:00)
-#define BOM 				0x114A		// Bombay				(+05:30)
-#define KAT 				0x1159		// Kathmandu			(+05:45)
-#define DHA 				0x1168		// Dhaka				(+06:00)
-#define BAN 				0x11A4		// Bangkok				(+07:00)
-#define HON 				0x11E0		// Hong Kong			(+08:00)
-#define TOK 				0x121C		// Tokyo				(+09:00)
-#define SYD 				0x1258		// Sydney				(+10:00)
-#define NOU 				0x1294		// Noumea				(+11:00)
-#define WEL 				0x12D0		// Wellington			(+12:00)
-
-										/* Valid hfield_t.types */
-#define SENDER				0x00
-#define SENDERAGENT 		0x01
-#define SENDERNETTYPE		0x02
-#define SENDERNETADDR		0x03
-#define SENDEREXT			0x04
-#define SENDERPOS			0x05
-#define SENDERORG			0x06
-
-#define AUTHOR				0x10
-#define AUTHORAGENT 		0x11
-#define AUTHORNETTYPE		0x12
-#define AUTHORNETADDR		0x13
-#define AUTHOREXT			0x14
-#define AUTHORPOS			0x15
-#define AUTHORORG			0x16
-
-#define REPLYTO 			0x20
-#define REPLYTOAGENT		0x21
-#define REPLYTONETTYPE		0x22
-#define REPLYTONETADDR		0x23
-#define REPLYTOEXT			0x24
-#define REPLYTOPOS			0x25
-#define REPLYTOORG			0x26
-
-#define RECIPIENT			0x30
-#define RECIPIENTAGENT		0x31
-#define RECIPIENTNETTYPE	0x32
-#define RECIPIENTNETADDR	0x33
-#define RECIPIENTEXT		0x34
-#define RECIPIENTPOS		0x35
-#define RECIPIENTORG		0x36
-
-#define FORWARDTO			0x40
-#define FORWARDTOAGENT		0x41
-#define FORWARDTONETTYPE	0x42
-#define FORWARDTONETADDR	0x43
-#define FORWARDTOEXT		0x44
-#define FORWARDTOPOS		0x45
-#define FORWARDTOORG		0x46
-
-#define FORWARDED			0x48
-
-#define RECEIVEDBY			0x50
-#define RECEIVEDBYAGENT 	0x51
-#define RECEIVEDBYNETTYPE	0x52
-#define RECEIVEDBYNETADDR	0x53
-#define RECEIVEDBYEXT		0x54
-#define RECEIVEDBYPOS		0x55
-#define RECEIVEDBYORG		0x56
-
-#define RECEIVED			0x58
-
-#define SUBJECT 			0x60
-#define SUMMARY 			0x61
-#define COMMENT 			0x62
-#define CARBONCOPY			0x63
-#define GROUP				0x64
-#define EXPIRATION			0x65
-#define PRIORITY			0x66
-
-#define FILEATTACH			0x70
-#define DESTFILE			0x71
-#define FILEATTACHLIST		0x72
-#define DESTFILELIST		0x73
-#define FILEREQUEST 		0x74
-#define FILEPASSWORD		0x75
-#define FILEREQUESTLIST 	0x76
-#define FILEPASSWORDLIST	0x77
-
-#define IMAGEATTACH 		0x80
-#define ANIMATTACH			0x81
-#define FONTATTACH			0x82
-#define SOUNDATTACH 		0x83
-#define PRESENTATTACH		0x84
-#define VIDEOATTACH 		0x85
-#define APPDATAATTACH		0x86
-
-#define IMAGETRIGGER		0x90
-#define ANIMTRIGGER 		0x91
-#define FONTTRIGGER 		0x92
-#define SOUNDTRIGGER		0x93
-#define PRESENTTRIGGER		0x94
-#define VIDEOTRIGGER		0x95
-#define APPDATATRIGGER		0x96
-
-#define FIDOCTRL			0xa0
-#define FIDOAREA			0xa1
-#define FIDOSEENBY			0xa2
-#define FIDOPATH			0xa3
-#define FIDOMSGID			0xa4
-#define FIDOREPLYID 		0xa5
-#define FIDOPID 			0xa6
-#define FIDOFLAGS			0xa7
-
-#define RFC822HEADER		0xb0
-#define RFC822MSGID 		0xb1
-#define RFC822REPLYID		0xb2
-
-#define UNKNOWN 			0xf1
-#define UNKNOWNASCII		0xf2
-#define UNUSED				0xff
-
-										/* Valid dfield_t.types */
-#define TEXT_BODY			0x00
-#define TEXT_SOUL			0x01
-#define TEXT_TAIL			0x02
-#define TEXT_WING			0x03
-#define IMAGEEMBED			0x20
-#define ANIMEMBED			0x21
-#define FONTEMBED			0x22
-#define SOUNDEMBED			0x23
-#define PRESENTEMBED		0x24
-#define VIDEOEMBED			0x25
-#define APPDATAEMBED		0x26
-#define UNUSED				0xff
-
-
-										/* Message attributes */
-#define MSG_PRIVATE 		(1<<0)
-#define MSG_READ			(1<<1)
-#define MSG_PERMANENT		(1<<2)
-#define MSG_LOCKED			(1<<3)
-#define MSG_DELETE			(1<<4)
-#define MSG_ANONYMOUS		(1<<5)
-#define MSG_KILLREAD		(1<<6)
-#define MSG_MODERATED		(1<<7)
-#define MSG_VALIDATED		(1<<8)
-
-										/* Auxillary header attributes */
-#define MSG_FILEREQUEST 	(1<<0)		// File request
-#define MSG_FILEATTACH		(1<<1)		// File(s) attached to Msg
-#define MSG_TRUNCFILE		(1<<2)		// Truncate file(s) when sent
-#define MSG_KILLFILE		(1<<3)		// Delete file(s) when sent
-#define MSG_RECEIPTREQ		(1<<4)		// Return receipt requested
-#define MSG_CONFIRMREQ		(1<<5)		// Confirmation receipt requested
-#define MSG_NODISP			(1<<6)		// Msg may not be displayed to user
-
-										/* Message network attributes */
-#define MSG_LOCAL			(1<<0)		// Msg created locally
-#define MSG_INTRANSIT		(1<<1)		// Msg is in-transit
-#define MSG_SENT			(1<<2)		// Sent to remote
-#define MSG_KILLSENT		(1<<3)		// Kill when sent
-#define MSG_ARCHIVESENT 	(1<<4)		// Archive when sent
-#define MSG_HOLD			(1<<5)		// Hold for pick-up
-#define MSG_CRASH			(1<<6)		// Crash
-#define MSG_IMMEDIATE		(1<<7)		// Send Msg now, ignore restrictions
-#define MSG_DIRECT			(1<<8)		// Send directly to destination
-#define MSG_GATE			(1<<9)		// Send via gateway
-#define MSG_ORPHAN			(1<<10) 	// Unknown destination
-#define MSG_FPU 			(1<<11) 	// Force pickup
-#define MSG_TYPELOCAL		(1<<12) 	// Msg is for local use only
-#define MSG_TYPEECHO		(1<<13) 	// Msg is for conference distribution
-#define MSG_TYPENET 		(1<<14) 	// Msg is direct network mail
-
-
-enum {
-     NET_NONE
-    ,NET_UNKNOWN
-    ,NET_FIDO
-    ,NET_POSTLINK
-    ,NET_QWK
-	,NET_INTERNET
-	,NET_WWIV
-	,NET_MHS
-
-/* Add new ones here */
-
-    ,NET_TYPES
-    };
-
-enum {
-     AGENT_PERSON
-    ,AGENT_PROCESS
-
-/* Add new ones here */
-
-    ,AGENT_TYPES
-    };
-
-enum {
-     XLAT_NONE              // No translation/End of translation list
-    ,XLAT_ENCRYPT           // Encrypted data
-    ,XLAT_ESCAPED           // 7-bit ASCII escaping for ctrl and 8-bit data
-    ,XLAT_HUFFMAN           // Static and adaptive Huffman coding compression
-    ,XLAT_LZW               // Limpel/Ziv/Welch compression
-    ,XLAT_MLZ78             // Modified LZ78 compression
-    ,XLAT_RLE               // Run length encoding compression
-    ,XLAT_IMPLODE           // Implode compression (PkZIP)
-    ,XLAT_SHRINK            // Shrink compression (PkZIP)
-	,XLAT_LZH				// LHarc (LHA) Dynamic Huffman coding
-
-/* Add new ones here */
-
-    ,XLAT_TYPES
-    };
-
-
-/************/
-/* Typedefs */
-/************/
-
-typedef struct {
-
-	ulong	time;			// Local time (unix format)
-	short	zone;			// Time zone
-
-	} when_t;
-
-typedef struct {
-
-	ushort	to; 			// 16-bit CRC of recipient name (lower case)
-	ushort	from;			// 16-bit CRC of sender name (lower case)
-	ushort	subj;			// 16-bit CRC of subject (lower case, w/o RE:)
-	ushort	attr;			// attributes (read, permanent, etc.)
-	ulong	offset; 		// offset into header file
-	ulong	number; 		// number of message (1 based)
-	ulong	time;			// time/date message was imported/posted
-
-	} idxrec_t;
-
-typedef struct {
-
-    uchar   id[4];          // text or binary unique hdr ID
-    ushort  version;        // version number (initially 100h for 1.00)
-    ushort  length;         // length including this struct
-
-	} smbhdr_t;
-
-typedef struct {
-
-	ulong	last_msg;		// last message number
-	ulong	total_msgs; 	// total messages
-	ulong	header_offset;	// byte offset to first header record
-	ulong	max_crcs;		// Maximum number of CRCs to keep in history
-    ulong   max_msgs;       // Maximum number of message to keep in sub
-    ushort  max_age;        // Maximum age of message to keep in sub (in days)
-	ushort	attr;			// Attributes for this message base (SMB_HYPER,etc)
-
-	} smbstatus_t;
-
-typedef struct {
-
-	uchar	id[4];			// SHD<^Z>
-    ushort  type;           // Message type (normally 0)
-    ushort  version;        // Version of type (initially 100h for 1.00)
-    ushort  length;         // Total length of fixed record + all fields
-	ushort	attr;			// Attributes (bit field) (duped in SID)
-	ulong	auxattr;		// Auxillary attributes (bit field)
-    ulong   netattr;        // Network attributes
-	when_t	when_written;	// Time message was written (unix format)
-	when_t	when_imported;	// Time message was imported
-    ulong   number;         // Message number
-    ulong   thread_orig;    // Original message number in thread
-    ulong   thread_next;    // Next message in thread
-    ulong   thread_first;   // First reply to this message
-	uchar	reserved[16];	// Reserved for future use
-    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-	ushort	total_dfields;	// Total number of data fields
-
-	} msghdr_t;
-
-typedef struct {
-
-	ushort	type;			// Type of data field
-    ulong   offset;         // Offset into buffer 
-    ulong   length;         // Length of data field
-
-    } dfield_t;
-
-typedef struct {
-
-	ushort	type;
-	ushort	length; 		// Length of buffer
-
-	} hfield_t;
-
-typedef struct {
-
-	ushort	zone;
-	ushort	net;
-	ushort	node;
-	ushort	point;
-
-    } fidoaddr_t;
-
-typedef struct {
-
-    ushort  type;
-	void	*addr;
-
-	} net_t;
-
-typedef struct {
-
-	idxrec_t	idx;			// Index
-	msghdr_t	hdr;			// Header record (fixed portion)
-	uchar		*to,			// To name
-				*to_ext,		// To extension
-				*from,			// From name
-				*from_ext,		// From extension
-				*replyto,		// Reply-to name
-				*replyto_ext,	// Reply-to extension */
-				*subj;			// Subject
-	ushort		to_agent,		// Type of agent message is to
-				from_agent, 	// Type of agent message is from
-				replyto_agent;	// Type of agent replies should be sent to
-	net_t		to_net, 		// Destination network type and address
-                from_net,       // Origin network address
-                replyto_net;    // Network type and address for replies
-	ushort		total_hfields;	// Total number of header fields
-	hfield_t	*hfield;		// Header fields (fixed length portion)
-	void		**hfield_dat;	// Header fields (variable length portion)
-	dfield_t	*dfield;		// Data fields (fixed length portion)
-	ulong		offset; 		// Offset (number of records) into index
-	uchar		forwarded;		// Forwarded from agent to another
-
-	} smbmsg_t;
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/smb/121a/smblib.c b/src/sbbs2/smb/121a/smblib.c
deleted file mode 100644
index e2d8a474b875feec0a6efaa1f49a01650ab396a9..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smblib.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-/* SMBLIB.C */
-
-#include "smblib.h"
-
-/****************************************************************************/
-/* Open a message base of name 'smb_file'                                   */
-/* If retry_time is 0, fast open method (no compatibility/validity check)	*/
-/* Opens files for READing messages or updating message indices only        */
-/****************************************************************************/
-int smb_open(int retry_time)
-{
-    int file;
-    char str[128];
-	smbhdr_t hdr;
-
-shd_fp=sdt_fp=sid_fp=NULL;
-sprintf(str,"%s.SHD",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (shd_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-    return(2); }
-
-if(retry_time && filelength(file)>=sizeof(smbhdr_t)) {
-	setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
-    if(smb_locksmbhdr(retry_time)) {
-		smb_close();
-        return(-1); }
-	memset(&hdr,0,sizeof(smbhdr_t));
-    fread(&hdr,sizeof(smbhdr_t),1,shd_fp);
-    if(memcmp(hdr.id,"SMB\x1a",4)) {
-		smb_close();
-        return(-2); }
-    if(hdr.version<0x110) {         /* Compatibility check */
-		smb_close();
-        return(-3); }
-    smb_unlocksmbhdr();
-	rewind(shd_fp); }
-
-setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
-
-sprintf(str,"%s.SDT",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (sdt_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close();
-	return(1); }
-setvbuf(sdt_fp,NULL,_IOFBF,2*1024);
-
-sprintf(str,"%s.SID",smb_file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (sid_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close();
-	return(3); }
-setvbuf(sid_fp,NULL,_IOFBF,2*1024);
-
-return(0);
-}
-
-/****************************************************************************/
-/* Closes the currently open message base									*/
-/****************************************************************************/
-void smb_close(void)
-{
-if(shd_fp!=NULL) {
-	smb_unlocksmbhdr(); 			/* In case it's been locked */
-	fclose(shd_fp); }
-if(sid_fp!=NULL)
-	fclose(sid_fp);
-if(sdt_fp!=NULL)
-	fclose(sdt_fp);
-sid_fp=shd_fp=sdt_fp=NULL;
-}
-
-/****************************************************************************/
-/* Opens the data block allocation table message base 'smb_file'            */
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_open_da(int retry_time)
-{
-    int file;
-    char str[128];
-	long start;
-
-start=time(NULL);
-sprintf(str,"%s.SDA",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-		return(-2); }
-if((sda_fp=fdopen(file,"r+b"))==NULL)
-	return(-3);
-setvbuf(sda_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-/****************************************************************************/
-/* Opens the header block allocation table for message base 'smb_file'      */
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_open_ha(int retry_time)
-{
-    int file;
-    char str[128];
-	long start;
-
-start=time(NULL);
-sprintf(str,"%s.SHA",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-		return(-2); }
-if((sha_fp=fdopen(file,"r+b"))==NULL)
-	return(-3);
-setvbuf(sha_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-/****************************************************************************/
-/* If the parameter 'push' is non-zero, this function stores the currently  */
-/* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
-/* message bases may be stored (defined in SMBDEFS.H).						*/
-/* The parameter 'op' is the operation to perform on the stack. Either      */
-/* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG						*/
-/* If the operation is SMB_STACK_POP, this function restores a message base */
-/* previously saved with a SMB_STACK_PUSH call to this same function.		*/
-/* If the operation is SMB_STACK_XCHNG, then the current message base is	*/
-/* exchanged with the message base on the top of the stack (most recently	*/
-/* pushed.																	*/
-/* If the current message base is not open, the SMB_STACK_PUSH and			*/
-/* SMB_STACK_XCHNG operations do nothing									*/
-/* Returns 0 on success, non-zero if stack full.                            */
-/* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.	*/
-/****************************************************************************/
-int smb_stack(int op)
-{
-	static char stack_file[SMB_STACK_LEN][128];
-	static FILE *stack_sdt[SMB_STACK_LEN],
-				*stack_shd[SMB_STACK_LEN],
-				*stack_sid[SMB_STACK_LEN],
-				*stack_sda[SMB_STACK_LEN],
-				*stack_sha[SMB_STACK_LEN];
-	static int	stack_idx;
-	char		tmp_file[128];
-	FILE		*tmp_sdt,
-				*tmp_shd,
-				*tmp_sid,
-				*tmp_sda,
-				*tmp_sha;
-
-if(op==SMB_STACK_PUSH) {
-	if(stack_idx>=SMB_STACK_LEN)
-		return(1);
-	if(shd_fp==NULL || sdt_fp==NULL || sid_fp==NULL) /* Msg base not open */
-		return(0);
-	memcpy(stack_file[stack_idx],smb_file,128);
-	stack_sdt[stack_idx]=sdt_fp;
-	stack_shd[stack_idx]=shd_fp;
-	stack_sid[stack_idx]=sid_fp;
-	stack_sda[stack_idx]=sda_fp;
-	stack_sha[stack_idx]=sha_fp;
-	stack_idx++;
-	return(0); }
-/* pop or xchng */
-if(!stack_idx)	/* Nothing on the stack, so do nothing */
-	return(0);
-if(op==SMB_STACK_XCHNG) {
-	if(!shd_fp)
-		return(0);
-	memcpy(tmp_file,smb_file,128);
-	tmp_sdt=sdt_fp;
-	tmp_shd=shd_fp;
-	tmp_sid=sid_fp;
-	tmp_sda=sda_fp;
-	tmp_sha=sha_fp; }
-
-stack_idx--;
-memcpy(smb_file,stack_file[stack_idx],128);
-sdt_fp=stack_sdt[stack_idx];
-shd_fp=stack_shd[stack_idx];
-sid_fp=stack_sid[stack_idx];
-sda_fp=stack_sda[stack_idx];
-sha_fp=stack_sha[stack_idx];
-if(op==SMB_STACK_XCHNG) {
-	stack_idx++;
-	memcpy(stack_file[stack_idx-1],tmp_file,128);
-	stack_sdt[stack_idx-1]=tmp_sdt;
-	stack_shd[stack_idx-1]=tmp_shd;
-	stack_sid[stack_idx-1]=tmp_sid;
-	stack_sda[stack_idx-1]=tmp_sda;
-	stack_sha[stack_idx-1]=tmp_sha; }
-return(0);
-}
-
-/****************************************************************************/
-/* Truncates header file													*/
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int smb_trunchdr(int retry_time)
-{
-	long start;
-
-start=time(NULL);
-rewind(shd_fp);
-while(1) {
-	if(!chsize(fileno(shd_fp),0L))
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)		/* Time-out */
-		return(-2); }
-return(0);
-}
-
-/*********************************/
-/* Message Base Header Functions */
-/*********************************/
-
-/****************************************************************************/
-/* Attempts for retry_time number of seconds to lock the message base hdr	*/
-/****************************************************************************/
-int smb_locksmbhdr(int retry_time)
-{
-	ulong start;
-
-start=time(NULL);
-while(1) {
-	if(!lock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
-		return(0);
-	if(time(NULL)-start>=retry_time)
-		break;							/* Incase we've already locked it */
-	unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Read the SMB header from the header file and place into "status"         */
-/****************************************************************************/
-int smb_getstatus(smbstatus_t *status)
-{
-    char    str[128];
-	int 	i;
-
-setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
-clearerr(shd_fp);
-fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fread(status,1,sizeof(smbstatus_t),shd_fp);
-setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Writes message base header												*/
-/****************************************************************************/
-int smb_putstatus(smbstatus_t status)
-{
-	int i;
-
-clearerr(shd_fp);
-fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
-fflush(shd_fp);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Unlocks previously locks message base header 							*/
-/****************************************************************************/
-int smb_unlocksmbhdr()
-{
-return(unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
-}
-
-/********************************/
-/* Individual Message Functions */
-/********************************/
-
-/****************************************************************************/
-/* Attempts for retry_time number of seconds to lock the header for 'msg'   */
-/****************************************************************************/
-int smb_lockmsghdr(smbmsg_t msg, int retry_time)
-{
-    ulong start;
-
-start=time(NULL);
-while(1) {
-	if(!lock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)))
-        return(0);
-    if(time(NULL)-start>=retry_time)
-		break;
-	unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Fills msg->idx with message index based on msg->hdr.number				*/
-/* OR if msg->hdr.number is 0, based on msg->offset (record offset).		*/
-/* if msg.hdr.number does not equal 0, then msg->offset is filled too.		*/
-/* Either msg->hdr.number or msg->offset must be initialized before 		*/
-/* calling this function													*/
-/* Returns 1 if message number wasn't found, 0 if it was                    */
-/****************************************************************************/
-int smb_getmsgidx(smbmsg_t *msg)
-{
-	idxrec_t idx;
-	ulong	 l,length,total,bot,top;
-
-clearerr(sid_fp);
-if(!msg->hdr.number) {
-	fseek(sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&msg->idx,sizeof(idxrec_t),1,sid_fp))
-		return(1);
-	return(0); }
-
-length=filelength(fileno(sid_fp));
-if(!length)
-	return(1);
-total=length/sizeof(idxrec_t);
-if(!total)
-	return(1);
-
-bot=0;
-top=total;
-l=total/2; /* Start at middle index */
-while(1) {
-	fseek(sid_fp,l*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
-		return(1);
-	if(bot==top-1 && idx.number!=msg->hdr.number)
-        return(1);
-	if(idx.number>msg->hdr.number) {
-		top=l;
-		l=bot+((top-bot)/2);
-		continue; }
-	if(idx.number<msg->hdr.number) {
-		bot=l;
-		l=top-((top-bot)/2);
-		continue; }
-	break; }
-msg->idx=idx;
-msg->offset=l;
-return(0);
-}
-
-/****************************************************************************/
-/* Reads the last index record in the open message base 					*/
-/****************************************************************************/
-int smb_getlastidx(idxrec_t *idx)
-{
-	long length;
-
-clearerr(sid_fp);
-length=filelength(fileno(sid_fp));
-if(length<sizeof(idxrec_t))
-	return(-1);
-fseek(sid_fp,length-sizeof(idxrec_t),SEEK_SET);
-if(!fread(idx,sizeof(idxrec_t),1,sid_fp))
-	return(-2);
-return(0);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the header record for 'msg'              */
-/* Returns length															*/
-/****************************************************************************/
-uint smb_getmsghdrlen(smbmsg_t msg)
-{
-	int i;
-
-/* fixed portion */
-msg.hdr.length=sizeof(msghdr_t);
-/* data fields */
-msg.hdr.length+=msg.hdr.total_dfields*sizeof(dfield_t);
-/* header fields */
-for(i=0;i<msg.total_hfields;i++) {
-	msg.hdr.length+=sizeof(hfield_t);
-	msg.hdr.length+=msg.hfield[i].length; }
-return(msg.hdr.length);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the data buffer for 'msg'                */
-/* Returns length															*/
-/****************************************************************************/
-ulong smb_getmsgdatlen(smbmsg_t msg)
-{
-	int i;
-	ulong length=0L;
-
-for(i=0;i<msg.hdr.total_dfields;i++)
-	length+=msg.dfield[i].length;
-return(length);
-}
-
-/****************************************************************************/
-/* Read header information into 'msg' structure                             */
-/* msg->idx.offset must be set before calling this function 				*/
-/* Must call smb_freemsgmem() to free memory allocated for var len strs 	*/
-/* Returns 0 on success, non-zero if error									*/
-/****************************************************************************/
-int smb_getmsghdr(smbmsg_t *msg)
-{
-	ushort	i;
-	ulong	l,offset;
-	idxrec_t idx;
-
-rewind(shd_fp);
-fseek(shd_fp,msg->idx.offset,SEEK_SET);
-idx=msg->idx;
-offset=msg->offset;
-memset(msg,0,sizeof(smbmsg_t));
-msg->idx=idx;
-msg->offset=offset;
-if(!fread(&msg->hdr,sizeof(msghdr_t),1,shd_fp))
-	return(-1);
-if(memcmp(msg->hdr.id,"SHD\x1a",4))
-	return(-2);
-if(msg->hdr.version<0x110)
-	return(-9);
-l=sizeof(msghdr_t);
-if(msg->hdr.total_dfields && (msg->dfield
-	=(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
-	smb_freemsgmem(*msg);
-	return(-3); }
-i=0;
-while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
-	if(!fread(&msg->dfield[i],sizeof(dfield_t),1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-4); }
-	i++;
-	l+=sizeof(dfield_t); }
-if(i<msg->hdr.total_dfields) {
-	smb_freemsgmem(*msg);
-	return(-8); }
-
-while(l<msg->hdr.length) {
-	i=msg->total_hfields;
-	if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
-		==NULL) {
-		smb_freemsgmem(*msg);
-		return(-3); }
-	if((msg->hfield=(hfield_t *)REALLOC(msg->hfield
-		,sizeof(hfield_t)*(i+1)))==NULL) {
-		smb_freemsgmem(*msg);
-		return(-3); }
-	msg->total_hfields++;
-	if(!fread(&msg->hfield[i],sizeof(hfield_t),1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-5); }
-	l+=sizeof(hfield_t);
-	if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
-		==NULL) {			/* Allocate 1 extra for NULL terminator */
-		smb_freemsgmem(*msg);  /* or 0 length field */
-		return(-3); }
-	memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
-	if(msg->hfield[i].length
-		&& !fread(msg->hfield_dat[i],msg->hfield[i].length,1,shd_fp)) {
-		smb_freemsgmem(*msg);
-		return(-6); }
-
-	switch(msg->hfield[i].type) {	/* convenience variables */
-		case SENDER:
-			if(!msg->from) {
-				msg->from=msg->hfield_dat[i];
-				break; }
-		case FORWARDED: 	/* fall through */
-			msg->forwarded=1;
-			break;
-		case SENDERAGENT:
-			if(!msg->forwarded)
-				msg->from_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDEREXT:
-			if(!msg->forwarded)
-				msg->from_ext=msg->hfield_dat[i];
-			break;
-		case SENDERNETTYPE:
-			if(!msg->forwarded)
-				msg->from_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDERNETADDR:
-			if(!msg->forwarded)
-				msg->from_net.addr=msg->hfield_dat[i];
-            break;
-		case REPLYTO:
-			msg->replyto=msg->hfield_dat[i];
-            break;
-		case REPLYTOEXT:
-			msg->replyto_ext=msg->hfield_dat[i];
-			break;
-		case REPLYTOAGENT:
-			msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETTYPE:
-			msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETADDR:
-			msg->replyto_net.addr=msg->hfield_dat[i];
-            break;
-		case RECIPIENT:
-			msg->to=msg->hfield_dat[i];
-            break;
-		case RECIPIENTEXT:
-			msg->to_ext=msg->hfield_dat[i];
-			break;
-		case RECIPIENTAGENT:
-			msg->to_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETTYPE:
-			msg->to_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETADDR:
-			msg->to_net.addr=msg->hfield_dat[i];
-            break;
-		case SUBJECT:
-			msg->subj=msg->hfield_dat[i];
-			break; }
-	l+=msg->hfield[i].length; }
-
-if(!msg->from || !msg->to || !msg->subj) {
-	smb_freemsgmem(*msg);
-	return(-7); }
-return(0);
-}
-
-/****************************************************************************/
-/* Frees memory allocated for 'msg'                                         */
-/****************************************************************************/
-void smb_freemsgmem(smbmsg_t msg)
-{
-	ushort	i;
-
-if(msg.dfield)
-	FREE(msg.dfield);
-for(i=0;i<msg.total_hfields;i++)
-	if(msg.hfield_dat[i])
-		FREE(msg.hfield_dat[i]);
-if(msg.hfield)
-	FREE(msg.hfield);
-if(msg.hfield_dat)
-	FREE(msg.hfield_dat);
-}
-
-/****************************************************************************/
-/* Unlocks header for 'msg'                                                 */
-/****************************************************************************/
-int smb_unlockmsghdr(smbmsg_t msg)
-{
-return(unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)));
-}
-
-
-/****************************************************************************/
-/* Adds a header field to the 'msg' structure (in memory only)              */
-/****************************************************************************/
-int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
-{
-	int i;
-
-i=msg->total_hfields;
-if((msg->hfield=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))
-	==NULL)
-	return(1);
-if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
-	==NULL)
-	return(2);
-msg->total_hfields++;
-msg->hfield[i].type=type;
-msg->hfield[i].length=length;
-if(length) {
-	if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
-		return(4);
-	memcpy(msg->hfield_dat[i],data,length); }
-else
-	msg->hfield_dat[i]=NULL;
-return(0);
-}
-
-/****************************************************************************/
-/* Adds a data field to the 'msg' structure (in memory only)                */
-/* Automatically figures out the offset into the data buffer from existing	*/
-/* dfield lengths															*/
-/****************************************************************************/
-int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
-{
-	int i,j;
-
-i=msg->hdr.total_dfields;
-if((msg->dfield=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))
-	==NULL)
-	return(1);
-msg->hdr.total_dfields++;
-msg->dfield[i].type=type;
-msg->dfield[i].length=length;
-for(j=msg->dfield[i].offset=0;j<i;j++)
-	msg->dfield[i].offset+=msg->dfield[j].length;
-return(0);
-}
-
-/****************************************************************************/
-/* Checks CRC history file for duplicate crc. If found, returns 1.			*/
-/* If no dupe, adds to CRC history and returns 0, or negative if error. 	*/
-/****************************************************************************/
-int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
-{
-	char	str[128];
-	int 	file;
-	long	length;
-	ulong	l,*buf;
-	time_t	start;
-
-if(!max_crcs)
-	return(0);
-start=time(NULL);
-sprintf(str,"%s.SCH",smb_file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(time(NULL)-start>=retry_time)
-        return(-2); }
-length=filelength(file);
-if(length<0L) {
-	close(file);
-	return(-4); }
-if((buf=(ulong *)MALLOC(max_crcs*4))==NULL) {
-	close(file);
-	return(-3); }
-if(length>=max_crcs*4) {			/* Reached or exceeds max crcs */
-	read(file,buf,max_crcs*4);
-	for(l=0;l<max_crcs;l++)
-		if(crc==buf[l])
-			break;
-	if(l<max_crcs) {				/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); }
-	chsize(file,0L);				/* truncate it */
-	lseek(file,0L,SEEK_SET);
-	write(file,buf+4,(max_crcs-1)*4); }
-
-else if(length/4) { 						/* Less than max crcs */
-	read(file,buf,length);
-	for(l=0;l<length/4;l++)
-		if(crc==buf[l])
-			break;
-	if(l<length/4) {					/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); } }
-
-lseek(file,0L,SEEK_END);
-write(file,&crc,4); 			   /* Write to the end */
-FREE(buf);
-close(file);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Creates a new message header record in the header file.					*/
-/* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
-/* If storage is SMB_FASTALLOC, fast allocation is used 					*/
-/* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)	*/
-/****************************************************************************/
-int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
-	,int retry_time)
-{
-	int i;
-	long l;
-
-if(smb_locksmbhdr(retry_time))
-    return(1);
-if(smb_getstatus(status))
-    return(2);
-
-if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(retry_time))!=0)
-    return(i);
-
-msg->hdr.length=smb_getmsghdrlen(*msg);
-if(storage==SMB_HYPERALLOC)
-	l=smb_hallochdr(status->header_offset);
-else if(storage==SMB_FASTALLOC)
-    l=smb_fallochdr(msg->hdr.length);
-else
-    l=smb_allochdr(msg->hdr.length);
-if(l==-1L) {
-	smb_unlocksmbhdr();
-	fclose(sha_fp);
-	return(-1); }
-
-status->last_msg++;
-msg->idx.number=msg->hdr.number=status->last_msg;
-msg->idx.offset=status->header_offset+l;
-msg->idx.time=msg->hdr.when_imported.time;
-msg->idx.attr=msg->hdr.attr;
-msg->offset=status->total_msgs;
-status->total_msgs++;
-smb_putstatus(*status);
-
-if(storage!=SMB_HYPERALLOC)
-	fclose(sha_fp);
-i=smb_putmsg(*msg);
-smb_unlocksmbhdr();
-return(i);
-}
-
-/****************************************************************************/
-/* Writes both header and index information for msg 'msg'                   */
-/****************************************************************************/
-int smb_putmsg(smbmsg_t msg)
-{
-	int i;
-
-i=smb_putmsghdr(msg);
-if(i)
-	return(i);
-return(smb_putmsgidx(msg));
-}
-
-/****************************************************************************/
-/* Writes index information for 'msg'                                       */
-/* msg.idx																	*/
-/* and msg.offset must be set prior to calling to this function             */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int smb_putmsgidx(smbmsg_t msg)
-{
-
-clearerr(sid_fp);
-fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-if(!fwrite(&msg.idx,sizeof(idxrec_t),1,sid_fp))
-	return(1);
-fflush(sid_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Writes header information for 'msg'                                      */
-/* msg.hdr.length                                                           */
-/* msg.idx.offset                                                           */
-/* and msg.offset must be set prior to calling to this function             */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int smb_putmsghdr(smbmsg_t msg)
-{
-	ushort	i;
-	ulong	l;
-
-clearerr(shd_fp);
-if(fseek(shd_fp,msg.idx.offset,SEEK_SET))
-	return(-1);
-
-/************************************************/
-/* Write the fixed portion of the header record */
-/************************************************/
-if(!fwrite(&msg.hdr,sizeof(msghdr_t),1,shd_fp))
-	return(-2);
-
-/************************************************/
-/* Write the data fields (each is fixed length) */
-/************************************************/
-for(i=0;i<msg.hdr.total_dfields;i++)
-	if(!fwrite(&msg.dfield[i],sizeof(dfield_t),1,shd_fp))
-		return(-3);
-
-/*******************************************/
-/* Write the variable length header fields */
-/*******************************************/
-for(i=0;i<msg.total_hfields;i++) {
-	if(!fwrite(&msg.hfield[i],sizeof(hfield_t),1,shd_fp))
-		return(-4);
-	if(msg.hfield[i].length 					/* more then 0 bytes long */
-		&& !fwrite(msg.hfield_dat[i],msg.hfield[i].length,1,shd_fp))
-		return(-5); }
-
-l=smb_getmsghdrlen(msg);
-while(l%SHD_BLOCK_LEN) {
-	if(fputc(0,shd_fp)==EOF)
-		return(-6); 			   /* pad block with NULL */
-	l++; }
-fflush(shd_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Creates a sub-board's initial header file                                */
-/* Truncates and deletes other associated SMB files 						*/
-/****************************************************************************/
-int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-	,int retry_time)
-{
-    char        str[128];
-	smbhdr_t	hdr;
-	smbstatus_t status;
-
-if(filelength(fileno(shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
-	&& smb_locksmbhdr(retry_time))	/* header exists, so lock it */
-	return(1);
-memset(&hdr,0,sizeof(smbhdr_t));
-memset(&status,0,sizeof(smbstatus_t));
-memcpy(hdr.id,"SMB\x1a",4);     /* <S> <M> <B> <^Z> */
-hdr.version=SMB_VERSION;
-hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-status.last_msg=status.total_msgs=0;
-status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-status.max_crcs=max_crcs;
-status.max_msgs=max_msgs;
-status.max_age=max_age;
-status.attr=attr;
-rewind(shd_fp);
-fwrite(&hdr,1,sizeof(smbhdr_t),shd_fp);
-fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
-rewind(shd_fp);
-chsize(fileno(shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
-fflush(shd_fp);
-
-rewind(sdt_fp);
-chsize(fileno(sdt_fp),0L);
-rewind(sid_fp);
-chsize(fileno(sid_fp),0L);
-
-sprintf(str,"%s.SDA",smb_file);
-remove(str);						/* if it exists, delete it */
-sprintf(str,"%s.SHA",smb_file);
-remove(str);                        /* if it exists, delete it */
-sprintf(str,"%s.SCH",smb_file);
-remove(str);
-smb_unlocksmbhdr();
-return(0);
-}
-
-/****************************************************************************/
-/* Returns number of data blocks required to store "length" amount of data  */
-/****************************************************************************/
-ulong smb_datblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SDT_BLOCK_LEN;
-if(length%SDT_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Returns number of header blocks required to store "length" size header   */
-/****************************************************************************/
-ulong smb_hdrblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SHD_BLOCK_LEN;
-if(length%SHD_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Finds unused space in data file based on block allocation table and		*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of data (in bytes, not blocks)				*/
-/* Assumes smb_open_da() has been called									*/
-/* fclose(sda_fp) should be called after									*/
-/* Returns negative on error												*/
-/****************************************************************************/
-long smb_allocdat(ulong length, ushort headers)
-{
-    ushort  i,j;
-	ulong	l,blocks,offset=0L;
-
-blocks=smb_datblocks(length);
-j=0;	/* j is consecutive unused block counter */
-fflush(sda_fp);
-rewind(sda_fp);
-while(!feof(sda_fp)) {
-	if(!fread(&i,2,1,sda_fp))
-        break;
-	offset+=SDT_BLOCK_LEN;
-    if(!i) j++;
-    else   j=0;
-	if(j==blocks) {
-		offset-=(blocks*SDT_BLOCK_LEN);
-        break; } }
-clearerr(sda_fp);
-fseek(sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,sda_fp))
-		return(-1);
-fflush(sda_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for data, but doesn't search for unused blocks           */
-/* Returns negative on error												*/
-/****************************************************************************/
-long smb_fallocdat(ulong length, ushort headers)
-{
-	ulong	l,blocks,offset;
-
-fflush(sda_fp);
-clearerr(sda_fp);
-blocks=smb_datblocks(length);
-fseek(sda_fp,0L,SEEK_END);
-offset=(ftell(sda_fp)/2L)*SDT_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,sda_fp))
-        break;
-fflush(sda_fp);
-if(l<blocks)
-	return(-1L);
-return(offset);
-}
-
-/****************************************************************************/
-/* De-allocates space for data												*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_freemsgdat(ulong offset, ulong length, ushort headers)
-{
-	ushort	i;
-	ulong	l,blocks;
-
-blocks=smb_datblocks(length);
-
-clearerr(sda_fp);
-for(l=0;l<blocks;l++) {
-	if(fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
-		return(1);
-	if(!fread(&i,2,1,sda_fp))
-		return(2);
-	if(headers>i)
-		i=0;			/* don't want to go negative */
-	else
-		i-=headers;
-	if(fseek(sda_fp,-2L,SEEK_CUR))
-		return(3);
-	if(!fwrite(&i,2,1,sda_fp))
-		return(4); }
-fflush(sda_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Adds to data allocation records for blocks starting at 'offset'          */
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_incdat(ulong offset, ulong length, ushort headers)
-{
-	ushort	i;
-	ulong	l,blocks;
-
-clearerr(sda_fp);
-blocks=smb_datblocks(length);
-for(l=0;l<blocks;l++) {
-	fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
-	if(!fread(&i,2,1,sda_fp))
-		return(1);
-	i+=headers;
-	fseek(sda_fp,-2L,SEEK_CUR);
-	if(!fwrite(&i,2,1,sda_fp))
-		return(2); }
-fflush(sda_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* De-allocates blocks for header record									*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int smb_freemsghdr(ulong offset, ulong length)
-{
-	uchar	c=0;
-	ulong	l,blocks;
-
-clearerr(sha_fp);
-blocks=smb_hdrblocks(length);
-fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(1);
-fflush(sha_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Frees all allocated header and data blocks for 'msg'                     */
-/****************************************************************************/
-int smb_freemsg(smbmsg_t msg, smbstatus_t status)
-{
-	int 	i;
-	ushort	x;
-
-if(status.attr&SMB_HYPERALLOC)	/* Nothing to do */
-	return(0);
-
-for(x=0;x<msg.hdr.total_dfields;x++) {
-	if((i=smb_freemsgdat(msg.hdr.offset+msg.dfield[x].offset
-		,msg.dfield[x].length,1))!=0)
-		return(i); }
-return(smb_freemsghdr(msg.idx.offset-status.header_offset,msg.hdr.length));
-}
-
-/****************************************************************************/
-/* Finds unused space in header file based on block allocation table and	*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of header (in bytes, not blocks) 			*/
-/* Assumes smb_open_ha() has been called									*/
-/* fclose(sha_fp) should be called after									*/
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long smb_allochdr(ulong length)
-{
-	uchar	c;
-	ushort	i;
-	ulong	l,blocks,offset=0;
-
-blocks=smb_hdrblocks(length);
-i=0;	/* i is consecutive unused block counter */
-fflush(sha_fp);
-rewind(sha_fp);
-while(!feof(sha_fp)) {
-	if(!fread(&c,1,1,sha_fp))
-        break;
-	offset+=SHD_BLOCK_LEN;
-	if(!c) i++;
-	else   i=0;
-	if(i==blocks) {
-		offset-=(blocks*SHD_BLOCK_LEN);
-        break; } }
-clearerr(sha_fp);
-fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-c=1;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(-1L);
-fflush(sha_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for index, but doesn't search for unused blocks          */
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long smb_fallochdr(ulong length)
-{
-	uchar	c=1;
-	ulong	l,blocks,offset;
-
-blocks=smb_hdrblocks(length);
-fflush(sha_fp);
-clearerr(sha_fp);
-fseek(sha_fp,0L,SEEK_END);
-offset=ftell(sha_fp)*SHD_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,sha_fp))
-		return(-1L);
-fflush(sha_fp);
-return(offset);
-}
-
-/************************************************************************/
-/* Allocate header blocks using Hyper Allocation						*/
-/* this function should be most likely not be called from anywhere but	*/
-/* smb_addmsghdr()														*/
-/************************************************************************/
-long smb_hallochdr(ulong header_offset)
-{
-	long l;
-
-fflush(shd_fp);
-fseek(shd_fp,0L,SEEK_END);
-l=ftell(shd_fp);
-if(l<header_offset) 					/* Header file truncated?!? */
-	return(header_offset);
-while((l-header_offset)%SHD_BLOCK_LEN)	/* Make sure even block boundry */
-	l++;
-return(l-header_offset);
-}
-
-/************************************************************************/
-/* Allocate data blocks using Hyper Allocation							*/
-/* smb_locksmbhdr() should be called before this function and not		*/
-/* unlocked until all data fields for this message have been written	*/
-/* to the SDT file														*/
-/************************************************************************/
-long smb_hallocdat()
-{
-	long l;
-
-fflush(sdt_fp);
-fseek(sdt_fp,0L,SEEK_END);
-l=ftell(sdt_fp);
-if(l<=0)
-	return(l);
-while(l%SDT_BLOCK_LEN)					/* Make sure even block boundry */
-	l++;
-return(l);
-}
-
-/* End of SMBLIB.C */
diff --git a/src/sbbs2/smb/121a/smblib.h b/src/sbbs2/smb/121a/smblib.h
deleted file mode 100644
index b682f74f039574009cd3ef2e0a77204231e8e5b7..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smblib.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* SMBLIB.H */
-
-#ifndef _SMBLIB_H
-#define _SMBLIB_H
-
-#if defined(__WATCOMC__) || defined(__TURBOC__)
-#	include <io.h>
-#	include <mem.h>
-#	include <share.h>
-#else
-#	include <memory.h>
-#endif
-
-#ifdef __WATCOMC__
-#	include <dos.h>
-#elif defined(__TURBOC__)
-#	include <dir.h>
-#endif
-
-#include <malloc.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define GLOBAL extern	/* turn smbvars.c files into header */
-
-#include "smbvars.c"
-
-#define SMB_STACK_LEN		4			/* Max msg bases in smb_stack() 	*/
-#define SMB_STACK_POP       0           /* Pop a msg base off of smb_stack() */
-#define SMB_STACK_PUSH      1           /* Push a msg base onto smb_stack() */
-#define SMB_STACK_XCHNG     2           /* Exchange msg base w/last pushed */
-
-int 	smb_open(int retry_time);
-void	smb_close(void);
-int 	smb_open_da(int retry_time);
-int 	smb_open_ha(int retry_time);
-int 	smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-				  ,int retry_time);
-int 	smb_stack(int op);
-int 	smb_trunchdr(int retry_time);
-int 	smb_locksmbhdr(int retry_time);
-int 	smb_getstatus(smbstatus_t *status);
-int 	smb_putstatus(smbstatus_t status);
-int 	smb_unlocksmbhdr(void);
-int 	smb_getmsgidx(smbmsg_t *msg);
-int 	smb_getlastidx(idxrec_t *idx);
-uint	smb_getmsghdrlen(smbmsg_t msg);
-ulong	smb_getmsgdatlen(smbmsg_t msg);
-int 	smb_lockmsghdr(smbmsg_t msg, int retry_time);
-int 	smb_getmsghdr(smbmsg_t *msg);
-int 	smb_unlockmsghdr(smbmsg_t msg);
-int 	smb_addcrc(ulong max_crcs, ulong crc, int retry_time);
-int 	smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data);
-int 	smb_dfield(smbmsg_t *msg, ushort type, ulong length);
-int 	smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
-				,int retry_time);
-int 	smb_putmsg(smbmsg_t msg);
-int 	smb_putmsgidx(smbmsg_t msg);
-int 	smb_putmsghdr(smbmsg_t msg);
-void	smb_freemsgmem(smbmsg_t msg);
-ulong	smb_hdrblocks(ulong length);
-ulong	smb_datblocks(ulong length);
-long	smb_allochdr(ulong length);
-long	smb_fallochdr(ulong length);
-long	smb_hallochdr(ulong header_offset);
-long	smb_allocdat(ulong length, ushort headers);
-long	smb_fallocdat(ulong length, ushort headers);
-long	smb_hallocdat(void);
-int 	smb_incdat(ulong offset, ulong length, ushort headers);
-int 	smb_freemsg(smbmsg_t msg, smbstatus_t status);
-int 	smb_freemsgdat(ulong offset, ulong length, ushort headers);
-int 	smb_freemsghdr(ulong offset, ulong length);
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/smb/121a/smbutil.bor b/src/sbbs2/smb/121a/smbutil.bor
deleted file mode 100644
index eaf0ec330bef3c3cfa5d11176bbd7f4dd6994cfb..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbutil.bor
+++ /dev/null
@@ -1,56 +0,0 @@
-###############################
-# Makefile for SMBUTIL        #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# ATTN: To use this MAKEFILE, you must create a directory "l" off of the
-#       current directory to store the large model .OBJ files
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -N -C -m$(MODEL) -I$(INCLUDE) -DLZH_DYNAMIC_BUF -w-pro
-LFLAGS	= -n -c
-MAIN	= smbutil.exe
-OBJS	= $(MODEL)\smbutil.obj $(MODEL)\smblib.obj $(MODEL)\smbvars.obj \
-          $(MODEL)\lzh.obj
-HEADERS = smbutil.h smblib.h smbdefs.h crc32.h lzh.h
-
-!ifdef __OS2__
-CC      = c:\bcos2\bin\bcc
-LD      = c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;smb
-LIB     = c:\bcos2\lib
-MODEL	= os2
-CFLAGS	= -d -C -I$(INCLUDE)
-#-DLZH_DYNAMIC_BUF
-LFLAGS	= -c -w-srf
-!endif
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(MODEL) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# All .obj modules
-$(MODEL)\smbutil.obj:	$(HEADERS)
-$(MODEL)\smbvars.obj:	$(HEADERS)
-$(MODEL)\smblib.obj:	$(HEADERS)
-$(MODEL)\lzh.obj:	$(HEADERS)
diff --git a/src/sbbs2/smb/121a/smbutil.c b/src/sbbs2/smb/121a/smbutil.c
deleted file mode 100644
index 9ed216a045f92bc53bf64c25e057d724f5ad8ca8..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbutil.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/* SMBUTIL.C */
-
-/* Synchronet Message Base Utility */
-
-#define SMBUTIL_VER "1.24"
-
-#include "smblib.h"
-#include "smbutil.h"
-#include "crc32.h"
-#include "crc16.c"
-
-#ifdef __WATCOMC__
-	#include <dos.h>
-#endif
-
-/********************/
-/* Global variables */
-/********************/
-
-ulong mode=0L;
-ushort tzone=PST;
-char filein[128];
-char attach[128];
-
-/************************/
-/* Program usage/syntax */
-/************************/
-
-char *usage=
-"usage: smbutil [/opts] cmd <filespec.SHD>\n"
-"\n"
-"cmd:\n"
-"       l[n] = list msgs starting at number n\n"
-"       r[n] = read msgs starting at number n\n"
-"       v[n] = view msg headers starting at number n\n"
-"       k[n] = kill (delete) n msgs\n"
-"       i<f> = import from text file f\n"
-"       s    = display msg base status\n"
-"       c    = change msg base status\n"
-"       m    = maintain msg base - delete old msgs and msgs over max\n"
-"       p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
-"opts:\n"
-"       a    = always pack msg base (disable compression analysis)\n"
-"       z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
-;
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-#ifdef __WATCOMC__
-	return(f.size);
-#else
-	return(f.ff_fsize);
-#endif
-return(-1L);
-}
-
-
-/****************************************************************************/
-/* Adds a new message to the message base									*/
-/****************************************************************************/
-void postmsg(smbstatus_t status)
-{
-	char	str[128],buf[SDT_BLOCK_LEN];
-	ushort	xlat;
-	int 	i,j,k,file;
-	long	length;
-	ulong	offset,crc=0xffffffffUL;
-	FILE	*instream;
-	smbmsg_t	msg;
-
-length=flength(filein);
-if(length<1L) {
-	printf("Invalid file size for '%s'\n",filein);
-	exit(1); }
-length+=2;	/* for translation string */
-if(!(status.attr&SMB_HYPERALLOC)) {
-	i=smb_open_da(10);
-	if(i) {
-		printf("smb_open_da returned %d\n",i);
-		exit(1); }
-	offset=smb_allocdat(length,1);
-	fclose(sda_fp); }
-else
-	offset=smb_hallocdat();
-
-if((file=open(filein,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	printf("Error opening %s for read\n",filein);
-	smb_freemsgdat(offset,length,1);
-	exit(1); }
-setvbuf(instream,NULL,_IOFBF,32*1024);
-fseek(sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,sdt_fp);
-k=SDT_BLOCK_LEN-2;
-while(!feof(instream)) {
-	memset(buf,0,k);
-	j=fread(buf,1,k,instream);
-	if(status.max_crcs)
-		for(i=0;i<j;i++)
-			crc=ucrc32(buf[i],crc);
-	fwrite(buf,k,1,sdt_fp);
-	k=SDT_BLOCK_LEN; }
-fflush(sdt_fp);
-fclose(instream);
-crc=~crc;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=SMB_VERSION;
-msg.hdr.when_written.time=time(NULL);
-msg.hdr.when_written.zone=tzone;
-msg.hdr.when_imported=msg.hdr.when_written;
-
-if(status.max_crcs) {
-	i=smb_addcrc(status.max_crcs,crc,10);
-	if(i) {
-		printf("smb_addcrc returned %d\n",i);
-		smb_freemsgdat(offset,length,1);
-		exit(1); } }
-
-msg.hdr.offset=offset;
-
-printf("To User Name: ");
-gets(str);
-i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,1);
-	exit(1); }
-if(status.attr&SMB_EMAIL) {
-	printf("To User Number: ");
-	gets(str);
-	i=smb_hfield(&msg,RECIPIENTEXT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(offset,length,1);
-		exit(1); }
-	msg.idx.to=atoi(str); }
-else {
-	strlwr(str);
-	msg.idx.to=crc16(str); }
-
-printf("From User Name: ");
-gets(str);
-i=smb_hfield(&msg,SENDER,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,1);
-    exit(1); }
-if(status.attr&SMB_EMAIL) {
-	printf("From User Number: ");
-	gets(str);
-	i=smb_hfield(&msg,SENDEREXT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(offset,length,1);
-		exit(1); }
-	msg.idx.from=atoi(str); }
-else {
-	strlwr(str);
-	msg.idx.from=crc16(str); }
-
-printf("Subject: ");
-gets(str);
-i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,1);
-    exit(1); }
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-i=smb_dfield(&msg,TEXT_BODY,length);
-if(i) {
-	printf("smb_dfield returned %d\n",i);
-	smb_freemsgdat(offset,length,1);
-	exit(1); }
-
-i=smb_addmsghdr(&msg,&status,status.attr&SMB_HYPERALLOC,10);
-
-if(i) {
-	printf("smb_addmsghdr returned %d\n",i);
-	smb_freemsgdat(offset,length,1);
-	exit(1); }
-smb_freemsgmem(msg);
-
-}
-
-/****************************************************************************/
-/* Shows the message base header											*/
-/****************************************************************************/
-void showstatus()
-{
-	int i;
-	smbstatus_t status;
-
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&status);
-smb_unlocksmbhdr();
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-printf("last_msg        =%lu\n"
-	   "total_msgs      =%lu\n"
-	   "header_offset   =%lu\n"
-	   "max_crcs        =%lu\n"
-	   "max_msgs        =%lu\n"
-	   "max_age         =%u\n"
-	   "attr            =%04Xh\n"
-	   ,status.last_msg
-	   ,status.total_msgs
-	   ,status.header_offset
-	   ,status.max_crcs
-	   ,status.max_msgs
-	   ,status.max_age
-	   ,status.attr
-	   );
-}
-
-/****************************************************************************/
-/* Configure message base header											*/
-/****************************************************************************/
-void config()
-{
-	char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
-	int i;
-	smbstatus_t status;
-
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&status);
-smb_unlocksmbhdr();
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-printf("Header offset =%-5lu  New value (CR=No Change): ",status.header_offset);
-gets(header_offset);
-printf("Max msgs      =%-5lu  New value (CR=No Change): ",status.max_msgs);
-gets(max_msgs);
-printf("Max crcs      =%-5lu  New value (CR=No Change): ",status.max_crcs);
-gets(max_crcs);
-printf("Max age       =%-5u  New value (CR=No Change): ",status.max_age);
-gets(max_age);
-printf("Attributes    =%-5u  New value (CR=No Change): ",status.attr);
-gets(attr);
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&status);
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	smb_unlocksmbhdr();
-    return; }
-if(isdigit(max_msgs[0]))
-	status.max_msgs=atol(max_msgs);
-if(isdigit(max_crcs[0]))
-	status.max_crcs=atol(max_crcs);
-if(isdigit(max_age[0]))
-	status.max_age=atoi(max_age);
-if(isdigit(header_offset[0]))
-	status.header_offset=atol(header_offset);
-if(isdigit(attr[0]))
-	status.attr=atoi(attr);
-i=smb_putstatus(status);
-smb_unlocksmbhdr();
-if(i)
-	printf("smb_putstatus returned %d\n",i);
-}
-
-/****************************************************************************/
-/* Lists messages' to, from, and subject                                    */
-/****************************************************************************/
-void listmsgs(ulong start, ulong count)
-{
-	int i;
-	ulong l=0;
-	smbmsg_t msg;
-	idxrec_t idxrec;
-
-if(!start)
-	start=1;
-fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
-while(l<count) {
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-		break;
-	i=smb_lockmsghdr(msg,10);
-	if(i) {
-		printf("smb_lockmsghdr returned %d\n",i);
-		break; }
-	i=smb_getmsghdr(&msg);
-	smb_unlockmsghdr(msg);
-	if(i) {
-		printf("smb_getmsghdr returned %d\n",i);
-		break; }
-	printf("%4lu %-25.25s %-25.25s %.20s\n"
-		,msg.hdr.number,msg.from,msg.to,msg.subj);
-	smb_freemsgmem(msg);
-	l++; }
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(fidoaddr_t addr)
-{
-	static char str[25];
-	char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-	sprintf(point,".%u",addr.point);
-	strcat(str,point); }
-return(str);
-}
-
-char *binstr(uchar *buf, ushort length)
-{
-	static char str[128];
-	char tmp[128];
-	int i;
-
-str[0]=0;
-for(i=0;i<length;i++)
-	if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
-		break;
-if(i==length)		/* not binary */
-	return(buf);
-for(i=0;i<length;i++) {
-	sprintf(tmp,"%02X ",buf[i]);
-	strcat(str,tmp); }
-return(str);
-}
-
-/****************************************************************************/
-/* Converts when_t.zone into ASCII format									*/
-/****************************************************************************/
-char *zonestr(short zone)
-{
-	static char str[32];
-
-switch(zone) {
-	case 0: 	return("UT");
-	case AST:	return("AST");
-	case EST:	return("EST");
-	case CST:	return("CST");
-	case MST:	return("MST");
-	case PST:	return("PST");
-	case YST:	return("YST");
-	case HST:	return("HST");
-	case BST:	return("BST");
-	case ADT:	return("ADT");
-	case EDT:	return("EDT");
-	case CDT:	return("CDT");
-	case MDT:	return("MDT");
-	case PDT:	return("PDT");
-	case YDT:	return("YDT");
-	case HDT:	return("HDT");
-	case BDT:	return("BDT");
-	case MID:	return("MID");
-	case VAN:	return("VAN");
-	case EDM:	return("EDM");
-	case WIN:	return("WIN");
-	case BOG:	return("BOG");
-	case CAR:	return("CAR");
-	case RIO:	return("RIO");
-	case FER:	return("FER");
-	case AZO:	return("AZO");
-	case LON:	return("LON");
-	case BER:	return("BER");
-	case ATH:	return("ATH");
-	case MOS:	return("MOS");
-	case DUB:	return("DUB");
-	case KAB:	return("KAB");
-	case KAR:	return("KAR");
-	case BOM:	return("BOM");
-	case KAT:	return("KAT");
-	case DHA:	return("DHA");
-	case BAN:	return("BAN");
-	case HON:	return("HON");
-	case TOK:	return("TOK");
-	case SYD:	return("SYD");
-	case NOU:	return("NOU");
-	case WEL:	return("WEL");
-	}
-
-sprintf(str,"%02d:%02d",zone/60,zone<0 ? (-zone)%60 : zone%60);
-return(str);
-}
-			 
-
-/****************************************************************************/
-/* Displays message header information										*/
-/****************************************************************************/
-void viewmsgs(ulong start, ulong count)
-{
-	char when_written[128]
-		,when_imported[128];
-	int i;
-	ulong l=0;
-	smbmsg_t msg;
-	idxrec_t idxrec;
-
-if(!start)
-	start=1;
-fseek(sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
-while(l<count) {
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-		break;
-	i=smb_lockmsghdr(msg,10);
-	if(i) {
-		printf("smb_lockmsghdr returned %d\n",i);
-		break; }
-	i=smb_getmsghdr(&msg);
-	smb_unlockmsghdr(msg);
-	if(i) {
-		printf("smb_getmsghdr returned %d\n",i);
-		break; }
-
-	sprintf(when_written,"%.24s %s"
-		,ctime((time_t *)&msg.hdr.when_written.time)
-		,zonestr(msg.hdr.when_written.zone));
-	sprintf(when_imported,"%.24s %s"
-		,ctime((time_t *)&msg.hdr.when_imported.time)
-		,zonestr(msg.hdr.when_imported.zone));
-
-	printf( "%-20.20s %s\n"
-			"%-20.20s %s\n"
-            "%-20.20s %s\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %u\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %08lXh\n"
-			"%-20.20s %08lXh\n"
-			"%-20.20s %s\n"
-			"%-20.20s %s\n"
-			"%-20.20s %ld (%ld)\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %s\n"
-			"%-20.20s %06lXh\n"
-			"%-20.20s %u\n",
-
-		"subj",
-		msg.subj,
-
-		"from",
-		msg.from,
-
-		"to",
-		msg.to,
-
-		"type",
-		msg.hdr.type,
-
-		"version",
-		msg.hdr.version,
-
-		"length",
-		msg.hdr.length,
-
-		"attr",
-		msg.hdr.attr,
-
-		"auxattr",
-		msg.hdr.auxattr,
-
-		"netattr",
-		msg.hdr.netattr,
-
-		"when_written",
-		when_written,
-
-		"when_imported",
-		when_imported,
-
-		"number",
-		msg.hdr.number,
-		ftell(sid_fp)/sizeof(idxrec_t),
-
-		"thread_orig",
-		msg.hdr.thread_orig,
-
-		"thread_next",
-		msg.hdr.thread_next,
-
-		"thread_first",
-		msg.hdr.thread_first,
-
-		"reserved[16]",
-		binstr(msg.hdr.reserved,16),
-
-		"offset",
-		msg.hdr.offset,
-
-		"total_dfields",
-		msg.hdr.total_dfields
-		);
-	for(i=0;i<msg.hdr.total_dfields;i++)
-		printf("dfield[%02u].type      %02Xh\n"
-			   "dfield[%02u].offset    %lu\n"
-			   "dfield[%02u].length    %lu\n"
-			   ,i,msg.dfield[i].type
-			   ,i,msg.dfield[i].offset
-			   ,i,msg.dfield[i].length);
-
-	for(i=0;i<msg.total_hfields;i++)
-		printf("hfield[%02u].type      %02Xh\n"
-			   "hfield[%02u].length    %d\n"
-			   "hfield[%02u]_dat       %s\n"
-			   ,i,msg.hfield[i].type
-			   ,i,msg.hfield[i].length
-			   ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
-
-	if(msg.from_net.type)
-		printf("from_net.type        %02Xh\n"
-			   "from_net.addr        %s\n"
-            ,msg.from_net.type
-            ,msg.from_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
-
-	if(msg.to_net.type)
-		printf("to_net.type          %02Xh\n"
-			   "to_net.addr          %s\n"
-			,msg.to_net.type
-			,msg.to_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-
-	if(msg.replyto_net.type)
-		printf("replyto_net.type     %02Xh\n"
-			   "replyto_net.addr     %s\n"
-			,msg.replyto_net.type
-			,msg.replyto_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
-				: msg.replyto_net.addr);
-
-	printf("from_agent           %02Xh\n"
-		   "to_agent             %02Xh\n"
-		   "replyto_agent        %02Xh\n"
-		   ,msg.from_agent
-		   ,msg.to_agent
-		   ,msg.replyto_agent);
-
-	printf("\n");
-	smb_freemsgmem(msg);
-	l++; }
-}
-
-/****************************************************************************/
-/* Maintain message base - deletes messages older than max age (in days)	*/
-/* or messages that exceed maximum											*/
-/****************************************************************************/
-void maint(void)
-{
-	int i;
-	ulong l,m,n,f,flagged=0;
-	time_t now;
-	smbstatus_t status;
-	smbmsg_t msg;
-	idxrec_t HUGE16 *idx;
-
-printf("Maintaining %s\r\n",smb_file);
-now=time(NULL);
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&status);
-if(i) {
-	smb_unlocksmbhdr();
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-if(!status.total_msgs) {
-	smb_unlocksmbhdr();
-	printf("Empty\n");
-	return; }
-printf("Loading index...\n");
-if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*status.total_msgs))
-	==NULL) {
-	smb_unlocksmbhdr();
-	printf("can't allocate %lu bytes of memory\n"
-		,sizeof(idxrec_t)*status.total_msgs);
-	return; }
-fseek(sid_fp,0L,SEEK_SET);
-for(l=0;l<status.total_msgs;l++) {
-	printf("%lu of %lu\r"
-		,l+1,status.total_msgs);
-	if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
-		break; }
-printf("\nDone.\n\n");
-
-printf("Scanning for pre-flagged messages...\n");
-for(m=0;m<l;m++) {
-	printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-	if(idx[m].attr&MSG_DELETE)
-		flagged++; }
-printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);
-
-if(status.max_age) {
-	printf("Scanning for messages more than %u days old...\n"
-		,status.max_age);
-	for(m=f=0;m<l;m++) {
-		printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-		if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-			continue;
-		if(now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)>status.max_age) {
-			f++;
-			flagged++;
-			idx[m].attr|=MSG_DELETE; } }  /* mark for deletion */
-	printf("\r100%% (%lu flagged for deletion)\n",f); }
-
-printf("Scanning for read messages to be killed...\n");
-for(m=f=0;m<l;m++) {
-	printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-	if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-		continue;
-	if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
-		f++;
-		flagged++;
-		idx[m].attr|=MSG_DELETE; } }
-printf("\r100%% (%lu flagged for deletion)\n",f);
-
-if(l-flagged>status.max_msgs) {
-	printf("Flagging excess messages for deletion...\n");
-	for(m=n=0,f=flagged;l-flagged>status.max_msgs && m<l;m++) {
-		if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-			continue;
-		printf("%lu of %lu\r",++n,(l-f)-status.max_msgs);
-		flagged++;
-		idx[m].attr|=MSG_DELETE; }			/* mark for deletion */
-	printf("\nDone.\n\n"); }
-
-if(!flagged) {				/* No messages to delete */
-	LFREE(idx);
-	smb_unlocksmbhdr();
-	return; }
-
-if(!(mode&NOANALYSIS)) {
-
-	printf("Freeing allocated header and data blocks for deleted messages...\n");
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		i=smb_open_da(10);
-		if(i) {
-			smb_unlocksmbhdr();
-			printf("smb_open_da returned %d\n",i);
-			exit(1); }
-		i=smb_open_ha(10);
-		if(i) {
-			smb_unlocksmbhdr();
-			printf("smb_open_ha returned %d\n",i);
-			exit(1); } }
-
-	for(m=n=0;m<l;m++) {
-		if(idx[m].attr&MSG_DELETE) {
-			printf("%lu of %lu\r",++n,flagged);
-			msg.idx=idx[m];
-			msg.hdr.number=msg.idx.number;
-			if((i=smb_getmsgidx(&msg))!=0) {
-				printf("\nsmb_getmsgidx returned %d\n",i);
-				continue; }
-			i=smb_lockmsghdr(msg,10);
-			if(i) {
-				printf("\nsmb_lockmsghdr returned %d\n",i);
-				break; }
-			if((i=smb_getmsghdr(&msg))!=0) {
-				smb_unlockmsghdr(msg);
-				printf("\nsmb_getmsghdr returned %d\n",i);
-				break; }
-			msg.hdr.attr|=MSG_DELETE;			/* mark header as deleted */
-			if((i=smb_putmsg(msg))!=0) {
-				smb_freemsgmem(msg);
-				smb_unlockmsghdr(msg);
-				printf("\nsmb_putmsg returned %d\n",i);
-				break; }
-			smb_unlockmsghdr(msg);
-			if((i=smb_freemsg(msg,status))!=0) {
-				smb_freemsgmem(msg);
-				printf("\nsmb_freemsg returned %d\n",i);
-				break; }
-			smb_freemsgmem(msg); } }
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		fclose(sha_fp);
-		fclose(sda_fp); }
-	printf("\nDone.\n\n"); }
-
-printf("Re-writing index...\n");
-rewind(sid_fp);
-if(chsize(fileno(sid_fp),0L))
-	printf("chsize failed!\n");
-for(m=n=0;m<l;m++) {
-	if(idx[m].attr&MSG_DELETE)
-		continue;
-	printf("%lu of %lu\r",++n,l-flagged);
-	fwrite(&idx[m],sizeof(idxrec_t),1,sid_fp); }
-printf("\nDone.\n\n");
-fflush(sid_fp);
-
-LFREE(idx);
-status.total_msgs-=flagged;
-smb_putstatus(status);
-smb_unlocksmbhdr();
-}
-
-/****************************************************************************/
-/* Kills 'msgs' number of messags                                           */
-/* Returns actual number of messages killed.								*/
-/****************************************************************************/
-ulong kill(ulong msgs)
-{
-    int i;
-	ulong l,m,n,flagged=0;
-	smbstatus_t status;
-	smbmsg_t msg;
-	idxrec_t *idx;
-
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return(0); }
-i=smb_getstatus(&status);
-if(i) {
-	smb_unlocksmbhdr();
-	printf("smb_getstatus returned %d\n",i);
-	return(0); }
-printf("Loading index...\n");
-if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*status.total_msgs))
-	==NULL) {
-	smb_unlocksmbhdr();
-	printf("can't allocate %lu bytes of memory\n"
-		,sizeof(idxrec_t)*status.total_msgs);
-	return(0); }
-fseek(sid_fp,0L,SEEK_SET);
-for(l=0;l<status.total_msgs;l++) {
-	printf("%lu of %lu\r"
-		,l+1,status.total_msgs);
-	if(!fread(&idx[l],1,sizeof(idxrec_t),sid_fp))
-		break; }
-printf("\nDone.\n\n");
-
-printf("Flagging messages for deletion...\n");
-for(m=0;m<l && flagged<msgs;m++) {
-	if(idx[m].attr&(MSG_PERMANENT))
-		continue;
-	printf("%lu of %lu\r",++flagged,msgs);
-	idx[m].attr|=MSG_DELETE; }			/* mark for deletion */
-printf("\nDone.\n\n");
-
-printf("Freeing allocated header and data blocks for deleted messages...\n");
-if(!(status.attr&SMB_HYPERALLOC)) {
-	i=smb_open_da(10);
-	if(i) {
-		smb_unlocksmbhdr();
-		printf("smb_open_da returned %d\n",i);
-		exit(1); }
-	i=smb_open_ha(10);
-	if(i) {
-		smb_unlocksmbhdr();
-		printf("smb_open_ha returned %d\n",i);
-		exit(1); } }
-
-for(m=n=0;m<l;m++) {
-	if(idx[m].attr&MSG_DELETE) {
-		printf("%lu of %lu\r",++n,flagged);
-		msg.idx=idx[m];
-		i=smb_lockmsghdr(msg,10);
-		if(i) {
-			printf("\nsmb_lockmsghdr returned %d\n",i);
-			break; }
-		msg.hdr.number=msg.idx.number;
-		if((i=smb_getmsgidx(&msg))!=0) {
-			smb_unlockmsghdr(msg);
-			printf("\nsmb_getmsgidx returned %d\n",i);
-            break; }
-		if((i=smb_getmsghdr(&msg))!=0) {
-			smb_unlockmsghdr(msg);
-			printf("\nsmb_getmsghdr returned %d\n",i);
-			break; }
-		msg.hdr.attr|=MSG_DELETE;			/* mark header as deleted */
-		if((i=smb_putmsg(msg))!=0) {
-			smb_unlockmsghdr(msg);
-			printf("\nsmb_putmsg returned %d\n",i);
-            break; }
-		smb_unlockmsghdr(msg);
-		smb_freemsg(msg,status);
-		smb_freemsgmem(msg); } }
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	fclose(sha_fp);
-	fclose(sda_fp); }
-
-printf("\nDone.\n\n");
-
-printf("Re-writing index...\n");
-rewind(sid_fp);
-chsize(fileno(sid_fp),0L);
-for(m=n=0;m<l;m++) {
-    if(idx[m].attr&MSG_DELETE)
-        continue;
-    printf("%lu of %lu\r",++n,l-flagged);
-    fwrite(&idx[m],1,sizeof(idxrec_t),sid_fp); }
-printf("\nDone.\n\n");
-
-fflush(sid_fp);
-
-LFREE(idx);
-status.total_msgs-=flagged;
-smb_putstatus(status);
-smb_unlocksmbhdr();
-return(flagged);
-}
-
-typedef struct {
-	ulong old,new;
-	} datoffset_t;
-
-/****************************************************************************/
-/* Removes all unused blocks from SDT and SHD files 						*/
-/****************************************************************************/
-void packmsgs(ulong packable)
-{
-	uchar buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
-	int i,file,size;
-	ulong l,m,n,datoffsets=0,length,total;
-	FILE *tmp_sdt,*tmp_shd,*tmp_sid;
-	smbhdr_t	hdr;
-	smbstatus_t status;
-	smbmsg_t	msg;
-	datoffset_t *datoffset=NULL;
-
-printf("Packing %s\n",smb_file);
-i=smb_locksmbhdr(10);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&status);
-if(i) {
-	smb_unlocksmbhdr();
-	printf("smb_getstatus returned %d\n",i);
-    return; }
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	i=smb_open_ha(10);
-	if(i) {
-		smb_unlocksmbhdr();
-		printf("smb_open_ha returned %d\n",i);
-		return; }
-	i=smb_open_da(10);
-	if(i) {
-		smb_unlocksmbhdr();
-		fclose(sha_fp);
-		printf("smb_open_da returned %d\n",i);
-		return; } }
-
-if(!status.total_msgs) {
-    printf("Empty\n");
-	rewind(shd_fp);
-    chsize(fileno(shd_fp),status.header_offset);
-	rewind(sdt_fp);
-    chsize(fileno(sdt_fp),0L);
-	rewind(sid_fp);
-    chsize(fileno(sid_fp),0L);
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		rewind(sha_fp);
-		chsize(fileno(sha_fp),0L);
-		rewind(sda_fp);
-		chsize(fileno(sda_fp),0L);
-		fclose(sha_fp);
-		fclose(sda_fp); }
-    smb_unlocksmbhdr();
-    return; }
-
-
-if(!(status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
-    printf("Analyzing data blocks...\n");
-
-    length=filelength(fileno(sda_fp));
-
-    fseek(sda_fp,0L,SEEK_SET);
-    for(l=m=0;l<length;l+=2) {
-        printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-        i=0;
-        if(!fread(&i,2,1,sda_fp))
-            break;
-        if(!i)
-            m++; }
-
-    printf("\rAnalyzing header blocks...\n");
-
-    length=filelength(fileno(sha_fp));
-
-    fseek(sha_fp,0L,SEEK_SET);
-    for(l=n=0;l<length;l++) {
-        printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-		ch=0;
-		if(!fread(&ch,1,1,sha_fp))
-            break;
-		if(!ch)
-            n++; }
-
-    if(!m && !n) {
-		printf("\rAlready compressed.\n\n");
-        fclose(sha_fp);
-        fclose(sda_fp);
-        smb_unlocksmbhdr();
-        return; }
-
-	if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
-		printf("\rLess than %luk compressable bytes.\n\n",packable);
-		fclose(sha_fp);
-		fclose(sda_fp);
-		smb_unlocksmbhdr();
-		return; }
-
-	printf("\rCompressing %lu data blocks (%lu bytes)\n"
-			 "        and %lu header blocks (%lu bytes)\n"
-			  ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	rewind(sha_fp);
-	chsize(fileno(sha_fp),0L);		/* Reset both allocation tables */
-	rewind(sda_fp);
-	chsize(fileno(sda_fp),0L); }
-
-if(status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
-	printf("Analyzing %s\n",smb_file);
-
-	length=filelength(fileno(shd_fp));
-	m=n=0;
-	for(l=status.header_offset;l<length;l+=size) {
-		printf("\r%2u%%  ",(long)(100.0/((float)length/l)));
-		msg.idx.offset=l;
-		if((i=smb_lockmsghdr(msg,10))!=0) {
-			printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-			size=SHD_BLOCK_LEN;
-			continue; }
-		if((i=smb_getmsghdr(&msg))!=0) {
-			smb_unlockmsghdr(msg);
-			m++;
-			size=SHD_BLOCK_LEN;
-			continue; }
-		smb_unlockmsghdr(msg);
-		if(msg.hdr.attr&MSG_DELETE) {
-			m+=smb_hdrblocks(msg.hdr.length);
-			total=0;
-			for(i=0;i<msg.hdr.total_dfields;i++)
-				total+=msg.dfield[i].length;
-			n+=smb_datblocks(total); }
-		size=smb_getmsghdrlen(msg);
-		if(size<1) size=SHD_BLOCK_LEN;
-		while(size%SHD_BLOCK_LEN)
-			size++;
-		smb_freemsgmem(msg); }
-
-
-    if(!m && !n) {
-		printf("\rAlready compressed.\n\n");
-        smb_unlocksmbhdr();
-        return; }
-
-	if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
-		printf("\rLess than %luk compressable bytes.\n\n",packable);
-		smb_unlocksmbhdr();
-		return; }
-
-	printf("\rCompressing %lu data blocks (%lu bytes)\n"
-			 "        and %lu header blocks (%lu bytes)\n"
-			  ,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN); }
-
-sprintf(fname,"%s.SD$",smb_file);
-tmp_sdt=fopen(fname,"wb");
-sprintf(fname,"%s.SH$",smb_file);
-tmp_shd=fopen(fname,"wb");
-sprintf(fname,"%s.SI$",smb_file);
-tmp_sid=fopen(fname,"wb");
-if(!tmp_sdt || !tmp_shd || !tmp_sid) {
-	smb_unlocksmbhdr();
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		fclose(sha_fp);
-		fclose(sda_fp); }
-	printf("error opening temp file\n");
-	return; }
-setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
-setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
-setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
-if(!(status.attr&SMB_HYPERALLOC)
-	&& (datoffset=(datoffset_t *)LMALLOC(sizeof(datoffset_t)*status.total_msgs))
-	==NULL) {
-	smb_unlocksmbhdr();
-	fclose(sha_fp);
-	fclose(sda_fp);
-	fclose(tmp_sdt);
-	fclose(tmp_shd);
-	fclose(tmp_sid);
-	printf("error allocating mem\n");
-    return; }
-fseek(shd_fp,0L,SEEK_SET);
-fread(&hdr,1,sizeof(smbhdr_t),shd_fp);
-fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
-fwrite(&status,1,sizeof(smbstatus_t),tmp_shd);
-for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<status.header_offset;l++) {
-	fread(&ch,1,1,shd_fp);			/* copy additional base header records */
-	fwrite(&ch,1,1,tmp_shd); }
-fseek(sid_fp,0L,SEEK_SET);
-total=0;
-for(l=0;l<status.total_msgs;l++) {
-	printf("%lu of %lu\r",l+1,status.total_msgs);
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-		break;
-	if(msg.idx.attr&MSG_DELETE) {
-		printf("\nDeleted index.\n");
-		continue; }
-	i=smb_lockmsghdr(msg,10);
-	if(i) {
-		printf("\nsmb_lockmsghdr returned %d\n",i);
-		continue; }
-	i=smb_getmsghdr(&msg);
-	smb_unlockmsghdr(msg);
-	if(i) {
-		printf("\nsmb_getmsghdr returned %d\n",i);
-		continue; }
-	if(msg.hdr.attr&MSG_DELETE) {
-		printf("\nDeleted header.\n");
-		smb_freemsgmem(msg);
-		continue; }
-	for(m=0;m<datoffsets;m++)
-		if(msg.hdr.offset==datoffset[m].old)
-			break;
-	if(m<datoffsets) {				/* another index pointed to this data */
-		printf("duplicate index\n");
-		msg.hdr.offset=datoffset[m].new;
-		smb_incdat(datoffset[m].new,smb_getmsgdatlen(msg),1); }
-	else {
-
-		if(!(status.attr&SMB_HYPERALLOC))
-			datoffset[datoffsets].old=msg.hdr.offset;
-
-		fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
-
-		m=smb_getmsgdatlen(msg);
-        if(m>16L*1024L*1024L) {
-            printf("\nInvalid data length (%lu)\n",m);
-            continue; }
-
-		if(!(status.attr&SMB_HYPERALLOC)) {
-			datoffset[datoffsets].new=msg.hdr.offset
-				=smb_fallocdat(m,1);
-			datoffsets++;
-			fseek(tmp_sdt,msg.hdr.offset,SEEK_SET); }
-		else {
-			fseek(tmp_sdt,0L,SEEK_END);
-			msg.hdr.offset=ftell(tmp_sdt); }
-
-		/* Actually copy the data */
-
-		n=smb_datblocks(m);
-		for(m=0;m<n;m++) {
-			fread(buf,1,SDT_BLOCK_LEN,sdt_fp);
-			if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
-				printf("\nUnsupported translation type (%04X)\n"
-					,*(ushort *)buf);
-				break; }
-			fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); }
-		if(m<n)
-			continue; }
-
-	/* Write the new index entry */
-	length=smb_getmsghdrlen(msg);
-	if(status.attr&SMB_HYPERALLOC)
-		msg.idx.offset=ftell(tmp_shd);
-	else
-		msg.idx.offset=smb_fallochdr(length)+status.header_offset;
-	fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
-
-	/* Write the new header entry */
-	fseek(tmp_shd,msg.idx.offset,SEEK_SET);
-	fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
-	for(n=0;n<msg.hdr.total_dfields;n++)
-		fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
-	for(n=0;n<msg.total_hfields;n++) {
-		fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
-		fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
-	while(length%SHD_BLOCK_LEN) {	/* pad with NULLs */
-		fputc(0,tmp_shd);
-		length++; }
-	total++;
-	smb_freemsgmem(msg); }
-
-if(datoffset)
-	LFREE(datoffset);
-if(!(status.attr&SMB_HYPERALLOC)) {
-	fclose(sha_fp);
-	fclose(sda_fp); }
-
-/* Change *.SH$ into *.SHD */
-fclose(shd_fp);
-fclose(tmp_shd);
-sprintf(fname,"%s.SHD",smb_file);
-remove(fname);
-sprintf(tmpfname,"%s.SH$",smb_file);
-rename(tmpfname,fname);
-
-/* Change *.SD$ into *.SDT */
-fclose(sdt_fp);
-fclose(tmp_sdt);
-sprintf(fname,"%s.SDT",smb_file);
-remove(fname);
-sprintf(tmpfname,"%s.SD$",smb_file);
-rename(tmpfname,fname);
-
-/* Change *.SI$ into *.SID */
-fclose(sid_fp);
-fclose(tmp_sid);
-sprintf(fname,"%s.SID",smb_file);
-remove(fname);
-sprintf(tmpfname,"%s.SI$",smb_file);
-rename(tmpfname,fname);
-
-if((i=smb_open(10))!=0) {
-	printf("Error %d reopening %s\n",i,smb_file);
-	return; }
-
-status.total_msgs=total;
-if((i=smb_putstatus(status))!=0)
-	printf("\nsmb_putstatus returned %d\n",i);
-printf("\nDone.\n\n");
-}
-
-
-/****************************************************************************/
-/* Read messages in message base											*/
-/****************************************************************************/
-void readmsgs(ulong start)
-{
-	char	str[128],*inbuf,*outbuf;
-	int 	i,ch,done=0,domsg=1,lzh;
-	ushort	xlat;
-	ulong	l,count,outlen;
-	smbmsg_t msg;
-
-if(start)
-	msg.offset=start-1;
-else
-	msg.offset=0;
-while(!done) {
-	if(domsg) {
-		fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-		if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-			break;
-		i=smb_lockmsghdr(msg,10);
-		if(i) {
-			printf("smb_lockmsghdr returned %d\n",i);
-			break; }
-		i=smb_getmsghdr(&msg);
-		if(i) {
-			printf("smb_getmsghdr returned %d\n",i);
-			break; }
-
-		printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
-		printf("Subj : %s\n",msg.subj);
-		printf("To   : %s",msg.to);
-		if(msg.to_net.type)
-			printf(" (%s)",msg.to_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-		printf("\nFrom : %s",msg.from);
-		if(msg.from_net.type)
-			printf(" (%s)",msg.from_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
-					: msg.from_net.addr);
-		printf("\nDate : %.24s %s",ctime((time_t *)&msg.hdr.when_written.time)
-			,zonestr(msg.hdr.when_written.zone));
-		printf("\n\n");
-		for(i=0;i<msg.hdr.total_dfields;i++)
-			switch(msg.dfield[i].type) {
-				case TEXT_BODY:
-				case TEXT_TAIL:
-					fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-						,SEEK_SET);
-					fread(&xlat,2,1,sdt_fp);
-					l=2;
-					lzh=0;
-					while(xlat!=XLAT_NONE) {
-						if(xlat==XLAT_LZH)
-							lzh=1;
-						fread(&xlat,2,1,sdt_fp);
-						l+=2; }
-					if(lzh) {
-						if((inbuf=(char *)LMALLOC(msg.dfield[i].length))
-							==NULL) {
-							printf("Malloc error of %lu\n"
-								,msg.dfield[i].length);
-							exit(1); }
-						fread(inbuf,msg.dfield[i].length-l,1,sdt_fp);
-						outlen=*(long *)inbuf;
-						if((outbuf=(char *)LMALLOC(outlen))==NULL) {
-							printf("Malloc error of lzh %lu\n"
-								,outlen);
-							exit(1); }
-						lzh_decode(inbuf,msg.dfield[i].length-l,outbuf);
-						LFREE(inbuf);
-						for(l=0;l<outlen;l++)
-							putchar(outbuf[l]);
-						LFREE(outbuf); }
-					else {
-						for(;l<msg.dfield[i].length;l++) {
-							ch=fgetc(sdt_fp);
-							if(ch)
-								putchar(ch); } }
-					printf("\n");
-					break; }
-		i=smb_unlockmsghdr(msg);
-        if(i) {
-			printf("smb_unlockmsghdr returned %d\n",i);
-			break; }
-		smb_freemsgmem(msg); }
-	domsg=1;
-	printf("\nReading %s (?=Menu): ",smb_file);
-	switch(toupper(getch())) {
-		case '?':
-			printf("\n"
-				   "\n"
-				   "(R)e-read current message\n"
-				   "(L)ist messages\n"
-				   "(T)en more titles\n"
-				   "(V)iew message headers\n"
-				   "(Q)uit\n"
-				   "(+/-) Forward/Backward\n"
-				   "\n");
-			domsg=0;
-			break;
-		case 'Q':
-			printf("Quit\n");
-			done=1;
-			break;
-		case 'R':
-			printf("Re-read\n");
-			break;
-		case '-':
-			printf("Backwards\n");
-			if(msg.offset)
-				msg.offset--;
-			break;
-		case 'T':
-			printf("Ten titles\n");
-			listmsgs(msg.offset+2,10);
-			msg.offset+=10;
-			domsg=0;
-			break;
-		case 'L':
-			printf("List messages\n");
-			listmsgs(1,-1);
-			domsg=0;
-			break;
-		case 'V':
-			printf("View message headers\n");
-			viewmsgs(1,-1);
-			domsg=0;
-			break;
-		case CR:
-		case '+':
-			printf("Next\n");
-			msg.offset++;
-			break; } }
-}
-
-/***************/
-/* Entry point */
-/***************/
-int main(int argc, char **argv)
-{
-	char cmd[128]="",*p,*s;
-	int i,j,x,y;
-	ulong l;
-	smbstatus_t status;
-
-#ifdef __TURBOC__
-	timezone=0; 		/* Fix for Borland C++ EST default */
-	daylight=0; 		/* Fix for Borland C++ EDT default */
-#elif defined(__WATCOMC__)
-	putenv("TZ=UCT0");  /* Fix for Watcom C++ EDT default */
-#endif
-setvbuf(stdout,0,_IONBF,0);
-
-smb_file[0]=0;
-printf("\nSynchronet Message Base Utility v%s  "\
-	"Copyright 1995 Digital Dynamics\n\n"
-	,SMBUTIL_VER);
-for(x=1;x<argc;x++) {
-	if(argv[x][0]=='/') {
-		for(j=1;argv[x][j];j++)
-			switch(toupper(argv[x][j])) {
-				case 'A':
-					mode|=NOANALYSIS;
-					break;
-				case 'Z':
-					if(isdigit(argv[x][j+1]))
-						tzone=atoi(argv[x]+j+1);
-					else if(!stricmp(argv[x]+j+1,"EST"))
-						tzone=EST;
-					else if(!stricmp(argv[x]+j+1,"EDT"))
-						tzone=EDT;
-					else if(!stricmp(argv[x]+j+1,"CST"))
-						tzone=CST;
-					else if(!stricmp(argv[x]+j+1,"CDT"))
-						tzone=CDT;
-					else if(!stricmp(argv[x]+j+1,"MST"))
-						tzone=MST;
-					else if(!stricmp(argv[x]+j+1,"MDT"))
-						tzone=MDT;
-					else if(!stricmp(argv[x]+j+1,"PST"))
-						tzone=PST;
-					else if(!stricmp(argv[x]+j+1,"PDT"))
-						tzone=PDT;
-					j=strlen(argv[x])-1;
-					break;
-				default:
-					printf("\nUnknown opt '%c'\n",argv[x][j]);
-				case '?':
-					printf("%s",usage);
-					exit(1);
-					break; } }
-	else {
-		if(!cmd[0])
-			strcpy(cmd,argv[x]);
-		else {
-			sprintf(smb_file,"%.64s",argv[x]);
-			p=strrchr(smb_file,'.');
-			s=strrchr(smb_file,'\\');
-			if(p>s) *p=0;
-			strupr(smb_file);
-			printf("Opening %s\r\n",smb_file);
-			if((i=smb_open(10))!=0) {
-				printf("error %d opening %s message base\n",i,smb_file);
-				exit(1); }
-			if(!filelength(fileno(shd_fp))) {
-				printf("Empty\n");
-				smb_close();
-				continue; }
-			for(y=0;cmd[y];y++)
-				switch(toupper(cmd[y])) {
-					case 'I':
-						strcpy(filein,cmd+1);
-						i=smb_locksmbhdr(10);
-						if(i) {
-							printf("smb_locksmbhdr returned %d\n",i);
-							return(1); }
-						i=smb_getstatus(&status);
-						if(i) {
-							printf("smb_getstatus returned %d\n",i);
-							return(1); }
-							smb_unlocksmbhdr();
-						postmsg(status);
-						y=strlen(cmd)-1;
-						break;
-					case 'K':
-						printf("Killing %lu messages...\n",atol(cmd+1));
-						l=kill(atol(cmd+1));
-						printf("%lu messages killed.\n",l);
-						y=strlen(cmd)-1;
-						break;
-					case 'S':
-						showstatus();
-						break;
-					case 'C':
-						config();
-						break;
-					case 'L':
-						listmsgs(atol(cmd+1),-1L);
-						y=strlen(cmd)-1;
-						break;
-					case 'P':
-						packmsgs(atol(cmd+y+1));
-						y=strlen(cmd)-1;
-						break;
-					case 'R':
-						readmsgs(atol(cmd+1));
-						y=strlen(cmd)-1;
-						break;
-					case 'V':
-						viewmsgs(atol(cmd+1),-1L);
-						y=strlen(cmd)-1;
-						break;
-					case 'M':
-						maint();
-						break;
-					default:
-						printf("%s",usage);
-						break; }
-			smb_close(); } } }
-if(!cmd[0])
-	printf("%s",usage);
-return(0);
-}
diff --git a/src/sbbs2/smb/121a/smbutil.h b/src/sbbs2/smb/121a/smbutil.h
deleted file mode 100644
index 1c8284fec124d28454ab5206a5019ffbbed159b4..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbutil.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SMBUTIL.H */
-
-#define NOANALYSIS		(1L<<0)
-
-#ifdef __WATCOMC__
-	#define ffblk find_t
-    #define findfirst(x,y,z) _dos_findfirst(x,z,y)
-	#define findnext(x) _dos_findnext(x)
-#endif
-
diff --git a/src/sbbs2/smb/121a/smbutil.wat b/src/sbbs2/smb/121a/smbutil.wat
deleted file mode 100644
index a5a588c6279228bee2059a6db59697ab7f34ab7c..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbutil.wat
+++ /dev/null
@@ -1,60 +0,0 @@
-#########################################################################
-# Makefile for SMBUTIL							#
-# For use with Watcom C       						#
-# Tabstop=8                                                             #
-#									#
-# To use this makefile, you must create the following sub-directories:	#
-# DOS, OS2, and DOSX.							#
-#									#
-# You must also copy the file \WATCOM\SRC\STARTUP\WILDARGV.C into the	#
-# current directory.							#
-#########################################################################
-
-# Macros
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc -ml
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-CFLAGS	= -I=\watcom\h -bt=$(OS) -fo=$(OS)\ -DLZH_DYNAMIC_BUF
-MAIN	= $(OS)\smbutil.exe
-OBJS	= $(OS)\smbutil.obj $(OS)\smblib.obj $(OS)\smbvars.obj $(OS)\lzh.obj &
-          $(OS)\wildargv.obj
-HEADERS = smbutil.h smblib.h smbdefs.h crc32.h lzh.h
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-
-LFLAGS	= system $(SYSTEM)
-
-
-# Implicit C Compile Rule
-.obj: $(OS)
-.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# All .obj modules
-$(OS)\smbutil.obj::   $(HEADERS)
-$(OS)\smbvars.obj::   $(HEADERS)
-$(OS)\smblib.obj::    $(HEADERS)
-$(OS)\lzh.obj::       $(HEADERS)
diff --git a/src/sbbs2/smb/121a/smbvars.c b/src/sbbs2/smb/121a/smbvars.c
deleted file mode 100644
index 9b80d699e636c3dcc01d5f15c464c5b544bcf47a..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/121a/smbvars.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SMBVARS.C */
-
-/*************************************************************************/
-/* Global variables for SMBLIB. Same file used for both header and code. */
-/*************************************************************************/
-
-#ifndef GLOBAL
-#define GLOBAL
-#endif
-
-#include "smbdefs.h"
-#include <stdio.h>
-
-GLOBAL char 	smb_file[128];	/* path and filename for SMB file (no ext) */
-GLOBAL char 	shd_buf[SHD_BLOCK_LEN];
-GLOBAL FILE 	*sdt_fp;
-GLOBAL FILE 	*shd_fp;
-GLOBAL FILE 	*sid_fp;
-GLOBAL FILE 	*sda_fp;
-GLOBAL FILE 	*sha_fp;
-GLOBAL FILE 	*sch_fp;
-
diff --git a/src/sbbs2/smb/chksmb/chksmb.c b/src/sbbs2/smb/chksmb/chksmb.c
deleted file mode 100644
index 9c8a5a86f929df9a2b786ee9b856739f07cf31c9..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/chksmb/chksmb.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/* CHKSMB.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <dos.h>
-#include "smblib.h"
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct find_t f;
-
-if(!_dos_findfirst(filespec,0,&f))
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns in 'string' a character representation of the number in l with   */
-/* commas.																	*/
-/****************************************************************************/
-char *ultoac(ulong l, char *string)
-{
-	char str[256];
-	signed char i,j,k;
-
-ultoa(l,str,10);
-i=strlen(str)-1;
-j=i/3+1+i;
-string[j--]=0;
-for(k=1;i>-1;k++) {
-	string[j--]=str[i--];
-	if(j>0 && !(k%3))
-		string[j--]=','; }
-return(string);
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(fidoaddr_t addr)
-{
-	static char str[25];
-	char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-	sprintf(point,".%u",addr.point);
-	strcat(str,point); }
-return(str);
-}
-
-char *usage="\nusage: chksmb [/opts] <filespec.SHD>\n"
-			"\n"
-			" opts:\n"
-			"       s - stop after errored message base\n"
-			"       p - pause after errored messsage base\n"
-			"       q - quiet mode (no beeps while checking)\n"
-			"       a - don't check allocation files\n"
-			"       t - don't check translation strings\n"
-			"       e - display extended info on corrupted msgs\n";
-
-int main(int argc, char **argv)
-{
-	char		str[128],*p,*s,*beep="\7";
-	int 		i,j,x,y,lzh,errors,errlast,stop_on_error=0,pause_on_error=0
-				,chkxlat=1,chkalloc=1,lzhmsg,extinfo=0,msgerr;
-	ushort		xlat;
-	ulong		l,m,n,length,size,total=0,orphan=0,deleted=0,headers=0
-				,*offset,*number,xlaterr
-				,delhdrblocks,deldatblocks,hdrerr=0,lockerr=0,hdrnumerr=0
-				,acthdrblocks,actdatblocks
-				,dfieldlength=0,dfieldoffset=0
-				,dupenum=0,dupenumhdr=0,dupeoff=0,attr=0,actalloc=0
-				,datactalloc=0,misnumbered=0,timeerr=0,idxofferr=0,idxerr
-				,zeronum,idxzeronum,idxnumerr,packable=0L,totallzhsaved=0L
-				,totalmsgs=0,totallzhmsgs=0,totaldelmsgs=0,totalmsgbytes=0L
-				,lzhblocks,lzhsaved;
-	smb_t		smb;
-	idxrec_t	idx;
-	smbmsg_t	msg;
-
-fprintf(stderr,"\nCHKSMB v2.00� � Check Synchronet Message Base � "
-	"Devloped 1995-1997 Rob Swindell\n");
-
-if(argc<2) {
-	printf("%s",usage);
-	exit(1); }
-
-errlast=errors=0;
-for(x=1;x<argc;x++) {
-	if(stop_on_error && errors)
-		break;
-	if(pause_on_error && errlast!=errors) {
-		fprintf(stderr,"\7\nHit any key to continue...");
-        if(!getch())
-            getch();
-        printf("\n"); }
-	errlast=errors;
-	if(argv[x][0]=='/') {
-		for(y=1;argv[x][y];y++)
-			switch(toupper(argv[x][y])) {
-				case 'Q':
-					beep="";
-					break;
-				case 'P':
-					pause_on_error=1;
-					break;
-				case 'S':
-					stop_on_error=1;
-					break;
-				case 'T':
-					chkxlat=0;
-					break;
-				case 'A':
-					chkalloc=0;
-					break;
-				case 'E':
-					extinfo=1;
-					break;
-				default:
-					printf("%s",usage);
-					exit(1); }
-		continue; }
-
-strcpy(smb.file,argv[x]);
-p=strrchr(smb.file,'.');
-s=strrchr(smb.file,'\\');
-if(p>s) *p=0;
-strupr(smb.file);
-
-sprintf(str,"%s.SHD",smb.file);
-if(!fexist(str)) {
-	printf("\n%s doesn't exist.\n",smb.file);
-	continue; }
-
-fprintf(stderr,"\nChecking %s Headers\n\n",smb.file);
-
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	printf("smb_open returned %d\n",i);
-	errors++;
-	continue; }
-
-length=filelength(fileno(smb.shd_fp));
-if(length<sizeof(smbhdr_t)) {
-	printf("Empty\n");
-	smb_close(&smb);
-	continue; }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-    printf("smb_locksmbhdr returned %d\n",i);
-    errors++;
-    continue; }
-
-if((length/SHD_BLOCK_LEN)*sizeof(ulong)) {
-	if((number=(ulong *)MALLOC(((length/SHD_BLOCK_LEN)+2)*sizeof(ulong)))
-		==NULL) {
-		printf("Error allocating %lu bytes of memory\n"
-			,(length/SHD_BLOCK_LEN)*sizeof(ulong));
-		return(++errors); } }
-else
-	number=NULL;
-
-if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
-	if((i=smb_open_ha(&smb))!=0) {
-		printf("smb_open_ha returned %d\n",i);
-		return(++errors); }
-
-	if((i=smb_open_da(&smb))!=0) {
-		printf("smb_open_da returned %d\n",i);
-		return(++errors); } }
-
-headers=deleted=orphan=dupenumhdr=attr=zeronum=timeerr=lockerr=hdrerr=0;
-actalloc=datactalloc=deldatblocks=delhdrblocks=xlaterr=0;
-lzhblocks=lzhsaved=acthdrblocks=actdatblocks=0;
-
-for(l=smb.status.header_offset;l<length;l+=size) {
-	fprintf(stderr,"\r%2u%%  ",(long)(100.0/((float)length/l)));
-	msg.idx.offset=l;
-	msgerr=0;
-	if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-		printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-		lockerr++;
-		headers++;
-		size=SHD_BLOCK_LEN;
-		continue; }
-	if((i=smb_getmsghdr(&smb,&msg))!=0) {
-		smb_unlockmsghdr(&smb,&msg);
-		if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
-			fseek(smb.sha_fp
-				,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-			j=fgetc(smb.sha_fp);
-			if(j) { 			/* Allocated block or at EOF */
-				printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i);
-				hdrerr++; }
-			else
-				delhdrblocks++; }
-		else {
-			/* printf("%s\n(%06lX) smb_getmsghdr returned %d\n",beep,l,i); */
-			delhdrblocks++; }
-		size=SHD_BLOCK_LEN;
-		continue; }
-	smb_unlockmsghdr(&smb,&msg);
-	fprintf(stderr,"#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
-
-	lzhmsg=0;
-	if(msg.hdr.attr&MSG_DELETE) {
-		deleted++;
-		if(number)
-			number[headers]=0;
-		if(smb.status.attr&SMB_HYPERALLOC)
-			deldatblocks+=smb_datblocks(smb_getmsgdatlen(&msg)); }
-	else {
-		actdatblocks+=smb_datblocks(smb_getmsgdatlen(&msg));
-		if(msg.hdr.number>smb.status.last_msg) {
-			fprintf(stderr,"%sOut-Of-Range message number\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number (%lu) greater than last (%lu)\n"
-					,msg.hdr.number,smb.status.last_msg);
-			hdrnumerr++; }
-
-		if(smb_getmsgidx(&smb,&msg)) {
-			fprintf(stderr,"%sNot found in index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number (%lu) not found in index\n"
-					,msg.hdr.number);
-			orphan++; }
-		else if(msg.hdr.attr!=msg.idx.attr) {
-			fprintf(stderr,"%sAttributes mismatch index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header attributes (%04X) do not match index "
-					"attributes (%04X)\n"
-					,msg.hdr.attr,msg.idx.attr);
-			attr++; }
-		else if(msg.hdr.when_imported.time!=msg.idx.time) {
-			fprintf(stderr,"%sImport date/time mismatch index\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header import date/time does not match "
-					"index import date/time\n");
-			timeerr++; }
-
-		if(msg.hdr.number==0) {
-			fprintf(stderr,"%sZero message number\n",beep);
-			msgerr=1;
-			if(extinfo)
-				printf("MSGERR: Header number is zero (invalid)\n");
-			zeronum++; }
-		if(number) {
-			for(m=0;m<headers;m++)
-				if(number[m] && msg.hdr.number==number[m]) {
-					fprintf(stderr,"%sDuplicate message number\n",beep);
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Header number (%lu) duplicated\n"
-							,msg.hdr.number);
-					dupenumhdr++;
-					break; }
-			number[headers]=msg.hdr.number; }
-		if(chkxlat) {		/* Check translation strings */
-			for(i=0;i<msg.hdr.total_dfields;i++) {
-				fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
-				if(!fread(&xlat,2,1,smb.sdt_fp))
-					xlat=0xffff;
-				lzh=0;
-				if(xlat==XLAT_LZH) {
-					lzh=1;
-					if(!fread(&xlat,2,1,smb.sdt_fp))
-						xlat=0xffff; }
-				if(xlat!=XLAT_NONE) {
-					fprintf(stderr,"%sUnsupported Xlat %04X dfield[%u]\n"
-						,beep,xlat,i);
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Unsupported translation type (%04X) "
-							"in dfield[%u]\n"
-							,xlat,i);
-					xlaterr++; }
-				else {
-					if(lzh) {
-						lzhmsg=1;
-						if(fread(&m,4,1,smb.sdt_fp)) { /* Get uncompressed len */
-							lzhsaved+=(smb_datblocks(m+2)
-								-smb_datblocks(msg.dfield[i].length))
-								*SDT_BLOCK_LEN;
-							lzhblocks+=smb_datblocks(msg.dfield[i].length);
-						} } } } } }
-
-	size=smb_getmsghdrlen(&msg);
-	while(size%SHD_BLOCK_LEN)
-		size++;
-
-	if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
-		fseek(smb.sha_fp,(l-smb.status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-		for(m=0;m<size;m+=SHD_BLOCK_LEN) {
-/***
-			if(msg.hdr.attr&MSG_DELETE && (i=fgetc(smb.sha_fp))!=0) {
-				fprintf(stderr,"%sDeleted Header Block %lu marked %02X\n"
-					,beep,m/SHD_BLOCK_LEN,i);
-				msgerr=1;
-				delalloc++; }
-***/
-			if(!(msg.hdr.attr&MSG_DELETE) && (i=fgetc(smb.sha_fp))!=1) {
-				fprintf(stderr,"%sActive Header Block %lu marked %02X\n"
-					,beep,m/SHD_BLOCK_LEN,i);
-				msgerr=1;
-				if(extinfo)
-					printf("MSGERR: Active header block %lu marked %02X "
-						"instead of 01\n"
-						,m/SHD_BLOCK_LEN,i);
-				actalloc++; } }
-
-		if(!(msg.hdr.attr&MSG_DELETE)) {
-			acthdrblocks+=(size/SHD_BLOCK_LEN);
-			for(n=0;n<msg.hdr.total_dfields;n++) {
-				if(msg.dfield[n].offset&0x80000000UL) {
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Invalid Data Field [%u] Offset: %lu\n"
-							,n,msg.dfield[n].offset);
-					dfieldoffset++; }
-				if(msg.dfield[n].length&0x80000000UL) {
-					msgerr=1;
-					if(extinfo)
-						printf("MSGERR: Invalid Data Field [%u] Length: %lu\n"
-							,n,msg.dfield[n].length);
-					dfieldlength++; }
-				fseek(smb.sda_fp
-					,((msg.hdr.offset+msg.dfield[n].offset)/SDT_BLOCK_LEN)*2
-					,SEEK_SET);
-				for(m=0;m<msg.dfield[n].length;m+=SDT_BLOCK_LEN) {
-					if(!fread(&i,2,1,smb.sda_fp) || !i) {
-						fprintf(stderr
-							,"%sActive Data Block %lu.%lu marked free\n"
-							,beep,n,m/SHD_BLOCK_LEN);
-						msgerr=1;
-						if(extinfo)
-							printf("MSGERR: Active Data Block %lu.%lu "
-								"marked free\n"
-								,n,m/SHD_BLOCK_LEN);
-						datactalloc++; } } } }
-		else
-			delhdrblocks+=(size/SHD_BLOCK_LEN); }
-
-	else {	 /* Hyper Alloc */
-		if(msg.hdr.attr&MSG_DELETE)
-			delhdrblocks+=(size/SHD_BLOCK_LEN);
-		else
-			acthdrblocks+=(size/SHD_BLOCK_LEN); }
-
-	totallzhmsgs+=lzhmsg;
-	headers++;
-	if(msgerr && extinfo) {
-		printf("\n");
-		printf("%-20s: %s\n","Message Base",smb.file);
-		printf("%-20s: %lu (%lu)\n","Message Number"
-			,msg.hdr.number,msg.offset+1);
-		printf("%-20s: %s\n","Subject",msg.subj);
-		printf("%-20s: %s","To",msg.to);
-		if(msg.to_net.type)
-			printf(" (%s)",msg.to_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-		printf("\n%-20s: %s","From",msg.from);
-		if(msg.from_net.type)
-			printf(" (%s)",msg.from_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
-                    : msg.from_net.addr);
-		printf("\n");
-		printf("%-20s: %.24s\n","When Written"
-			,ctime((time_t *)&msg.hdr.when_written.time));
-		printf("%-20s: %.24s\n","When Imported"
-			,ctime((time_t *)&msg.hdr.when_imported.time));
-		printf("%-20s: %04hXh\n","Type"
-			,msg.hdr.type);
-		printf("%-20s: %04hXh\n","Version"
-			,msg.hdr.version);
-		printf("%-20s: %u\n","Length"
-			,msg.hdr.length);
-		printf("%-20s: %04hXh\n","Attributes"
-			,msg.hdr.attr);
-		printf("%-20s: %08lXh\n","Auxilary Attributes"
-			,msg.hdr.auxattr);
-		printf("%-20s: %08lXh\n","Network Attributes"
-			,msg.hdr.netattr);
-		printf("%-20s: %06lXh\n","Header Offset"
-			,msg.idx.offset);
-		printf("%-20s: %06lXh\n","Data Offset"
-			,msg.hdr.offset);
-		printf("%-20s: %u\n","Total Data Fields"
-			,msg.hdr.total_dfields);
-		printf("\n"); }
-
-	smb_freemsgmem(&msg); }
-
-if(number)
-    FREE(number);
-
-fprintf(stderr,"\r%79s\r100%%\n","");
-
-
-if(chkalloc && !(smb.status.attr&SMB_HYPERALLOC)) {
-
-	fprintf(stderr,"\nChecking %s Data Blocks\n\n",smb.file);
-
-	length=filelength(fileno(smb.sda_fp));
-
-	fseek(smb.sda_fp,0L,SEEK_SET);
-	for(l=0;l<length;l+=2) {
-		fprintf(stderr,"\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-		i=0;
-		if(!fread(&i,2,1,smb.sda_fp))
-			break;
-		if(!i)
-			deldatblocks++; }
-
-	fclose(smb.sha_fp);
-	fclose(smb.sda_fp);
-
-	fprintf(stderr,"\r%79s\r100%%\n",""); }
-
-total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
-
-dupenum=dupeoff=misnumbered=idxzeronum=idxnumerr=idxofferr=idxerr=0;
-
-if(total) {
-
-fprintf(stderr,"\nChecking %s Index\n\n",smb.file);
-
-if((offset=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
-    printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
-	return(++errors); }
-if((number=(ulong *)MALLOC(total*sizeof(ulong)))==NULL) {
-    printf("Error allocating %lu bytes of memory\n",total*sizeof(ulong));
-	return(++errors); }
-fseek(smb.sid_fp,0L,SEEK_SET);
-
-for(l=0;l<total;l++) {
-	fprintf(stderr,"\r%2lu%%  %5lu ",l ? (long)(100.0/((float)total/l)) : 0,l);
-	if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
-		break;
-	fprintf(stderr,"#%-5lu (%06lX) 1st Pass ",idx.number,idx.offset);
-/***
-	if(idx.attr&MSG_DELETE) {
-		fprintf(stderr,"%sMarked for deletion\n",beep);
-		delidx++; }
-***/
-	for(m=0;m<l;m++)
-        if(number[m]==idx.number) {
-			fprintf(stderr,"%sDuplicate message number\n",beep);
-			dupenum++;
-			break; }
-	for(m=0;m<l;m++)
-        if(offset[m]==idx.offset) {
-			fprintf(stderr,"%sDuplicate offset\n",beep,idx.offset);
-			dupeoff++;
-			break; }
-	if(idx.offset<smb.status.header_offset) {
-		fprintf(stderr,"%sInvalid offset\n",beep);
-		idxofferr++;
-		break; }
-	if(idx.number==0) {
-		fprintf(stderr,"%sZero message number\n",beep);
-		idxzeronum++;
-		break; }
-	if(idx.number>smb.status.last_msg) {
-		fprintf(stderr,"%sOut-Of-Range message number\n",beep);
-		idxnumerr++;
-		break; }
-    number[l]=idx.number;
-    offset[l]=idx.offset; }
-
-if(l<total) {
-	fprintf(stderr,"%sError reading index record\n",beep);
-	idxerr=1; }
-else {
-	fprintf(stderr,"\r%79s\r","");
-	for(m=0;m<total;m++) {
-		fprintf(stderr,"\r%2lu%%  %5lu ",m ? (long)(100.0/((float)total/m)) : 0,m);
-		fprintf(stderr,"#%-5lu (%06lX) 2nd Pass ",number[m],offset[m]);
-		for(n=0;n<m;n++)
-			if(number[m] && number[n] && number[m]<number[n]) {
-				fprintf(stderr,"%sMisordered message number\n",beep);
-				misnumbered++;
-				number[n]=0;
-				break; } }
-	fprintf(stderr,"\r%79s\r100%%\n",""); }
-FREE(number);
-FREE(offset);
-
-}	/* if(total) */
-
-totalmsgs+=smb.status.total_msgs;
-totalmsgbytes+=(acthdrblocks*SHD_BLOCK_LEN)+(actdatblocks*SDT_BLOCK_LEN);
-totaldelmsgs+=deleted;
-totallzhsaved+=lzhsaved;
-printf("\n");
-printf("%-35.35s (=): %lu\n"
-	,"Status Total"
-	,smb.status.total_msgs);
-printf("%-35.35s (=): %lu\n"
-	,"Index Records"
-	,total);
-printf("%-35.35s (=): %lu\n"
-	,"Active Headers"
-	,headers-deleted);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Active Header Blocks"
-	,acthdrblocks,ultoac(acthdrblocks*SHD_BLOCK_LEN,str));
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Active Data Blocks"
-	,actdatblocks,ultoac(actdatblocks*SDT_BLOCK_LEN,str));
-if(lzhblocks)
-	printf("%-35.35s ( ): %-8lu %13s bytes saved\n"
-		,"Active LZH Compressed Data Blocks"
-		,lzhblocks,ultoac(lzhsaved,str));
-printf("%-35.35s ( ): %lu\n"
-	,"Header Records"
-    ,headers);
-printf("%-35.35s ( ): %lu\n"
-	,"Deleted Headers"
-	,deleted);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Deleted Header Blocks"
-	,delhdrblocks,ultoac(delhdrblocks*SHD_BLOCK_LEN,str));
-packable+=(delhdrblocks*SHD_BLOCK_LEN);
-printf("%-35.35s ( ): %-8lu %13s bytes used\n"
-	,"Deleted Data Blocks"
-	,deldatblocks,ultoac(deldatblocks*SDT_BLOCK_LEN,str));
-packable+=(deldatblocks*SDT_BLOCK_LEN);
-
-if(orphan)
-	printf("%-35.35s (!): %lu\n"
-		,"Orphaned Headers"
-		,orphan);
-if(idxzeronum)
-	printf("%-35.35s (!): %lu\n"
-		,"Zeroed Index Numbers"
-		,idxzeronum);
-if(zeronum)
-	printf("%-35.35s (!): %lu\n"
-		,"Zeroed Header Numbers"
-		,zeronum);
-/***
-if(delidx)
-	printf("%-35.35s (!): %lu\n"
-		,"Deleted Index Records"
-		,delidx);
-***/
-if(idxofferr)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Index Offsets"
-		,idxofferr);
-if(dupenum)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Index Numbers"
-		,dupenum);
-if(dupeoff)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Index Offsets"
-		,dupeoff);
-if(dupenumhdr)
-	printf("%-35.35s (!): %lu\n"
-		,"Duplicate Header Numbers"
-		,dupenumhdr);
-if(misnumbered)
-	printf("%-35.35s (!): %lu\n"
-		,"Misordered Index Numbers"
-		,misnumbered);
-if(lockerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Unlockable Header Records"
-		,lockerr);
-if(hdrerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Unreadable Header Records"
-		,hdrerr);
-if(idxnumerr)
-    printf("%-35.35s (!): %lu\n"
-		,"Out-Of-Range Index Numbers"
-		,idxnumerr);
-if(hdrnumerr)
-    printf("%-35.35s (!): %lu\n"
-		,"Out-Of-Range Header Numbers"
-		,hdrnumerr);
-if(attr)
-	printf("%-35.35s (!): %lu\n"
-		,"Mismatched Header Attributes"
-		,attr);
-if(timeerr)
-	printf("%-35.35s (!): %lu\n"
-		,"Mismatched Header Import Time"
-		,timeerr);
-if(xlaterr)
-    printf("%-35.35s (!): %lu\n"
-        ,"Unsupported Translation Types"
-        ,xlaterr);
-if(datactalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Active Data Blocks"
-		,datactalloc);
-if(actalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Active Header Blocks"
-		,actalloc);
-/***
-if(delalloc)
-	printf("%-35.35s (!): %lu\n"
-		,"Misallocated Deleted Header Blocks"
-		,delalloc);
-***/
-
-if(dfieldoffset)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Data Field Offsets"
-		,dfieldoffset);
-
-if(dfieldlength)
-	printf("%-35.35s (!): %lu\n"
-		,"Invalid Data Field Lengths"
-		,dfieldlength);
-
-
-printf("\n%s Message Base ",smb.file);
-if((headers-deleted)!=smb.status.total_msgs || total!=smb.status.total_msgs
-	|| (headers-deleted)!=total || idxzeronum || zeronum
-	|| orphan || dupenumhdr || dupenum || dupeoff || attr
-	|| lockerr || hdrerr || hdrnumerr || idxnumerr || idxofferr
-	|| actalloc || datactalloc || misnumbered || timeerr
-	|| dfieldoffset || dfieldlength || xlaterr || idxerr) {
-	printf("%shas Errors!\n",beep);
-	errors++; }
-else
-	printf("is OK\n");
-
-smb_unlocksmbhdr(&smb);
-smb_close(&smb);
-}
-
-if((totalmsgs && (totalmsgs!=smb.status.total_msgs || totallzhmsgs))
-	|| packable)
-	printf("\n");
-if(totalmsgs && totalmsgs!=smb.status.total_msgs)
-	printf("%-39.39s: %-8lu %13s bytes used\n"
-		,"Total Active Messages"
-		,totalmsgs,ultoac(totalmsgbytes,str));
-if(totallzhmsgs && totalmsgs!=smb.status.total_msgs)
-	printf("%-39.39s: %-8lu %13s bytes saved\n"
-		,"Total LZH Compressed Messages"
-		,totallzhmsgs,ultoac(totallzhsaved,str));
-if(packable)
-	printf("%-39.39s: %-8lu %13s bytes used\n"
-		,"Total Deleted Messages"
-		,totaldelmsgs,ultoac(packable,str));
-
-if(pause_on_error && errlast!=errors) {
-    fprintf(stderr,"\7\nHit any key to continue...");
-    if(!getch())
-        getch();
-    fprintf(stderr,"\n"); }
-
-
-return(errors);
-}
diff --git a/src/sbbs2/smb/chksmb/makefile b/src/sbbs2/smb/chksmb/makefile
deleted file mode 100644
index 186a09f140fd50148f1f6243412e36609467c326..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/chksmb/makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-###############################
-# Makefile for CHKSMB         #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-
-OS	= DOS
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include;..
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LFLAGS	= -n -c
-
-!ifdef __OS2__
-OS	= OS2
-CC      = c:\bcos2\bin\bcc
-LD      = c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;..
-LIB     = c:\bcos2\lib
-CFLAGS	= -d -C -I$(INCLUDE) -w-pro
-LFLAGS  = -c -w-srf
-!endif
-
-MAIN	= $(OS)\chksmb.exe
-OBJS	= $(OS)\chksmb.obj $(OS)\smblib.obj
-HEADERS = ..\smblib.h ..\smbdefs.h ..\crc32.h
-
-# Implicit C Compile Rule
-{.;..}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# All .obj modules
-$(OS)\chksmb.obj:	 $(HEADERS)
-$(OS)\smblib.obj:	 $(HEADERS)
diff --git a/src/sbbs2/smb/crc16.c b/src/sbbs2/smb/crc16.c
deleted file mode 100644
index 81ba4c9a9839f7d6e29c8a5fe37951aafc34b7ad..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/crc16.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* CRC16.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* 16-bit CRC routines */
-
-#include "smblib.h"
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort SMBCALL crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
diff --git a/src/sbbs2/smb/crc32.c b/src/sbbs2/smb/crc32.c
deleted file mode 100644
index f432032d1ca020206548ea0016ee9bb3939acc51..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/crc32.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* CRC32.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* 32-bit CRC of a buffer */
-
-#include "smblib.h"
-#include "crc32.h"
-
-#ifdef __NT__
-#	define CRCCALL _pascal
-#else
-#	define CRCCALL
-#endif
-
-ulong CRCCALL crc32(char *buf, ulong len)
-{
-	ulong l,crc=0xffffffff;
-
-for(l=0;l<len;l++)
-	crc=ucrc32(buf[l],crc);
-return(~crc);
-}
diff --git a/src/sbbs2/smb/crc32.h b/src/sbbs2/smb/crc32.h
deleted file mode 100644
index d0127ab888f88059c8bd06d64dd07a4663c4533b..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/crc32.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 32-bit CRC */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-long crc32tbl[]={	/* CRC polynomial 0xedb88320 */
-0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-#define ucrc32(ch,crc) (crc32tbl[(crc^ch)&0xff]^(crc>>8))
-
-
diff --git a/src/sbbs2/smb/docs/smb.hst b/src/sbbs2/smb/docs/smb.hst
deleted file mode 100644
index c13f8c1a98adfdbae930df07d87f45b8e72dd361..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/docs/smb.hst
+++ /dev/null
@@ -1,327 +0,0 @@
-Synchronet Message Base Specification Modification History
-==========================================================
-
-******************************
-01/20/94 Initial Release v1.00
-******************************
-
-Quite a few spelling errors in SMB.TXT corrected.
-
-Estimated maximum number of messages (in Introduction of SMB.TXT) formula
-corrected (1500 rounded to nearest 256 is 1536, not 2048).
-
-Pages 32 and 38 (SENDEREXT and RECIPIENTEXT header field types) incorrectly
-stated the index record contains CRC-32s, when in fact the index contains
-CRC-16s of the agent names or extensions.
-
-FORWARDTO header field types incorrectly stated they were for replies, rather
-than forwarding instructions.
-
-Trigger header field types incorrectly stated they were "attachments" rather
-than triggers.
-
-Bug fixed in smb_open() function in smblib.c: was allocating buffer via
-setvbuf for wrong file pointer when opening header file. Caused loss of 
-memory (2k) everytime smb_open() was called.
-
-Bug fixed in smb_getmsghdr() function in smblib.c: msg->from_agent,to_agent,
-and replyto_agent were not initialized properly.
-
-Added from_ext, to_ext, and replyto_ext fields to msg struct. Initialized
-with call to smb_getmsghdr() function. These are convenience pointers for
-the to, from, and replyto agent extensions (user numbers, usually).
-
-Fixed a nasty bug in the smb_freemsgdat() function, causing odd values in the
-SDA file and cross-linked messages when fast allocation mode was not used for
-new messages.
-
-smb_putmsghdr() function replaced by smb_putmsg() and it calls smb_putmsghdr()
-and smb_putmsgidx() - previously smb_putmsghdr() actually wrote the header
-and the index. So you must change any occurances of smb_putmsghdr() to
-smb_putmsg() if you intend to write to both the index and header records.
-
-smb_open() now takes a "retry_time" parameter (number of seconds) to lock
-and read the message base header and verify the "id" and "version". Added
-new error codes: -1 indicates failure to lock message base header, -2 indicates
-id mismatch, and -3 indicates incompatible message base version.
-
-rewind() and clearerr() calls added to library functions to eliminate the
-problem of "sticky" error flags when using fread() and fwrite(). Reordered
-the use of chsize() to force seeking (with fseek()) before using the file
-descriptor operation (chsize()) would would fail under some circumstances.
-
-smb_getmsgidx() function now uses "fast" message number look-up algorythm.
-
-Added smb_getlastidx() function to retrieve the last index in the message
-base.
-
-Allocation strategy for hfield and dfield elements of the smbmsg_t structure
-were changed to require less memory. Rather than an array of pointers (pointer
-to a pointer) of type hfield_t or dfield_t, they are simply an array (pointer)
-of type hfield_t or dfield_t. The only change you need to make are any
-references to "smbmsg_t.hfield[x]->etc" to "smbmsg_t.hfield[x].etc".
-
-Added several new error codes to smb_getmsghdr(). -7 indicates missing one
-of the three mandatory header fields (sender, recipient, or subject). -8
-indicates that total_dfields element of smbhdr_t is incorrect (extends beyond
-smbhdr_t.length). -9 indicates incompatible header version.
-
-New error code to smb_addcrc(), -4 indicates error getting length of file.
-
-smb_putmsghdr() returns -2 on failure write header, -3 on failure to write
-dfield, -4 on failure to write hfield (fixed), -5 on failure to write hfield
-(data), and -6 on failure to pad record with NULLs.
-
-Bugs fixed in sample conversion source code and SMBUTIL: Overwriting first
-two bytes of next record when using self-packing storage, SBBSFIDO would
-crash on blank kludge lines, SEEN-BYs weren't converted properly by SBBSFIDO,
-and more.
-
-*** IMPORTANT ***
-Index format changed, added message time field to idxrec_t for fast pointer
-manipulation by (import) date/time stamp. This is SMB format v1.10 and is
-not compatible with the v1.00 format. A conversion program (100TO110.EXE)
-is included with source code for converted any existing message bases.
-
-CHKSMB, a utility for checking message bases for corruption, included with
-SMBLIB.
-
-SMBUTIL and CHKSMB both accept wildcard arguments for processing multiple
-message bases.
-
-idxrec_t.to and idxrec_t.from may contain USER NUMBER instead of CRC of user
-names. This implementation is currently specific to E-mail boxes on Synchronet
-BBS. E-mail from non-local users are stored with a "from" field of 0.
-
-**********************
-03/28/94 Release v1.10
-**********************
-
-Forgot to include this file (oops).
-
-***********************
-03/28/94 Release v1.10a
-***********************
-
-Fixed problem with buffered fread() routine attempting to read into a locked
-regions.
-
-Added smb_stack() function for saving (pushing) currently open message base
-and ability to pop it off later.
-
-Added fix for keeping original sender information in smbmsg_t structure when
-a message has been forwarded.
-
-CHKSMB now correctly support multiple destination messages (without reporting
-missallocated active data blocks) and now reports packable bytes available.
-
-SMBUTIL can now conditionally compress a message base, only if so many K are
-compressable.
-
-Fixed problem with incorrect UTC value.
-
-Added NET_WWIV network type.
-
-**********************
-06/02/94 Release v1.11
-**********************
-
-Created Watcom compatible MAKEFILE for DOS, 32-bit DOS, and 32-bit OS/2
-versions of SMBUTIL.
-
-Enhanced macro definitions in SMBDEFS.H for MALLOC, FREE, and REALLOC to
-support Watcom and other compilers other than Borland. Also added LMALLOC
-and LFREE macros for large allocation (>64k) operations.
-
-Fixed problem with multiple calls to setvbuf() when using Watcom C libraries.
-Memory allocated by setvbuf() would never be released. To work around this
-Watcom C bug, a static buffer, shd_buf[], is now used instead.
-
-Fixed bug in smb_getmsghdr() that would cause it to return -6 when attempting
-to allocate 0 length header fields.
-
-Added LZH.C to SMBLIB for message data compression/decompression.
-
-Removed the 16-bit CRC functions from SMBUTIL and put them in CRC16.C (now part
-of SMBLIB) for easier integration into other applications.
-
-Added Hyper Allocation storage method to specification: smbstatus_t.reserved
-changed to smbstatus_t.attr and SMB_HYPERALLOC bit is set when Hyper Allocation
-storage is used for a message base. This is the only change between v1.10 and 
-v1.20 of the message base format. No other bits in smbstatus_t.attr are 
-currently defined. See the specification for definition of the Hyper Allocation
-storage method.
-
-Changed SMB Storage and Retrieval Protocol chapters in the specification to
-Pseudo-code examples.
-
-Added SMBLIB Storage and Retrieval C example chapters to the specification.
-
-Added field descriptions for message base header record fields and Status Info
-(base header #1) record fields to the specification.
-
-Changed SMBLIB smb_addmsghdr() 'fast' argument to 'storage' to specify the
-storage method to use (either SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC).
-Previous usage (0 for self-pack, 1 for fast) still compatible.
-
-Added smb_hallocdat() and smb_hallochdr() to SMBLIB functions for the Hyper
-Allocation storage method.
-
-Added SMB_STACK_XCHNG operation to smb_stack() function, to exchange the top
-of the stack with the currently open message base.
-
-**********************
-02/14/95 Release v1.20
-**********************
-
-smb_close() was modified in the following ways:
-	Only attempts to close non-NULL file pointers
-	If shd_fp is currently open, calls smb_unlocksmbhdr() before closing
-		(just in case it was left locked by application)
-
-smb_open() was modified in the following ways:
-	Initializes all file pointers to NULL
-	calls smb_close() if any of the files couldn't be opened
-
-smb_locksmbhdr() was modified in the following ways:
-	If lock fails, attempts to unlock the header before next lock
-		attempt (just incase application attempts to lock a locked
-		header without first unlocking it)
-
-smb_lockmsghdr() was modified in the following ways:
-	If lock fails, attempts to unlock the header before next lock
-		attempt (same reason stated above)
-
-CHKSMB (1.21) was modified in the following ways:
-	Tests for valid translations strings in the .SDT files
-	Displays totals for bytes used by header and data blocks, bytes used
-		by deleted messages, and bytes saved by LZH compression
-
-SMBUTIL (1.21) underwent some minor cosmetic changes.
-
-***********************
-03/18/95 Release v1.20a
-***********************
-
-SMBUTIL (1.22) now compiles correctly under Watcom, using correct time zone
-information. SMBUTIL maint() will no longer delete messages if max_age is
-specified in the SMB header and the when_imported time for a message is in the
-future.
-
-Fixed problem in LZH.C that would cause lzh_decode() to generate exception
-errors when compiled with a 32-bit compiler.
-
-CHKSMB (1.22) now supports /E command line switch to display extended
-information about corrupted messages. CHKSMB.C is now Watcom compatible.
-
-Added fflush() calls to all smblib functions that write to the SDT, SHA, or SDA
-files. This eliminates the problem of duplicate data offsets (data blocks for
-multiple messages pointing to the same location) causing corrupted SDT files
-(unsupported translation types reported by CHKSMB).
-
-Added fflush() call after writing to SDT file in SMB_PUT example in SMB.TXT.
-
-Fixed example *2SMB.C files to be compatible with SMBLIB v1.20 smb_create()
-function.
-
-Fixed smb_hallocdat() function prototype to stop redeclaration warnings.
-
-Minor typos in specification fixed.
-
-***********************
-04/24/95 Release v1.20b
-***********************
-
-Added SMB_EMAIL (1<<0) attribute definition for the message base status header
-to specify a local e-mail message base where index "to" and "from" fields are
-stored as user numbers, not CRC-16s (this is the only change between v1.20
-and v1.21 of the SMB format).
-
-Version 1.21 of FIXSMB no longer needs the "/M" switch to correctly fix a
-Synchronet e-mail message base (as long as the SMB_EMAIL status attr is set).
-
-Version 1.23 of SMBUTIL can now import text into a Synchronet e-mail message
-base (as long as the SMB_EMAIL status attr has been set). It will ask for the
-sender and recipient user numbers. Fixed an apparently nasty bug that would
-cause damage to message bases when (I)mporting (check for SMB_HYPERALLOC
-attribute was backwards). Excess baggage in the SMBUTIL source code was also
-removed (no longer supports /L, /F, and /D command line switches). Only
-supports self-packing and hyper-allocated message bases (it will not damage
-fast allocated bases, however). "SMBUTIL M" now correctly handles message bases
-that contain messages that have been pre-flagged for deletion (MSG_DELETE attr
-set).
-
-Changed smb_open(int retry_count) function: if retry_count is 0, then a "fast
-open" method is used which doesn't lock and read the status header to check
-for compatibility and validity of message base.
-
-Added SMBLIB_VERSION definition (string constant) to contain the current
-version and revision (if applicable) of the SMB library. This version number
-may not always be the same as SMB_VERSION (version of the SMB format) or the
-current version of the specification. It may be helpful to include a display
-of this version number somewhere in your application (i.e. printf("SMBLIB v%s"
-,SMBLIB_VERSION);).
-
-Changed smb_stack() example in the Performance Issues chapter to keep two
-message bases always open using SMB_STACK_XCHNG.
-
-Fixed bug in SMBUTIL that would cause an infinite loop when analysing an
-extrememly corrupted HyperAllocated message base.
-
-Fixed bug in smb_stack() function when using SMB_STACK_XCHNG operation. Would
-previously set current message base to an undefined message base, rather than
-the message base on top of the stack (last pushed or exchanged).
-
-CHKSMB v1.22 compiled in the 1.20b release did not support wildcards (wasn't
-linked with WILDARGS.OBJ) - this has been fixed and is the only change in
-CHKSMB v1.23.
-
-**********************
-05/31/95 Release v1.21
-**********************
-
-Add uchar forwarded element to smbmsg_t structure. This variable is initialized
-by the smb_getmsghdr() function. If the message has been forwarded, it will
-be set to non-zero.
-
-Fixed bug in LZH.C which caused lzh_decode() to produce incorrect results
-(usually t's and spaces) when compiled with a 32-bit compiler.
-
-Added HUGE16 and FAR16 macros to SMBDEFS.H for huge and far pointers for
-16-bit compilers only (default pointer type for 32-bit compilers).
-
-Fixed bug in FIXSMB.C that would initialize the SDA file to the wrong length.
-
-Added net type NET_MHS for MHS gateways.
-
-SMBUTIL (1.24) will no longer free deleted headers when maintaining a message
-base if the /A (no analysis) command line switch is used. This speeds up the
-message base maintenance/pack operation significantly by using: SMBUTIL /A MP
-
-***********************
-08/31/95 Release v1.21a
-***********************
-
-All smb_*() functions changed to accept pointers to an smb_t structure. This
-eliminates the use of global variables (making DLLs difficult or impossible
-to program). A pointer is used even if the function doesn't modify the data
-to maintain a consistent API and compatibility with languages that don't
-support the passing of user defined types by value (e.g. Visual Basic).
-
-The smb_t structure contains a retry_time element that defines the maximum
-number of seconds to wait while trying to open a locked message base or record.
-If this element of the passed smb_t variable is 0, a default value of 10
-seconds is used.
-
-Added smb_getmsgtxt() and smb_freemsgtxt() functions to SMBLIB.C (only included
-if SMB_GETMSGTXT is defined).
-
-*******************
-11/18/95 Beta v2.00
-*******************
-
-Bug in smb_getmsgtxt() with message data field lengths less than 2.
-
-**********************
-03/22/96 Release v2.01
-**********************
diff --git a/src/sbbs2/smb/docs/smb.src b/src/sbbs2/smb/docs/smb.src
deleted file mode 100644
index 35fe9b22c9e08183b8b74d9214a45cecb83ca30e..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/docs/smb.src
+++ /dev/null
@@ -1,3592 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-                     Synchronet Message Base Specification
-								 Version 1.21
-							   Updated 08/31/95
-
-						Copyright 1995 Digital Dynamics
-
-                                  PO Box 501
-                             Yorba Linda, CA 92686
-
-				 Voice: 714-529-6328   BBS: 714-529-9525 V.32/V.32bis
-				   FAX: 714-529-9721		714-529-9547 V.FC
-				  Fido: 1:103/705	   ftp: netcom.com /pub/sb/sbbs
-
-Table of Contents
-=================
-&&Contents
-
-Introduction....................................................@@INTRO___
-Implementation Levels...........................................@@IMPLEVEL
-Definitions.....................................................@@DEFINES_
-        Acronyms................................................@@ACRONYMS
-        Data Types..............................................@@DATATYPE
-File Formats....................................................@@FILEFORM
-        Index.....................(*.SID).......................@@SID_FORM
-        Header....................(*.SHD).......................@@SHD_FORM
-        Header Allocation.........(*.SHA).......................@@SHA_FORM
-        Data......................(*.SDT).......................@@SDT_FORM
-        Data Allocation...........(*.SDA).......................@@SDA_FORM
-        CRC History...............(*.SCH).......................@@SCH_FORM
-Header Field Types..............................................@@HFIELD_T
-Data Field Types................................................@@DFIELD_T
-Messsage Attributes.............................................@@ATTRBITS
-Translation Types...............................................@@XLATTYPE
-Agent Types.....................................................@@AGENTTYP
-Network Types...................................................@@NETWORKS
-Media Types.....................................................@@MEDIATYP
-Message Storage Pseudo Code.....................................@@STORPCOD
-Message Retrieval Pseudo Code...................................@@READPCOD
-SMBUTIL.........................................................@@SMBUTIL_
-CHKSMB..........................................................@@CHKSMB__
-FIXSMB..........................................................@@FIXSMB__
-SMBLIB (C library)..............................................@@SMBLIB__
-		Data Types and Constants..(SMBDEFS.H)...................@@SMBDEFS_
-        Global Variables..........(SMBVARS.C)...................@@SMBVARS_
-        Function Prototypes.......(SMBLIB.H)....................@@SMBLIB.H
-        Library Functions.........(SMBLIB.C)....................@@SMBLIB.C
-		Miscellaneous.............(CRC*.* and LZH.*)............@@SMB_MISC
-SMBLIB Storage Example..........................................@@SMB_PUT_
-SMBLIB Retrieval Example........................................@@SMB_GET_
-SMBLIB Performance Issues.......................................@@PERFORM_
-Bibliography....................................................@@BIBLIOGR
-Implementations.................................................@@IMPLEMEN
-
-Introduction
-============
-&&Introduction
-$$INTRO___
-
-Q. What is SMB?
-
-A. SMB (Synchronet Message Base) is a technical specification for the storage
-   format of electronic mail messages. These e-mail messages may all be
-   contained in one database, or, more commonly, separated into catagorized
-   databases. These message databases (or message bases) are also referred to
-   as "sub-boards", "forums", "conferences", and "SIGs". The messages may be
-   directed to an individual person, sent to a group of individuals, or sent
-   to everyone who can read messages in that message base. Messages may be
-   created and read soley at one physical location, or imported from and
-   exported to a message network that may span continents. Message bases that
-   are connected to a message network are often called "echoes".
-
-
-Q. Why SMB?
-
-A. The Synchronet Message Base is designed to store high volumes of messages
-   while maintaining optimum search, retrieval, and creation performance.
-   These messages are not limited to mere text. In addition to text, SMB
-   defines the storage of digitized sound, MIDI, graphics, fonts, animation,
-   as well as other multimedia data and triggers for localized multimedia.
-   SMB thrives on a multi-user environment where messages are being created,
-   read, modified, and deleted by multiple tasks simultaneously. With the
-   large message networks of today being the rule, rather than the exception,
-   and high volumes of messages being imported on a daily, sometimes hourly
-   basis, creation and deletion speed is of the utmost importance. This is
-   where SMB really shines. Being extensible enough to handle message formats
-   from networks of today and tomorrow, and fast enough to import more messages
-   that humanly readable, the SMB format will more than meet your message
-   storage needs.
-
-
-Q. Why a specification?
-
-A. Message bases are often accessed and modified by a number of different
-   programs. Often these programs are developed by individuals or companies
-   other than the original designer of the message base format. This
-   specification is an attempt to aid developers in creating programs that
-   access or modify a message base stored in the SMB format.
-
-
-Q. Who can use this specification?
-
-A. Anyone that has interest in the Synchronet Message Base format at either
-   an educational or professional level. Specifically, software developers
-   interested or currently involved in the development of message readers,
-   editors, echomail (toss/scan) programs, message transfer agents (MTAs),
-   network gateways, and bulletin board systems. Much of the information in
-   this specification is intended for those with preexisting programming
-   knowledge, so those with little or no programming experience may find it
-   hard to comprehend.
-
-
-Q. What does the SMB specification include?
-
-A. The text you are reading is part of the SMB specification: a single text
-   document that defines the storage format of each of the six files of an
-   SMB format message base and how they are related to each other.
-
-   Included with this specification is C source code to be used as an example
-   to programmers of how to access an SMB format message base and public domain
-   library functions (SMBLIB) that can be compiled and linked into programs
-   that access an SMB format message base developed by third parties. An SMB
-   utility program (SMBUTIL) is also included with C source code as an example
-   of how to use the SMBLIB functions.
-
-
-Q. Where did the SMB specification come from?
-
-A. Digital Dynamics (southern California based software development company)
-   released "Synchronet Multinode BBS Software Version 1a" in June of 1992 as
-   one of the first BBS packages to be designed from the ground-up to operate
-   in a multinode environment with incredible speed and reliability, with a
-   large suite of multinode specific features and design innovations.
-
-   The original message base format was designed with localized messaging and
-   low volume message networks in mind. By January of 1993, it was clear that
-   high volume message networks (FidoNet, RelayNet, Usenet, etc.) were the
-   preference of most BBS users and a new message base format was required to
-   allow for high volume message storage, improved storage, retrieval, and
-   maintenance performance, as well as lower storage space requirements.
-
-   Rather than introduce another new message format, Digital Dynamics sought
-   to implement an existing public specification for a format that would meet
-   current and future message storage needs. More than a few specifications
-   were seriously considered at one time or another, but after careful
-   examination, design flaws and lack of extensibility eliminated them from the
-   long term plans of Digital Dynamics and Synchronet BBS Software. Thus began
-   the design of the "Synchronet Message Base" (SMB) format.
-
-   At the request of many message related program developers, Digital Dynamics
-   created and released the SMB specification before the release of "Synchronet
-   Version 2.00" to allow lead-time on developing support programs for the new
-   format.
-
-   Digital Dynamics strongly encourages developers of message related programs
-   (including software that directly competes with Synchronet or other Digital
-   Dynamics products) to implement support for SMB. Though this is a public
-   specification and Digital Dynamics encourages developer suggestions, it will
-   remain under the sole control of Digital Dynamics unless specifically stated
-   otherwise in a future revision of this specification.
-
-   Digital Dynamics requests that any organizations that wish to adopt or
-   ratify this specification, in part or whole, notify Digital Dynamics through
-   any of the contact methods listed at the beginning of this document.
-
-
-Q. How does SMB store messages?
-
-A. Each message base is stored in a set of binary files. This set consists
-   of between three and six files depending the storage method used. The base
-   filename (maximum of eight characters under DOS) is the same for all six
-   files of the same message base and unique amoung the filenames of other
-   message bases in the same directory. The six files each have a different
-   three character extension. The first character of the extension is always
-   the letter 'S' (for SMB), while the second and third characters define the
-   contents of the file.
-
-   Two of the six files associated with each message base are not recreatable
-   and therefore are the most important when considering data integrity. These
-   two files are the data file (with a .SDT extension) and header file (.SHD
-   extension). Both of these files use 256 byte blocks and have associated
-   block allocation tables (stored in .SDA and .SHA respectively) so that
-   deleted message blocks may be used by new messages without creating odd
-   sized unused 'holes' in the files. The block allocation table files (.SDA
-   and .SHA) can be recreated with the information stored in the header (.SHD)
-   file. When using Hyper Allocation storage method, the allocation files (.SDA
-   and .SHA) are not used.
-
-   For fast indexing, there is a small fixed length index file (with a .SID
-   extension). This file allows for the immediate location of message header
-   records based on sender's name or user number, recipient's name or user
-   number, subject, message number, or message attributes. This file can be
-   recreated with the data stored in the header (.SHD) file.
-
-   The last file is an optional CRC history (.SCH) file. It contains 32-bit
-   CRCs of a configurable number of messages imported or created locally. This
-   is to help eliminate duplicate messages created by user or program error.
-   The CRC history file can be recreated with the combination of information
-   stored in the data (.SDT) and header (.SHD) files.
-
-Q. How fast do messages import into an SMB message base?
-
-A. This is a very important question for systems for that import large volumes
-   of messages. Of course, the answer depends on the storage format which you
-   are importing from, the average length of messages, the design of the
-   program which is peforming the import process, as well as the hardware and
-   system software being used. What's important is that SMB will allow the
-   fastest import process possible with any given combination of the above
-   factors.
-
-   Since system storage capacity is rarely infinite, neither is the number
-   of messages which can be stored in a message base. System operators must
-   define the maximum number of messages to be stored in a message base, the
-   maximum age of the messages in that message base, or a combination of both.
-   When using the Self-packing storage method (defined later in this document),
-   the smaller the number of messages stored in a message base, the faster the
-   import process. The SMB format is flexible enough to support multiple levels
-   of import performance based on optimizations for storage space or speed.
-   Most system operators will almost invariably choose speed over space, but
-   which choices are available is determined by the importing program. This
-   specification defines three storage methods, from slowest to fastest:
-   Self-packing, Fast Allocation, and Hyper Allocation. Other options defined
-   in this specification may affect storage performance, including duplicate
-   message checking and message compression/encryption.
-
-
-Q. How much storage is required for an SMB message base?
-
-A. The biggest factor in determining storage requirements for a message base
-   is the maximum number of messages to be stored in the base (defined by the
-   system operator) and the average size of each message. The minimum required
-   storage for a message base is 32 bytes plus 532 bytes per message (plus four
-   bytes per message if duplicate message checking is used and three bytes
-   per message if Self-packing or Fast Allocation storage methods are used).
-
-   The SMB format was originally designed to be "self-packing", meaning purged
-   (deleted) message header and data blocks will be used automatically by new
-   messages. Relying solely on self-packing, an SMB format message base will
-   never "shrink" in size. This is not to say that it will continually "grow"
-   in size, but that without specific packing procedures, deleted message
-   blocks may remain unused for extended periods of time, meanwhile using some
-   amount of storage space that could be recovered using specific packing
-   procedures. The Fast Allocation and Hyper Allocation storage methods do not
-   use deleted message blocks for new messages so specific packing procedures
-   must be used if any messages are deleted and that storage space is to ever
-   be recovered.
-
-   Limiting the maximum age of messages in an SMB message base is another way
-   to control the storage requirements. While maximum message age definition is
-   optional, the definition of the maximum number of messages is not.
-
-Q. How many messages can be stored per SMB message base?
-
-A. Without considering storage limitations or message data lengths greater than
-   256, the theoretical maximum number of messages that can be stored in a
-   single SMB message base is 16.7 million. Considering the variable length
-   nature of message and header data, it is suggested that the system operator
-   allow no more than 1 million messages per base.
-
-   To determine an estimated maximum number of messages for a message base
-   using the average message data length as a factor, use the following
-   formula:
-
-   4.2 billion divided by the average message length rounded up to be evenly
-   divisible by 256.
-
-   If the average message data length is 1500 bytes, the estimated maximum
-   number of messages would be 2,734,375 (4.2 billion divided by 1536).
-
-   Implementations of this format may be further limited by available system
-   memory.
-
-Implementation Levels
-=====================
-&&Implementation Levels
-$$IMPLEVEL
-The SMB format can be implemented to varying degrees between programs without
-creating compatibilty issues. Rather than have developers specifically state
-which features they have and have not implemented, we have defined seven levels
-of implementation (represented by Roman numerals I through VII). For a program
-or software package to meet an implementation level, it must have all of the
-features listed for that level and all of those for each level below it. The
-minimum suggested imlementation is level I. The SMBUTIL program included with
-this specification is an example of a level I implementation with features
-from some of the higher implementation levels.
-
-Level I
--------
-The minimum suggested level of implementation. Messages contain merely ASCII
-text displayable on an ANSI terminal. Messages can be added to the message
-base and if the maximum number of messages is exceeded, messages are removed
-or marked for deletion.
-
-Level II
---------
-The addition of file attachments, multiple index/header entries per message
-(multiple destinations), multiple text bodies for the separation of message
-text and tag/origin lines (for example), forwarding, threading, and specific
-FidoNet kludge header field support makes this level of implementation more
-realistic for bulletin board system and EchoMail software implementation.
-
-Synchronet Multinode BBS Software v2.00 has a level II implementation of this
-specification.
-
-Level III
----------
-This implementation adds support for translation strings defined later in this
-document for data compression, encryption, escaping, and encoding. This level
-is still limited to basic ASCII text and ANSI escape sequence entry and
-retrieval.
-
-Synchronet Multinode BBS Software v2.10 has a level III implementation of this
-specification.
-
-Level IV
---------
-The storage and retrieval of embedded and attached images is added in this
-level of implementation. Supported images are limited to single binary or text
-data blocks that can be displayed or transferred to the user (automatically,
-or by request) if their display and translation protocols define specific
-support for the image type.
-
-Level V
--------
-This level of implementation adds support for embedded and attached sound data.
-This includes digitized sound and MIDI data. Supported sounds are limited to
-single binary or text data blocks that can be played or transferred to the user
-(automatically or by request) if their presentation and translation protocols
-define specific support for the sound type.
-
-Level VI
---------
-Localized sound and image data can be triggered by messages stored and
-retrieved in an implementation of this level.
-
-Level VII
----------
-Complete multimedia support is reached in this implementation level with
-support for embedded and attached animation, sound, and video data.
-
-
-Definitions
-===========
-&&Definitions
-$$DEFINES_
-
-Control Characters
-------------------
-When specifying control characters (ASCII 1 through 31), the caret symbol "^"
-or the abreviation "ctrl-" followed by a character will be used to indicate the
-value. ^A is equivalent to ASCII 1, ^B ASCII 2, etc. The case of the control
-character is not significant (i.e. ^z and ^Z are equivalent). The control
-character ^@ (ASCII 0) will be specified as NULL or 0.
-
-
-Hexadecimal
------------
-Base sixteen numbering system which includes the digits 0-9 and A-F.
-Hexadecimal numbers are represented in this document with a prefix of "0x" or
-"\x" or a suffix of "h". Hexadecimal letter digits are not case sensitive
-(i.e. the number 0xff is the same as 0xFF).
-
-
-File dump
----------
-When example file dumps are displayed, the format is similar to that of the
-output from the DOS DEBUG program. With the exception of the ASCII characters,
-all numbers are in hexadecimal.
-
-Offset    Byte values                                          ASCII characters
-
-000000	  53 4D 42 1A 10 01 20 00	F4 01 00 00 F4 01 00 00    SMB... .�...�...
-000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-
-
-Bit values
-----------
-Bit (or flag) values are represented in C notation as (1<<x) where x is the bit
-number. (i.e. bit number 7 (1<<7) is the same as 0x80).
-
-
-Word storage
-------------
-All words (16-bit) and double words (32-bit) are stored in Intel 80x86 (little
-endian) format with bytes stored from low to high (reverse of the Motorola
-680x0 word storage format).
-
-A 16-bit word with the value 1234h is stored as 34h 12h.
-
-Translation strings
--------------------
-Translation strings (xlat variables) are arrays of words (16-bit) in the order
-of the original storage translation. The last translation type is followed by a
-16-bit zero (defined later as XLAT_NONE). If there are no translations, then
-the first and only element of the array is XLAT_NONE.
-
-If multiple translations are used, the translation order must be reversed
-upon retrieval to obtain the proper data.
-
-
-Local e-mail
-------------
-When referring to the local e-mail message base of a Synchronet BBS, we are
-referring specifically the message base with the name "MAIL" stored in the
-"DATA" directory (e.g. \SBBS\DATA\MAIL).
-
-Messages stored in this message base are different in the following respects:
-
-	The SMB_EMAIL status header attribute is set ON
-	Hyper Allocation storage method is not supported
-	The "To" and and "From" fields of the message indexes do NOT contain CRCs
-
-Acronyms:
-========
-&&Definition of Acronyms
-$$ACRONYMS
-
-ANSI            American National Standards Institute
-ASCII           American Standard Code for Information Interchange
-BBS             Bulletin Board System
-C               The C programming language as defined by ANSI X3.159-1989
-CR              Carriage Return character (ASCII 13)
-CRC             Cyclic Redundancy Check
-CRC-16			Standard 16-bit CRC using 1021h polynomial (seed 0)
-CRC-32			Standard 32-bit CRC using EDB88320h polynomial (seed -1)
-CRLF            Carriage Return character followed by a Line Feed character
-FSC             FidoNet Standards Commitee (FTS proposal)
-FTN             FidoNet Technology Network
-FTS             FidoNet Technical Standard
-LF              Line Feed character (ASCII 10)
-QWK 			Compressed message packet format for message reading/networking
-RFC             Request for Comments
-SMB             Synchronet Message Base
-UT              Universal Time (formerly called "Greenwhich Mean Time")
-
-Data types
-==========
-&&Definition of Data Types
-$$DATATYPE
-
-uchar           Unsigned 8-bit value (0 through 255).
-                C example:
-
-                #define uchar unsigned char
-
-
-short           Signed 16-bit value (-32768 through 32767).
-				"short" is a C keyword indicating "short int".
-
-
-ushort          Unsigned 16-bit value (0 through 65535).
-                C example:
-
-                #define ushort unsigned short
-
-
-ulong           Unsigned 32-bit value (0 through 4294967295).
-                C example:
-
-                #define ulong unsigned long
-
-
-time_t          Unsigned 32-bit value.
-                Seconds since 00:00 Jan 01 1970 (Unix format).
-                Used for all time/date storage in SMB as part of the when_t
-                data type. This time format will support dates through the year
-                2105.
-                time_t is defined by ANSI C as a long (signed) which can
-                limit its date support to the year 2038 depending on the
-                library routines used.
-
-
-ASCII           String (aka character array) of 8-bit ASCII characters.
-                Characters with the bit 7 set (80h through FFh) represent
-                the IBM PC extended ASCII character set. When data or header
-                fields of this type are stored in the header, a NULL
-                terminator may or may not be present.
-                C example:
-
-                uchar str[80];
-
-
-ASCIIZ          ASCII string with (non-optional) NULL terminator.
-                C example:
-
-                uchar str[81];
-
-nulstr          ASCII string immediately terminated by NULL.
-                C example:
-
-                uchar *nulstr="";
-
-
-undef           Data buffer with undefined contents.
-                C example:
-
-                uchar buf[BUF_LEN];
-
-when_t          Date/Time stamp including time-zone adjustment information.
-                C example:
-
-                typedef struct {
-
-                    time_t  time;   // Time stamp (in local time)
-                    short   zone;   // Zone constant or Minutes (+/-) from UT
-
-                    } when_t;
-
-                time:
-
-                A time value of 0 is invalid and indicates an uninitialized
-                time stamp.
-
-				Time stamps are always stored in universal time. i.e.
-				Regardless of what the local time zone is, Jan 1st 1994 00:00
-				will always be stored as 2D24BD00h.
-
-                zone:
-
-				If the zone is in the range -720 to +720, it represents the
-				number of minutes east or west of UT. Values in this range
-				should only be used for time zones not otherwise represented
-				here.
-
-                If the zone is greater than 720 or less than -720, then the
-                following bits have special meaning:
-
-                (1<<12)         // Non-US time zone     (east of UT)
-                (1<<13)         // Non-US time zone     (west of UT)
-                (1<<14)         // U.S. time zone
-                (1<<15)         // Daylight savings
-
-                The lower 12 bits (0 through 11) contain the number of minutes
-                east or west of UT (not accounting for daylight savings).
-
-                If the time zone is one specified in the U.S. Uniform Time Act,
-                the following values represent the zone:
-
-                AST 0x40F0      // Atlantic             (-04:00)
-                EST 0x412C      // Eastern              (-05:00)
-                CST 0x4168      // Central              (-06:00)
-                MST 0x41A4      // Mountain             (-07:00)
-                PST 0x41E0      // Pacific              (-08:00)
-                YST 0x421C      // Yukon                (-09:00)
-                HST 0x4258      // Hawaii/Alaska        (-10:00)
-                BST 0x4294      // Bering               (-11:00)
-
-                With bit 15 set, the following values represent the same zone
-                with the presence of daylight savings:
-
-                ADT 0xC0F0      // Atlantic             (-03:00)
-                EDT 0xC12C      // Eastern              (-04:00)
-                CDT 0xC168      // Central              (-05:00)
-                MDT 0xC1A4      // Mountain             (-06:00)
-                PDT 0xC1E0      // Pacific              (-07:00)
-                YDT 0xC21C      // Yukon                (-08:00)
-                HDT 0xC258      // Hawaii/Alaska        (-09:00)
-                BDT 0xC294      // Bering               (-10:00)
-
-                The following non-standard time zone specifications may also be
-                used:
-
-                MID 0x2294      // Midway               (-11:00)
-                VAN 0x21E0      // Vancouver            (-08:00)
-                EDM 0x21A4      // Edmonton             (-07:00)
-                WIN 0x2168      // Winnipeg             (-06:00)
-                BOG 0x212C      // Bogota               (-05:00)
-                CAR 0x20F0      // Caracas              (-04:00)
-                RIO 0x20B4      // Rio de Janeiro       (-03:00)
-                FER 0x2078      // Fernando de Noronha  (-02:00)
-                AZO 0x203C      // Azores               (-01:00)
-                LON 0x1000      // London               (+00:00)
-                BER 0x103C      // Berlin               (+01:00)
-                ATH 0x1078      // Athens               (+02:00)
-                MOS 0x10B4      // Moscow               (+03:00)
-                DUB 0x10F0      // Dubai                (+04:00)
-                KAB 0x110E      // Kabul                (+04:30)
-                KAR 0x112C      // Karachi              (+05:00)
-                BOM 0x114A      // Bombay               (+05:30)
-                KAT 0x1159      // Kathmandu            (+05:45)
-                DHA 0x1168      // Dhaka                (+06:00)
-                BAN 0x11A4      // Bangkok              (+07:00)
-                HON 0x11E0      // Hong Kong            (+08:00)
-                TOK 0x121C      // Tokyo                (+09:00)
-                SYD 0x1258      // Sydney               (+10:00)
-                NOU 0x1294      // Noumea               (+11:00)
-                WEL 0x12D0      // Wellington           (+12:00)
-
-fidoaddr_t      FidoNet address stored as four ushorts that represent the zone,
-                network, node, and point (in that order).
-                C example:
-
-                typedef struct {
-
-                    ushort zone,
-                           net,
-                           node,
-                           point;
-
-                    } fidoaddr_t;
-
-
-typestr_t       ASCIIZ string with ushort type prefix.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'str'
-                    uchar   str[];  // ASCIIZ filename or other string data
-
-                    } typestr_t;
-
-
-mattach_t       File attachment information with type prefix, translation
-                string, and filename.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Attachment type
-                    ushort  xlat[]; // Translations of data in attachment
-                    uchar   str[];  // ASCIIZ filename
-
-                    } mattach_t;
-
-vattach_t		Video file attachment information with type, compression,
-				translation string, and filename.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Attachment type
-					ushort	comp;	// Compression method
-                    ushort  xlat[]; // Translations of data in attachment
-                    uchar   str[];  // ASCIIZ filename
-
-					} vattach_t;
-
-mtext_t         Message text with translation string prefix.
-                C example:
-
-                typedef struct {
-
-                    ushort  xlat[]; // Translations of text
-                    uchar   text[]; // Actual text data
-
-					} mtext_t;
-
-
-ftext_t         Formatted message text with translation string prefix and
-                format type.
-                C example:
-
-                typedef struct {
-
-					ushort	type;	// See Image Types for valid types
-					ushort	xlat[]; // Translations of data
-					uchar	data[]; // Actual formatted text data
-
-					} ftext_t;
-
-
-membed_t        Embedded data with type prefix, translation string, and ASCIIZ
-                description.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'dat'
-                    ushort  xlat[]; // Translations of embedded data
-                    uchar   name[]; // ASCIIZ char description of embedded data
-					uchar	data[]; // Binary data
-
-                    } membed_t;
-
-vembed_t		Embedded video data with type, compression method, translation
-				string, and ASCIIZ description.
-                C example:
-
-                typedef struct {
-
-                    ushort  type;   // Specifier for type of 'dat'
-					ushort	comp;	// Compression method
-                    ushort  xlat[]; // Translations of embedded data
-                    uchar   name[]; // ASCIIZ char description of embedded data
-					uchar	data[]; // Binary data
-
-					} vembed_t;
-
-File formats
-============
-&&File Formats
-$$FILEFORM
-&&Index (*.SID) File Format
-$$SID_FORM
-
-Index File (*.SID)
-------------------
-The index file for each message base contains one record per message in the
-base. Each record is fixed length using the following format:
-
-Index Record:
-------------
-C example:
-
-typedef struct {
-
-	ushort	to; 	// 16-bit CRC of recipient name (lower case) or user number
-	ushort	from;	// 16-bit CRC of sender name (lower case) or user number
-	ushort	subj;	// 16-bit CRC of title/subject (lower case)
-	ushort	attr;	// attributes (MSG_PRIVATE, MSG_READ, etc. flags)
-	ulong	offset; // byte offset of message header in header file
-	ulong	number; // message serial number (1 based)
-	time_t	time;	// import date/time stamp (Unix format)
-
-    } idxrec_t;
-
-
-Example file dump (16 messages starting with message number 15):
----------------------------------------------------------------
-000000	  36 4F 13 07 2A 77 00 00	20 00 00 00 0F 00 00 00    6O..*w.. .......
-000010    BE 62 76 2C 36 4F 46 0A   7F B2 00 00 20 01 00 00    �bv,6OF.�.. ...
-000020    10 00 00 00 C7 29 78 2C   36 4F 70 6F 46 FF 00 00    ....�)x,6OpoF�..
-000030    20 02 00 00 11 00 00 00   AD D3 7A 2C 70 6F 13 07     .......��z,po..
-000040    46 FF 00 00 20 03 00 00   12 00 00 00 D6 F8 7F 2C    F�.. .......��,
-000050    36 4F E1 EA E7 E9 00 00   20 04 00 00 13 00 00 00    6O����.. .......
-000060    1E 7B 85 2C 37 0D 2E DF   4D 79 00 00 20 05 00 00    .{�,7..�My.. ...
-000070    14 00 00 00 5C E1 A1 2C   90 54 2D 5A 86 62 00 00    ....\�,�T-Z�b..
-000080    20 06 00 00 15 00 00 00   39 2E A2 2C 70 6F 1A 8B     .......9.�,po.�
-000090    46 FF 00 00 20 07 00 00   16 00 00 00 D0 7B A8 2C    F�.. .......�{�,
-0000A0    2E DF 1A 8B 4D 79 00 00   20 08 00 00 17 00 00 00    .�.�My.. .......
-0000B0    FF 7B A8 2C B4 D9 35 7C   23 B1 00 00 20 09 00 00    �{�,��5|#�.. ...
-0000C0    18 00 00 00 CE D4 BA 2C   36 4F BC D8 B2 E7 00 00    ....�Ժ,6O�ز�..
-0000D0    20 0A 00 00 19 00 00 00   14 5F C3 2C BA A8 4E B0     ........_�,��N�
-0000E0    67 76 00 00 20 0B 00 00   1A 00 00 00 6F 89 C3 2C    gv.. .......o��,
-0000F0    36 4F 0C 01 19 9C 00 00   20 0C 00 00 1B 00 00 00    6O...�.. .......
-000100    F8 30 C6 2C 36 4F FA 48   0E 55 00 00 20 0D 00 00    �0�,6O�H.U.. ...
-000110    1C 00 00 00 6A 94 D3 2C   36 4F F1 CE CF A2 00 00    ....j��,6O��Ϣ..
-000120    20 0E 00 00 1D 00 00 00   53 DB D5 2C 8D A6 21 CE     .......S��,��!�
-000130    F7 AB 00 00 20 0F 00 00   1E 00 00 00 31 29 DC 2C    ��.. .......1)�,
-
-
-Field descriptions:
-------------------
-To:
-The 'To' field is the CRC-16 of the name of the intended recipient agent of
-this message or the intended recipient's user number. If the CRC is stored, the
-text must be converted to lower case (A-Z changed to a-z) before the CRC is
-calculated. If the message is forwarded to another agent, the original or new
-index record must be changed to contain the CRC-16 of the new recipient name or
-user number. This field must always contain the recipient user number for local
-e-mail on a Synchronet BBS. Outbound netmail stored in the Synchronet local
-e-mail message base will contain 0 in this field.
-
-From:
-This field, similar to the 'To' field, contains the CRC-16 of the name of the
-sending agent of this message or the sender's user number. If the CRC is
-stored, the text must be converted to lower case (A-Z changed to a-z) before
-the CRC is calculated. If the message is forwarded to another agent, the
-original or new index record must be changed to contain the CRC-16 of the new
-sender name or user number. If the message was imported into the local e-mail
-message base on a Synchronet BBS via netmail, this field will contain 0.
-
-Subj:
-The 'Subj' field contains the CRC-16 of the message's subject. The subject
-must be converted to lower case (A-Z changed to a-z) and all preceeding
-"re: "'s and "re:"'s removed before calculating the CRC-16.
-
-Attr:
-This ushort is a bit field of the specific attributes for this message.
-It is a clone of the 'attr' element of the msghdr_t structure.
-
-Offset:
-This ulong is the offset (in bytes) in the header file for this message's
-header record.
-
-Number:
-This ulong is the serial number of this message. Valid values are 1 through
-0xffffffff. No two index records in the same message base may have the same
-message number. All index records must have sequential, but not necessarily
-consequetive, message numbers.
-
-Time:
-This field is the date/time stamp the message was imported to or posted in
-the message base. It is a clone of the 'when_imported.time' element of the
-msghdr_t structure.
-
-Header File (*.SHD)
-===================
-&&Header File (*.SHD) Format
-$$SHD_FORM
-
-Each SMB header file is made up of two distinct sections: base header records
-and message header records (usually the bulk of the file).
-
-Base Header Records:
--------------------
-Base header records are blocks of data that apply to the entire message base
-and are of variable length. This specification defines only one base header
-record, the "Status info" (smbstatus_t) record. This status info record must be
-the first base header record in the file and must be modified if additional
-base header records are added.
-
-Additional header records allow other developers to store configuration and
-status information particular to their application needs. It also allows for
-future header record definitions as part of this specification without causing
-backward compatibility issues.
-
-Each base header record contains a fixed length portion (smbhdr_t) and an
-optional variable length portion.
-
-Whenever a base header record is read or updated (written), it must first
-be successfully locked and subsequently unlocked.
-
-The first base header record (Status Info) is used as a semaphore when writing
-to the message index (.SID) file and, when using the Hyper Allocation storage
-method, writing to the message data (.SDT) file. This record must be
-succesfully locked before writing and subsequently unlocked. This is to insure
-that multiple applications simultaneously writing to the same message base
-does result in corrrupted data.
-
-
-Message Header Records:
-----------------------
-Following the last base header record is the first message header record. Each
-header record is stored in one or more 256 byte blocks. There must be exactly
-one active message header record for every index record in the index file.
-(Note: This does not include deleted message headers that have not been
-overwritten by a new message header).
-
-Each message header record contains a fixed length portion (msghdr_t), a list
-of zero or more fixed length data fields (dfield_t), and a list of three or
-more variable length header fields (hfield_t).
-
-The value of the data stored in the zero or more unused bytes of the last
-header record block have an undefined value, though whenever possible
-developers should initialize to binary zero for human readability.
-
-Whenever a message header record is read or updated (written), it must first
-be successfully locked and subsequently unlocked.
-
-Base Header Record (Fixed Portion):
-----------------------------------
-C example:
-
-typedef struct {
-
-    uchar   id[4];          // text or binary unique hdr ID
-    ushort  version;        // version number (initially 100h for 1.00)
-    ushort  length;         // length including this struct
-
-    } smbhdr_t;
-
-
-Base Header Record Field Descriptions:
--------------------------------------
-Id:
-This is a four byte unique ID identifying the type of the base header record.
-The bytes may contain any value, but printable ASCII characters are preferred.
-The only ID defined in this specification is "SMB^Z" used by the Status Info
-base header record.
-
-Version:
-This is a version number of the base header record type. Base header records
-of different versions may have different formats or contain different
-information. This is to aid the application in determining if the record
-is pertinent and if so, to what degree. The Status Info base header record
-uses this version field to define the version of the format for the entire
-message base (currently 0x121 for version 1.21).
-
-Length:
-This is entire length in bytes of this header record (including both fixed
-and variable portions).
-
-
-Base Header #1 (Status info) Record (Variable Portion):
-------------------------------------------------------
-C example:
-
-typedef struct {
-
-	ulong	last_msg;		// last message number posted or imported
-	ulong	total_msgs; 	// total messages currently in message base
-    ulong   header_offset;  // byte offset to first header record
-    ulong   max_crcs;       // Maximum number of CRCs to keep in history
-	ulong	max_msgs;		// Maximum number of messages to keep in base
-    ushort  max_age;        // Maximum age of messages (days) to keep in base
-	ushort	attr;			// Attribute bits
-
-    } smbstatus_t;
-
-Base Header #1 (Status Info) Record (Variable Portion) Field Descriptions:
--------------------------------------------------------------------------
-Last_msg:
-This is the serial number of the last message imported or posted into this
-message base. The index, header, and data records for this message may possibly
-not exist (due to deletion). This field is used for determining the message
-number to give to a new message being imported or posted into this message
-base. This field must be updated for every message added to the message base.
-
-Total_msgs:
-This is the total number of active messages currently in the message base.
-This number should match the number of records in the index (.SID) file
-and active header records in the header (.SHD) file. This field must be
-updated whenever a message is added to or removed from the message base.
-
-Header_offset:
-This is the byte offset to the first message header record. It is useful
-for skipping all the base header records and going directly to the first
-message header record.
-
-Max_crcs:
-This is the maximum number of message CRCs to store in the CRC history (.SCH)
-file for duplicate message checking. If this field contains 0, then duplicate
-message checking is disabled.
-
-Max_msgs:
-This is the preferred maximum number of messages to keep in this message
-base as specified by the system operator. It is used by maintenance programs
-that trim the message base down by removing old messages. This field should
-be ignored by applications importing or posting messages allowing them to
-exceed this maximum at will.
-
-Max_age:
-This field is the maximum age (in days) of messages to keep in the message
-base. It is used by maintenance programs to purge out-dated messages from
-the message base.
-
-Attr:
-This is a bit field containing specific attributes (or flags) that may define
-the way messages are stored or retrieved from the this message base. The
-following attributes are defined:
-
-	SMB_EMAIL		(1<<0)
-
-	Indicates the message base is specifically for messages to or from local
-	users. When this bit is set, the idxrec.to and idxrec.from fields will
-	contain the user numbers (or 0 for non-user destination/source) instead of
-	the CRC-16 of the agent name.
-
-	SMB_HYPERALLOC	(1<<1)
-
-	Indicates the message base uses the Hyper Allocation storage method. This
-	bit should not be cleared by an application without first deleting all the
-	messages in the message base. This is due to the fact the Hyper Allocation
-	is not downward compatible with the Self-packing and Fast Allocation
-	storage methods.
-
-When used with Synchronet BBS software, a message base must NOT have both of
-the above attributes set. The only message base that should have the SMB_EMAIL
-attribute set is the DATA\MAIL message base.
-
-
-Base Header #1 (Status info) Record Contents:
---------------------------------------------
-smbhdr.id="SMB\x1a";        // SMB^Z
-smbhdr.version=0x121;		// v1.21
-smbhdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); smbstatus_t status;
-
-
-Additional Base Headers:
------------------------
-Additional headers from developers must have initial 8 bytes in smbhdr_t
-format, length must include size of smbhdr_t, and header_offset of smbstatus_t
-must be changed to include the size of the additional header(s).
-
-
-Example file dump (base header portion only):
---------------------------------------------
-000000	  53 4D 42 1A 20 01 20 00	F4 01 00 00 F4 01 00 00    SMB. . .�...�...
-000010    20 00 00 00 D0 07 00 00   D0 07 00 00 00 00 00 00     ...�...�.......
-
-
-Message Header Record (Fixed portion):
--------------------------------------
-C example:
-
-typedef struct {
-
-    uchar   id[4];          // SHD^Z (same for all types and versions)
-    ushort  type;           // Message type (this is the definition of type 0)
-    ushort  version;        // Version of type (initially 100h for 1.00)
-    ushort  length;         // Total length of fixed portion + all fields
-    ushort  attr;           // Attributes (bit field) (duplicated in SID)
-    ulong   auxattr;        // Auxillary attributes (bit field)
-    ulong   netattr;        // Network attributes (bit field)
-    when_t  when_written;   // Date/Time message was originally created
-    when_t  when_imported;  // Date/Time message was imported (locally)
-    ulong   number;         // Message number (unique, not necessarily seq.)
-    ulong   thread_orig;    // Original message number in thread
-    ulong   thread_next;    // Next message in thread
-    ulong   thread_first;   // Number of first reply to this message
-    uchar   reserved[16];   // 16 reserved bytes for future use
-    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-    ushort  total_dfields;  // Total number of data fields
-
-    } msghdr_t;
-
-typedef struct {
-
-    ushort  type;           // See "Data Field Types" values
-    ulong   offset;         // Offset into buffer 
-    ulong   length;         // Length of data field in buffer
-
-    } dfield_t;
-
-typedef struct {
-
-    ushort  type;           // See "Header Field Types" for values
-    ushort  length;         // Length of buffer
-    uchar   dat[length];
-
-    } hfield_t;
-
-Example file dump (one header record, both fixed and variable length portions):
-------------------------------------------------------------------------------
-000020	  53 48 44 1A 00 00 20 01	F5 00 00 00 00 00 00 00    SHD... .�.......
-000030    00 00 00 00 46 DB F7 2C   00 00 7D D7 29 2D 00 00    ....F��,..}�)-..
-000040    01 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-000050    00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00    ................
-000060    00 00 00 00 02 00 00 00   00 00 00 00 4A 01 00 00    ............J...
-000070    02 00 4A 01 00 00 53 00   00 00 00 00 13 00 4D 61    ..J...S.......Ma
-000080    72 69 61 6E 6E 65 20 4D   6F 6E 74 67 6F 6D 65 72    rianne Montgomer
-000090    79 30 00 0C 00 43 61 72   6F 6C 20 47 61 69 73 65    y0...Carol Gaise
-0000A0    72 60 00 07 00 46 61 72   6E 68 61 6D A4 00 14 00    r`...Farnham�...
-0000B0    31 3A 31 33 38 2F 31 30   32 2E 30 20 32 63 66 38    1:138/102.0 2cf8
-0000C0    30 35 37 36 A5 00 14 00   31 3A 33 34 33 2F 31 30    0576�...1:343/10
-0000D0    30 2E 30 20 32 63 66 33   62 39 30 61 A3 00 23 00    0.0 2cf3b90a�.#.
-0000E0    31 33 38 2F 31 30 32 20   31 20 32 37 30 2F 31 30    138/102 1 270/10
-0000F0    31 20 32 30 39 2F 32 30   39 20 31 30 33 2F 30 20    1 209/209 103/0 
-000100    33 35 35 02 00 02 00 02   00 03 00 08 00 01 00 8A    355............�
-000110    00 66 00 00 00 00 00 00   00 00 00 00 00 00 00 00    .f..............
-
-Contents of example header:
---------------------------
-id					 SHD^Z
-type				 0000h
-version 			 0120h
-length               245
-attr                 0000h
-auxattr              00000000h
-netattr              00000000h
-when_written         Sat Nov 27 17:57:10 1993
-when_imported        Tue Jan 04 15:54:21 1994
-number               1
-thread_orig          0
-thread_next          0
-thread_first         0
-reserved[16]         
-offset               0
-total_dfields        2
-
-dfield[0].type       00h
-dfield[0].offset     0
-dfield[0].length     330
-dfield[1].type		 02h
-dfield[1].offset     330
-dfield[1].length     83
-
-hfield[0].type       00h
-hfield[0].length     19
-hfield[0]_dat        Marianne Montgomery
-hfield[1].type		 30h
-hfield[1].length     12
-hfield[1]_dat        Carol Gaiser
-hfield[2].type		 60h
-hfield[2].length     7
-hfield[2]_dat        Farnham
-hfield[3].type		 A4h
-hfield[3].length     20
-hfield[3]_dat        1:138/102.0 2cf80576
-hfield[4].type		 A5h
-hfield[4].length     20
-hfield[4]_dat        1:343/100.0 2cf3b90a
-hfield[5].type		 A3h
-hfield[5].length     35
-hfield[5]_dat        138/102 1 270/101 209/209 103/0 355
-hfield[6].type		 02h
-hfield[6].length     2
-hfield[6]_dat		 02 00
-hfield[7].type		 03h
-hfield[7].length     8
-hfield[7]_dat        01 00 8A 00 66 00 00 00
-
-Fixed Portion Field descriptions:
---------------------------------
-Id:
-This field (regardless of the header type or version) must always contain the
-the string "SHD^Z". This is to aid in the restoration of a corrupted header
-file and give a visual indication of the beginning of a new header record when
-viewing dumps of the header file.
-
-Type:
-This is the message header type. Only one type is currently defined by this
-specification (type 0). Any and all future header types will have the first
-4 fields (10 bytes) in the same format of type 0. This allows other types
-(with different lengths) to be skipped because the 4th field (length) will
-always be in the same position.
-
-Version:
-This is the version of this header type. This specification defines version
-1.21 of message header type 0 (stored as 121h).
-
-Length:
-This is the total length of this message header record (including both fixed
-and variable length portions, but NOT including unused block space).
-
-Attr:
-This is a bit field (16-bit) containing basic message attributes (flags) for
-this message. An exact duplicate of this field is stored in the index file as
-well. They must always match.
-
-Auxattr:
-This is a bit field (32-bit) containing the auxillary attributes (flags) for
-this message. The attributes stored in this variable are more specific in
-nature and less critical than those in the Attr field.
-
-Netattr:
-This is a bit field (32-bit) containing the network attributes (flags) for this
-message. The attributes stored in this variable are related solely to message
-networking.
-
-When_written:
-This is the date and time when the message was originally created.
-
-When_imported:
-This is the date and time when the message was posted on or imported into the
-local message system.
-
-Number:
-This is the message's unique serial number (from 1 to FFFFFFFFh). This field
-is duplicated in the index file. They must always match.
-
-Thread_orig:
-If this message is a reply, then this field contains the number of the original
-message that was replied to. If this message was not a reply, this field will
-contain the value 0.
-
-Thread_next:
-If this message is a reply, and there are later replies to that message
-(the message number contained in the Thread_orig field), then this field will
-contain the number of the next reply in the chain. If this message is the only
-reply to the orignal message, this field will contain the value 0.
-
-Thread_first:
-If there are any replies to this message (after it has been posted), this field
-will contain the number of the first reply to this message. If there are no
-replies to this message, this field will contain the value 0.
-
-Reserved:
-Unused bytes, reserved for future definition in the message header type 0
-specification.
-
-Offset:
-The byte offset into the data file, specifying the start of the buffer for
-all data associated with this message. This value must be either 0 or modula
-256. When retrieving the actual data portion of data fields, the physical
-offset into the file will be the offset of the message data buffer (this field)
-plus the offset of the individual data field (msghdr_t.offset+dfield_t.offset).
-
-Total_dfields:
-This field contains the total number of data fields associated with this
-message. The value of this field must match the actual number of data fields
-stored in the header (dfield_t data types following the fixed portion of the
-message header).
-
-
-Variable Portion Field descriptions:
------------------------------------
-See the Header Field Type and Data Field Type sections for the descriptions
-of the values contained in these fields.
-
-Message Header Block Allocation (*.SHA)
-=======================================
-&&Header Allocation File (*.SHA) Format
-$$SHA_FORM
-
-If this message base uses the Hyper Allocation storage method (the
-SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-not created or used.
-
-This file contains no header or signature data. Each byte (uchar) in the file
-specifies the allocation state of the corresponding 256 byte block in the
-header (*.SHD) file. A value of 0 indicates a free header block, and a value of
-1 indicates an allocated block. Other non-zero values are undefined.
-
-This file must always be opened DENY ALL (non-shareable).
-
-Message Data (*.SDT)
-====================
-&&Data File (*.SDT) Format
-$$SDT_FORM
-
-This file contains no header or signature data. It contains the text and other
-embedded data for the messages in a single message base. The data for each
-message always begins on a 256 byte block boundary. The data in the unused
-portion of a data block is undefined, but should be initialized to NULL
-whenever possible.
-
-This file must always be opened DENY NONE (shareable).
-
-Data fields of type TEXT_BODY and TEXT_TAIL must have all trailing white space
-and control characters removed (i.e. the last character of the data record
-must be in the range 21h to FFh). The only exception to this rule, is if the
-TEXT_BODY is terminated with multiple contiguous CRLFs, only the last CRLF
-should be removed. A CRLF should always be appended to the text data when it is
-displayed.
-
-When reading from this file, it is a good idea to make sure the message header
-for the data being read is currently locked (though no single message header
-should be locked for extended durations of time). This will insure that no
-other application will write to this portion of the file while it's being
-read (read from disk, not displayed).
-
-When using the Hyper Allocation storage method, the Status Info message base
-header must be successfully locked before writing to this file and subsequently
-unlocked.
-
-Message Data Block Allocation (*.SDA)
-=====================================
-&&Data Allocation File (*.SDA) Format
-$$SDA_FORM
-
-If this message base uses the Hyper Allocation storage method (the
-SMB_HYPERALLOC bit is set in the smbstatus_t.attr field), then this file is
-not created or used.
-
-This file contains no header or signature data. Each word (ushort) in the file
-specifies the allocation state of the corresponding 256 byte block in the data
-(*.SDT) file. A value of 0 indicates a free block, and a non-zero value
-indicates the number of message header records associated with this message
-data (most often 1). Each block can be used by up to 65,535 header records.
-
-This file must always be opened DENY ALL (non-shareable).
-
-CRC history for duplicate message checking (*.SCH)
-==================================================
-&&CRC History File (*.SCH) Format
-$$SCH_FORM
-
-This file is optional and contains no header or signature data. Each long word
-(ulong) in the file contains a CRC-32 of previously posted/imported messages.
-These CRCs can be used to check a candidate message for posting/import to be
-sure the message isn't a duplicate created by human or program error. The
-maximum number of CRCs to store is defined in the first message base header
-record (smbstatus_t.max_crcs).
-
-The CRC is calculated on the first TEXT_BODY data field before any translations
-are applied (e.g. encoding, compression, encryption).
-
-This file must always be opened DENY ALL (non-shareable).
-
-Header Field Types:
-==================
-&&Header Field Types
-$$HFIELD_T
-
-These are the defined valid values for hfield_t.type:
-
-Name     : SENDER
-Value    : 00h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes
-Summary  : Name of agent that sent this message
-
-If blank (0 length or nulstr), assumed "Anonymous". If multiple SENDER fields
-exist, then the message has been forwarded and the order of the fields in the
-record must match the forwarding order (chronologically). When forwarding a
-message, the original SENDER field should be left intact and new SENDER,
-FORWARDED, and RECIPIENT fields added to the end of the record.
-
-Name     : SENDERAGENT
-Value    : 01h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : AGENT_PERSON or previous SENDERAGENT if exists
-Summary  : Type of agent that sent this message
-
-If multiple SENDER fields exist, then the message has been forwarded. If any of the
-forwarding agents is of a type other than AGENT_PERSON, then this field must
-follow that SENDER field to specify the agent type.
-
-Name     : SENDERNETTYPE
-Value    : 02h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : NET_NONE or previous SENDERNETTYPE if exists
-Summary  : Type of network message was sent from
-
-If multiple SENDERNETADDR fields are included, a SENDERNETTYPE field should be
-included before each to determine what data type the address is stored in.
-
-Name     : SENDERNETADDR
-Value    : 03h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERNETADDR if exists
-Summary  : Network address for agent that sent this message
-
-The SENDERNETTYPE field indicates the data type of this field. If the
-SENDERNETTYPE is of type NET_INTERNET, the local-part of the Internet
-address is optional. If the local-part separator character ('@') is omitted,
-the SENDER field is assumed to be the local-part of the address.
-
-Name     : SENDEREXT
-Value    : 04h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDEREXT if exists
-Summary  : Extension of sending agent
-
-This field is useful for storing the sending agent's extension, when the
-agent's extension binds more tightly than the agent's name.
-
-For example, Synchronet Multinode BBS Software stores local e-mail with the
-sending and receiving agent's user numbers stored as their respective
-extensions. This is done so that if a user name changes for some reason,
-messages will not "disappear" from the user's mail box.
-
-If the SMB_EMAIL status header attribute is set, then the "From" field in the
-index must contain the binary value of this field rather than the CRC-16 of the
-SENDER (name) field.
-
-Name     : SENDERPOS
-Value    : 05h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERPOS if exists
-Summary  : Position of sending agent
-
-Primarily for documentary purposes, this field contains the position of the
-sending agent (i.e. President, Sysop, C.E.O., MIS Director, etc).
-
-It can also be useful for getting a message or reply to the intended
-recipient when the agent name is not located or is unknown, but the position
-of the agent is known and specified.
-
-Name     : SENDERORG
-Value    : 06h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous SENDERORG if exists
-Summary  : Organization name of sending agent
-
-Primarily for documentary purposes, this field contains the organization to
-which the sending agent belongs (i.e. Microsoft, Joe's BBS, SoCal User's Group,
-etc).
-
-Name     : AUTHOR
-Value    : 10h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Default  : First SENDER
-Summary  : Name of agent that created this message
-
-This field can only be added by the process that originally creates the
-message. It should not be included if same as first SENDER field. If multiple
-AUTHOR fields exist, then the message was created by multiple agents and is
-considered valid. The order of multiple AUTHOR fields in the record is not
-significant.
-
-Name     : AUTHORAGENT
-Value    : 11h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERAGENT or previous AUTHORAGENT if exists
-Summary  : Type of agent that created this message
-
-This field can only be added by the process that originally creates the
-message. It should not be included if same as first SENDERAGENT field. If
-multiple AUTHOR fields exist, then the message was created by multiple agents
-and if the agent type for any of the authors is other than AGENT_PERSON, an
-AUTHORAGENT field must follow to specify the agent type.
-
-Name     : AUTHORNETTYPE
-Value    : 12h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERNETTYPE or previous AUTHORNETTYPE if exists
-Summary  : Type of network this author is member of
-
-Name     : AUTHORNETADDR
-Value    : 13h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERNETADDR or previous AUTHORNETADDR if exists
-Summary  : Network address of this author
-
-Name     : AUTHOREXT
-Value    : 14h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDEREXT or previous AUTHOREXT if exists
-Summary  : Extension of this author
-
-Name     : AUTHORPOS
-Value    : 15h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERPOS or previous AUTHORPOS if exists
-Summary  : Position of this author
-
-Name     : AUTHORORG
-Value    : 16h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : SENDERORG or previous AUTHORORG if exists
-Summary  : Organization this author belongs to
-
-Name     : REPLYTO
-Value    : 20h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDER
-Summary  : Name of agent that replies should go to
-
-Name     : REPLYTOAGENT
-Value    : 21h
-Data     : ushort
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERAGENT
-Summary  : Type of agent that replies should go to
-
-Name     : REPLYTONETTYPE
-Value    : 22h
-Data     : ushort
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERNETTYPE
-Summary  : Type of network that replies should go to
-
-Name     : REPLYTONETADDR
-Value    : 23h
-Data     : undef
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERNETADDR
-Summary  : Network address that replies should go to
-
-Name     : REPLYTOEXT
-Value    : 24h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDEREXT
-Summary  : Extension of agent that replies should go to
-
-Name     : REPLYTOPOS
-Value    : 25h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERPOS
-Summary  : Position of agent that replies should go to
-
-Name     : REPLYTOORG
-Value    : 26h
-Data     : ASCII
-Multiple : Yes, but only last is valid
-Required : No
-Default  : SENDERORG
-Summary  : Organization of agent that replies should go to
-
-Name     : RECIPIENT
-Value    : 30h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes
-Default  : "All"
-Summary  : Name of agent to receive this message
-
-If multiple RECIPIENT fields exist, the message has been forwarded and for each
-additional RECIPIENT field (after the initial RECIPIENT), there should be a
-FORWARDED field. The order of the RECIPIENT fields in the record must match the
-order in which the message was sent and forwarded (chronologically).
-
-Name     : RECIPIENTAGENT
-Value    : 31h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : AGENT_PERSON or previous RECIPIENTAGENT if exists
-Summary  : Type of agent to receive this message
-
-If multiple RECIPIENT fields exist, the message has been forwarded. If any of
-the recipient agents are of a type other than AGENT_PERSON, this field must
-follow the RECIPIENT field to specify the agent type.
-
-Name     : RECIPIENTNETTYPE
-Value    : 32h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : NET_NONE or previous RECIPIENTNETTYPE if exists
-Summary  : Type of network to receive this message
-
-Name     : RECIPIENTNETADDR
-Value    : 33h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTNETADDR if exists
-Summary  : Address of network to receive this message
-
-Name     : RECIPIENTEXT
-Value    : 34h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTEXT if exists
-Summary  : Extension of agent to receive this message
-
-If SMB_EMAIL status header attribute is set, then the "To" field in the index
-must contain the binary value of this field rather than the CRC-16 of the
-RECIPIENT (name) field. This is the case specifically with the local e-mail
-message base on a Synchronet BBS.
-
-Name     : RECIPIENTPOS
-Value    : 35h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTPOS if exists
-Summary  : Position of agent to receive this message
-
-Name     : RECIPIENTORG
-Value    : 36h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : Previous RECIPIENTORG if exists
-Summary  : Type of agent to receive this message
-
-Name     : FORWARDTO
-Value    : 40h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of agent this message is to be forwarded to
-
-Name     : FORWARDTOAGENT
-Value    : 41h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTAGENT or previous FORWARDTOAGENT if exists
-Summary  : Type of agent this message is to be forwarded to
-
-Name     : FORWARDTONETTYPE
-Value    : 42h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETTYPE or previous FORWARDTONETTYPE if exists
-Summary  : Type of network this message is to be forwarded to
-
-Name     : FORWARDTONETADDR
-Value    : 43h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETADDR or previous FORWARDTONETADDR if exists
-Summary  : Network address this message is to be forwarded to
-
-Name     : FORWARDTOEXT
-Value    : 44h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTEXT or previous FORWARDTOEXT if exists
-Summary  : Extension of agent this message is to be forwarded to
-
-Name     : FORWARDTOPOS
-Value    : 45h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTPOS or previous FORWARDTOPOS if exists
-Summary  : Position of agent this message is to be forwarded to
-
-Name     : FORWARDTOORG
-Value    : 46h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTORG or previous FORWARDTOORG if exists
-Summary  : Organization of agent this message is to be forwarded to
-
-Name     : FORWARDED
-Value    : 48h
-Data     : when_t
-Multiple : Yes, order significant
-Required : Yes, if forwarded
-Summary  : Date/Time this message was forwarded to another agent
-
-Name     : RECEIVEDBY
-Value    : 50h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : Yes, if receiving agent is other than RECIPIENT
-Summary  : Name of agent that received this message
-
-Name     : RECEIVEDBYAGENT
-Value    : 51h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTAGENT or previous RECEIVEDBYAGENT if exists
-Summary  : Type of agent that received this message
-
-Name     : RECEIVEDBYNETTYPE
-Value    : 52h
-Data     : ushort
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETTYPE or previous RECEIVEDBYNETTYPE if exists
-Summary  : Type of network that received this message
-
-Name     : RECEIVEDBYNETADDR
-Value    : 53h
-Data     : undef
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTNETADDR or previous RECEIVEDBYNETADDR if exists
-Summary  : Network address that received this message
-
-Name     : RECEIVEDBYEXT
-Value    : 54h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTEXT or previous RECEIVEDBYEXT if exists
-Summary  : Extension of agent that received this message
-
-Name     : RECEIVEDBYPOS
-Value    : 55h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTPOS or previous RECEIVEDBYPOS if exists
-Summary  : Position of agent that received this message
-
-Name     : RECEIVEDBYORG
-Value    : 56h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Default  : RECIPIENTORG or previous RECEIVEDBYORG if exists
-Summary  : Organization of agent that received this message
-
-Name     : RECEIVED
-Value    : 58h
-Data     : when_t
-Multiple : Yes, order significant
-Required : Yes, if received
-Default  : NULL
-Summary  : Date/Time this message was received
-
-Name     : SUBJECT
-Value    : 60h
-Data     : ASCII
-Multiple : No
-Required : Yes, but may be blank (0 length or nulstr)
-Summary  : Subject/title of message
-
-Name     : SUMMARY
-Value    : 61h
-Data     : ASCII
-Multiple : No
-Required : No
-Summary  : Summary of message contents, created by AUTHOR
-
-Name     : COMMENT
-Value    : 62h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Comment about this message, created by SENDER
-
-This field is useful for adding notes to a message when forwarding to a new
-recipient.
-
-Name     : CARBONCOPY
-Value    : 63h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : List of agents this message was also sent to
-
-This field is optional and only for the use of notifying the recipient of who
-else received the message.
-
-Name     : GROUP
-Value    : 64h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of group of users to receive message on recipient system
-
-This field is used when sending to a group name across a network, where the
-group can be expanded into multiple header records for each agent on the
-destination system.
-
-Name     : EXPIRATION
-Value    : 65h
-Data     : when_t
-Multiple : No
-Required : No
-Summary  : Date/Time that this message will expire
-
-Name     : PRIORITY
-Value    : 66h
-Data     : ulong
-Multiple : No
-Required : No
-Default  : 0
-Summary  : Message priority (0 is lowest, FFFFFFFFh is highest)
-
-Name     : FILEATTACH
-Value    : 70h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name/file specification of attached file(s)
-
-Name of attached file(s). Wildcards allowed. MSG_FILEATTACH attribute must be
-set. If the MSG_FILEATTACH attribute is set but this field is not included,
-the SUBJECT field is assumed to be the filename(s).
-
-Name     : DESTFILE
-Value    : 71h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Destination name for attached file(s)
-
-Wildcards allowed. FILEATTACH field must also be included.
-
-Name     : FILEATTACHLIST
-Value    : 72h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of ASCII list of attached filenames
-
-Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-MSG_FILEATTACH attribute must be set.
-
-Name     : DESTFILELIST
-Value    : 73h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of ASCII list of destination filenames
-
-Wildcards not allowed in ASCII list filename. Wildcards allowed in ASCII list.
-
-Name     : FILEREQUEST
-Value    : 74h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of requested file
-
-Wildcards allowed. MSG_FILEREQUEST attribute must be set
-
-Name     : FILEPASSWORD
-Value    : 75h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Password for FILEREQUEST
-
-Name     : FILEREQUESTLIST
-Value    : 76h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Name of ASCII list of filenames to request
-
-Wildcards allowed.
-
-Name     : FILEPASSWORDLIST
-Value    : 77h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of ASCII list of passwords for FILEREQUESTLIST
-
-Name     : IMAGEATTACH
-Value    : 80h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached image file for display
-
-MSG_FILEATTACH attribute must be set. See Image Types for valid
-mattach_t.type values.
-
-Name     : ANIMATTACH
-Value    : 81h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached graphical animation file for display
-
-MSG_FILEATTACH attribute must be set. See Animation Types for valid
-mattach_t.type values.
-
-Name     : FONTATTACH
-Value    : 82h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached font definition file
-
-MSG_FILEATTACH attribute must be set. See Font Types for valid mattach_t.type
-values.
-
-Name     : SOUNDATTACH
-Value    : 83h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached sound file for playback
-
-MSG_FILEATTACH attribute must be set. See Sound Types for valid mattach_t.type
-values.
-
-Name     : PRESENTATTACH
-Value    : 84h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached presentation definition file
-
-MSG_FILEATTACH attribute must be set. See Present Types for valid
-mattach_t.type values.
-
-Name     : VIDEOATTACH
-Value    : 85h
-Data	 : vattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of attached interleaved video/sound file
-
-MSG_FILEATTACH attribute must be set. See Video Types for valid
-vattach_t.type values and Video Compression Types for valid vattach_t.comp
-values.
-
-Name     : APPDATAATTACH
-Value    : 86h
-Data     : mattach_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Name of attached application data file for process/display
-
-MSG_FILEATTACH attribute must be set. See Application Data Types for valid
-mattach_t.type values.
-
-Name     : IMAGETRIGGER
-Value    : 90h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of image file to trigger for display
-
-See Image Types for valid typestr_t.type values.
-
-Name     : ANIMTRIGGER
-Value    : 91h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of animation file to trigger for display
-
-See Animation Types for valid typestr_t.type values.
-
-Name     : FONTTRIGGER
-Value    : 92h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of font definition file to trigger
-
-See Font Types for valid typestr_t.type values.
-
-Name     : SOUNDTRIGGER
-Value    : 93h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of sound file to trigger for playback
-
-See Sound Types for valid typestr_t.type values.
-
-Name     : PRESENTTRIGGER
-Value    : 94h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of presentation definition file to trigger
-
-See Present Types for valid typestr_t.type values.
-
-Name     : VIDEOTRIGGER
-Value    : 95h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of interleaved video/sound file to trigger
-
-See Video Types for valid typestr_t.type values.
-
-Name     : APPDATATRIGGER
-Value    : 96h
-Data     : typestr_t
-Multiple : Yes, order significant
-Required : No
-Summary  : Type and filename of application data file to trigger
-
-See Application Data Types for valid typestr_t.type values.
-
-Name     : FIDOCTRL
-Value    : A0h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : keyword ":" [" "] appdata
-Summary  : FTS/FSC-compliant control information line
-
-Any FidoNet FTS/FSC-compliant control information ("kludge") line that
-does not have an equivalent representation here. All data not unique to the
-actual control line, including leading and trailing white space, Ctrl-A (01h)
-character and terminating CR must be ommited. Defined in FTS-0001.
-
-Name     : FIDOAREA
-Value    : A1h
-Data     : ASCII
-Multiple : No
-Required : No
-Summary  : FTN EchoMail conference name.
-
-Defined in FTS-0004.
-
-Name     : FIDOSEENBY
-Value    : A2h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : net"/"node [" "[net"/"]node] [...]
-Summary  : Used to store two-dimensional (net/node) SEEN-BY information
-
-Often used in FTN EchoMail environments. Only the actual SEEN-BY data is stored
-and SEEN-BY: is stripped along with any leading and trailing white space
-characters. Defined in FTS-0004.
-
-Name     : FIDOPATH
-Value    : A3h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : net"/"node [" "[net"/"]node] [...]
-Summary  : Used to store two-dimensional (net/node)
-
-Defined in FTS-0004. ^aPATH: is stripped along with any leading and trailing
-white space characters.
-
-Name     : FIDOMSGID
-Value    : A4h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : origaddr " " serialno
-Summary  : MSGID field as specified in FTS-0009.
-
-Name     : FIDOREPLYID
-Value    : A5h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : origaddr " " serialno
-Summary  : REPLY field as specified in FTS-0009.
-
-Name     : FIDOPID
-Value    : A6h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : pID " " version [" "serialno]
-Summary  : Indentification string of program that created this message
-
-Defined FSC-0046. "^aPID:" and any white space is not included.
-
-Name     : FIDOFLAGS
-Value    : A7h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Used to store the FTN FLAGS kludge information
-
-Note that all FLAG options that have binary representation in the message
-header must be removed from the FLAGS string prior to storing it. Only the
-actual flags option string is stored and ^aFLAGS is stripped along with any
-leading and trailing white space characters. Defined in FSC-0053.
-
-Name     : RFC822HEADER
-Value    : B0h
-Data     : ASCII
-Multiple : Yes, order significant
-Required : No
-Format   : field-name ":" [field-body] [CRLF]
-Summary  : Undefined RFC-822 header field
-
-Internet Message storage format, that does not have an equivalent
-representation here. Folded header fields are allowed. Terminating CRLF may be
-ommited.
-
-Name     : RFC822MSGID
-Value    : B1h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : "<" addr-spec ">"
-Summary  : Message-ID field as specified in RFC-822.
-
-Name     : RFC822REPLYID
-Value    : B2h
-Data     : ASCII
-Multiple : No
-Required : No
-Format   : "<" addr-spec ">"
-Summary  : In-Reply-To field as specified in RFC-822.
-
-Name     : UNKNOWN
-Value    : F0h
-Data     : undef
-Multiple : Yes
-Required : No
-Summary  : Undefined header field of undefined type
-
-This field is useful for retaining binary header fields (that do not have an
-equivalent representation here) between message storage formats.
-
-Name     : UNKNOWNASCII
-Value    : F1h
-Data     : ASCII
-Multiple : Yes
-Required : No
-Summary  : Undefined header field of type ASCII
-
-This field is useful for retaining ASCII header fields (that do not have an
-equivalent representation here) between message storage formats.
-
-Name     : UNUSED
-Value    : FFh
-Data     : undef
-Multiple : Yes
-Required : No
-Summary  : Unused (deleted) header field
-
-The data contained in this header field is of an unknown type and should not be
-processed.
-
-
-Note:
-----
-Specifically, not defined are the values F000h through FFFFh. These values
-are to be used for user or system defined header fields. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-header fields added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-Data Field Types:
-================
-&&Data Field Types
-$$DFIELD_T
-
-These are the defined valid values for dfield_t.type:
-
-
-Val Name                Data        Description
---- ----                ----        -----------
-00h TEXT_BODY           mtext_t     Displayable text (body of message).
-                                    Included in duplicate message checking.
-									All terminating white space and control
-									characters are to be truncated from data
-									(except when multiple contiguous CRLFs
-									terminate the text, only the last CRLF
-									is removed).
-
-01h TEXT_SOUL           mtext_t     Non-displayed text.
-                                    Not normally displayed. Not necessarily
-                                    displayable.
-                                    Included in duplicate message checking.
-
-02h TEXT_TAIL			mtext_t 	Displayable text (tag/tear/origin lines,
-									etc).
-                                    Not included in duplicate message checking.
-									All terminating white space and control
-                                    characters are to be truncated from data.
-
-03h TEXT_WING           mtext_t     Non-displayed text.
-                                    Not normally displayed. Not necessarily
-                                    displayable.
-                                    Not included in duplicate message checking.
-
-10h FTEXT_BODY			ftext_t 	Formatted equivalent of TEXT_BODY to be
-									displayed in place of TEXT_BODY if format
-									is supported. See Image Types for valid
-									values of ftext_t.type.
-
-12h FTEXT_TAIL			ftext_t 	Formatted equivalent of TEXT_TAIL to be
-									displayed in place of TEXT_TAIL if format
-									is supported. See Image Types for valid
-									values of ftext_t.type.
-
-20h IMAGEEMBED          membed_t    Type and data of embedded raster image file
-                                    for display.
-									See Image Types for valid membed.type
-									values.
-
-21h ANIMEMBED			membed_t	Type and data of embedded graphical
-									animation file for display.
-									See Animation Types for valid membed.type
-                                    values.
-
-22h FONTEMBED			membed_t	Type and data of embedded font definition
-									file. See Font Types for valid
-									membed_t.type values.
-
-23h SOUNDEMBED          membed_t    Type and data of embedded sound file for
-                                    playback.
-									See Sound Types for valid membed_t.type
-									values.
-
-24h PRESENTEMBED        membed_t    Type and data of embedded presentation
-                                    definition file.
-                                    See Present Types for valid membed_t.type
-                                    values.
-
-25h VIDEOEMBED			vembed_t	Type and data of embedded video/sound file
-                                    for playback.
-									See Video Types for valid vembed_t.type
-                                    values.
-									See Video Compression Types for valid
-									vembed_t.comp values.
-
-26h APPDATAEMBED		membed_t	Type and data of embedded application data
-									file for process/display.
-                                    See Application Data Types for valid
-                                    membed_t.type values.
-
-FFh UNUSED              undef       Space allocated for future update/expansion
-
-
-Specifically, not defined are the values F000h through FFFFh. These values
-are to be used for user or system defined data fields. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-data fields added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-
-Message Attributes:
-------------------
-&&Message Attributes
-$$ATTRBITS
-
-These are the bit values for idxrec_t.attr and msghdr_t.attr:
-
-MSG_PRIVATE         (1<<0)  // Private
-MSG_READ            (1<<1)  // Read by addressee
-MSG_PERMANENT       (1<<2)  // Permanent
-MSG_LOCKED          (1<<3)  // Msg is locked, no editing possible
-MSG_DELETE          (1<<4)  // Msg is marked for deletion
-MSG_ANONYMOUS       (1<<5)  // Anonymous author
-MSG_KILLREAD        (1<<6)  // Delete message after it has been read
-MSG_MODERATED		(1<<7)	// This message must be validated before export
-MSG_VALIDATED       (1<<8)  // This message has been validated by a moderator
-
-
-Auxillary Attributes:
---------------------
-These are the bit values for msghdr_t.auxattr:
-
-MSG_FILEREQUEST     (1<<0)  // File request
-MSG_FILEATTACH      (1<<1)  // File(s) attached to Msg
-MSG_TRUNCFILE       (1<<2)  // Truncate file(s) when sent
-MSG_KILLFILE        (1<<3)  // Delete file(s) when sent
-MSG_RECEIPTREQ      (1<<4)  // Return receipt requested
-MSG_CONFIRMREQ      (1<<5)  // Confirmation receipt requested
-MSG_NODISP          (1<<6)  // Msg may not be displayed to user
-
-
-Network Attributes:
-------------------
-These are the bit values for msghdr_t.netattr:
-
-MSG_LOCAL           (1<<0)  // Msg created locally
-MSG_INTRANSIT       (1<<1)  // Msg is in-transit
-MSG_SENT            (1<<2)  // Sent to remote
-MSG_KILLSENT        (1<<3)  // Kill when sent
-MSG_ARCHIVESENT     (1<<4)  // Archive when sent
-MSG_HOLD            (1<<5)  // Hold for pick-up
-MSG_CRASH           (1<<6)  // Crash
-MSG_IMMEDIATE       (1<<7)  // Send Msg now, ignore restrictions
-MSG_DIRECT          (1<<8)  // Send directly to destination
-MSG_GATE            (1<<9)  // Send via gateway
-MSG_ORPHAN          (1<<10) // Unknown destination
-MSG_FPU             (1<<11) // Force pickup
-MSG_TYPELOCAL       (1<<12) // Msg is for local use only
-MSG_TYPEECHO        (1<<13) // Msg is for conference distribution
-MSG_TYPENET         (1<<14) // Msg is direct network mail
-
-Translation Types:
------------------
-&&Translation Types
-$$XLATTYPE
-
-Definition for values of *.xlat[x]:
-
-XLAT_NONE           0       // No translation/End of translation list
-XLAT_LF2CRLF        1       // Expand sole LF to CRLF
-XLAT_ESCAPED        2       // 7-bit ASCII escaping for ctrl and 8-bit data
-XLAT_HUFFMAN        3       // Static and adaptive Huffman coding compression
-XLAT_LZW			4		// LZW (Lempel-Ziv-Welch) encoding for compression
-							// Terry Welch, IEEE Computer Vol 17, No 6
-							// June 1984, pp 8-19
-XLAT_LZC			5		// LZC (modified LZW) encoding for compression
-							// Unix compress program
-XLAT_RLE            6       // Run length encoding compression
-XLAT_IMPLODE		7		// Implode compression (PKZIP v1.x)
-XLAT_SHRINK 		8		// Shrink compression (PKZIP v1.x)
-XLAT_LZH			9		// LZH dynamic Huffman coding
-							// Haruyasu Yoshizaki, LHarc
-							// November, 1988
-
-Agent Types:
------------
-&&Agent Types
-$$AGENTTYP
-
-AGENT_PERSON		0		// To or from person
-AGENT_PROCESS       1       // Unknown process, identified by agent name
-
-Agent types E000h through EFFFh are reserved for Synchronet process types
-(defined specifically by Digital Dynamics).
-
-Note:
-----
-Specifically not defined are agent types F000h through FFFFh. These values
-are to be used for user or system defined agent types. Digital Dynamics
-requests that any developers or organizations that wish to have additional
-agent types added to this specification notify Digital Dynamics through any
-of the contact methods listed at the beginning of this document.
-
-Network Types:
--------------
-&&Network Types
-$$NETWORKS
-
-							// Net Type 			Address Format
-							// -----------------------------------
-NET_NONE			0		// Locally created		none
-NET_UNKNOWN 		1		// Unknown				undef
-NET_FIDO			2		// FTN network			fidoaddr_t
-NET_POSTLINK		3		// PostLink network 	none
-NET_QWK 			4		// QWK based network	ASCII
-NET_INTERNET		5		// The Internet 		ASCII
-NET_WWIV			6		// WWIV based network	ulong
-NET_MHS 			7		// MHS network			ASCII
-
-
-Media Types:
-===========
-&&Media Types
-$$MEDIATYP
-
-Image Types:
------------
-
-IMAGE_UNKNOWN       0x00    // Use image signature header to determine format
-IMAGE_ASC           0x01    // ASCII text/IBM extended ASCII graphics
-IMAGE_ANS           0x02    // ANSI X3.64 terminal escape sequences
-IMAGE_AVT           0x03    // AVATAR terminal escape sequences
-IMAGE_LVI           0x04    // LVI terminal escape sequences
-IMAGE_GIF           0x05    // Compuserve Graphics Interchange Format (GIF)
-IMAGE_TIF           0x06    // Tagged Image Format (AKA TIFF)
-IMAGE_JPG           0x07    // Joint Photographers Electronics Group (JPEG)
-IMAGE_T16           0x08    // TrueVision 16-bit bitmap (TGA)
-IMAGE_T24           0x09    // TrueVision 24-bit bitmap (TGA)
-IMAGE_T32           0x0a    // TrueVision 32-bit bitmpa (TGA)
-IMAGE_PCX           0x0b    // ZSoft PaintBrush graphics
-IMAGE_BMP           0x0c    // Windows bitmap
-IMAGE_RLE           0x0d    // Windows bitmap (compressed)
-IMAGE_DIB           0x0e    // Display independant bitmap
-IMAGE_PCD           0x0f    // Kodak PhotoCD
-IMAGE_G3F           0x10    // Group 3 FAX
-IMAGE_EPS           0x11    // Ecapsulated PostScript
-IMAGE_RTF           0x12    // Rich text format
-IMAGE_RIP           0x13    // Remote Imaging Protocol Script (RIPscrip)
-IMAGE_NAP           0x14    // NAPLPS
-IMAGE_CDR           0x15    // Corel Draw!
-IMAGE_CGM           0x16    // Computer graphics metafile
-IMAGE_WMF           0x17    // Windows metafile
-IMAGE_DFX           0x18    // Autodesk AutoCAD
-IMAGE_IFF			0x19	// Amiga Interchange File Format
-IMAGE_HTM			0x20	// HyperText Markup Language (MTML) Document
-IMAGE_OS2			0x21	// OS/2 bitmap (BMP)
-
-Animation Types:
----------------
-
-ANIM_UNKNOWN        0       // Use file signature header to determine format
-ANIM_FLI            1       // Autodesk animator
-ANIM_FLC            2       // Autodesk
-ANIM_GL             3       // Grasprt
-ANIM_IFF			4		// Amiga Interchange File Format
-
-
-Video Types:
------------
-
-VIDEO_UNKNOWN       0       // Use file signature header to determine format
-VIDEO_QTIME         1       // Apple Quick-time
-VIDEO_FQTIME        2       // Apple Flattened Quick-time
-VIDEO_AVI           3       // Windows Auto/Video Interleave
-VIDEO_ULT           4       // OS/2 Ultimotion
-
-Video Compression Types:
------------------------
-
-VCOMP_UNKNOWN		0		// Use file signature header to determine codec
-VCOMP_RLE			1		// Apple animation
-VCOMP_SMC			2		// Apple graphics
-VCOMP_RPZA			3		// Apple video
-VCOMP_KLIC			4		// Captain crunch
-VCOMP_CVID			5		// CinePak
-VCOMP_RT21			6		// Intel indeo R2
-VCOMP_IV31			7		// Intel indeo R3
-VCOMP_YVU9			8		// Intel YVU9
-VCOMP_JPEG			9		// JPEG
-VCOMP_MRLE			10		// Microsoft RLE
-VCOMP_MSVC			11		// Microsoft video 1
-
-
-Font Types:
-----------
-
-FONT_UNKNOWN        0       // Use file signature header to determine format
-FONT_TTF            1       // Windows TrueType
-FONT_PFB            2       // PostScript Type 1 Font Binary
-FONT_PFM            3       // PostScript Type 1 Font Metric
-FONT_AMIGA			4		// Amiga Bitmapped
-FONT_AGFA			5		// CompuGraphic Fonts
-
-
-Sound Types:
------------
-
-SOUND_UNKNOWN       0       // Use file signature header to determine format
-SOUND_MOD           1       // MOD format
-SOUND_VOC           2       // Sound Blaster VOC format
-SOUND_WAV			3		// Windows 3.1 WAV RIFF format
-SOUND_MID           4       // MIDI format
-SOUND_GMID          5       // General MIDI format (standardized patches)
-SOUND_SMP			6		// Turtle Beach SampleVision format
-SOUND_SF			7		// IRCAM format
-SOUND_AU			8		// Sun Microsystems AU format
-SOUND_IFF			9		// Amiga Interchange File Format
-
-Application Data Types:
-----------------------
-
-APPDATA_UNKNOWN     0       // Use file signature header to determine format
-APPDATA_WORDPERFECT 1       // WordPerfect Document
-APPDATA_WKS         2       // Lotus 123 Worksheet (?)
-APPDATA_WK1         3       // Lotus 123 Worksheet rev 1
-APPDATA_WK2         4       // Lotus 123 Worksheet rev 2
-APPDATA_WK3         5       // Lotus 123 Worksheet rev 3
-APPDATA_DBF         6       // dBase III data file
-APPDATA_PDX         7       // Paradox data file
-APPDATA_EXCEL		8		// Excel data file
-APPDATA_QUATRO		9		// Borland Quatro Pro file
-APPDATA_WORD		10		// Microsoft Word
-
-Message Storage Pseudo Code
-===========================
-&&Message Storage Pseudo Code
-$$STORPCOD
-
-The following is a "C like" pseudo code listing example of adding a message to
-an SMB message base. SMBLIB contains C functions to do most of the following
-operations. We are supplying this pseudo code as a general definition of the
-order of required operations in writing to the message base. Many details have
-been left out to simplify the code and to demonstrate only the basic
-principles.
-
-shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-
-lock ( shd , smbhdr )
-read ( shd , smbstatus )
-
-if ( smbstatus.attr & SMB_HYPERALLOC )
-	msg.hdr.offset = filelength ( sdt )
-
-else {
-	number_of_blocks = length_of_message_data / SDT_BLOCK_LEN
-	if ( length_of_message_data % SDT_BLOCK_LEN )	/* unevenly divisible */
-		number_of_blocks = number_of_blocks + 1
-
-	sda = open ( MSGBASE.SDA , READ/WRITE/DENY_ALL )
-
-	if ( fast_allocation_mode )
-		seek ( sda , END_OF_FILE )
-
-	else {
-		seek ( sda , BEGINNING_OF_FILE )
-		while ( not end_of_file ( sda ) ) {
-			read ( sda , allocated , number_of_blocks * 2 )
-			if ( allocated = 0 ) {
-				seek_backwards ( sda , number_of_blocks * 2 )
-				break
-			}
-		}
-	}
-
-	msg.hdr.offset = ( current_position ( sda ) / 2 ) * SDT_BLOCK_LEN
-
-	allocated = 1
-
-	write ( sda , allocated , number_of_blocks * 2 )
-
-	close ( sda )
-}
-
-seek ( sdt , msg.hdr.offset )
-
-write ( sdt , message_data )
-
-if ( smbstatus.attr & SMB_HYPERALLOC )
-	msg.idx.offset = filelength ( shd )
-
-else {
-	number_of_blocks = length_of_message_header / SHD_BLOCK_LEN
-	if ( length_of_message_header % SHD_BLOCK_LEN )   /* unevenly divisible */
-		number_of_blocks = number_of_blocks + 1
-
-	sha = open ( MSGBASE.SHA , READ/WRITE/DENY_ALL )
-
-	if ( fast_allocation_mode )
-		seek ( sha , END_OF_FILE )
-
-	else {
-		seek ( sha , BEGINNING_OF_FILE )
-		while ( not end_of_file ( sha ) ) {
-			read ( sha , allocated , number_of_blocks )
-			if ( allocated = 0 ) {
-				seek_backwards ( sha , number_of_blocks )
-				break
-			}
-		}
-	}
-
-	msg.idx.offset = ( current_position ( sha ) * SHD_BLOCK_LEN )
-	msg.idx.offset = msg.idx.offset + smbstatus.header_offset
-
-	allocated = 1
-
-	write ( sha , allocated , number_of_blocks )
-
-	close ( sha )
-}
-
-seek ( shd , msg.idx.offset )
-
-msg.hdr.number = smbstatus.last_msg+1
-
-write ( shd , msg.hdr )
-
-smbstatus.total_msgs = smbstatus.total_msgs + 1
-smbstatus.last_msg = msg.hdr.number
-
-write ( shd , smbstatus )
-
-write ( sid , msg.idx )
-
-unlock ( shd , smbstatus )
-
-Message Retrieval Pseudo Code
-=============================
-&&Message Retrieval Pseudo Code
-$$READPCOD
-
-shd = open ( MSGBASE.SHD , READ/WRITE/DENY_NONE )
-sdt = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-sid = open ( MSGBASE.SDT , READ/WRITE/DENY_NONE )
-
-read ( sid , msg.idx )
-
-seek ( shd , msg.idx.offset )
-
-lock ( shd , msg.hdr )
-
-read ( shd , msg.hdr )
-
-seek ( sdt , msg.hdr.offset )
-
-read ( sdt , msg.hdr.data_length )
-
-unlock ( shd , msg.hdr )
-
-SMBUTIL
-=======
-&&SMBUTIL
-$$SMBUTIL_
-
-SMBUTIL is a utility that can perform various functions on an SMB message base.
-The primary purpose of SMBUTIL is as an example to C programmers of how to use
-the SMBLIB functions to access and modify an SMB message base. The complete C
-source code for SMBUTIL is included and functions from it can be used or
-modified by developers at their own discretion. The following files make up
-SMBUTIL:
-
-SMBUTIL.EXE 	Compiled and linked for 16-bit DOS (ready to run)
-SMBUTIL.C		C functions
-SMBUTIL.H		C definitions and variable prototypes
-SMBUTIL.WAT 	Makefile for Watcom C/C++ (type wmake -f smbutil.wat)
-SMBUTIL.BOR 	Makefile for Borland C/C++ (type make -f smbutil.bor)
-
-The usage syntax is as follows:
-
-SMBUTIL [/opts] cmd smb_filespec.shd
-
-where cmd is one or more of the following:
-
-	   l[n] = list msgs starting at number n
-	   r[n] = read msgs starting at number n
-	   v[n] = view msg headers starting at number n
-	   k[n] = kill (delete) n msgs
-	   i<f> = import from text file f
-	   s	= display msg base status
-	   c	= change msg base status
-	   m	= maintain msg base - delete old msgs and msgs over max
-       p[k] = pack msg base (k specifies minimum packable Kbytes)
-
-where opts is one or more of the following:
-
-	   a	= always (force) packing
-	   z<n> = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)
-
-and smb_filespec is the base filename or file specification (wildcards) for the
-message base. If wildcards are used, the ".SHD" extension must be specified.
-
-An example command line:
-
-SMBUTIL MP C:\SBBS\DATA\SUBS\*.SHD
-
-would maintain and pack all the message bases found in the C:\SBBS\DATA\SUBS
-directory.
-
-CHKSMB
-======
-&&CHKSMB
-$$CHKSMB__
-
-CHKSMB is a utility that performs a comprehensive analysis of a message base
-to find any possible errors and calculate the number of packable bytes. It does
-not "fix" a message base if any errors are found, it only reports the specific
-errors (and exits with a non-zero error level). If any errors are reported,
-packing the message base with SMBUTIL may rebuild the damaged files. If that
-doesn't work, then use FIXSMB as a last resort.
-
-C source code for CHKSMB is also included as an example to programmers of how
-to use SMBLIB functions.
-
-The usage syntax is as follows:
-
-CHKSMB [/opts] smb_filespec.shd
-
-where opts is one or more of the following:
-
-		q	= quiet mode (no beeps)
-		s	= stop after an errored message base (for use with wildcards)
-		p	= pause after an errored message base (wait for key press)
-		t	= don't check for unsupported translation strings (faster)
-		e	= display extended information on corrupted messages
-
-An example command line:
-
-CHKSMB /QP C:\SBBS\DATA\SUBS\*.SHD
-
-would check all the message bases in the C:\SBBS\DATA\SUBS directory, without
-beeping on errors, and pausing after an errored message base.
-
-FIXSMB
-======
-&&FIXSMB
-$$FIXSMB__
-
-FIXSMB is a utility that will rebuild the index and allocation files for a
-message base. Since the message headers are not necessarily stored
-sequentially, the order of the messages in the index may be changed when the
-index is rebuilt. Messages are also re-numbered, so only use this program if
-the index is corrupted and the messages are extremely important.
-
-C source code for FIXSMB is also included as an example to programmers of how
-to use SMBLIB functions.
-
-The usage syntax is as follows:
-
-FIXSMB [/M] smb_file
-
-An example command line:
-
-FIXSMB \SBBS\DATA\MAIL
-
-Only use the "/M" command line switch if fixing an older Synchronet e-mail
-message base (created with SBBS v2.1 or earlier). Once the SMB_EMAIL status
-attr is set ("SMBUTIL S" will report a status attr of 1), the "/M" is not
-required.
-
-SMBLIB
-======
-&&SMBLIB
-$$SMBLIB__
-
-SMBLIB is a library of C functions for accessing and storing messages in an
-SMB format message base. It can eliminate much of the development time for
-developers that wish to use the library in whole or in part, or use the
-functions as examples for their own message base function library. The library
-consists of the following files:
-
-SMBDEFS.H		Constant definitions, macros, and data types
-SMBLIB.H		Library constants and function prototypes
-SMBLIB.C		Function definitions
-SMBVARS.C		Global variable definitions (doubles as declaration file)
-
-For developers to use this library with their program, they must include the
-"SMBLIB.H" header file at the top of each C file that uses any of the library
-functions, global variables, data types, macros, and constants. This can be
-done by simply adding the following line to each .C file:
-
-#include "smblib.h"
-
-If SMBLIB.H is included, there is no need to include SMBDEFS.H or SMBVARS.C.
-
-To link the library functions and variables with a main program, the files
-SMBVARS.OBJ and SMBLIB.OBJ must be linked with the main program .OBJ files.
-If the operating system is DOS, be sure that all .OBJ files are compiled for
-the same memory model.
-
-Example MAKEFILEs for compiling and linking SMBUTIL with Borland C/C++
-(SMBUTIL.BOR) and Watcom C/C++ (SMBUTIL.WAT) are included.
-
-SMBDEFS.H
-=========
-&&SMBDEFS.H
-$$SMBDEFS_
-
-The SMBDEFS.H file contains important constant definitions and data types (also
-defined in this document). If ever this document and SMBDEFS.H are inconsistent
-with each other, then SMBDEFS.H is to be considered correct and this document
-in error. If such a discrepency is found, please notifiy Digital Dynamics so it
-can be corrected in a future revision of the specification.
-
-Most notable of the data types is a structure called smbmsg_t (not defined
-in this document). It contains the fixed and variable portions of a message's
-header record as well as convenience pointers to the sender's name
-(smbmsg_t.to), recipient's name (smbmsg_t.from), network addresses, and more.
-If multiple SENDER header fields are included (for example), then smbmsg_t.to
-will point to the last SENDER header field in the header record. Convenience
-pointers for other data items work in the same fasion if multiple header fields
-of the same type exist in the header record.
-
-Variables of the smbmsg_t data type (and pointers to variables of smbmsg_t
-type) are used as arguments to many of the SMBLIB functions.
-
-SMBVARS.C
-=========
-&&SMBVARS.C
-$$SMBVARS_
-
-The SMBVARS.C file contains definitions of the global variables used by the
-SMBLIB functions. It is a fairly small file since there are a small number of
-global variables (by design). This file is used for both definitions and
-declarations, so no "extern" declarations need to be made in developers source
-code as long as SMBVARS.C or (preferably) SMBLIB.H is included in the source
-code.
-
-SMBLIB.H
-=======
-&&SMBLIB.H
-$$SMBLIB.H
-
-The SMBLIB.H file contains prototypes of all the functions in the SMBLIB.C
-file. It is necessary to include this file in C source code if any of the
-SMBLIB functions are used. The following C source line will include this file:
-
-#include "smblib.h"
-
-and should be placed near the top of all C source files that use SMBLIB
-functions, variables, constants, or data types.
-
-Function prototypes are necessary for compilers to know the correct calling
-syntax of a function and detect incorrect usage. Prototypes are also useful
-as a quick reference for programmers as to the correct calling syntax of a
-specific function.
-
-SMBLIB.C
-=======
-&&SMBLIB.C
-$$SMBLIB.C
-
-The SMBLIB.C file contains the actual SMBLIB library functions. This source
-file is not a stand alone program, but instead must be compiled and linked
-with a main source file to create the executable program.
-
-The functions in this file are organized in a logical order, but their order
-is actually irrelevant to the compiling, linking, and execution of the
-resulting program.
-
-A comment block preceeds each function, explaining what the function does,
-how the passed parameters are used, and what the return code (if any)
-indicates. A more detailed explanation of each function is included here:
-
-int smb_open(int retry_time)
-----------------------------
-The smb_open() function must be called before the message base is accessed
-(read from or written to). The parameter, retry_time, is the maximum number
-of seconds to wait while retrying to lock the message base header. If
-retry_time is 0, then the message base header is not locked or read (this is
-called "Fast Open" and should only be used when speed is more important than
-checking for compatibility and validity upon opening). The global variable
-smb_file must be initialized with the path and base filename of the message
-base. This function returns 0 on success, 1 if the .SDT file could not be
-opened, 2 if the .SHD file could not be opened, and 3 if the .SID file could
-not be opened. If the message base header could not be locked, this function
-returns -1. If the message base ID is incorrect, it returns -2. And if the
-message base is of an incompatible version, it returns -3.
-
-The errno global variable (standard of most C libraries) will most likely
-contain the error code for open failure.
-
-int smb_open_da(int retry_time)
--------------------------------
-The smb_open_da() function is used to open the data block allocation file for
-writing messages to a message base. The parameter, retry_time, is the maximum
-number of seconds to wait while retrying to open the file. This function
-returns 0 on success. -1 is returned if an open error other than "Access
-Denied" is returned from the operating system, and the global variable errno
-will contain the error code. -2 is returned if the retry_time has been
-reached, and -3 is returned if the file descriptor could not be converted to
-a stream by the fdopen() function.
-
-fclose(sda_fp) should be called immediately after all necessary file access
-has been completed.
-
-This function is not used with the Hyper Allocation storage method.
-
-int smb_open_ha(int retry_time)
--------------------------------
-The smb_open_ha() function is used to open the header block allocation file for
-writing messages to a message base. The parameter, retry_time, is the maximum
-number of seconds to wait while retrying to open the file. This function
-returns 0 on success. -1 is returned if an open error other than "Access
-Denied" is returned from the operating system, and the global variable errno
-will contain the error code. -2 is returned if the retry_time has been
-reached, and -3 is returned if the file descriptor could not be converted to
-a stream by the fdopen() function.
-
-fclose(sha_fp) should be called immediately after all necessary file access
-has been completed.
-
-This function is not used with the Hyper Allocation storage method.
-
-int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
-	,int retry_time)
---------------------------------------------------------------------------
-The smb_create() function is used to create a new message base or reset an
-existing message base. The parameters max_crcs, max_msgs, max_age, and attr
-are used to set the initial status of the message base status header. The
-parameter, retry_time is the maximum number of seconds to wait while retrying
-to lock the message base header. This functions returns 0 on success or 1 if
-the message base header could not be locked.
-
-int smb_trunchdr(int retry_time)
---------------------------------
-The smb_trunchdr() function is used to truncate the header file when packing
-the message base and writing the new header information back to the header
-file. The parameter, retry_time is the maximum number of seconds to wait while
-retrying to truncate the header file. Returns 0 on success, -1 if error was
-other than "Access Denied", or -2 if retry_time reached.
-
-int smb_locksmbhdr(int retry_time)
-----------------------------------
-The smb_locksmbhdr() function is used to lock the first message base (status)
-header. The parameter, retry_time is the number of seconds to wait while
-retrying to lock the header. The smb_unlocksmbhdr() function should always be
-used to unlock the header after accessing the message base header (usually
-with smb_getstatus() and/or smb_putstatus()). Returns 0 if successful, -1 if
-unsuccessful.
-
-int smb_unlocksmbhdr()
-----------------------
-The smb_unlocksmbhdr() function is used to unlock a previously locked message
-base header (using smb_lockmsghdr()). Returns 0 on success, non-zero on
-failure.
-
-int smb_getstatus(smbstatus_t *hdr)
------------------------------------
-The smb_getstatus() function is used to read the status message base header
-into the hdr structure. Returns 0 on success, 1 on failure.
-
-int smb_putstatus(smbstatus_t hdr)
-----------------------------------
-The smb_putstatus() function is used to write the status information to the
-first message base header. The parameter hdr, contains the status information
-to be written. Returns 0 on success, 1 on failure.
-
-int smb_getmsgidx(smbmsg_t *msg)
---------------------------------
-The smb_getmsgidx() function is used to get the byte offset for a specific
-message header in the message header file based on the message base index.
-
-If msg->hdr.number is non-zero when this function is called, then the index
-will be searched for this message number. If the message number is found in
-the index, the msg->idx.offset is set to the byte offset of the message header
-record in the header file and msg->offset is set to the record offset of the
-index record in the index file, and the function returns 0. If the message
-number is not found in the index, the function returns 1.
-
-If msg->hdr.number is zero, msg->idx.offset and msg->idx.number are obtained
-from the index record at record offset msg->offset. If msg->offset is an
-invalid record offset when this function is called, the function returns 1.
-Otherwise, the function returns 0.
-
-int smb_getlastidx(idxrec_t *idx)
----------------------------------
-Reads the last index record of the currently open message base into the
-idxrec_t structure pointed to by idx. Returns 0 if successful, -1 if the index
-is empty or unopened, or -2 if the record can't be read.
-
-int smb_getmsghdrlen(smbmsg_t msg)
-----------------------------------
-The smb_getmsghdrlen() function is used to calculate the total length of
-message header msg including both fixed and variable length portions. This
-function returns the length of the header record in bytes.
-
-long smb_getmsgdatlen(smbmsg_t msg)
------------------------------------
-The smb_getmsgdatlen() function is used to calculate the total length of the
-data for message msg. This function returns the length of all data fields
-combined.
-
-int smb_lockmsghdr(smbmsg_t msg, int retry_time)
-------------------------------------------------
-The smb_lockmsghdr() function is used to lock the header record for message
-msg. The parameter retry_time is the maximum number of seconds to wait while
-retrying to lock the header. Returns 0 on success, -1 on failure. The function
-smb_unlockmsghdr() should immediately be called after accessing the message
-header (usually with smb_getmsghdr() or smb_putmsghdr()).
-
-int smb_getmsghdr(smbmsg_t *msg)
---------------------------------
-The function smb_getmsghdr() is used to read the header record for message
-msg. msg->idx.offset must be initialized to the byte offset of the header
-record in the header file before this function is called. The function
-smb_freemsgmem() must be called to free the memory allocated by this function
-for the header and data felds. This function returns 0 on success, -1 if
-the fixed portion of the message header record could not be read, -2 if the
-message header ID was incorrect, -3 if memory could not be allocated, -4
-if a data field could not be read, -5 if the fixed length portion of a header
-field could not be read, -6 if the variable length portion of a header field
-could not be read, -7 if one or more of the mandatory header fields (SENDER,
-RECIPIENT, or SUBJECT) are missing, -8 if total_dfields extends beyond the
-end of the header record, or -9 if incompatible header version.
-
-Several convenience pointers in the msg structure are initialized by this
-function to point to the last occurance of the SENDER (msg->from), RECIPIENT
-(msg->to), SUBJECT (msg->subj), etc.
-
-int smb_unlockmsghdr(smbmsg_t msg)
-----------------------------------
-The smb_unlockmsghdr() function is used to unlock a previously locked message
-header (with smb_lockmsghdr()). This function returns 0 on success, non-zero
-on failure.
-
-int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
----------------------------------------------------------
-The smb_addcrc() function is used to add a CRC-32 to the CRC history file
-for a message base, automatically checking for duplicates. The parameter
-max_crcs should be the max_crcs defined in the status header of the message
-base. The parameter crc, is the CRC-32 of the TEXT_BODY and TEXT_SOUL data
-fields for the message. The parameter retry_time is the maximum number of
-seconds to wait when retrying to open the CRC history file.
-
-This function returns -1 if there was an open error, -2 if the retry_time
-was reached, -3 if there was a memory allocation error, 1 if the CRC already
-exists in the CRC history file (indicating a duplicate message), or 0 on
-success (and no duplicate).
-
-int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
----------------------------------------------------------------------
-The smb_hfield() function is used to add a header field to the structure msg.
-The parameters type, length, and data, must be specified according to the
-header field values listed in this specification. This function returns 0
-on success, non-zero on memory allocation error. The function smb_freemsgmem()
-must be called to free the memory allocated by this function.
-
-int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
---------------------------------------------------------
-The smb_dfield() function is used to add a data field to the structure msg.
-The parameters type and length must be specified according to the data field
-values listed in this specification. This function returns 0 on success,
-non-zero on memory allocation error. The function smb_freemsgmem() must be
-called to free the memory allocated by this function.
-
-int smb_addmsghdr(smbmsg_t *msg,smbstatus_t *status,int storage,int retry_time)
--------------------------------------------------------------------------------
-The smb_addmsghdr() function is used to add a new message header to the message
-header file and update the index file. The msg and status structures are
-updated to reflect the new total messages, last message number, etc. The
-storage parameter is used to indicate the storage method to use (either
-SMB_SELFPACK, SMB_FASTALLOC, or SMB_HYPERALLOC). If the storage type is
-SMB_SELFPACK, the header block allocation file will be searched for unused
-block(s) to store this header. If the storage type is SMB_FASTALLOC or
-SMB_HYPERALLOC, the header is stored at the end of the header file. Returns 0
-on success, non-zero on failure. The parameter retry_time is the maximum number
-of seconds to wait while retrying to lock and open files.
-
-int smb_putmsg(smbmsg_t msg)
-----------------------------
-The smb_putmsg() function calls both the smb_putmsghdr() and smb_putmsgidx()
-functions to write the header and index elements of a message to the
-appropriate files. Returns 0 on success, non-zero on failure.
-
-int smb_putmsgidx(smbmsg_t msg)
--------------------------------
-The smb_putmsgidx() function is used to store a message index in the message
-index file. The message index can be for a new message or an existing
-message. Returns 0 on success, non-zero on failure.
-
-int smb_putmsghdr(smbmsg_t msg)
--------------------------------
-The smb_putmsghdr() function is used to store a message header in the message
-header file. The message header can be for a new message or an existing
-message. Returns 0 on success, non-zero on failure.
-
-void smb_freemsgmem(smbmsg_t msg)
----------------------------------
-Frees allocated memory for the header and data fields in the msg structure.
-This function must be called to free the memory allocated by the functions
-smb_hfield(), smb_dfield(), and smb_getmsghdr().
-
-long smb_hdrblocks(ulong length)
---------------------------------
-The smb_hdrblocks() function is used to calculate the number of blocks
-required to store a message header of length size (in bytes). This function
-returns the number of blocks required.
-
-long smb_datblocks(ulong length)
---------------------------------
-The smb_datblocks() function is used to calculate the number of blocks
-required to store message data of length size (in byte). This function returns
-the number of blocks required.
-
-long smb_allochdr(ulong length)
--------------------------------
-The smb_allochdr() function is used to search for free blocks to store a
-message header of length bytes and mark the free blocks as allocated in the
-header allocation file. This function returns the byte offset to the header
-record or a negative number on error. The function smb_open_ha() should be
-called prior to calling this function and fclose(sha_fp) should be called
-after. The function is called from smb_addmsghdr(), so you probably have no
-need to call this function directly.
-
-long smb_fallochdr(ulong length)
---------------------------------
-The smb_fallochdr() function works exactly the same as the smb_allochdr()
-function except it is much faster because the header allocation file is not
-searched for free blocks. The function is called from smb_addmsghdr(), so you
-probably have no need to call this function directly.
-
-long smb_hallochdr(ulong header_offset)
----------------------------------------
-This smb_hallochdr() functions works exactly the same as the smb_fallochdr()
-function except the status.header_offset is passed as the argument and the
-header allocation (.SHA) file is not updated so smb_open_ha() need not be
-called. The function is called from smb_addmsghdr(), so you probably have no
-need to call this function directly.
-
-long smb_allocdat(ulong length, ushort headers)
------------------------------------------------
-The smb_allocdat() function is used to search for free blocks to store length
-amount of data for a message. The parameter headers, indicates the number of
-message headers that are associated with this data. Normally, the headers
-parameter will be 1, unless this message is part of a mass mailing. The offset
-to the allocated data blocks is returned, or a negative value on error. The
-function smb_open_da() should be called prior to calling this function and
-fclose(sda_fp) should be called after.
-
-long smb_fallocdat(ulong length, ushort headers)
-------------------------------------------------
-The smb_fallocdat() function works exactly the same as the smb_allocdat()
-function except it is much faster because the data allocation file is not
-searched for free blocks.
-
-long smb_hallocdat()
---------------------
-The smb_hallocdat() function works exactly the same as the smb_hallocdat()
-function except no argument is passed and the data allocation file (.SDA) is
-not updated so smb_open_da() need not be called.
-
-int smb_incdat(ulong offset, ulong length, ushort headers)
-----------------------------------------------------------
-The smb_incdat() function is used to increment the header counter in the data
-allocation file for the data starting at the byte offset and length size in
-bytes. The parameter headers, indicates the number of headers to add to the
-current allocation value in the data allocation file. Returns 0 on success,
-non-zero on failure.
-
-int smb_freemsg(smbmsg_t msg, smbstatus_t status)
--------------------------------------------------
-The smb_freemsg() function is used to free the disk space allocated for the
-header and data fields of the message msg. Returns 0 on success, non-zero on
-failure. The parameter, status, must be the current status from the message
-base header for this message base.
-
-int smb_freemsgdat(ulong offset, ulong length, ushort headers)
---------------------------------------------------------------
-The smb_freemsgdat() function is used to decrement the data block allocation
-records in the data allocation file associated with the data in the data file
-by the value of the headers parameter (normally 1). The parameter offset
-indicates the byte offset to the beginning of the message data in the data
-file and the parameter length is the total length of the message data.
-Returns 0 on success, non-zero on failure.
-
-int smb_freemsghdr(ulong offset, ulong length)
-----------------------------------------------
-The smb_freemsghdr() function is used to set the header block allocation
-records in the header allocation file to 0 (indicated non-allocated block).
-The parameter offset indicates the byte offset to the beginning of the header
-record being freed and the parameter length indicates the total length of the
-header record. Returns 0 on success, non-zero on failure.
-
-int smb_stack(int op)
----------------------
-The smb_stack() function is used to save and restore message base information
-so that multiple message bases can be open simultaneously. The stack can
-save up to 4 message bases (allowing 5 simultaneously open message bases).
-The stack is a "last in, first out" storage area for open message bases.
-If the op parameter is SMB_STACK_PUSH, smb_stack() will save (push) the current
-message base onto the stack. Calling smb_stack(SMB_STACK_POP) will restore
-(pop) the most recently pushed message base off the stack. Calling
-smb_stack(SMB_STACK_XCHNG) will exchange the most recently pushed message base
-and the current message base (replacing the top of the stack with the current
-message base).
-
-void smb_close()
-----------------
-Closes the header, data, and index files for the currently open message base.
-
-
-Miscellaneous SMBLIB Files
-==========================
-&&Miscellaneous SMBLIB Files
-$$SMB_MISC
-
-CRC32.H 		C header file for CRC-32 calculations
------------------------------------------------------
-This file contains a static 32-bit CRC table (crc32tbl[]) and a macro (ucrc32)
-that uses this table to calculate 32-bit CRCs one byte at a time.
-
-Example:
-
-	ulong crc=0xffffffff;
-
-for(i=0;i<length;i++)
-	crc=ucrc32(buf[i],crc);
-crc=~crc;
-
-
-CRC16.C 		C functions for 16-bit CRC calculations
--------------------------------------------------------
-This file contains a function (ucrc16), to calculate 16-bit CRCs one byte at a
-time and a function (crc16) that uses the ucrc16() function to calculate the
-16-bit CRC of an ASCIIZ character string.
-
-Example:
-
-	ushort crc;
-
-crc=crc16("Text");
-
-LZH.H			Function prototypes for LZH.C
----------------------------------------------
-This file contains function prototypes for the two most important functions
-in LZH.C, lzh_encode() and lzh_decode().
-
-Example:
-
-	uchar str[256],lzh[512];
-	long length;
-
-strcpy(str,"This is a string of text");
-length=lzh_encode(str,strlen(str),lzh);
-lzh_decode(lzh,length,str);
-
-
-LZH.C           C functions for LZH encoding (compression/decompression)
-------------------------------------------------------------------------
-This file contains the functions for encoding and decoding LZH compressed
-data. If the macro LZH_DYNAMIC_BUF is defined when this file is compiled,
-temporary buffers will be dynamically allocated as opposed to static. This
-may be slower than the static buffer method, but frees the allocated memory
-after encoding or decoding. If free memory for your application is an issue,
-then define this macro when compiling this file.
-
-Example (Borland C):
-
-bcc -c -DLZH_DYNAMIC_BUF lzh
-
-Example (Watcom C):
-
-wcc -dLZH_DYNAMIC_BUF lzh
-
-SMBLIB Storage Example
-======================
-&&SMBLIB Storage Example
-$$SMB_PUT_
-
-#include "smblib.h"
-#include "crc16.c"
-
-int main(void)
-{
-	char	str[256]						// General purpose string
-		   ,*msg_text="Hello, world!"       // Message text
-		   ,nul_buf[SDT_BLOCK_LEN]={0}		// NULL initialized buffer
-		   ;
-	int 	i								// General purpose integer
-		   ,storage=SMB_SELFPACK			// Default storage method
-		   ,retry=10						// Retry for opening/locking files
-		   ;
-	ushort	max_age=0						// Default maximum age of messages
-		   ,xlat=XLAT_NONE					// Translation string
-		   ,tzone=PST						// Time zone
-		   ,copies=1						// Number of copies of this msg
-		   ;
-	ulong	max_msgs=500					// Default max number of msgs
-		   ,max_crcs=0						// Default max crcs
-		   ,length							// Length of msg text
-		   ,offset							// Offset to msg text in data file
-		   ;
-	smbmsg_t	msg;						// Message structure
-	smbstatus_t status; 					// Message base status record
-
-strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-if((i=smb_open(retry))!=0) {				// Can't open!?!
-	printf("smb_open returned %d\n",i);
-	return(1); }
-
-if(!filelength(fileno(shd_fp))) 			// Message base not created yet
-	smb_create(max_crcs 					// Create with default settings
-			  ,max_msgs
-			  ,max_age
-			  ,storage==SMB_HYPERALLOC
-					? SMB_HYPERALLOC : 0	// SMB_EMAIL if this was e-mail
-			  ,retry
-			  );
-
-if((i=smb_locksmbhdr(retry))!=0) {			// Can't lock status base header
-	printf("smb_locksmbhdr returned %d\n",i);
-	smb_close();
-	return(1); }
-
-if((i=smb_getstatus(&status))!=0) { 		// Can't read status base header
-	smb_unlocksmbhdr();
-	smb_close();
-	printf("smb_getstatus returned %d\n",i);
-	return(1); }
-
-if(status.attr&SMB_HYPERALLOC)
-	storage=SMB_HYPERALLOC;
-else
-	storage=SMB_SELFPACK;
-
-length=strlen(msg_text);					// Get length of message
-length+=sizeof(xlat);						// Add length of xlat string
-
-if(storage==SMB_HYPERALLOC) 				// Allocate space for message text
-	offset=smb_hallocdat();
-else {
-	if((i=smb_open_da(retry))!=0) {
-		smb_unlocksmbhdr();
-		printf("smb_open_da returned %d\n",i);
-		smb_close();
-		return(1); }
-	if(storage==SMB_FASTALLOC)
-		offset=smb_fallocdat(length,copies);
-	else
-		offset=smb_allocdat(length,copies);
-	fclose(sda_fp); }
-
-fseek(sdt_fp,offset,SEEK_SET);				// Seek to beginning of data block
-fwrite(&xlat,sizeof(xlat),1,sdt_fp);		// Write xlat string
-fwrite(msg_text,strlen(msg_text),1,sdt_fp); // Write message text
-fwrite(nul_buf,SDT_BLOCK_LEN-length 		// Write NULLs out to end of block
-	,1,sdt_fp);
-fflush(sdt_fp); 							// Flush output buffer
-smb_unlocksmbhdr(); 						// Unlock status base header
-
-memset(&msg,0,sizeof(smbmsg_t));			// Initialize header to NULL
-memcpy(msg.hdr.id,"SHD\x1a",4);             // Always set to SHD^Z
-msg.hdr.version=SMB_VERSION;
-msg.hdr.when_written.time=time(NULL);
-msg.hdr.when_written.zone=tzone;
-msg.hdr.when_imported.time=time(NULL);
-msg.hdr.when_imported.zone=tzone;
-msg.hdr.offset=offset;
-
-strcpy(str,"All");                          // Send message to "All"
-if((i=smb_hfield(&msg,RECIPIENT,strlen(str),str))!=0) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,copies);
-	smb_close();
-	return(1); }
-strlwr(str);								// If this were e-mail, idx.to
-msg.idx.to=crc16(str);						// would be the "to" user number
-
-strcpy(str,"Sysop");                        // Send message from "Sysop"
-if((i=smb_hfield(&msg,SENDER,strlen(str),str))!=0) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,copies);
-	smb_freemsgmem(msg);
-	smb_close();
-	return(1); }
-strlwr(str);								// If this were e-mail, idx.from
-msg.idx.from=crc16(str);					// would be the "from" user number
-
-strcpy(str,"This is a test");               // Set the message subject/title
-if((i=smb_hfield(&msg,SUBJECT,strlen(str),str))!=0) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(offset,length,copies);
-	smb_freemsgmem(msg);
-	smb_close();
-	return(1); }
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-if((i=smb_dfield(&msg,TEXT_BODY,length))!=0) {
-	printf("smb_dfield returned %d\n",i);
-	smb_freemsgdat(offset,length,copies);
-	smb_freemsgmem(msg);
-	smb_close();
-	return(1); }
-
-if((i=smb_addmsghdr(&msg,&status,storage,retry))!=0) {
-	printf("smb_addmsghdr returned %d\n",i);
-	smb_freemsgdat(offset,length,copies);
-	smb_freemsgmem(msg);
-	smb_close();
-	return(1); }
-
-smb_freemsgmem(msg);						// Unnecessary if exiting main()
-smb_close();								// Unnecessary if exiting main()
-return(0);
-}
-
-SMBLIB Retrieval Example
-========================
-&&SMBLIB Retrieval Example
-$$SMB_GET_
-
-#include "smblib.h"
-
-int main(void)
-{
-	char		ch; 						// General purpose character
-	int 		i,							// General purpose integer
-				retry=10;					// Retry for opening/locking files
-	ushort		xlat;						// Translation string
-	ulong		l;							// General purpose long integer
-    smbmsg_t    msg;                        // Message structure
-
-strcpy(smb_file,"MSGBASE");                 // We'll use "MSGBASE" for the name
-if((i=smb_open(retry))!=0) {				// Can't open!?!
-	printf("smb_open returned %d\n",i);
-	return(1); }
-
-if(!filelength(fileno(shd_fp))) {			// Message base not created yet
-	printf("Empty\n");
-	smb_close();
-	return(0); }
-
-for(msg.offset=0;!ferror(sid_fp);msg.offset++) {
-
-	fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),sid_fp))
-		break;
-
-	if((i=smb_lockmsghdr(msg,retry))!=0) {
-		printf("smb_lockmsghdr returned %d\n",i);
-		break; }
-	if((i=smb_getmsghdr(&msg))!=0) {
-		smb_unlockmsghdr(msg);
-		printf("smb_getmsghdr returned %d\n",i);
-		break; }
-	if((i=smb_unlockmsghdr(msg))!=0) {
-        smb_freemsgmem(msg);
-        printf("smb_unlockmsghdr returned %d\n",i);
-        break; }
-
-	printf("Subj : %s\n",msg.subj);
-	printf("To   : %s\n",msg.to);
-	printf("From : %s\n",msg.from);
-	printf("Date : %s\n",ctime((time_t *)&msg.hdr.when_written.time));
-
-	for(i=0;i<msg.hdr.total_dfields;i++)
-		switch(msg.dfield[i].type) {
-			case TEXT_BODY: 			// Only show BODY and TAIL data fields
-			case TEXT_TAIL:
-				fseek(sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-					,SEEK_SET);
-				fread(&xlat,sizeof(xlat),1,sdt_fp);
-				if(xlat!=XLAT_NONE) 	// No translations supported
-					continue;
-				for(l=sizeof(xlat);l<msg.dfield[i].length;l++) {
-					ch=fgetc(sdt_fp);
-					if(ch)
-						putchar(ch); }
-				printf("\n");
-				break; }
-	printf("\n");
-
-	smb_freemsgmem(msg); }			// Free memory allocated by smb_getmsghdr()
-
-smb_close();
-return(0);
-}
-
-SMBLIB Performance Issues
-=========================
-&&SMBLIB Performance Issues
-$$PERFORM_
-
-Since importing messages is the usually the most time consuming task likely
-undertaken by an SMB application, it is also the most susceptable to design
-issues that effect performance.
-
-Opening and Closing
--------------------
-When importing multiple messages for a single message base, it appears logical
-to open the message base, import all the messages, then close it. This indeed
-is preferred over opening and closing the message base for each message.
-
-When importing multiple messages for possibly non-consecutive message bases,
-developers may easily make the mistake of opening and closing the message base
-for each message. This is not necessary and can considerably hinder the
-import performance. The easiest solution is to only close the message base and
-open a new one if the next message to be imported is not for the same message
-base as the previously imported message. Example:
-
-smb_file[0]=0;
-for(i=0;i<total_messages_to_be_imported;i++) {
-	if(stricmp(get_messagebase_for_this_message(i),smb_file)) {
-		if(smb_file[0]) 	/* We've already opened one */
-			smb_close();
-		strcpy(smb_file,get_messagebase_for_this_message(i));
-		smb_open(10); }
-	/* Import this message */
-	}
-if(smb_file[0])
-	smb_close();
-
-A more advanced method is to keep multiple message bases open at the same time.
-Due to the likely limitation of total file handles on the system, it is
-suggested to keep the number of simultaneously open message bases at or below
-3. SMBLIB includes the function smb_stack() to easily "push" and "pop" message
-bases without closing them (push is the equivalent to "save" and pop is the
-equivalent to "restore"). The downside of this function is that you cannot
-access message bases on the stack without actually popping them off (in reverse
-of the order they were pushed). You can however "exchange" the current message
-base with the message base on the top of the stack (most recently pushed).
-To intelligently juggle more than two open message bases, the developer should
-create their own equivalent of the smb_stack() function so they can access the
-message bases on the stack without popping them off. An example of keeping a
-maximum of two message bases open using smb_stack():
-
-	char last_messagebase[128],new_messagebase[128];
-
-smb_file[0]=0;
-last_messagebase[0]=0;
-for(i=0;i<total_messages_to_be_imported;i++) {
-	strcpy(new_messagebase,get_messagebase_for_this_message(i));
-	if(stricmp(new_messagebase,smb_file)) { 	/* Not current message base */
-		if(smb_file[0]) {						/* We've already opened one */
-			if(!stricmp(new_messagebase,last_messagebase)) { /* Same as last */
-				strcpy(last_messagebase,smb_file);
-				smb_stack(SMB_STACK_XCHNG); }		/* Retore previous base */
-			else {
-				if(last_messagebase[0]) {
-					smb_stack(SMB_STACK_XCHNG);
-					smb_close();
-					strcpy(last_messagebase,new_messagebase); }
-				else {
-					strcpy(last_messagebase,smb_file);
-					smb_stack(SMB_STACK_PUSH); }	/* Save current base */
-				strcpy(smb_file,new_messagebase);
-				smb_open(10); } }
-		else {
-			strcpy(smb_file,new_messagebase);
-			smb_open(10); } }
-	/* Import this message */
-	}
-if(smb_file[0])
-    smb_close();
-if(last_messagebase[0]) {
-	smb_stack(SMB_STACK_POP);
-	smb_close(); }
-
-The second example would be of negligible performance gain over the first
-example (6 open operations versus 7) if the messages to import were in the
-following order:
-
-msg[0] --> msgbase[0]		// 0 opened
-msg[1] --> msgbase[1]		// 0 pushed 1 opened
-msg[2] --> msgbase[1]
-msg[3] --> msgbase[2]		// 1 closed 0 popped 0 closed 2 opened
-msg[4] --> msgbase[0]		// 2 pushed 0 opened
-msg[5] --> msgbase[2]		// 0 pushed 2 popped (exchanged)
-msg[6] --> msgbase[3]		// 2 closed 0 popped 0 closed 3 opened
-msg[7] --> msgbase[0]		// 3 pushed 0 opened
-
-The second example would be of significant performance gain over the first
-example (4 open operations versus 8) if the messages to import were in the
-following order:
-
-msg[0] --> msgbase[0]		// 0 opened
-msg[1] --> msgbase[1]		// 0 pushed 1 opened
-msg[2] --> msgbase[0]		// 1 pushed 0 popped (exchanged)
-msg[3] --> msgbase[1]		// 0 pushed 1 popped (exchanged)
-msg[4] --> msgbase[0]		// 1 pushed 0 popped (exchanged)
-msg[5] --> msgbase[2]		// 0 pushed 1 popped (exchanged) 1 closed 2 opened
-msg[6] --> msgbase[3]		// 2 pushed 0 popped (exchanged) 0 closed 3 opened
-msg[7] --> msgbase[2]		// 3 pushed 2 popped (exchanged)
-
-More advanced use of "stack-like" message base file handle storage can easily
-reduce the number of open operations, therefore increasing import performance
-under more adverse message base ordering conditions.
-
-Compression
------------
-If any message data compression features are offered by the application, it
-is important the the application not unnecessarily compress data that will
-not save any storage space. While this may seem an obvious statement, please
-review the following pseudo-code example:
-
-if ( message_data_length < SDT_BLOCK_LEN )
-	// Store uncompressed data
-else {
-	// Compress data
-	if ( ( compressed_data_length / SDT_BLOCK_LEN )
-		< ( message_data_length / SDT_BLOCK_LEN ) ) // Saves a block or more
-		// Store compressed data
-	else
-		// Store uncompressed data
-	}
-
-Since the SMB format stores message data in fixed length blocks, there is no
-point in storing a message in compressed format if it requires the same number
-of blocks as the uncompressed format (i.e. a message that is two blocks in
-length in uncompressed format and only a block and a half in length when
-compressed should not be stored in compressed format since it still requires
-two full blocks of storage). It is important to note that in the above example,
-the length of the data translation string was not taken into account in
-determining the number of required blocks. Also, the smb_datblocks() function
-is normally used in determing the number of required blocks to store a given
-data length and it is a little more involved than simply dividing the length of
-the data by SDT_BLOCK_LEN.
-
-
-Bibliography
-============
-&&Bibliography
-$$BIBLIOGR
-
-Title	  : The C Programming Language
-Publisher : Prentice Hall
-Author	  : Brian W. Kernighan and Dennis M. Ritchie
-
-Document  : ARPANET Request for Comments (RFC) #822
-Title	  : Standard for the Format of ARPA Internet text messages
-Publisher : SRI International
-Author	  : David H. Crocker, University of Delaware
-
-Document  : FTS-0001
-Publisher : FSC
-Author	  : Randy Bush, Pacific Systems Group
-
-Document  : FTS-0004
-Title	  : EchoMail Specification
-Publisher : FSC
-Author	  : Bob Hartman
-
-Document  : FTS-0009
-Title	  : A standard for unique message identifiers and reply chain linkage
-Publisher : FSC
-Author	  : Jim Nutt
-
-Document  : FSC-00046
-Title	  : A Product Idenfifier for FidoNet Message Handlers
-Publisher : FSC
-Author	  : Joaquim H. Homrighausen
-
-Document  : FSC-00053
-Title	  : Specifications for the ^aFLAGS field
-Publisher : FSC
-Author	  : Joaquim H. Homrighausen
-
-
-Implementations
-===============
-&&Implementations
-$$IMPLEMEN
-
-Product   : Synchronet Multinode BBS Software
-Developer : Digital Dynamics
-Level	  : III
-Version   : 2.20
-
-Product   : Synchronet/FidoNet Import/Export Utility (SBBSFIDO)
-Developer : Digital Dynamics
-Level	  : III
-Version   : 2.23
-
-Product   : Synchronet UTI (Universal Text Interface) Driver
-Developer : Digital Dynamics
-Level	  : III
-Version   : 2.23
-
-Product   : SBBSecho FidoNet Packet Tosser for Synchronet
-Developer : Digital Dynamics
-Level	  : III
-Version   : 1.11
-
-Product   : NetXpress Internet UUCP for Synchronet
-Developer : Merlin Systems
-Level	  : II
-Version   : 1.50
-
-Product   : InterEcho FidoNet Packet Tosser
-Developer : InterMail Sales Inc
-Level	  : II
-Version   : 1.11
diff --git a/src/sbbs2/smb/docs/smb_read.me b/src/sbbs2/smb/docs/smb_read.me
deleted file mode 100644
index 9cccaf613bee5bb679ab5c0beac307537680a57f..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/docs/smb_read.me
+++ /dev/null
@@ -1,64 +0,0 @@
-Synchronet Message Base (SMB) Specification v2.01 - READ.ME -
-=============================================================
-
-Files:
-
-        Miscellaneous
-        -------------
-        SMB_READ.ME     This file
-        FILE_ID.DIZ     Description of archive
-        SMB.HST         History of changes made since v1.00
-
-	Technical Specification
-        -----------------------
-        SMB.PRN         Paginated, to be printed at 12cpi (!)
-        SMB.TXT         Not paginated, for online viewing
-
-        Message Base C Library
-        ----------------------
-        SMBDEFS.H       C data types and constants
-        SMBLIB.H        C function prototypes
-        SMBLIB.C        C library functions
-	CRC32.H 	C header file for 32-bit CRC calculations
-        CRC16.C         C source file for 16-bit CRC calculations
-        LZH.H           C header file for LZH compression functions
-        LZH.C           C source file for LZH compression functions
-
-        Message Base Utility
-        --------------------
-        SMBUTIL.H       C header file
-        SMBUTIL.C       C source file
-        SMBUTIL.BOR     C makefile (for Borland C: make -f smbutil.bor)
-	SMBUTIL.WAT     C makefile (for Watcom C: wmake -f smbutil.wat
-                                      32-bit OS2: wmake -f smbutil.wat OS=OS2
-				      32-bit DOS: wmake -f smbutil.wat OS=DOSX)
-        SMBUTIL.EXE     Compiled and linked for 16-bit DOS
-
-        Check Message Base for Corruption
-        ---------------------------------
-        CHKSMB.C        C source file
-        CHKSMB.MAK      C makefile (for Borland C: make -f chksmb)
-        CHKSMB.EXE      Compiled and linked for 16-bit DOS
-
-	Rebuild Message Base Index and Allocation Files
-	-----------------------------------------------
-	FIXSMB.C	C source file
-	FIXSMB.MAK	C makefile (for Borland C: make -f fixsmb)
-	FIXSMB.EXE	Compiled and linked for 16-bit DOS
-
-        Convert from FidoNet (FTSC-1) to SMB
-        ------------------------------------
-        FIDO2SMB.C      C source file
-        FIDO2SMB.MAK    C makefile (for Borland C: make -f fido2smb)
-
-        Convert from Internet (RFC-822) to SMB
-        --------------------------------------
-        INET2SMB.C      C source file
-        INET2SMB.MAK    C makefile (for Borland C: make -f inet2smb)
-
-        Convert from QWK to SMB
-        -----------------------
-        QWK2SMB.C       C source file
-        QWK2SMB.MAK     C makefile (for Borland C: make -f qwk2smb)
-
-/* END of SMB_READ.ME */
diff --git a/src/sbbs2/smb/fixsmb/fixsmb.c b/src/sbbs2/smb/fixsmb/fixsmb.c
deleted file mode 100644
index 4a6973822bea05dbf31d527efa448d0e9d7e0d52..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/fixsmb/fixsmb.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* FIXSMB.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Re-generates an SMB message base based on SHD and SDT files */
-
-#include "smblib.h"
-
-smb_t smb;
-
-char *usage="usage: fixsmb [/opts] <smb_file>\n"
-			"\n"
-			" opts:\n"
-			"       m - force mail format instead of sub-board format\n"
-			"\n"
-			"   ex: FIXSMB /M MAIL\n"
-			"   or: FIXSMB DEBATE\n";
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-#define MAIL (1<<0)
-
-int main(int argc, char **argv)
-{
-	char		str[128],c;
-	int 		i,w,mode=0;
-	ulong		l,length,size,n,m;
-	smbmsg_t	msg;
-	smbstatus_t status;
-
-printf("\nFIXSMB v1.22 � Rebuild Synchronet Message Base � Developed 1995-1997 "
-	"Rob Swindell\n");
-
-smb.file[0]=0;
-for(i=1;i<argc;i++)
-	if(argv[i][0]=='/')
-		switch(toupper(argv[i][1])) {
-			case 'M':
-				mode|=MAIL;
-				break;
-			default:
-				printf(usage);
-				exit(1); }
-	else
-		strcpy(smb.file,argv[i]);
-
-if(!smb.file[0]) {
-	printf(usage);
-	exit(1); }
-
-strupr(smb.file);
-smb.retry_time=30;
-
-if((i=smb_open(&smb))!=0) {
-	printf("smb_open returned %d\n",i);
-	exit(1); }
-
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	printf("smb_locksmbhdr returned %d\n",i);
-	exit(1); }
-
-if((i=smb_getstatus(&smb))!=0) {
-	smb_unlocksmbhdr(&smb);
-	smb_close(&smb);
-	printf("smb_getstatus returned %d\n",i);
-	exit(1); }
-
-if(mode&MAIL && !(status.attr&SMB_EMAIL)) {
-	status.attr|=SMB_EMAIL;
-	if((i=smb_putstatus(&smb))!=0) {
-		smb_unlocksmbhdr(&smb);
-		smb_close(&smb);
-		printf("smb_putstatus returned %d\n",i);
-		exit(1); } }
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-
-	if((i=smb_open_ha(&smb))!=0) {
-		smb_close(&smb);
-		printf("smb_open_ha returned %d\n",i);
-		exit(1); }
-
-	if((i=smb_open_da(&smb))!=0) {
-		smb_close(&smb);
-		printf("smb_open_da returned %d\n",i);
-		exit(1); }
-
-	rewind(smb.sha_fp);
-	chsize(fileno(smb.sha_fp),0L);		/* Truncate the header allocation file */
-	rewind(smb.sda_fp);
-	chsize(fileno(smb.sda_fp),0L);		/* Truncate the data allocation file */
-	}
-
-rewind(smb.sid_fp);
-chsize(fileno(smb.sid_fp),0L);			/* Truncate the index */
-
-
-if(!(status.attr&SMB_HYPERALLOC)) {
-	length=filelength(fileno(smb.sdt_fp));
-	w=0;
-	for(l=0;l<length;l+=SDT_BLOCK_LEN)	/* Init .SDA file to NULL */
-		fwrite(&w,2,1,smb.sda_fp);
-
-	length=filelength(fileno(smb.shd_fp));
-	c=0;
-	for(l=0;l<length;l+=SHD_BLOCK_LEN)	/* Init .SHD file to NULL */
-		fwrite(&c,1,1,smb.sha_fp); }
-else
-	length=filelength(fileno(smb.shd_fp));
-
-n=1;	/* messsage number */
-for(l=status.header_offset;l<length;l+=size) {
-	printf("\r%2u%%  ",(long)(100.0/((float)length/l)));
-	msg.idx.offset=l;
-	if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-		printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-		continue; }
-	if((i=smb_getmsghdr(&smb,&msg))!=0) {
-		smb_unlockmsghdr(&smb,&msg);
-		printf("\n(%06lX) smb_getmsghdr returned %d\n",l,i);
-		size=SHD_BLOCK_LEN;
-		continue; }
-	smb_unlockmsghdr(&smb,&msg);
-	printf("#%-5lu (%06lX) %-25.25s ",msg.hdr.number,l,msg.from);
-	if(!(msg.hdr.attr&MSG_DELETE)) {   /* Don't index deleted messages */
-		msg.offset=n-1;
-		msg.hdr.number=n;
-		msg.idx.number=n;
-		msg.idx.attr=msg.hdr.attr;
-		msg.idx.time=msg.hdr.when_imported.time;
-		strcpy(str,msg.subj);
-		strlwr(str);
-		remove_re(str);
-		msg.idx.subj=crc16(str);
-		if(status.attr&SMB_EMAIL) {
-			if(msg.to_ext)
-				msg.idx.to=atoi(msg.to_ext);
-			else
-				msg.idx.to=0;
-			if(msg.from_ext)
-				msg.idx.from=atoi(msg.from_ext);
-			else
-				msg.idx.from=0; }
-		else {
-			strcpy(str,msg.to);
-			strlwr(str);
-			msg.idx.to=crc16(str);
-			strcpy(str,msg.from);
-			strlwr(str);
-			msg.idx.from=crc16(str); }
-		if((i=smb_putmsg(&smb,&msg))!=0) {
-			printf("\nsmb_putmsg returned %d\n",i);
-			continue; }
-		n++; }
-	else
-		printf("Not indexing deleted message\n");
-	size=smb_getmsghdrlen(&msg);
-	while(size%SHD_BLOCK_LEN)
-		size++;
-
-	if(!(status.attr&SMB_HYPERALLOC)) {
-		/**************************/
-		/* Allocate header blocks */
-		/**************************/
-		fseek(smb.sha_fp,(l-status.header_offset)/SHD_BLOCK_LEN,SEEK_SET);
-		if(msg.hdr.attr&MSG_DELETE) c=0;		/* mark as free */
-		else c=1;								/* or allocated */
-
-		for(i=0;i<size/SHD_BLOCK_LEN;i++)
-			fputc(c,smb.sha_fp);
-
-		/************************/
-		/* Allocate data blocks */
-		/************************/
-
-		if(!(msg.hdr.attr&MSG_DELETE))
-			smb_incdat(&smb,msg.hdr.offset,smb_getmsgdatlen(&msg),1);
-		}
-
-	smb_freemsgmem(&msg); }
-printf("\nDone.\n");
-status.total_msgs=status.last_msg=n-1;
-if((i=smb_putstatus(&smb))!=0)
-	printf("\nsmb_putstatus returned %d\n",i);
-smb_unlocksmbhdr(&smb);
-smb_close(&smb);
-return(0);
-}
diff --git a/src/sbbs2/smb/fixsmb/makefile b/src/sbbs2/smb/fixsmb/makefile
deleted file mode 100644
index aaa5a8c7351f3d342cf8b501de2a7f0d255c60c4..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/fixsmb/makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-###############################
-# Makefile for FIXSMB	      #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# Macros
-
-OS	= DOS
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include;..
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LFLAGS	= -n -c
-
-!ifdef __OS2__
-OS	= OS2
-CC      = c:\bcos2\bin\bcc
-LD      = c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;..
-LIB     = c:\bcos2\lib
-CFLAGS	= -d -C -I$(INCLUDE) -w-pro
-LFLAGS  = -c -w-srf
-!endif
-
-MAIN	= $(OS)\fixsmb.exe
-OBJS	= $(OS)\fixsmb.obj $(OS)\smblib.obj
-HEADERS = ..\smblib.h ..\smbdefs.h ..\crc32.h
-
-# Implicit C Compile Rule
-{.;..}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) 
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# All .obj modules
-$(OS)\fixsmb.obj:	$(HEADERS)
-$(OS)\smblib.obj:     	$(HEADERS)
diff --git a/src/sbbs2/smb/lzh.c b/src/sbbs2/smb/lzh.c
deleted file mode 100644
index d7f2519beb997bf75d302da8049891fc49ef9acd..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/lzh.c
+++ /dev/null
@@ -1,784 +0,0 @@
-/* LZH.C */
-
-/* Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions     */
-/* Based on Japanese version 29-NOV-1988								*/
-/* LZSS coded by Haruhiko Okumura										*/
-/* Adaptive Huffman Coding coded by Haruyasu Yoshizaki					*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifndef __WATCOMC__
-	#include <alloc.h>
-#endif
-#include "lzh.h"
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-	#if defined(__TURBOC__)
-		#define REALLOC(x,y) farrealloc(x,y)
-		#define LMALLOC(x) farmalloc(x)
-		#define MALLOC(x) farmalloc(x)
-		#define LFREE(x) farfree(x)
-		#define FREE(x) farfree(x)
-	#elif defined(__WATCOMC__)
-		#define REALLOC realloc
-		#define LMALLOC(x) halloc(x,1)	/* far heap, but slow */
-		#define MALLOC malloc			/* far heap, but 64k max */
-		#define LFREE hfree
-		#define FREE free
-	#else	/* Other 16-bit Compiler */
-		#define REALLOC realloc
-		#define LMALLOC malloc
-		#define MALLOC malloc
-		#define LFREE free
-		#define FREE free
-	#endif
-#else		/* 32-bit Compiler or Small Memory Model */
-	#define REALLOC realloc
-	#define LMALLOC malloc
-	#define MALLOC malloc
-	#define LFREE free
-	#define FREE free
-#endif
-
-
-
-/* LZSS Parameters */
-
-#define LZH_N			4096	/* Size of string buffer */
-#define LZH_F			60		/* Size of look-ahead buffer */
-#define LZH_THRESHOLD	2
-#define LZH_NIL 		LZH_N	/* End of tree's node  */
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned char *lzh_text_buf;
-short int	lzh_match_position, lzh_match_length,
-	  *lzh_lson, *lzh_rson, *lzh_dad;
-
-#else
-
-unsigned char lzh_text_buf[LZH_N + LZH_F - 1];
-short int	  lzh_match_position, lzh_match_length,
-		lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
-
-#endif
-
-
-void lzh_init_tree(void)  /* Initializing tree */
-{
-	short int  i;
-
-	for (i = LZH_N + 1; i <= LZH_N + 256; i++)
-		lzh_rson[i] = LZH_NIL;			/* root */
-	for (i = 0; i < LZH_N; i++)
-		lzh_dad[i] = LZH_NIL;			/* node */
-}
-
-/******************************/
-/* Inserting node to the tree */
-/* Only used during encoding  */
-/******************************/
-void lzh_insert_node(short int r)
-{
-	short int  i, p, cmp;
-	unsigned char  *key;
-	unsigned c;
-
-	cmp = 1;
-	key = lzh_text_buf+r;
-	p = LZH_N + 1 + key[0];
-	lzh_rson[r] = lzh_lson[r] = LZH_NIL;
-	lzh_match_length = 0;
-	for ( ; ; ) {
-		if (cmp >= 0) {
-			if (lzh_rson[p] != LZH_NIL)
-				p = lzh_rson[p];
-			else {
-				lzh_rson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		} else {
-			if (lzh_lson[p] != LZH_NIL)
-				p = lzh_lson[p];
-			else {
-				lzh_lson[p] = r;
-				lzh_dad[r] = p;
-				return;
-			}
-		}
-		for (i = 1; i < LZH_F; i++)
-			if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
-				break;
-		if (i > LZH_THRESHOLD) {
-			if (i > lzh_match_length) {
-				lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
-				if ((lzh_match_length = i) >= LZH_F)
-					break;
-			}
-			if (i == lzh_match_length) {
-				if ((c = ((r - p) & (LZH_N - 1)) - 1) < lzh_match_position) {
-					lzh_match_position = c;
-				}
-			}
-		}
-	}
-	lzh_dad[r] = lzh_dad[p];
-	lzh_lson[r] = lzh_lson[p];
-	lzh_rson[r] = lzh_rson[p];
-	lzh_dad[lzh_lson[p]] = r;
-	lzh_dad[lzh_rson[p]] = r;
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = r;
-	else
-		lzh_lson[lzh_dad[p]] = r;
-	lzh_dad[p] = LZH_NIL;  /* remove p */
-}
-
-void lzh_delete_node(short int p)  /* Deleting node from the tree */
-{
-	short int  q;
-
-	if (lzh_dad[p] == LZH_NIL)
-		return;			/* unregistered */
-	if (lzh_rson[p] == LZH_NIL)
-		q = lzh_lson[p];
-	else
-	if (lzh_lson[p] == LZH_NIL)
-		q = lzh_rson[p];
-	else {
-		q = lzh_lson[p];
-		if (lzh_rson[q] != LZH_NIL) {
-			do {
-				q = lzh_rson[q];
-			} while (lzh_rson[q] != LZH_NIL);
-			lzh_rson[lzh_dad[q]] = lzh_lson[q];
-			lzh_dad[lzh_lson[q]] = lzh_dad[q];
-			lzh_lson[q] = lzh_lson[p];
-			lzh_dad[lzh_lson[p]] = q;
-		}
-		lzh_rson[q] = lzh_rson[p];
-		lzh_dad[lzh_rson[p]] = q;
-	}
-	lzh_dad[q] = lzh_dad[p];
-	if (lzh_rson[lzh_dad[p]] == p)
-		lzh_rson[lzh_dad[p]] = q;
-	else
-		lzh_lson[lzh_dad[p]] = q;
-	lzh_dad[p] = LZH_NIL;
-}
-
-/* Huffman coding parameters */
-
-#define LZH_N_CHAR		(256 - LZH_THRESHOLD + LZH_F)
-					/* character code (= 0..LZH_N_CHAR-1) */
-#define LZH_T		(LZH_N_CHAR * 2 - 1)	/* Size of table */
-#define LZH_R		(LZH_T - 1) 		/* root position */
-#define MAX_FREQ	0x8000
-					/* update when cumulative frequency */
-					/* reaches to this value */
-
-/*
- * Tables for encoding/decoding upper 6 bits of
- * sliding dictionary pointer
- */
-/* encoder table */
-uchar lzh_p_len[64] = {
-	0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-uchar lzh_p_code[64] = {
-	0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
-	0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
-	0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
-	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
-	0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
-	0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
-	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
-};
-
-/* decoder table */
-uchar lzh_d_code[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
-	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
-	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
-	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
-	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
-	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
-	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
-	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
-	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
-	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
-	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
-	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
-	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
-	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
-};
-
-uchar lzh_d_len[256] = {
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-};
-
-#ifdef LZH_DYNAMIC_BUF
-
-unsigned short *lzh_freq=NULL;	 /* cumulative freq table */
-
-/*
- * pointing parent nodes.
- * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
- */
-short int *lzh_prnt=NULL;
-
-/* pointing children nodes (son[], son[] + 1)*/
-short int *lzh_son=NULL;
-
-#else	/* STATIC */
-
-unsigned short lzh_freq[LZH_T + 1];   /* cumulative freq table */
-short int lzh_prnt[LZH_T + LZH_N_CHAR];
-short int lzh_son[LZH_T + 1];		  /* bug fixed by Digital Dynamics */
-
-#endif
-
-
-unsigned short lzh_getbuf = 0;		/* Was just "unsigned" fixed 04/12/95 */
-uchar lzh_getlen = 0;
-
-int lzh_getbit(uchar *inbuf, long *incnt, long inlen)    /* get one bit */
-{
-	short int i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 1;
-	lzh_getlen--;
-	return (i < 0);
-}
-
-short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen)   /* get a byte */
-{
-	unsigned short i;
-
-	while (lzh_getlen <= 8) {
-		if((*incnt)>=inlen)
-			i=0;
-		else
-			i=inbuf[(*incnt)++];
-		lzh_getbuf |= i << (8 - lzh_getlen);
-		lzh_getlen += 8;
-	}
-	i = lzh_getbuf;
-	lzh_getbuf <<= 8;
-	lzh_getlen -= 8;
-	return i >> 8;
-}
-
-unsigned lzh_putbuf = 0;
-uchar lzh_putlen = 0;
-
-/* output c bits */
-void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen)
-{
-	lzh_putbuf |= c >> lzh_putlen;
-	if ((lzh_putlen += l) >= 8) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-		if ((lzh_putlen -= 8) >= 8) {
-			outbuf[(*outlen)++]=lzh_putbuf;
-			lzh_putlen -= 8;
-			lzh_putbuf = c << (l - lzh_putlen);
-		} else {
-			lzh_putbuf <<= 8;
-		}
-	}
-}
-
-
-/* initialize freq tree */
-
-void lzh_start_huff()
-{
-	short int i, j;
-
-lzh_getbuf = 0; 	/* Added by Digital Dynamics for repeating operations */
-lzh_getlen = 0;
-lzh_putbuf = 0;
-lzh_putlen = 0;
-
-	for (i = 0; i < LZH_N_CHAR; i++) {
-		lzh_freq[i] = 1;
-		lzh_son[i] = i + LZH_T;
-		lzh_prnt[i + LZH_T] = i;
-	}
-	i = 0; j = LZH_N_CHAR;
-	while (j <= LZH_R) {
-		lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
-		lzh_son[j] = i;
-		lzh_prnt[i] = lzh_prnt[i + 1] = j;
-		i += 2; j++;
-	}
-	lzh_freq[LZH_T] = 0xffff;
-    lzh_prnt[LZH_R] = 0;
-}
-
-
-/* reconstruct freq tree */
-
-void lzh_reconst()
-{
-	short int i, j, k;
-	unsigned short f, l;
-
-	/* halven cumulative freq for leaf nodes */
-	j = 0;
-	for (i = 0; i < LZH_T; i++) {
-		if (lzh_son[i] >= LZH_T) {
-			lzh_freq[j] = (lzh_freq[i] + 1) / 2;
-			lzh_son[j] = lzh_son[i];
-			j++;
-		}
-	}
-	/* make a tree : first, connect children nodes */
-	for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
-		k = i + 1;
-		f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
-		for (k = j - 1; f < lzh_freq[k]; k--);
-		k++;
-		l = (j - k) * 2;
-		
-		/* movmem() is Turbo-C dependent
-		   rewritten to memmove() by Kenji */
-		
-		/* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
-		(void)memmove(lzh_freq+k+1,lzh_freq+k, l);
-		lzh_freq[k] = f;
-		/* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
-		(void)memmove(lzh_son+k+1,lzh_son+k, l);
-		lzh_son[k] = i;
-	}
-	/* connect parent nodes */
-	for (i = 0; i < LZH_T; i++) {
-		if ((k = lzh_son[i]) >= LZH_T) {
-			lzh_prnt[k] = i;
-		} else {
-			lzh_prnt[k] = lzh_prnt[k + 1] = i;
-		}
-	}
-}
-
-/* update freq tree */
-
-void lzh_update(short int c)
-{
-	short int i, j, k, l;
-
-	if (lzh_freq[LZH_R] == MAX_FREQ) {
-		lzh_reconst();
-	}
-	c = lzh_prnt[c + LZH_T];
-	do {
-		k = ++lzh_freq[c];
-
-		/* swap nodes to keep the tree freq-ordered */
-		if (k > lzh_freq[l = c + 1]) {
-			while (k > lzh_freq[++l]);
-			l--;
-			lzh_freq[c] = lzh_freq[l];
-			lzh_freq[l] = k;
-
-			i = lzh_son[c];
-			lzh_prnt[i] = l;
-			if (i < LZH_T) lzh_prnt[i + 1] = l;
-
-			j = lzh_son[l];
-			lzh_son[l] = i;
-
-			lzh_prnt[j] = c;
-			if (j < LZH_T) lzh_prnt[j + 1] = c;
-			lzh_son[c] = j;
-
-			c = l;
-		}
-	} while ((c = lzh_prnt[c]) != 0);	/* do it until reaching the root */
-}
-
-unsigned short lzh_code, lzh_len;
-
-void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-	short int j, k;
-
-	i = 0;
-	j = 0;
-	k = lzh_prnt[c + LZH_T];
-
-	/* search connections from leaf node to the root */
-	do {
-		i >>= 1;
-
-		/*
-		if node's address is odd, output 1
-		else output 0
-		*/
-		if (k & 1) i += 0x8000;
-
-		j++;
-	} while ((k = lzh_prnt[k]) != LZH_R);
-	lzh_putcode(j, i, outbuf, outlen);
-	lzh_code = i;
-	lzh_len = j;
-	lzh_update(c);
-}
-
-void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen)
-{
-	unsigned short i;
-
-	/* output upper 6 bits with encoding */
-	i = c >> 6;
-	lzh_putcode(lzh_p_len[i], (unsigned)lzh_p_code[i] << 8, outbuf, outlen);
-
-	/* output lower 6 bits directly */
-	lzh_putcode(6, (c & 0x3f) << 10, outbuf, outlen);
-}
-
-void lzh_encode_end(uchar *outbuf, long *outlen)
-{
-	if (lzh_putlen) {
-		outbuf[(*outlen)++]=(lzh_putbuf >> 8);
-	}
-}
-
-short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short c;
-
-	c = lzh_son[LZH_R];
-
-	/*
-	 * start searching tree from the root to leaves.
-	 * choose node #(lzh_son[]) if input bit == 0
-	 * else choose #(lzh_son[]+1) (input bit == 1)
-	 */
-	while (c < LZH_T) {
-		c += lzh_getbit(inbuf,incnt,inlen);
-		c = lzh_son[c];
-	}
-	c -= LZH_T;
-	lzh_update(c);
-	return c;
-}
-
-short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen)
-{
-	unsigned short i, j, c;
-
-	/* decode upper 6 bits from given table */
-	i = lzh_getbyte(inbuf,incnt,inlen);
-	c = (unsigned)lzh_d_code[i] << 6;
-	j = lzh_d_len[i];
-
-	/* input lower 6 bits directly */
-	j -= 2;
-	while (j--) {
-		i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
-	}
-	return c | i & 0x3f;
-}
-
-/* Compression */
-
-/* Encoding/Compressing */
-/* Returns length of outbuf */
-long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, c, len, r, s, last_match_length;
-	long incnt,outlen; /* textsize=0; */
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		return(-1); }
-	if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-		FREE(lzh_lson);
-		return(-1); }
-	if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-		FREE(lzh_rson);
-		return(-1); }
-#endif
-
-	incnt=0;
-	memcpy(outbuf,&inlen,sizeof(inlen));
-	outlen=sizeof(inlen);
-	if(!inlen) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-        FREE(lzh_lson);
-        FREE(lzh_rson);
-		FREE(lzh_dad);
-#endif
-		return(outlen); }
-	lzh_start_huff();
-	lzh_init_tree();
-	s = 0;
-	r = LZH_N - LZH_F;
-	for (i = s; i < r; i++)
-		lzh_text_buf[i] = ' ';
-	for (len = 0; len < LZH_F && incnt<inlen; len++)
-		lzh_text_buf[r + len] = inbuf[incnt++];
-	/* textsize = len; */
-	for (i = 1; i <= LZH_F; i++)
-		lzh_insert_node(r - i);
-	lzh_insert_node(r);
-	do {
-		if (lzh_match_length > len)
-			lzh_match_length = len;
-		if (lzh_match_length <= LZH_THRESHOLD) {
-			lzh_match_length = 1;
-			lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
-		} else {
-			lzh_encode_char(255 - LZH_THRESHOLD + lzh_match_length
-				,outbuf,&outlen);
-			lzh_encode_position(lzh_match_position
-				,outbuf,&outlen);
-		}
-		last_match_length = lzh_match_length;
-		for (i = 0; i < last_match_length && incnt<inlen; i++) {
-			lzh_delete_node(s);
-			c=inbuf[incnt++];
-			lzh_text_buf[s] = c;
-			if (s < LZH_F - 1)
-				lzh_text_buf[s + LZH_N] = c;
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			lzh_insert_node(r);
-		}
-/***
-		if ((textsize += i) > printcount) {
-			printf("%12ld\r", textsize);
-			printcount += 1024;
-		}
-***/
-		while (i++ < last_match_length) {
-			lzh_delete_node(s);
-			s = (s + 1) & (LZH_N - 1);
-			r = (r + 1) & (LZH_N - 1);
-			if (--len) lzh_insert_node(r);
-		}
-	} while (len > 0);
-	lzh_encode_end(outbuf,&outlen);
-/*
-	printf("input: %ld (%ld) bytes\n", inlen,textsize);
-	printf("output: %ld bytes\n", outlen);
-	printf("output/input: %.3f\n", (double)outlen / inlen);
-*/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-	FREE(lzh_lson);
-	FREE(lzh_rson);
-	FREE(lzh_dad);
-#endif
-
-	return(outlen);
-}
-
-/* Decoding/Uncompressing */
-/* Returns length of outbuf */
-long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf)
-{
-	short int  i, j, k, r, c;
-	unsigned long int  count;
-	long incnt,textsize;
-
-#ifdef LZH_DYNAMIC_BUF
-
-	if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
-		return(-1);
-	if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short)))
-		==NULL) {
-		FREE(lzh_text_buf);
-		return(-1); }
-	if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_freq);
-		return(-1); }
-	if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		return(-1); }
-
-#endif
-
-	incnt=0;
-	memcpy(&textsize,inbuf,sizeof(textsize));
-	incnt+=sizeof(textsize);
-	if (textsize == 0) {
-#ifdef LZH_DYNAMIC_BUF
-		FREE(lzh_text_buf);
-		FREE(lzh_prnt);
-		FREE(lzh_freq);
-		FREE(lzh_son);
-#endif
-		return(textsize); }
-	lzh_start_huff();
-	for (i = 0; i < LZH_N - LZH_F; i++)
-		*(lzh_text_buf+i) = ' ';
-	r = LZH_N - LZH_F;
-    for (count = 0; count < textsize; ) {
-		c = lzh_decode_char(inbuf,&incnt,inlen);
-		if (c < 256) {
-			outbuf[count]=c;
-#if 0
-			if(r>(LZH_N + LZH_F - 1) || r<0) {
-				printf("Overflow! (%d)\n",r);
-				getch();
-				exit(-1); }
-#endif
-			*(lzh_text_buf+r) = c;
-			r++;
-			r &= (LZH_N - 1);
-			count++;
-		} else {
-			i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
-				& (LZH_N - 1);
-			j = c - 255 + LZH_THRESHOLD;
-			for (k = 0; k < j && count<textsize; k++) {
-				c = lzh_text_buf[(i + k) & (LZH_N - 1)];
-				outbuf[count]=c;
-#if 0
-				if(r>(LZH_N + LZH_F - 1) || r<0) {
-					printf("Overflow! (%d)\n",r);
-					exit(-1); }
-#endif
-				*(lzh_text_buf+r) = c;
-				r++;
-				r &= (LZH_N - 1);
-				count++;
-			}
-		}
-	}
-/***
-	printf("%12ld\n", count);
-***/
-
-#ifdef LZH_DYNAMIC_BUF
-	FREE(lzh_text_buf);
-	FREE(lzh_prnt);
-	FREE(lzh_freq);
-	FREE(lzh_son);
-#endif
-
-return(count);
-}
-
-
diff --git a/src/sbbs2/smb/lzh.h b/src/sbbs2/smb/lzh.h
deleted file mode 100644
index 4972cc3a1aa09bb8ab9875b84779716e0292e4f1..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/lzh.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* LZH.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifdef __NT__
-#define LZHCALL _pascal
-#else
-#define LZHCALL
-#endif
-
-#ifndef uchar
-#define uchar unsigned char
-#endif
-
-long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf);
-long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf);
-
-#ifdef __WATCOMC__	/* Use MSC standard (prepended underscore) */
-#pragma aux lzh_encode			"_*"
-#pragma aux lzh_decode          "_*"
-#endif
diff --git a/src/sbbs2/smb/smbdefs.h b/src/sbbs2/smb/smbdefs.h
deleted file mode 100644
index 2e845c0fd25b1eb2ba7d70ddd3cb7b2ccd864f20..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbdefs.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/* SMBDEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _SMBDEFS_H
-#define _SMBDEFS_H
-
-#include <stdio.h>
-
-/**********/
-/* Macros */
-/**********/
-
-										/* Control characters */
-#define TAB 				0x09		/* Horizontal tabulation	^I */
-#define LF					0x0a		/* Line feed				^J */
-#define FF					0x0c		/* Form feed				^L */
-#define CR					0x0d		/* Carriage return			^M */
-#define ESC 				0x1b		/* Escape					^[ */
-#define SP					0x20		/* Space					   */
-
-#define ulong				unsigned long
-#define ushort				unsigned short
-#define uchar				unsigned char
-#define uint				unsigned int
-
-/****************************************************************************/
-/* Memory allocation macros for various compilers and environments			*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-#	define HUGE16 huge
-#	define FAR16 far
-#	if defined(__TURBOC__)
-#		define REALLOC(x,y) farrealloc(x,y)
-#		define LMALLOC(x) farmalloc(x)
-#		define MALLOC(x) farmalloc(x)
-#		define LFREE(x) farfree(x)
-#		define FREE(x) farfree(x)
-#	elif defined(__WATCOMC__)
-#		define REALLOC realloc
-#		define LMALLOC(x) halloc(x,1)  /* far heap, but slow */
-#		define MALLOC malloc		   /* far heap, but 64k max */
-#		define LFREE hfree
-#		define FREE free
-#	else	/* Other 16-bit Compiler */
-#		define REALLOC realloc
-#		define LMALLOC malloc
-#		define MALLOC malloc
-#		define LFREE free
-#		define FREE free
-#	endif
-#else		/* 32-bit Compiler or Small Memory Model */
-#	define HUGE16
-#	define FAR16
-#	define REALLOC realloc
-#	define LMALLOC malloc
-#	define MALLOC malloc
-#	define LFREE free
-#	define FREE free
-#endif
-
-
-#define SDT_BLOCK_LEN		256 		/* Size of data blocks */
-#define SHD_BLOCK_LEN		256 		/* Size of header blocks */
-
-#define SMB_SELFPACK		0			/* Self-packing storage allocation */
-#define SMB_FASTALLOC		1			/* Fast allocation */
-#define SMB_HYPERALLOC		2			/* No allocation */
-
-#define SMB_EMAIL			1			/* User numbers stored in Indexes */
-
-										/* Time zone macros for when_t.zone */
-#define DAYLIGHT			0x8000		/* Daylight savings is active */
-#define US_ZONE 			0x4000		/* U.S. time zone */
-#define WESTERN_ZONE		0x2000		/* Non-standard zone west of UT */
-#define EASTERN_ZONE		0x1000		/* Non-standard zone east of UT */
-
-										/* US Time Zones (standard) */
-#define AST 				0x40F0		// Atlantic 			(-04:00)
-#define EST 				0x412C		// Eastern				(-05:00)
-#define CST 				0x4168		// Central				(-06:00)
-#define MST 				0x41A4		// Mountain 			(-07:00)
-#define PST 				0x41E0		// Pacific				(-08:00)
-#define YST 				0x421C		// Yukon				(-09:00)
-#define HST 				0x4258		// Hawaii/Alaska		(-10:00)
-#define BST 				0x4294		// Bering				(-11:00)
-
-										/* US Time Zones (daylight) */
-#define ADT 				0xC0F0		// Atlantic 			(-03:00)
-#define EDT 				0xC12C		// Eastern				(-04:00)
-#define CDT 				0xC168		// Central				(-05:00)
-#define MDT 				0xC1A4		// Mountain 			(-06:00)
-#define PDT 				0xC1E0		// Pacific				(-07:00)
-#define YDT 				0xC21C		// Yukon				(-08:00)
-#define HDT 				0xC258		// Hawaii/Alaska		(-09:00)
-#define BDT 				0xC294		// Bering				(-10:00)
-
-										/* Non-standard Time Zones */
-#define MID 				0x2294		// Midway				(-11:00)
-#define VAN 				0x21E0		// Vancouver			(-08:00)
-#define EDM 				0x21A4		// Edmonton 			(-07:00)
-#define WIN 				0x2168		// Winnipeg 			(-06:00)
-#define BOG 				0x212C		// Bogota				(-05:00)
-#define CAR 				0x20F0		// Caracas				(-04:00)
-#define RIO 				0x20B4		// Rio de Janeiro		(-03:00)
-#define FER 				0x2078		// Fernando de Noronha	(-02:00)
-#define AZO 				0x203C		// Azores				(-01:00)
-#define LON 				0x1000		// London				(+00:00)
-#define BER 				0x103C		// Berlin				(+01:00)
-#define ATH 				0x1078		// Athens				(+02:00)
-#define MOS 				0x10B4		// Moscow				(+03:00)
-#define DUB 				0x10F0		// Dubai				(+04:00)
-#define KAB 				0x110E		// Kabul				(+04:30)
-#define KAR 				0x112C		// Karachi				(+05:00)
-#define BOM 				0x114A		// Bombay				(+05:30)
-#define KAT 				0x1159		// Kathmandu			(+05:45)
-#define DHA 				0x1168		// Dhaka				(+06:00)
-#define BAN 				0x11A4		// Bangkok				(+07:00)
-#define HON 				0x11E0		// Hong Kong			(+08:00)
-#define TOK 				0x121C		// Tokyo				(+09:00)
-#define SYD 				0x1258		// Sydney				(+10:00)
-#define NOU 				0x1294		// Noumea				(+11:00)
-#define WEL 				0x12D0		// Wellington			(+12:00)
-
-										/* Valid hfield_t.types */
-#define SENDER				0x00
-#define SENDERAGENT 		0x01
-#define SENDERNETTYPE		0x02
-#define SENDERNETADDR		0x03
-#define SENDEREXT			0x04
-#define SENDERPOS			0x05
-#define SENDERORG			0x06
-
-#define AUTHOR				0x10
-#define AUTHORAGENT 		0x11
-#define AUTHORNETTYPE		0x12
-#define AUTHORNETADDR		0x13
-#define AUTHOREXT			0x14
-#define AUTHORPOS			0x15
-#define AUTHORORG			0x16
-
-#define REPLYTO 			0x20
-#define REPLYTOAGENT		0x21
-#define REPLYTONETTYPE		0x22
-#define REPLYTONETADDR		0x23
-#define REPLYTOEXT			0x24
-#define REPLYTOPOS			0x25
-#define REPLYTOORG			0x26
-
-#define RECIPIENT			0x30
-#define RECIPIENTAGENT		0x31
-#define RECIPIENTNETTYPE	0x32
-#define RECIPIENTNETADDR	0x33
-#define RECIPIENTEXT		0x34
-#define RECIPIENTPOS		0x35
-#define RECIPIENTORG		0x36
-
-#define FORWARDTO			0x40
-#define FORWARDTOAGENT		0x41
-#define FORWARDTONETTYPE	0x42
-#define FORWARDTONETADDR	0x43
-#define FORWARDTOEXT		0x44
-#define FORWARDTOPOS		0x45
-#define FORWARDTOORG		0x46
-
-#define FORWARDED			0x48
-
-#define RECEIVEDBY			0x50
-#define RECEIVEDBYAGENT 	0x51
-#define RECEIVEDBYNETTYPE	0x52
-#define RECEIVEDBYNETADDR	0x53
-#define RECEIVEDBYEXT		0x54
-#define RECEIVEDBYPOS		0x55
-#define RECEIVEDBYORG		0x56
-
-#define RECEIVED			0x58
-
-#define SUBJECT 			0x60
-#define SUMMARY 			0x61
-#ifndef COMMENT
-#define COMMENT 			0x62
-#endif
-#define CARBONCOPY			0x63
-#define GROUP				0x64
-#define EXPIRATION			0x65
-#define PRIORITY			0x66
-
-#define FILEATTACH			0x70
-#define DESTFILE			0x71
-#define FILEATTACHLIST		0x72
-#define DESTFILELIST		0x73
-#define FILEREQUEST 		0x74
-#define FILEPASSWORD		0x75
-#define FILEREQUESTLIST 	0x76
-#define FILEPASSWORDLIST	0x77
-
-#define IMAGEATTACH 		0x80
-#define ANIMATTACH			0x81
-#define FONTATTACH			0x82
-#define SOUNDATTACH 		0x83
-#define PRESENTATTACH		0x84
-#define VIDEOATTACH 		0x85
-#define APPDATAATTACH		0x86
-
-#define IMAGETRIGGER		0x90
-#define ANIMTRIGGER 		0x91
-#define FONTTRIGGER 		0x92
-#define SOUNDTRIGGER		0x93
-#define PRESENTTRIGGER		0x94
-#define VIDEOTRIGGER		0x95
-#define APPDATATRIGGER		0x96
-
-#define FIDOCTRL			0xa0
-#define FIDOAREA			0xa1
-#define FIDOSEENBY			0xa2
-#define FIDOPATH			0xa3
-#define FIDOMSGID			0xa4
-#define FIDOREPLYID 		0xa5
-#define FIDOPID 			0xa6
-#define FIDOFLAGS			0xa7
-
-#define RFC822HEADER		0xb0
-#define RFC822MSGID 		0xb1
-#define RFC822REPLYID		0xb2
-
-#define UNKNOWN 			0xf1
-#define UNKNOWNASCII		0xf2
-#define UNUSED				0xff
-
-										/* Valid dfield_t.types */
-#define TEXT_BODY			0x00
-#define TEXT_SOUL			0x01
-#define TEXT_TAIL			0x02
-#define TEXT_WING			0x03
-#define IMAGEEMBED			0x20
-#define ANIMEMBED			0x21
-#define FONTEMBED			0x22
-#define SOUNDEMBED			0x23
-#define PRESENTEMBED		0x24
-#define VIDEOEMBED			0x25
-#define APPDATAEMBED		0x26
-#define UNUSED				0xff
-
-
-										/* Message attributes */
-#define MSG_PRIVATE 		(1<<0)
-#define MSG_READ			(1<<1)
-#define MSG_PERMANENT		(1<<2)
-#define MSG_LOCKED			(1<<3)
-#define MSG_DELETE			(1<<4)
-#define MSG_ANONYMOUS		(1<<5)
-#define MSG_KILLREAD		(1<<6)
-#define MSG_MODERATED		(1<<7)
-#define MSG_VALIDATED		(1<<8)
-#define MSG_REPLIED			(1<<9)		// User replied to this message
-
-										/* Auxillary header attributes */
-#define MSG_FILEREQUEST 	(1<<0)		// File request
-#define MSG_FILEATTACH		(1<<1)		// File(s) attached to Msg
-#define MSG_TRUNCFILE		(1<<2)		// Truncate file(s) when sent
-#define MSG_KILLFILE		(1<<3)		// Delete file(s) when sent
-#define MSG_RECEIPTREQ		(1<<4)		// Return receipt requested
-#define MSG_CONFIRMREQ		(1<<5)		// Confirmation receipt requested
-#define MSG_NODISP			(1<<6)		// Msg may not be displayed to user
-
-										/* Message network attributes */
-#define MSG_LOCAL			(1<<0)		// Msg created locally
-#define MSG_INTRANSIT		(1<<1)		// Msg is in-transit
-#define MSG_SENT			(1<<2)		// Sent to remote
-#define MSG_KILLSENT		(1<<3)		// Kill when sent
-#define MSG_ARCHIVESENT 	(1<<4)		// Archive when sent
-#define MSG_HOLD			(1<<5)		// Hold for pick-up
-#define MSG_CRASH			(1<<6)		// Crash
-#define MSG_IMMEDIATE		(1<<7)		// Send Msg now, ignore restrictions
-#define MSG_DIRECT			(1<<8)		// Send directly to destination
-#define MSG_GATE			(1<<9)		// Send via gateway
-#define MSG_ORPHAN			(1<<10) 	// Unknown destination
-#define MSG_FPU 			(1<<11) 	// Force pickup
-#define MSG_TYPELOCAL		(1<<12) 	// Msg is for local use only
-#define MSG_TYPEECHO		(1<<13) 	// Msg is for conference distribution
-#define MSG_TYPENET 		(1<<14) 	// Msg is direct network mail
-
-
-enum {
-     NET_NONE
-    ,NET_UNKNOWN
-    ,NET_FIDO
-    ,NET_POSTLINK
-    ,NET_QWK
-	,NET_INTERNET
-	,NET_WWIV
-	,NET_MHS
-
-/* Add new ones here */
-
-    ,NET_TYPES
-    };
-
-enum {
-     AGENT_PERSON
-    ,AGENT_PROCESS
-
-/* Add new ones here */
-
-    ,AGENT_TYPES
-    };
-
-enum {
-     XLAT_NONE              // No translation/End of translation list
-    ,XLAT_ENCRYPT           // Encrypted data
-    ,XLAT_ESCAPED           // 7-bit ASCII escaping for ctrl and 8-bit data
-    ,XLAT_HUFFMAN           // Static and adaptive Huffman coding compression
-    ,XLAT_LZW               // Limpel/Ziv/Welch compression
-    ,XLAT_MLZ78             // Modified LZ78 compression
-    ,XLAT_RLE               // Run length encoding compression
-    ,XLAT_IMPLODE           // Implode compression (PkZIP)
-    ,XLAT_SHRINK            // Shrink compression (PkZIP)
-	,XLAT_LZH				// LHarc (LHA) Dynamic Huffman coding
-
-/* Add new ones here */
-
-    ,XLAT_TYPES
-    };
-
-
-/************/
-/* Typedefs */
-/************/
-
-#ifdef _WIN32	/* necessary for compatibility with SBBS v2 */
-#pragma pack(push)
-#pragma pack(1)
-#endif
-
-typedef struct {			// Time with time-zone
-
-	ulong	time;			// Local time (unix format)
-	short	zone;			// Time zone
-
-	} when_t;
-
-typedef struct {			// Index record
-
-	ushort	to; 			// 16-bit CRC of recipient name (lower case)
-	ushort	from;			// 16-bit CRC of sender name (lower case)
-	ushort	subj;			// 16-bit CRC of subject (lower case, w/o RE:)
-	ushort	attr;			// attributes (read, permanent, etc.)
-	ulong	offset; 		// offset into header file
-	ulong	number; 		// number of message (1 based)
-	ulong	time;			// time/date message was imported/posted
-
-	} idxrec_t;
-
-typedef struct {			// Message base header (fixed portion)
-
-    uchar   id[4];          // text or binary unique hdr ID
-    ushort  version;        // version number (initially 100h for 1.00)
-    ushort  length;         // length including this struct
-
-	} smbhdr_t;
-
-typedef struct {			// Message base status header
-
-	ulong	last_msg;		// last message number
-	ulong	total_msgs; 	// total messages
-	ulong	header_offset;	// byte offset to first header record
-	ulong	max_crcs;		// Maximum number of CRCs to keep in history
-    ulong   max_msgs;       // Maximum number of message to keep in sub
-    ushort  max_age;        // Maximum age of message to keep in sub (in days)
-	ushort	attr;			// Attributes for this message base (SMB_HYPER,etc)
-
-	} smbstatus_t;
-
-typedef struct {			// Message header
-
-	uchar	id[4];			// SHD<^Z>
-    ushort  type;           // Message type (normally 0)
-    ushort  version;        // Version of type (initially 100h for 1.00)
-    ushort  length;         // Total length of fixed record + all fields
-	ushort	attr;			// Attributes (bit field) (duped in SID)
-	ulong	auxattr;		// Auxillary attributes (bit field)
-    ulong   netattr;        // Network attributes
-	when_t	when_written;	// Time message was written (unix format)
-	when_t	when_imported;	// Time message was imported
-    ulong   number;         // Message number
-    ulong   thread_orig;    // Original message number in thread
-    ulong   thread_next;    // Next message in thread
-    ulong   thread_first;   // First reply to this message
-	uchar	reserved[16];	// Reserved for future use
-    ulong   offset;         // Offset for buffer into data file (0 or mod 256)
-	ushort	total_dfields;	// Total number of data fields
-
-	} msghdr_t;
-
-typedef struct {			// Data field
-
-	ushort	type;			// Type of data field
-    ulong   offset;         // Offset into buffer 
-    ulong   length;         // Length of data field
-
-    } dfield_t;
-
-typedef struct {			// Header field
-
-	ushort	type;
-	ushort	length; 		// Length of buffer
-
-	} hfield_t;
-
-typedef struct {			// FidoNet address (zone:net/node.point)
-
-	ushort	zone;
-	ushort	net;
-	ushort	node;
-	ushort	point;
-
-    } fidoaddr_t;
-
-typedef struct {			// Network (type and address)
-
-    ushort  type;
-	void	*addr;
-
-	} net_t;
-
-typedef struct {				// Message
-
-	idxrec_t	idx;			// Index
-	msghdr_t	hdr;			// Header record (fixed portion)
-	char		*to,			// To name
-				*to_ext,		// To extension
-				*from,			// From name
-				*from_ext,		// From extension
-				*replyto,		// Reply-to name
-				*replyto_ext,	// Reply-to extension */
-				*subj;			// Subject
-	ushort		to_agent,		// Type of agent message is to
-				from_agent, 	// Type of agent message is from
-				replyto_agent;	// Type of agent replies should be sent to
-	net_t		to_net, 		// Destination network type and address
-                from_net,       // Origin network address
-                replyto_net;    // Network type and address for replies
-	ushort		total_hfields;	// Total number of header fields
-	hfield_t	*hfield;		// Header fields (fixed length portion)
-	void		**hfield_dat;	// Header fields (variable length portion)
-	dfield_t	*dfield;		// Data fields (fixed length portion)
-	ulong		offset; 		// Offset (number of records) into index
-	uchar		forwarded;		// Forwarded from agent to another
-	when_t		expiration; 	// Message will exipre on this day (if >0)
-
-	} smbmsg_t;
-
-typedef struct {			// Message base
-
-    char    file[128];      // Path and base filename (no extension)
-    FILE    *sdt_fp;        // File pointer for data (.sdt) file
-    FILE    *shd_fp;        // File pointer for header (.shd) file
-    FILE    *sid_fp;        // File pointer for index (.sid) file
-    FILE    *sda_fp;        // File pointer for data allocation (.sda) file
-    FILE    *sha_fp;        // File pointer for header allocation (.sha) file
-	ulong	retry_time; 	// Maximum number of seconds to retry opens/locks
-	smbstatus_t status; 	// Status header record
-	char	shd_buf[SHD_BLOCK_LEN]; 	// File I/O buffer for header file
-
-    } smb_t;
-
-#ifdef _WIN32
-#pragma pack(pop)		/* original packing */
-#endif
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/smb/smblib.c b/src/sbbs2/smb/smblib.c
deleted file mode 100644
index e414456e22729bbd1bc67b42d84276ea5259b392..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smblib.c
+++ /dev/null
@@ -1,1383 +0,0 @@
-/* SMBLIB.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "smblib.h"
-
-/* Use smb_ver() and smb_lib_ver() to obtain these values */
-#define SMBLIB_VERSION		"2.10"      /* SMB library version */
-#define SMB_VERSION 		0x0121		/* SMB format version */
-										/* High byte major, low byte minor */
-
-#ifdef _MSC_VER	  /* Microsoft C */
-#define sopen(f,o,s,p)	   _sopen(f,o,s,p)
-#define close(f)		   _close(f)
-#define SH_DENYNO		   _SH_DENYNO
-#define SH_DENYRW		   _SH_DENYRW
-
-#include <sys/locking.h>
-
-int lock(int file, long offset, int size) 
-{
-	int	i;
-	long	pos;
-   
-	pos=tell(file);
-	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
-	i=locking(file,LK_NBLCK,size);
-	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
-	return(i);
-}
-
-int unlock(int file, long offset, int size)
-{
-	int	i;
-	long	pos;
-   
-	pos=tell(file);
-	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
-	i=locking(file,LK_UNLCK,size);
-	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
-	return(i);
-}
-
-#endif /* _MSC_VER */
-
-
-int SMBCALL smb_ver(void)
-{
-	return(SMB_VERSION);
-}
-
-char * SMBCALL smb_lib_ver(void)
-{
-	return(SMBLIB_VERSION);
-}
-
-/****************************************************************************/
-/* Open a message base of name 'smb->file'                                  */
-/* Opens files for READing messages or updating message indices only        */
-/****************************************************************************/
-int SMBCALL smb_open(smb_t *smb)
-{
-    int file;
-    char str[128];
-	smbhdr_t hdr;
-
-if(!smb->retry_time)
-	smb->retry_time=10;
-smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
-sprintf(str,"%s.SHD",smb->file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (smb->shd_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-    return(2); }
-
-if(filelength(file)>=sizeof(smbhdr_t)) {
-	setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
-	if(smb_locksmbhdr(smb)) {
-		smb_close(smb);
-        return(-1); }
-	memset(&hdr,0,sizeof(smbhdr_t));
-	fread(&hdr,sizeof(smbhdr_t),1,smb->shd_fp);
-    if(memcmp(hdr.id,"SMB\x1a",4)) {
-		smb_close(smb);
-        return(-2); }
-    if(hdr.version<0x110) {         /* Compatibility check */
-		smb_close(smb);
-        return(-3); }
-	if(fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp)
-		!=sizeof(smbstatus_t)) {
-		smb_close(smb);
-		return(-4); }
-	smb_unlocksmbhdr(smb);
-	rewind(smb->shd_fp); }
-
-setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
-
-sprintf(str,"%s.SDT",smb->file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (smb->sdt_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close(smb);
-	return(1); }
-setvbuf(smb->sdt_fp,NULL,_IOFBF,2*1024);
-
-sprintf(str,"%s.SID",smb->file);
-if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
-	|| (smb->sid_fp=fdopen(file,"r+b"))==NULL) {
-	if(file!=-1)
-		close(file);
-	smb_close(smb);
-	return(3); }
-setvbuf(smb->sid_fp,NULL,_IOFBF,2*1024);
-
-return(0);
-}
-
-/****************************************************************************/
-/* Closes the currently open message base									*/
-/****************************************************************************/
-void SMBCALL smb_close(smb_t *smb)
-{
-if(smb->shd_fp!=NULL) {
-	smb_unlocksmbhdr(smb);		   /* In case it's been locked */
-	fclose(smb->shd_fp); }
-if(smb->sid_fp!=NULL)
-	fclose(smb->sid_fp);
-if(smb->sdt_fp!=NULL)
-	fclose(smb->sdt_fp);
-smb->sid_fp=smb->shd_fp=smb->sdt_fp=NULL;
-}
-
-/****************************************************************************/
-/* Opens the data block allocation table message base 'smb->file'           */
-/* Retrys for retry_time number of seconds									*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int SMBCALL smb_open_da(smb_t *smb)
-{
-	int 	file;
-	char	str[128];
-	ulong	start=0;
-
-sprintf(str,"%s.SDA",smb->file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)
-			return(-2); }
-if((smb->sda_fp=fdopen(file,"r+b"))==NULL) {
-	close(file);
-	return(-3); }
-setvbuf(smb->sda_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-void SMBCALL smb_close_da(smb_t *smb)
-{
-if(smb->sda_fp!=NULL)
-	fclose(smb->sda_fp);
-smb->sda_fp=NULL;
-}
-
-/****************************************************************************/
-/* Opens the header block allocation table for message base 'smb.file'      */
-/* Retrys for smb.retry_time number of seconds								*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int SMBCALL smb_open_ha(smb_t *smb)
-{
-	int 	file;
-	char	str[128];
-	ulong	start=0;
-
-sprintf(str,"%s.SHA",smb->file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)
-			return(-2); }
-if((smb->sha_fp=fdopen(file,"r+b"))==NULL) {
-	close(file);
-	return(-3); }
-setvbuf(smb->sha_fp,NULL,_IOFBF,2*1024);
-return(0);
-}
-
-void SMBCALL smb_close_ha(smb_t *smb)
-{
-if(smb->sha_fp!=NULL)
-	fclose(smb->sha_fp);
-smb->sha_fp=NULL;
-}
-
-
-/****************************************************************************/
-/* If the parameter 'push' is non-zero, this function stores the currently  */
-/* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
-/* message bases may be stored (defined in SMBDEFS.H).						*/
-/* The parameter 'op' is the operation to perform on the stack. Either      */
-/* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG						*/
-/* If the operation is SMB_STACK_POP, this function restores a message base */
-/* previously saved with a SMB_STACK_PUSH call to this same function.		*/
-/* If the operation is SMB_STACK_XCHNG, then the current message base is	*/
-/* exchanged with the message base on the top of the stack (most recently	*/
-/* pushed.																	*/
-/* If the current message base is not open, the SMB_STACK_PUSH and			*/
-/* SMB_STACK_XCHNG operations do nothing									*/
-/* Returns 0 on success, non-zero if stack full.                            */
-/* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.	*/
-/****************************************************************************/
-int SMBCALL smb_stack(smb_t *smb, int op)
-{
-	static char stack_file[SMB_STACK_LEN][128];
-	static FILE *stack_sdt[SMB_STACK_LEN],
-				*stack_shd[SMB_STACK_LEN],
-				*stack_sid[SMB_STACK_LEN],
-				*stack_sda[SMB_STACK_LEN],
-				*stack_sha[SMB_STACK_LEN];
-	static int	stack_idx;
-	char		tmp_file[128];
-	FILE		*tmp_sdt,
-				*tmp_shd,
-				*tmp_sid,
-				*tmp_sda,
-				*tmp_sha;
-
-if(op==SMB_STACK_PUSH) {
-	if(stack_idx>=SMB_STACK_LEN)
-		return(1);
-	if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
-		return(0);	  /* Msg base not open */
-	memcpy(stack_file[stack_idx],smb->file,128);
-	stack_sdt[stack_idx]=smb->sdt_fp;
-	stack_shd[stack_idx]=smb->shd_fp;
-	stack_sid[stack_idx]=smb->sid_fp;
-	stack_sda[stack_idx]=smb->sda_fp;
-	stack_sha[stack_idx]=smb->sha_fp;
-	stack_idx++;
-	return(0); }
-/* pop or xchng */
-if(!stack_idx)	/* Nothing on the stack, so do nothing */
-	return(0);
-if(op==SMB_STACK_XCHNG) {
-	if(!smb->shd_fp)
-		return(0);
-	memcpy(tmp_file,smb->file,128);
-	tmp_sdt=smb->sdt_fp;
-	tmp_shd=smb->shd_fp;
-	tmp_sid=smb->sid_fp;
-	tmp_sda=smb->sda_fp;
-	tmp_sha=smb->sha_fp; }
-
-stack_idx--;
-memcpy(smb->file,stack_file[stack_idx],128);
-smb->sdt_fp=stack_sdt[stack_idx];
-smb->shd_fp=stack_shd[stack_idx];
-smb->sid_fp=stack_sid[stack_idx];
-smb->sda_fp=stack_sda[stack_idx];
-smb->sha_fp=stack_sha[stack_idx];
-if(op==SMB_STACK_XCHNG) {
-	stack_idx++;
-	memcpy(stack_file[stack_idx-1],tmp_file,128);
-	stack_sdt[stack_idx-1]=tmp_sdt;
-	stack_shd[stack_idx-1]=tmp_shd;
-	stack_sid[stack_idx-1]=tmp_sid;
-	stack_sda[stack_idx-1]=tmp_sda;
-	stack_sha[stack_idx-1]=tmp_sha; }
-return(0);
-}
-
-/****************************************************************************/
-/* Truncates header file													*/
-/* Retrys for smb.retry_time number of seconds								*/
-/* Return 0 on success, non-zero otherwise									*/
-/****************************************************************************/
-int SMBCALL smb_trunchdr(smb_t *smb)
-{
-	ulong	start=0;
-
-rewind(smb->shd_fp);
-while(1) {
-	if(!chsize(fileno(smb->shd_fp),0L))
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)		 /* Time-out */
-			return(-2); }
-return(0);
-}
-
-/*********************************/
-/* Message Base Header Functions */
-/*********************************/
-
-/****************************************************************************/
-/* Attempts for smb.retry_time number of seconds to lock the msg base hdr	*/
-/****************************************************************************/
-int SMBCALL smb_locksmbhdr(smb_t *smb)
-{
-	ulong	start=0;
-
-while(1) {
-	if(!lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
-		return(0);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)
-			break;						/* Incase we've already locked it */
-	unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Read the SMB header from the header file and place into smb.status		*/
-/****************************************************************************/
-int SMBCALL smb_getstatus(smb_t *smb)
-{
-	int 	i;
-
-setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
-clearerr(smb->shd_fp);
-fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
-setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Writes message base header												*/
-/****************************************************************************/
-int SMBCALL smb_putstatus(smb_t *smb)
-{
-	int i;
-
-clearerr(smb->shd_fp);
-fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
-i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
-fflush(smb->shd_fp);
-if(i==sizeof(smbstatus_t))
-	return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Unlocks previously locks message base header 							*/
-/****************************************************************************/
-int SMBCALL smb_unlocksmbhdr(smb_t *smb)
-{
-return(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
-}
-
-/********************************/
-/* Individual Message Functions */
-/********************************/
-
-/****************************************************************************/
-/* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg'  */
-/****************************************************************************/
-int SMBCALL smb_lockmsghdr(smb_t *smb, smbmsg_t *msg)
-{
-	ulong	start=0;
-
-while(1) {
-	if(!lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)))
-        return(0);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)
-			break;
-	unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)); }
-return(-1);
-}
-
-/****************************************************************************/
-/* Fills msg->idx with message index based on msg->hdr.number				*/
-/* OR if msg->hdr.number is 0, based on msg->offset (record offset).		*/
-/* if msg.hdr.number does not equal 0, then msg->offset is filled too.		*/
-/* Either msg->hdr.number or msg->offset must be initialized before 		*/
-/* calling this function													*/
-/* Returns 1 if message number wasn't found, 0 if it was                    */
-/****************************************************************************/
-int SMBCALL smb_getmsgidx(smb_t *smb, smbmsg_t *msg)
-{
-	idxrec_t idx;
-	ulong	 l,length,total,bot,top;
-
-clearerr(smb->sid_fp);
-if(!msg->hdr.number) {
-	fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp))
-		return(1);
-	return(0); }
-
-length=filelength(fileno(smb->sid_fp));
-if(!length)
-	return(1);
-total=length/sizeof(idxrec_t);
-if(!total)
-	return(1);
-
-bot=0;
-top=total;
-l=total/2; /* Start at middle index */
-while(1) {
-	fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET);
-	if(!fread(&idx,sizeof(idxrec_t),1,smb->sid_fp))
-		return(1);
-	if(bot==top-1 && idx.number!=msg->hdr.number)
-        return(1);
-	if(idx.number>msg->hdr.number) {
-		top=l;
-		l=bot+((top-bot)/2);
-		continue; }
-	if(idx.number<msg->hdr.number) {
-		bot=l;
-		l=top-((top-bot)/2);
-		continue; }
-	break; }
-msg->idx=idx;
-msg->offset=l;
-return(0);
-}
-
-/****************************************************************************/
-/* Reads the last index record in the open message base 					*/
-/****************************************************************************/
-int SMBCALL smb_getlastidx(smb_t *smb, idxrec_t *idx)
-{
-	long length;
-
-clearerr(smb->sid_fp);
-length=filelength(fileno(smb->sid_fp));
-if(length<sizeof(idxrec_t))
-	return(-1);
-fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET);
-if(!fread(idx,sizeof(idxrec_t),1,smb->sid_fp))
-	return(-2);
-return(0);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the header record for 'msg'              */
-/* Returns length															*/
-/****************************************************************************/
-uint SMBCALL smb_getmsghdrlen(smbmsg_t *msg)
-{
-	int i;
-
-/* fixed portion */
-msg->hdr.length=sizeof(msghdr_t);
-/* data fields */
-msg->hdr.length+=msg->hdr.total_dfields*sizeof(dfield_t);
-/* header fields */
-for(i=0;i<msg->total_hfields;i++) {
-	msg->hdr.length+=sizeof(hfield_t);
-	msg->hdr.length+=msg->hfield[i].length; }
-return(msg->hdr.length);
-}
-
-/****************************************************************************/
-/* Figures out the total length of the data buffer for 'msg'                */
-/* Returns length															*/
-/****************************************************************************/
-ulong SMBCALL smb_getmsgdatlen(smbmsg_t *msg)
-{
-	int i;
-	ulong length=0L;
-
-for(i=0;i<msg->hdr.total_dfields;i++)
-	length+=msg->dfield[i].length;
-return(length);
-}
-
-/****************************************************************************/
-/* Read header information into 'msg' structure                             */
-/* msg->idx.offset must be set before calling this function 				*/
-/* Must call smb_freemsgmem() to free memory allocated for var len strs 	*/
-/* Returns 0 on success, non-zero if error									*/
-/****************************************************************************/
-int SMBCALL smb_getmsghdr(smb_t *smb, smbmsg_t *msg)
-{
-	void	*vp,**vpp;
-	ushort	i;
-	ulong	l,offset;
-	idxrec_t idx;
-
-rewind(smb->shd_fp);
-fseek(smb->shd_fp,msg->idx.offset,SEEK_SET);
-idx=msg->idx;
-offset=msg->offset;
-memset(msg,0,sizeof(smbmsg_t));
-msg->idx=idx;
-msg->offset=offset;
-if(!fread(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp))
-	return(-1);
-if(memcmp(msg->hdr.id,"SHD\x1a",4))
-	return(-2);
-if(msg->hdr.version<0x110)
-	return(-9);
-l=sizeof(msghdr_t);
-if(msg->hdr.total_dfields && (msg->dfield
-	=(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
-	smb_freemsgmem(msg);
-	return(-3); }
-i=0;
-while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
-	if(!fread(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
-		smb_freemsgmem(msg);
-		return(-4); }
-	i++;
-	l+=sizeof(dfield_t); }
-if(i<msg->hdr.total_dfields) {
-	smb_freemsgmem(msg);
-	return(-8); }
-
-while(l<msg->hdr.length) {
-	i=msg->total_hfields;
-	if((vpp=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))==NULL) {
-		smb_freemsgmem(msg);
-		return(-3); }
-	msg->hfield_dat=vpp;
-	if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
-		smb_freemsgmem(msg);
-		return(-3); }
-	msg->hfield=vp;
-	msg->total_hfields++;
-	if(!fread(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
-		smb_freemsgmem(msg);
-		return(-5); }
-	l+=sizeof(hfield_t);
-	if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
-		==NULL) {			/* Allocate 1 extra for NULL terminator */
-		smb_freemsgmem(msg);  /* or 0 length field */
-		return(-3); }
-	memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
-	if(msg->hfield[i].length
-		&& !fread(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
-		smb_freemsgmem(msg);
-		return(-6); }
-
-	switch(msg->hfield[i].type) {	/* convenience variables */
-		case SENDER:
-			if(!msg->from) {
-				msg->from=msg->hfield_dat[i];
-				break; }
-		case FORWARDED: 	/* fall through */
-			msg->forwarded=1;
-			break;
-		case SENDERAGENT:
-			if(!msg->forwarded)
-				msg->from_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDEREXT:
-			if(!msg->forwarded)
-				msg->from_ext=msg->hfield_dat[i];
-			break;
-		case SENDERNETTYPE:
-			if(!msg->forwarded)
-				msg->from_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case SENDERNETADDR:
-			if(!msg->forwarded)
-				msg->from_net.addr=msg->hfield_dat[i];
-            break;
-		case REPLYTO:
-			msg->replyto=msg->hfield_dat[i];
-            break;
-		case REPLYTOEXT:
-			msg->replyto_ext=msg->hfield_dat[i];
-			break;
-		case REPLYTOAGENT:
-			msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETTYPE:
-			msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case REPLYTONETADDR:
-			msg->replyto_net.addr=msg->hfield_dat[i];
-            break;
-		case RECIPIENT:
-			msg->to=msg->hfield_dat[i];
-            break;
-		case RECIPIENTEXT:
-			msg->to_ext=msg->hfield_dat[i];
-			break;
-		case RECIPIENTAGENT:
-			msg->to_agent=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETTYPE:
-			msg->to_net.type=*(ushort *)msg->hfield_dat[i];
-            break;
-		case RECIPIENTNETADDR:
-			msg->to_net.addr=msg->hfield_dat[i];
-            break;
-		case SUBJECT:
-			msg->subj=msg->hfield_dat[i];
-			break; }
-	l+=msg->hfield[i].length; }
-
-if(!msg->from || !msg->to || !msg->subj) {
-	smb_freemsgmem(msg);
-	return(-7); }
-return(0);
-}
-
-/****************************************************************************/
-/* Frees memory allocated for 'msg'                                         */
-/****************************************************************************/
-void SMBCALL smb_freemsgmem(smbmsg_t *msg)
-{
-	ushort	i;
-
-	if(msg->dfield) {
-		FREE(msg->dfield);
-		msg->dfield=NULL;
-	}
-	for(i=0;i<msg->total_hfields;i++)
-		if(msg->hfield_dat[i]) {
-			FREE(msg->hfield_dat[i]);
-			msg->hfield_dat[i]=NULL;
-		}
-	msg->total_hfields=0;
-	if(msg->hfield) {
-		FREE(msg->hfield);
-		msg->hfield=NULL;
-	}
-	if(msg->hfield_dat) {
-		FREE(msg->hfield_dat);
-		msg->hfield_dat=NULL;
-	}
-}
-
-/****************************************************************************/
-/* Unlocks header for 'msg'                                                 */
-/****************************************************************************/
-int SMBCALL smb_unlockmsghdr(smb_t *smb, smbmsg_t *msg)
-{
-return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
-}
-
-
-/****************************************************************************/
-/* Adds a header field to the 'msg' structure (in memory only)              */
-/****************************************************************************/
-int SMBCALL smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
-{
-	void *vp,**vpp;
-	int i;
-
-i=msg->total_hfields;
-if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL)
-	return(1);
-msg->hfield=vp;
-if((vpp=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))==NULL)
-	return(2);
-msg->hfield_dat=vpp;
-msg->total_hfields++;
-msg->hfield[i].type=type;
-msg->hfield[i].length=length;
-if(length) {
-	if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
-		return(4);
-	memcpy(msg->hfield_dat[i],data,length); }
-else
-	msg->hfield_dat[i]=NULL;
-return(0);
-}
-
-/****************************************************************************/
-/* Adds a data field to the 'msg' structure (in memory only)                */
-/* Automatically figures out the offset into the data buffer from existing	*/
-/* dfield lengths															*/
-/****************************************************************************/
-int SMBCALL smb_dfield(smbmsg_t *msg, ushort type, ulong length)
-{
-	void *vp;
-	int i,j;
-
-i=msg->hdr.total_dfields;
-if((vp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL)
-	return(1);
-msg->dfield=vp;
-msg->hdr.total_dfields++;
-msg->dfield[i].type=type;
-msg->dfield[i].length=length;
-for(j=msg->dfield[i].offset=0;j<i;j++)
-	msg->dfield[i].offset+=msg->dfield[j].length;
-return(0);
-}
-
-/****************************************************************************/
-/* Checks CRC history file for duplicate crc. If found, returns 1.			*/
-/* If no dupe, adds to CRC history and returns 0, or negative if error. 	*/
-/****************************************************************************/
-int SMBCALL smb_addcrc(smb_t *smb, ulong crc)
-{
-	char	str[128];
-	int 	file;
-	long	length;
-	ulong	l,*buf;
-	ulong	start=0;
-
-if(!smb->status.max_crcs)
-	return(0);
-
-sprintf(str,"%s.SCH",smb->file);
-while(1) {
-	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
-		break;
-	if(errno!=EACCES)
-		return(-1);
-	if(!start)
-		start=time(NULL);
-	else
-		if(time(NULL)-start>=smb->retry_time)
-			return(-2); }
-
-length=filelength(file);
-if(length<0L) {
-	close(file);
-	return(-4); }
-if((buf=(ulong *)MALLOC(smb->status.max_crcs*4))==NULL) {
-	close(file);
-	return(-3); }
-if(length>=smb->status.max_crcs*4) { /* Reached or exceeds max crcs */
-	read(file,buf,smb->status.max_crcs*4);
-	for(l=0;l<smb->status.max_crcs;l++)
-		if(crc==buf[l])
-			break;
-	if(l<smb->status.max_crcs) {				/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); }
-	chsize(file,0L);				/* truncate it */
-	lseek(file,0L,SEEK_SET);
-	write(file,buf+4,(smb->status.max_crcs-1)*4); }
-
-else if(length/4) { 						/* Less than max crcs */
-	read(file,buf,length);
-	for(l=0;l<length/4;l++)
-		if(crc==buf[l])
-			break;
-	if(l<length/4) {					/* Dupe CRC found */
-		close(file);
-		FREE(buf);
-		return(1); } }
-
-lseek(file,0L,SEEK_END);
-write(file,&crc,4); 			   /* Write to the end */
-FREE(buf);
-close(file);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Creates a new message header record in the header file.					*/
-/* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
-/* If storage is SMB_FASTALLOC, fast allocation is used 					*/
-/* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)	*/
-/****************************************************************************/
-int SMBCALL smb_addmsghdr(smb_t *smb, smbmsg_t *msg, int storage)
-{
-	int i;
-	long l;
-
-if(smb_locksmbhdr(smb))
-    return(1);
-if(smb_getstatus(smb))
-    return(2);
-
-if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=0)
-    return(i);
-
-msg->hdr.length=smb_getmsghdrlen(msg);
-if(storage==SMB_HYPERALLOC)
-	l=smb_hallochdr(smb);
-else if(storage==SMB_FASTALLOC)
-	l=smb_fallochdr(smb,msg->hdr.length);
-else
-	l=smb_allochdr(smb,msg->hdr.length);
-if(l==-1L) {
-	smb_unlocksmbhdr(smb);
-	smb_close_ha(smb);
-	return(-1); }
-
-smb->status.last_msg++;
-msg->idx.number=msg->hdr.number=smb->status.last_msg;
-msg->idx.offset=smb->status.header_offset+l;
-msg->idx.time=msg->hdr.when_imported.time;
-msg->idx.attr=msg->hdr.attr;
-msg->offset=smb->status.total_msgs;
-smb->status.total_msgs++;
-smb_putstatus(smb);
-
-if(storage!=SMB_HYPERALLOC)
-	smb_close_ha(smb);
-i=smb_putmsg(smb,msg);
-smb_unlocksmbhdr(smb);
-return(i);
-}
-
-/****************************************************************************/
-/* Writes both header and index information for msg 'msg'                   */
-/****************************************************************************/
-int SMBCALL smb_putmsg(smb_t *smb, smbmsg_t *msg)
-{
-	int i;
-
-i=smb_putmsghdr(smb,msg);
-if(i)
-	return(i);
-return(smb_putmsgidx(smb,msg));
-}
-
-/****************************************************************************/
-/* Writes index information for 'msg'                                       */
-/* msg->idx 																 */
-/* and msg->offset must be set prior to calling to this function			 */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int SMBCALL smb_putmsgidx(smb_t *smb, smbmsg_t *msg)
-{
-
-clearerr(smb->sid_fp);
-fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
-if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp))
-	return(1);
-fflush(smb->sid_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Writes header information for 'msg'                                      */
-/* msg->hdr.length															 */
-/* msg->idx.offset															 */
-/* and msg->offset must be set prior to calling to this function			 */
-/* Returns 0 if everything ok                                               */
-/****************************************************************************/
-int SMBCALL smb_putmsghdr(smb_t *smb, smbmsg_t *msg)
-{
-	ushort	i;
-	ulong	l;
-
-clearerr(smb->shd_fp);
-if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET))
-	return(-1);
-
-/************************************************/
-/* Write the fixed portion of the header record */
-/************************************************/
-if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp))
-	return(-2);
-
-/************************************************/
-/* Write the data fields (each is fixed length) */
-/************************************************/
-for(i=0;i<msg->hdr.total_dfields;i++)
-	if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp))
-		return(-3);
-
-/*******************************************/
-/* Write the variable length header fields */
-/*******************************************/
-for(i=0;i<msg->total_hfields;i++) {
-	if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp))
-		return(-4);
-	if(msg->hfield[i].length					 /* more then 0 bytes long */
-		&& !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp))
-		return(-5); }
-
-l=smb_getmsghdrlen(msg);
-while(l%SHD_BLOCK_LEN) {
-	if(fputc(0,smb->shd_fp)==EOF)
-		return(-6); 			   /* pad block with NULL */
-	l++; }
-fflush(smb->shd_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Creates a sub-board's initial header file                                */
-/* Truncates and deletes other associated SMB files 						*/
-/****************************************************************************/
-int SMBCALL smb_create(smb_t *smb)
-{
-    char        str[128];
-	smbhdr_t	hdr;
-
-if(filelength(fileno(smb->shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
-	&& smb_locksmbhdr(smb))  /* header exists, so lock it */
-	return(1);
-memset(&hdr,0,sizeof(smbhdr_t));
-memcpy(hdr.id,"SMB\x1a",4);     /* <S> <M> <B> <^Z> */
-hdr.version=SMB_VERSION;
-hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-smb->status.last_msg=smb->status.total_msgs=0;
-smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
-rewind(smb->shd_fp);
-fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
-fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
-rewind(smb->shd_fp);
-chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
-fflush(smb->shd_fp);
-
-rewind(smb->sdt_fp);
-chsize(fileno(smb->sdt_fp),0L);
-rewind(smb->sid_fp);
-chsize(fileno(smb->sid_fp),0L);
-
-sprintf(str,"%s.SDA",smb->file);
-remove(str);						/* if it exists, delete it */
-sprintf(str,"%s.SHA",smb->file);
-remove(str);                        /* if it exists, delete it */
-sprintf(str,"%s.SCH",smb->file);
-remove(str);
-smb_unlocksmbhdr(smb);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns number of data blocks required to store "length" amount of data  */
-/****************************************************************************/
-ulong SMBCALL smb_datblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SDT_BLOCK_LEN;
-if(length%SDT_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Returns number of header blocks required to store "length" size header   */
-/****************************************************************************/
-ulong SMBCALL smb_hdrblocks(ulong length)
-{
-	ulong blocks;
-
-blocks=length/SHD_BLOCK_LEN;
-if(length%SHD_BLOCK_LEN)
-	blocks++;
-return(blocks);
-}
-
-/****************************************************************************/
-/* Finds unused space in data file based on block allocation table and		*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of data (in bytes, not blocks)				*/
-/* Assumes smb_open_da() has been called									*/
-/* smb_close_da() should be called after									*/
-/* Returns negative on error												*/
-/****************************************************************************/
-long SMBCALL smb_allocdat(smb_t *smb, ulong length, ushort headers)
-{
-    ushort  i,j;
-	ulong	l,blocks,offset=0L;
-
-blocks=smb_datblocks(length);
-j=0;	/* j is consecutive unused block counter */
-fflush(smb->sda_fp);
-rewind(smb->sda_fp);
-while(!feof(smb->sda_fp)) {
-	if(!fread(&i,2,1,smb->sda_fp))
-        break;
-	offset+=SDT_BLOCK_LEN;
-    if(!i) j++;
-    else   j=0;
-	if(j==blocks) {
-		offset-=(blocks*SDT_BLOCK_LEN);
-        break; } }
-clearerr(smb->sda_fp);
-fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,smb->sda_fp))
-		return(-1);
-fflush(smb->sda_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for data, but doesn't search for unused blocks           */
-/* Returns negative on error												*/
-/****************************************************************************/
-long SMBCALL smb_fallocdat(smb_t *smb, ulong length, ushort headers)
-{
-	ulong	l,blocks,offset;
-
-fflush(smb->sda_fp);
-clearerr(smb->sda_fp);
-blocks=smb_datblocks(length);
-fseek(smb->sda_fp,0L,SEEK_END);
-offset=(ftell(smb->sda_fp)/2L)*SDT_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&headers,2,1,smb->sda_fp))
-        break;
-fflush(smb->sda_fp);
-if(l<blocks)
-	return(-1L);
-return(offset);
-}
-
-/****************************************************************************/
-/* De-allocates space for data												*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int SMBCALL smb_freemsgdat(smb_t *smb, ulong offset, ulong length
-			, ushort headers)
-{
-	int		da_opened=0;
-	ushort	i;
-	ulong	l,blocks;
-
-blocks=smb_datblocks(length);
-
-if(smb->sda_fp==NULL) {
-	if((i=smb_open_da(smb))!=0)
-		return(i);
-	da_opened=1;
-}
-
-clearerr(smb->sda_fp);
-for(l=0;l<blocks;l++) {
-	if(fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
-		return(1);
-	if(!fread(&i,2,1,smb->sda_fp))
-		return(2);
-	if(headers>i)
-		i=0;			/* don't want to go negative */
-	else
-		i-=headers;
-	if(fseek(smb->sda_fp,-2L,SEEK_CUR))
-		return(3);
-	if(!fwrite(&i,2,1,smb->sda_fp))
-		return(4); }
-fflush(smb->sda_fp);
-if(da_opened)
-	smb_close_da(smb);
-return(0);
-}
-
-/****************************************************************************/
-/* Adds to data allocation records for blocks starting at 'offset'          */
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int SMBCALL smb_incdat(smb_t *smb, ulong offset, ulong length, ushort headers)
-{
-	ushort	i;
-	ulong	l,blocks;
-
-clearerr(smb->sda_fp);
-blocks=smb_datblocks(length);
-for(l=0;l<blocks;l++) {
-	fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
-	if(!fread(&i,2,1,smb->sda_fp))
-		return(1);
-	i+=headers;
-	fseek(smb->sda_fp,-2L,SEEK_CUR);
-	if(!fwrite(&i,2,1,smb->sda_fp))
-		return(2); }
-fflush(smb->sda_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* De-allocates blocks for header record									*/
-/* Returns non-zero on error												*/
-/****************************************************************************/
-int SMBCALL smb_freemsghdr(smb_t *smb, ulong offset, ulong length)
-{
-	uchar	c=0;
-	ulong	l,blocks;
-
-clearerr(smb->sha_fp);
-blocks=smb_hdrblocks(length);
-fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,smb->sha_fp))
-		return(1);
-fflush(smb->sha_fp);
-return(0);
-}
-
-/****************************************************************************/
-/* Frees all allocated header and data blocks for 'msg'                     */
-/****************************************************************************/
-int SMBCALL smb_freemsg(smb_t *smb, smbmsg_t *msg)
-{
-	int 	i;
-	ushort	x;
-
-if(smb->status.attr&SMB_HYPERALLOC)  /* Nothing to do */
-	return(0);
-
-for(x=0;x<msg->hdr.total_dfields;x++) {
-	if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset
-		,msg->dfield[x].length,1))!=0)
-		return(i); }
-return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset
-	,msg->hdr.length));
-}
-
-/****************************************************************************/
-/* Finds unused space in header file based on block allocation table and	*/
-/* marks space as used in allocation table.                                 */
-/* File must be opened read/write DENY ALL									*/
-/* Returns offset to beginning of header (in bytes, not blocks) 			*/
-/* Assumes smb_open_ha() has been called									*/
-/* smb_close_ha() should be called after									*/
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long SMBCALL smb_allochdr(smb_t *smb, ulong length)
-{
-	uchar	c;
-	ushort	i;
-	ulong	l,blocks,offset=0;
-
-blocks=smb_hdrblocks(length);
-i=0;	/* i is consecutive unused block counter */
-fflush(smb->sha_fp);
-rewind(smb->sha_fp);
-while(!feof(smb->sha_fp)) {
-	if(!fread(&c,1,1,smb->sha_fp))
-        break;
-	offset+=SHD_BLOCK_LEN;
-	if(!c) i++;
-	else   i=0;
-	if(i==blocks) {
-		offset-=(blocks*SHD_BLOCK_LEN);
-        break; } }
-clearerr(smb->sha_fp);
-fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
-c=1;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,smb->sha_fp))
-		return(-1L);
-fflush(smb->sha_fp);
-return(offset);
-}
-
-/****************************************************************************/
-/* Allocates space for index, but doesn't search for unused blocks          */
-/* Returns -1L on error 													*/
-/****************************************************************************/
-long SMBCALL smb_fallochdr(smb_t *smb, ulong length)
-{
-	uchar	c=1;
-	ulong	l,blocks,offset;
-
-blocks=smb_hdrblocks(length);
-fflush(smb->sha_fp);
-clearerr(smb->sha_fp);
-fseek(smb->sha_fp,0L,SEEK_END);
-offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN;
-for(l=0;l<blocks;l++)
-	if(!fwrite(&c,1,1,smb->sha_fp))
-		return(-1L);
-fflush(smb->sha_fp);
-return(offset);
-}
-
-/************************************************************************/
-/* Allocate header blocks using Hyper Allocation						*/
-/* this function should be most likely not be called from anywhere but	*/
-/* smb_addmsghdr()														*/
-/************************************************************************/
-long SMBCALL smb_hallochdr(smb_t *smb)
-{
-	ulong l;
-
-fflush(smb->shd_fp);
-fseek(smb->shd_fp,0L,SEEK_END);
-l=ftell(smb->shd_fp);
-if(l<smb->status.header_offset) 			 /* Header file truncated?!? */
-	return(smb->status.header_offset);
-while((l-smb->status.header_offset)%SHD_BLOCK_LEN)	/* Even block boundry */
-	l++;
-return(l-smb->status.header_offset);
-}
-
-/************************************************************************/
-/* Allocate data blocks using Hyper Allocation							*/
-/* smb_locksmbhdr() should be called before this function and not		*/
-/* unlocked until all data fields for this message have been written	*/
-/* to the SDT file														*/
-/************************************************************************/
-long SMBCALL smb_hallocdat(smb_t *smb)
-{
-	long l;
-
-fflush(smb->sdt_fp);
-fseek(smb->sdt_fp,0L,SEEK_END);
-l=ftell(smb->sdt_fp);
-if(l<=0)
-	return(l);
-while(l%SDT_BLOCK_LEN)					/* Make sure even block boundry */
-	l++;
-return(l);
-}
-
-
-int SMBCALL smb_feof(FILE *fp)
-{
-return(feof(fp));
-}
-
-int SMBCALL smb_ferror(FILE *fp)
-{
-return(ferror(fp));
-}
-
-int SMBCALL smb_fflush(FILE *fp)
-{
-return(fflush(fp));
-}
-
-int SMBCALL smb_fgetc(FILE *fp)
-{
-return(fgetc(fp));
-}
-
-int SMBCALL smb_fputc(int ch, FILE *fp)
-{
-return(fputc(ch,fp));
-}
-
-int SMBCALL smb_fseek(FILE *fp, long offset, int whence)
-{
-return(fseek(fp,offset,whence));
-}
-
-long SMBCALL smb_ftell(FILE *fp)
-{
-return(ftell(fp));
-}
-
-long SMBCALL smb_fgetlength(FILE *fp)
-{
-return(filelength(fileno(fp)));
-}
-
-int SMBCALL smb_fsetlength(FILE *fp, long length)
-{
-return(chsize(fileno(fp),length));
-}
-
-void SMBCALL smb_rewind(FILE *fp)
-{
-rewind(fp);
-}
-
-void SMBCALL smb_clearerr(FILE *fp)
-{
-clearerr(fp);
-}
-
-long SMBCALL smb_fread(void HUGE16 *buf, long bytes, FILE *fp)
-{
-#ifdef __FLAT__
-	return(fread(buf,1,bytes,fp));
-#else
-	long count;
-
-for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
-	if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
-		return(bytes-count);
-if(fread((char *)buf,1,(size_t)count,fp)!=(size_t)count)
-	return(bytes-count);
-return(bytes);
-#endif
-}
-
-long SMBCALL smb_fwrite(void HUGE16 *buf, long bytes, FILE *fp)
-{
-#ifdef __FLAT__
-	return(fwrite(buf,1,bytes,fp));
-#else
-	long count;
-
-for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
-	if(fwrite((char *)buf,1,0x7fff,fp)!=0x7fff)
-		return(bytes-count);
-if(fwrite((char *)buf,1,(size_t)count,fp)!=(size_t)count)
-	return(bytes-count);
-return(bytes);
-#endif
-}
-
-#ifdef SMB_GETMSGTXT
-
-char HUGE16 * SMBCALL smb_getmsgtxt(smb_t *smb, smbmsg_t *msg, ulong mode)
-{
-	char	HUGE16 *buf=NULL,HUGE16 *lzhbuf,HUGE16 *p;
-	ushort	xlat;
-	int 	i,lzh;
-	long	l=0,lzhlen,length;
-
-for(i=0;i<msg->hdr.total_dfields;i++) {
-	if(!(msg->dfield[i].type==TEXT_BODY
-		|| (mode&GETMSGTXT_TAILS && msg->dfield[i].type==TEXT_TAIL))
-		|| msg->dfield[i].length<=2L)
-		continue;
-	fseek(smb->sdt_fp,msg->hdr.offset+msg->dfield[i].offset
-		,SEEK_SET);
-	fread(&xlat,2,1,smb->sdt_fp);
-	lzh=0;
-	if(xlat==XLAT_LZH) {
-		lzh=1;
-		fread(&xlat,2,1,smb->sdt_fp); }
-	if(xlat!=XLAT_NONE) 	/* no other translations currently supported */
-		continue;
-
-	length=msg->dfield[i].length-2L;
-	if(lzh) {
-		length-=2;
-		if(length<1)
-			continue;
-		if((lzhbuf=LMALLOC(length))==NULL)
-			return(buf);
-		smb_fread(lzhbuf,length,smb->sdt_fp);
-		lzhlen=*(long *)lzhbuf;
-		if((p=REALLOC(buf,l+lzhlen+3L))==NULL) {
-			FREE(lzhbuf);
-			return(buf); }
-		buf=p;
-		lzh_decode((char *)lzhbuf,length,(char *)buf+l);
-		FREE(lzhbuf);
-		l+=lzhlen; }
-	else {
-		if((p=REALLOC(buf,l+length+3L))==NULL)
-			return(buf);
-		buf=p;
-		p=buf+l;
-		l+=fread(p,1,length,smb->sdt_fp);
-		}
-	if(!l)
-		continue;
-	l--;
-	while(l && buf[l]==0) l--;
-	l++;
-	*(buf+l)=CR;
-	l++;
-	*(buf+l)=LF;
-	l++;
-	*(buf+l)=0; }
-return(buf);
-}
-
-void SMBCALL smb_freemsgtxt(char HUGE16 *buf)
-{
-if(buf!=NULL)
-	FREE(buf);
-}
-
-#endif
-
-/* End of SMBLIB.C */
diff --git a/src/sbbs2/smb/smblib.h b/src/sbbs2/smb/smblib.h
deleted file mode 100644
index beab8210bbe223e01b9bc105cc53e67f3714cda2..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smblib.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SMBLIB.H */
-
-/* Developed 1990-2000 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#ifndef _SMBLIB_H
-#define _SMBLIB_H
-
-#include "lzh.h"
-
-#if defined(__WATCOMC__) || defined(__TURBOC__) || defined(_MSC_VER)
-#	include <io.h>
-#	include <share.h>
-#endif
-
-#if defined(__WATCOMC__) || defined(__TURBOC__)
-#	include <mem.h>
-#else
-#	include <memory.h>
-#endif
-
-#if defined(__WATCOMC__)
-#	include <dos.h>
-#elif defined(__TURBOC__)
-#	include <dir.h>
-#endif
-
-#if defined(_WIN32)
-#	ifndef __FLAT__
-#	define __FLAT__
-#	endif
-#	define SMBCALL __stdcall	/* VB Compatible */
-#	if defined (EXPORT32)
-#		undef EXPORT32
-#	endif
-#	if defined(SMBDLL)
-#		define EXPORT32 __declspec( dllexport )
-#	else
-#		define EXPORT32 __declspec( dllimport )
-#	endif
-#elif defined(__FLAT__)
-#	if defined(SMBDLL)
-#		define SMBCALL	_pascal
-#		define EXPORT32 _export
-#	else
-#		define SMBCALL
-#		define EXPORT32
-#	endif
-#
-#else
-#	define SMBCALL
-#	define EXPORT32
-#endif
-
-#include <malloc.h>
-#include <time.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "smbdefs.h"
-
-#define SMB_STACK_LEN		4			/* Max msg bases in smb_stack() 	*/
-#define SMB_STACK_POP       0           /* Pop a msg base off of smb_stack() */
-#define SMB_STACK_PUSH      1           /* Push a msg base onto smb_stack() */
-#define SMB_STACK_XCHNG     2           /* Exchange msg base w/last pushed */
-
-#define GETMSGTXT_TAILS 	1			/* Get message tail(s) too */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EXPORT32 int 	SMBCALL smb_ver(void);
-EXPORT32 char *	SMBCALL smb_lib_ver(void);
-EXPORT32 int 	SMBCALL smb_open(smb_t *smb);
-EXPORT32 void	SMBCALL smb_close(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_open_da(smb_t *smb);
-EXPORT32 void	SMBCALL smb_close_da(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_open_ha(smb_t *smb);
-EXPORT32 void	SMBCALL smb_close_ha(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_create(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_stack(smb_t *smb, int op);
-EXPORT32 int 	SMBCALL smb_trunchdr(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_locksmbhdr(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_getstatus(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_putstatus(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_unlocksmbhdr(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_getmsgidx(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_getlastidx(smb_t *smb, idxrec_t *idx);
-EXPORT32 uint	SMBCALL smb_getmsghdrlen(smbmsg_t *msg);
-EXPORT32 ulong	SMBCALL smb_getmsgdatlen(smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_lockmsghdr(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_getmsghdr(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_unlockmsghdr(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_addcrc(smb_t *smb, ulong crc);
-EXPORT32 int 	SMBCALL smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data);
-EXPORT32 int 	SMBCALL smb_dfield(smbmsg_t *msg, ushort type, ulong length);
-EXPORT32 int 	SMBCALL smb_addmsghdr(smb_t *smb, smbmsg_t *msg,int storage);
-EXPORT32 int 	SMBCALL smb_putmsg(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_putmsgidx(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_putmsghdr(smb_t *smb, smbmsg_t *msg);
-EXPORT32 void	SMBCALL smb_freemsgmem(smbmsg_t *msg);
-EXPORT32 ulong	SMBCALL smb_hdrblocks(ulong length);
-EXPORT32 ulong	SMBCALL smb_datblocks(ulong length);
-EXPORT32 long	SMBCALL smb_allochdr(smb_t *smb, ulong length);
-EXPORT32 long	SMBCALL smb_fallochdr(smb_t *smb, ulong length);
-EXPORT32 long	SMBCALL smb_hallochdr(smb_t *smb);
-EXPORT32 long	SMBCALL smb_allocdat(smb_t *smb, ulong length, ushort headers);
-EXPORT32 long	SMBCALL smb_fallocdat(smb_t *smb, ulong length, ushort headers);
-EXPORT32 long	SMBCALL smb_hallocdat(smb_t *smb);
-EXPORT32 int 	SMBCALL smb_incdat(smb_t *smb, ulong offset, ulong length, ushort headers);
-EXPORT32 int 	SMBCALL smb_freemsg(smb_t *smb, smbmsg_t *msg);
-EXPORT32 int 	SMBCALL smb_freemsgdat(smb_t *smb, ulong offset, ulong length, ushort headers);
-EXPORT32 int 	SMBCALL smb_freemsghdr(smb_t *smb, ulong offset, ulong length);
-EXPORT32 void	SMBCALL smb_freemsgtxt(char HUGE16 *buf);
-EXPORT32 char HUGE16 * SMBCALL smb_getmsgtxt(smb_t *smb, smbmsg_t *msg, ulong mode);
-
-/* FILE pointer I/O functions */
-
-EXPORT32 int 	SMBCALL smb_feof(FILE *fp);
-EXPORT32 int 	SMBCALL smb_ferror(FILE *fp);
-EXPORT32 int 	SMBCALL smb_fflush(FILE *fp);
-EXPORT32 int 	SMBCALL smb_fgetc(FILE *fp);
-EXPORT32 int 	SMBCALL smb_fputc(int ch, FILE *fp);
-EXPORT32 int 	SMBCALL smb_fseek(FILE *fp, long offset, int whence);
-EXPORT32 long	SMBCALL smb_ftell(FILE *fp);
-EXPORT32 long	SMBCALL smb_fread(void HUGE16 *buf, long bytes, FILE *fp);
-EXPORT32 long	SMBCALL smb_fwrite(void HUGE16 *buf, long bytes, FILE *fp);
-EXPORT32 long	SMBCALL smb_fgetlength(FILE *fp);
-EXPORT32 int 	SMBCALL smb_fsetlength(FILE *fp, long length);
-EXPORT32 void	SMBCALL smb_rewind(FILE *fp);
-EXPORT32 void	SMBCALL smb_clearerr(FILE *fp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __WATCOMC__	/* Use MSC standard (prepended underscore) */
-#pragma aux smb_ver 			"_*"
-#pragma aux smb_lib_ver 		"_*"
-#pragma aux smb_open			"_*"
-#pragma aux smb_close			"_*"
-#pragma aux smb_open_da 		"_*"
-#pragma aux smb_close_da		"_*"
-#pragma aux smb_open_ha 		"_*"
-#pragma aux smb_close_ha		"_*"
-#pragma aux smb_create			"_*"
-#pragma aux smb_stack			"_*"
-#pragma aux smb_trunchdr		"_*"
-#pragma aux smb_locksmbhdr		"_*"
-#pragma aux smb_getstatus		"_*"
-#pragma aux smb_putstatus		"_*"
-#pragma aux smb_unlocksmbhdr	"_*"
-#pragma aux smb_getmsgidx		"_*"
-#pragma aux smb_getlastidx		"_*"
-#pragma aux smb_getmsghdrlen	"_*"
-#pragma aux smb_getmsgdatlen	"_*"
-#pragma aux smb_lockmsghdr		"_*"
-#pragma aux smb_getmsghdr		"_*"
-#pragma aux smb_unlockmsghdr	"_*"
-#pragma aux smb_addcrc			"_*"
-#pragma aux smb_hfield			"_*"
-#pragma aux smb_dfield			"_*"
-#pragma aux smb_addmsghdr		"_*"
-#pragma aux smb_putmsg			"_*"
-#pragma aux smb_putmsgidx		"_*"
-#pragma aux smb_putmsghdr		"_*"
-#pragma aux smb_freemsgmem		"_*"
-#pragma aux smb_hdrblocks		"_*"
-#pragma aux smb_datblocks		"_*"
-#pragma aux smb_allochdr		"_*"
-#pragma aux smb_fallochdr		"_*"
-#pragma aux smb_hallochdr		"_*"
-#pragma aux smb_allocdat		"_*"
-#pragma aux smb_fallocdat		"_*"
-#pragma aux smb_hallocdat		"_*"
-#pragma aux smb_incdat			"_*"
-#pragma aux smb_freemsg 		"_*"
-#pragma aux smb_freemsgdat		"_*"
-#pragma aux smb_freemsghdr		"_*"
-#pragma aux smb_getmsgtxt		"_*"
-#pragma aux smb_freemsgtxt		"_*"
-#pragma aux smb_feof			"_*"
-#pragma aux smb_ferror			"_*"
-#pragma aux smb_fflush			"_*"
-#pragma aux smb_fgetc			"_*"
-#pragma aux smb_fputc			"_*"
-#pragma aux smb_fseek			"_*"
-#pragma aux smb_ftell			"_*"
-#pragma aux smb_fread			"_*"
-#pragma aux smb_fwrite			"_*"
-#pragma aux smb_fgetlength		"_*"
-#pragma aux smb_fsetlength		"_*"
-#pragma aux smb_rewind			"_*"
-#pragma aux smb_clearerr		"_*"
-#pragma aux lzh_encode			"_*"
-#pragma aux lzh_decode			"_*"
-#endif	/* Watcom */
-
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/smb/smbutil/makeall.bat b/src/sbbs2/smb/smbutil/makeall.bat
deleted file mode 100755
index e4036c97725e6ff1dba6dd95b5d24bc31b6335be..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbutil/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOS4G %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/smb/smbutil/makefile b/src/sbbs2/smb/smbutil/makefile
deleted file mode 100644
index 5877440fa58436e32ba91fefcc5b28cefc71cde4..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbutil/makefile
+++ /dev/null
@@ -1,73 +0,0 @@
-#########################################################################
-# Makefile for SMBUTIL							#
-# For use with Watcom C       						#
-# Tabstop=8                                                             #
-#									#
-# To use this makefile, you must create the following sub-directories:	#
-# DOS, OS2, and DOSX.							#
-#									#
-# *** IMPORTANT NOTE ***
-# You must also copy the file \WATCOM\SRC\STARTUP\WILDARGV.C into the	#
-# current directory.							#
-#########################################################################
-
-# Macros
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc -ml
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-MAIN	= $(OS)\smbutil.exe
-OBJS	= $(OS)\smbutil.obj $(OS)\smblib.obj $(OS)\lzh.obj $(OS)\wildargv.obj
-HEADERS = smbutil.h smblib.h smbdefs.h crc32.h lzh.h
-
-!ifeq OS DOS
-CFLAGS	= -I=\watcom\h;.. -bt=$(OS) -fo=$(OS)\ -DSMB_GETMSGTXT
-!else
-CFLAGS	= -I=\watcom\h;.. -bt=$(OS) -fo=$(OS)\ -DSMB_GETMSGTXT -DLZH_DYNAMIC_BUF
-!endif
-
-!ifeq OS NT
-SYSTEM  = NT
-!endif
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOS4G
-SYSTEM  = DOS4G
-!endif
-
-LFLAGS	= system $(SYSTEM)
-
-
-# Implicit C Compile Rule
-.obj: $(OS)
-.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# All .obj modules
-$(OS)\smbutil.obj::   $(HEADERS)
-
-$(OS)\smblib.obj: ..\smblib.c ..\smblib.h ..\smbdefs.h
-        @echo Compiling $[@ to $^@ ...
-        $(CC) -DSMB_GETMSGTXT $(CFLAGS) $[@
-
-$(OS)\lzh.obj: ..\lzh.c ..\lzh.h
-        @echo Compiling $[@ to $^@ ...
-        $(CC) $(CFLAGS) $[@
diff --git a/src/sbbs2/smb/smbutil/makefile.bc b/src/sbbs2/smb/smbutil/makefile.bc
deleted file mode 100644
index 993c75da1d0a0e154cce43e950ed73f2a6bb5c87..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbutil/makefile.bc
+++ /dev/null
@@ -1,57 +0,0 @@
-###############################
-# Makefile for SMBUTIL        #
-# For use with Borland C++    #
-# Tabstop=8		      #
-###############################
-
-# ATTN: To use this MAKEFILE, you must create a directory "l" off of the
-#       current directory to store the large model .OBJ files
-
-# Macros
-OS	= DOS
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include;..
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -N -C -m$(MODEL) -I$(INCLUDE) -DLZH_DYNAMIC_BUF -DSMB_GETMSGTXT -w-pro
-LFLAGS	= -n -c
-
-!ifdef __OS2__
-OS	= OS2
-CC      = c:\bcos2\bin\bcc
-LD      = c:\bcos2\bin\tlink
-INCLUDE = c:\bcos2\include;..
-LIB     = c:\bcos2\lib
-MODEL	= os2
-CFLAGS	= -d -C -I$(INCLUDE) -DSMB_GETMSGTXT -w-pro
-LFLAGS	= -c -w-srf
-!endif
-
-HEADERS = smbutil.h ..\smblib.h ..\smbdefs.h ..\crc32.h ..\lzh.h
-MAIN	= $(OS)\smbutil.exe
-OBJS	= $(OS)\smbutil.obj $(OS)\smblib.obj $(OS)\lzh.obj
-
-
-# Implicit C Compile Rule
-{.;..}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS)
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS) $(LIB)\wildargs.obj
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# All .obj modules
-$(OS)\smbutil.obj:	$(HEADERS)
-$(OS)\smblib.obj:	$(HEADERS)
-$(OS)\lzh.obj:		$(HEADERS)
diff --git a/src/sbbs2/smb/smbutil/smbutil.c b/src/sbbs2/smb/smbutil/smbutil.c
deleted file mode 100644
index 3a37a9391488f81658fe346fb521d34e62a27711..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbutil/smbutil.c
+++ /dev/null
@@ -1,1428 +0,0 @@
-/* SMBUTIL.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet Message Base Utility */
-
-#define SMBUTIL_VER "2.01"
-
-#include "smblib.h"
-#include "smbutil.h"
-#include "crc32.h"
-#include "crc16.c"
-
-#ifdef __WATCOMC__
-	#include <dos.h>
-#endif
-
-/********************/
-/* Global variables */
-/********************/
-
-smb_t smb;
-ulong mode=0L;
-ushort tzone=PST;
-char filein[128];
-char attach[128];
-
-/************************/
-/* Program usage/syntax */
-/************************/
-
-char *usage=
-"usage: smbutil [/opts] cmd <filespec.SHD>\n"
-"\n"
-"cmd:\n"
-"       l[n] = list msgs starting at number n\n"
-"       r[n] = read msgs starting at number n\n"
-"       v[n] = view msg headers starting at number n\n"
-"       i<f> = import msg from text file f\n"
-"       e<f> = import e-mail from text file f\n"
-"       n<f> = import netmail from text file f\n"
-"       s    = display msg base status\n"
-"       c    = change msg base status\n"
-"       m    = maintain msg base - delete old msgs and msgs over max\n"
-"       p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
-"opts:\n"
-"       a    = always pack msg base (disable compression analysis)\n"
-"       z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
-;
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-#ifdef __WATCOMC__
-	return(f.size);
-#else
-	return(f.ff_fsize);
-#endif
-return(-1L);
-}
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Adds a new message to the message base									*/
-/****************************************************************************/
-void postmsg(char type)
-{
-	char	str[128],buf[SDT_BLOCK_LEN];
-	ushort	xlat,net;
-	int 	i,j,k,file;
-	long	length;
-	ulong	offset,crc=0xffffffffUL;
-	FILE	*instream;
-	smbmsg_t	msg;
-
-length=flength(filein);
-if(length<1L) {
-	printf("Invalid file size for '%s'\n",filein);
-	exit(1); }
-length+=2;	/* for translation string */
-if(!(smb.status.attr&SMB_HYPERALLOC)) {
-	i=smb_open_da(&smb);
-	if(i) {
-		printf("smb_open_da returned %d\n",i);
-		exit(1); }
-	offset=smb_allocdat(&smb,length,1);
-	smb_close_da(&smb); }
-else
-	offset=smb_hallocdat(&smb);
-
-if((file=open(filein,O_RDONLY|O_BINARY))==-1
-	|| (instream=fdopen(file,"rb"))==NULL) {
-	printf("Error opening %s for read\n",filein);
-	smb_freemsgdat(&smb,offset,length,1);
-	exit(1); }
-setvbuf(instream,NULL,_IOFBF,32*1024);
-fseek(smb.sdt_fp,offset,SEEK_SET);
-xlat=XLAT_NONE;
-fwrite(&xlat,2,1,smb.sdt_fp);
-k=SDT_BLOCK_LEN-2;
-while(!feof(instream)) {
-	memset(buf,0,k);
-	j=fread(buf,1,k,instream);
-	if(smb.status.max_crcs)
-		for(i=0;i<j;i++)
-			crc=ucrc32(buf[i],crc);
-	fwrite(buf,k,1,smb.sdt_fp);
-	k=SDT_BLOCK_LEN; }
-fflush(smb.sdt_fp);
-fclose(instream);
-crc=~crc;
-
-memset(&msg,0,sizeof(smbmsg_t));
-memcpy(msg.hdr.id,"SHD\x1a",4);
-msg.hdr.version=SMB_VERSION;
-msg.hdr.when_written.time=time(NULL);
-msg.hdr.when_written.zone=tzone;
-msg.hdr.when_imported=msg.hdr.when_written;
-
-if(smb.status.max_crcs) {
-	i=smb_addcrc(&smb,crc);
-	if(i) {
-		printf("smb_addcrc returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); } }
-
-msg.hdr.offset=offset;
-
-printf("To User Name: ");
-gets(str);
-i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(&smb,offset,length,1);
-	exit(1); }
-if(type=='E' || type=='N')
-	smb.status.attr|=SMB_EMAIL;
-if(smb.status.attr&SMB_EMAIL) {
-	printf("To User Number (0=QWKnet or Internet): ");
-	gets(str);
-	i=smb_hfield(&msg,RECIPIENTEXT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	msg.idx.to=atoi(str); }
-else {
-	strlwr(str);
-	msg.idx.to=crc16(str); }
-
-if(type=='N') {
-	printf("To Address: ");
-	gets(str);
-	if(*str) {
-		if(strchr(str,'.'))
-			net=NET_INTERNET;
-		else
-			net=NET_QWK;
-		i=smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		i=smb_hfield(&msg,RECIPIENTNETADDR,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); } } }
-
-printf("From User Name: ");
-gets(str);
-i=smb_hfield(&msg,SENDER,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(&smb,offset,length,1);
-    exit(1); }
-if(smb.status.attr&SMB_EMAIL) {
-	printf("From User Number: ");
-	gets(str);
-	i=smb_hfield(&msg,SENDEREXT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	msg.idx.from=atoi(str); }
-else {
-	strlwr(str);
-	msg.idx.from=crc16(str); }
-
-printf("Subject: ");
-gets(str);
-i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-if(i) {
-	printf("smb_hfield returned %d\n",i);
-	smb_freemsgdat(&smb,offset,length,1);
-    exit(1); }
-remove_re(str);
-strlwr(str);
-msg.idx.subj=crc16(str);
-
-i=smb_dfield(&msg,TEXT_BODY,length);
-if(i) {
-	printf("smb_dfield returned %d\n",i);
-	smb_freemsgdat(&smb,offset,length,1);
-	exit(1); }
-
-i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-
-if(i) {
-	printf("smb_addmsghdr returned %d\n",i);
-	smb_freemsgdat(&smb,offset,length,1);
-	exit(1); }
-smb_freemsgmem(&msg);
-
-}
-
-/****************************************************************************/
-/* Shows the message base header											*/
-/****************************************************************************/
-void showstatus()
-{
-	int i;
-
-i=smb_locksmbhdr(&smb);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&smb);
-smb_unlocksmbhdr(&smb);
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-printf("last_msg        =%lu\n"
-	   "total_msgs      =%lu\n"
-	   "header_offset   =%lu\n"
-	   "max_crcs        =%lu\n"
-	   "max_msgs        =%lu\n"
-	   "max_age         =%u\n"
-	   "attr            =%04Xh\n"
-	   ,smb.status.last_msg
-	   ,smb.status.total_msgs
-	   ,smb.status.header_offset
-	   ,smb.status.max_crcs
-	   ,smb.status.max_msgs
-	   ,smb.status.max_age
-	   ,smb.status.attr
-	   );
-}
-
-/****************************************************************************/
-/* Configure message base header											*/
-/****************************************************************************/
-void config()
-{
-	char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
-	int i;
-
-i=smb_locksmbhdr(&smb);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&smb);
-smb_unlocksmbhdr(&smb);
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-printf("Header offset =%-5lu  New value (CR=No Change): "
-	,smb.status.header_offset);
-gets(header_offset);
-printf("Max msgs      =%-5lu  New value (CR=No Change): "
-	,smb.status.max_msgs);
-gets(max_msgs);
-printf("Max crcs      =%-5lu  New value (CR=No Change): "
-	,smb.status.max_crcs);
-gets(max_crcs);
-printf("Max age       =%-5u  New value (CR=No Change): "
-	,smb.status.max_age);
-gets(max_age);
-printf("Attributes    =%-5u  New value (CR=No Change): "
-	,smb.status.attr);
-gets(attr);
-i=smb_locksmbhdr(&smb);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&smb);
-if(i) {
-	printf("smb_getstatus returned %d\n",i);
-	smb_unlocksmbhdr(&smb);
-    return; }
-if(isdigit(max_msgs[0]))
-	smb.status.max_msgs=atol(max_msgs);
-if(isdigit(max_crcs[0]))
-	smb.status.max_crcs=atol(max_crcs);
-if(isdigit(max_age[0]))
-	smb.status.max_age=atoi(max_age);
-if(isdigit(header_offset[0]))
-	smb.status.header_offset=atol(header_offset);
-if(isdigit(attr[0]))
-	smb.status.attr=atoi(attr);
-i=smb_putstatus(&smb);
-smb_unlocksmbhdr(&smb);
-if(i)
-	printf("smb_putstatus returned %d\n",i);
-}
-
-/****************************************************************************/
-/* Lists messages' to, from, and subject                                    */
-/****************************************************************************/
-void listmsgs(ulong start, ulong count)
-{
-	int i;
-	ulong l=0;
-	smbmsg_t msg;
-	idxrec_t idxrec;
-
-if(!start)
-	start=1;
-fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
-while(l<count) {
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
-		break;
-	i=smb_lockmsghdr(&smb,&msg);
-	if(i) {
-		printf("smb_lockmsghdr returned %d\n",i);
-		break; }
-	i=smb_getmsghdr(&smb,&msg);
-	smb_unlockmsghdr(&smb,&msg);
-	if(i) {
-		printf("smb_getmsghdr returned %d\n",i);
-		break; }
-	printf("%4lu %-25.25s %-25.25s %.20s\n"
-		,msg.hdr.number,msg.from,msg.to,msg.subj);
-	smb_freemsgmem(&msg);
-	l++; }
-}
-
-/****************************************************************************/
-/* Returns an ASCII string for FidoNet address 'addr'                       */
-/****************************************************************************/
-char *faddrtoa(fidoaddr_t addr)
-{
-	static char str[25];
-	char point[25];
-
-sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
-if(addr.point) {
-	sprintf(point,".%u",addr.point);
-	strcat(str,point); }
-return(str);
-}
-
-char *binstr(uchar *buf, ushort length)
-{
-	static char str[128];
-	char tmp[128];
-	int i;
-
-str[0]=0;
-for(i=0;i<length;i++)
-	if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
-		break;
-if(i==length)		/* not binary */
-	return(buf);
-for(i=0;i<length;i++) {
-	sprintf(tmp,"%02X ",buf[i]);
-	strcat(str,tmp); }
-return(str);
-}
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()                                        */
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-    static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-printf("before localtime\n");
-gm=localtime(intime);
-printf("after\n");
-if(gm==NULL) {
-	strcpy(str,"Invalid Time");
-	return(str); }
-if(gm->tm_hour>=12) {
-    if(gm->tm_hour==12)
-        hour=12;
-    else
-        hour=gm->tm_hour-12;
-    strcpy(mer,"pm"); }
-else {
-    if(gm->tm_hour==0)
-        hour=12;
-    else
-        hour=gm->tm_hour;
-    strcpy(mer,"am"); }
-sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-    ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-    ,hour,gm->tm_min,mer);
-return(str);
-}
-
-
-/****************************************************************************/
-/* Converts when_t.zone into ASCII format									*/
-/****************************************************************************/
-char *zonestr(short zone)
-{
-	static char str[32];
-
-switch((ushort)zone) {
-	case 0: 	return("UT");
-	case AST:	return("AST");
-	case EST:	return("EST");
-	case CST:	return("CST");
-	case MST:	return("MST");
-	case PST:	return("PST");
-	case YST:	return("YST");
-	case HST:	return("HST");
-	case BST:	return("BST");
-	case ADT:	return("ADT");
-	case EDT:	return("EDT");
-	case CDT:	return("CDT");
-	case MDT:	return("MDT");
-	case PDT:	return("PDT");
-	case YDT:	return("YDT");
-	case HDT:	return("HDT");
-	case BDT:	return("BDT");
-	case MID:	return("MID");
-	case VAN:	return("VAN");
-	case EDM:	return("EDM");
-	case WIN:	return("WIN");
-	case BOG:	return("BOG");
-	case CAR:	return("CAR");
-	case RIO:	return("RIO");
-	case FER:	return("FER");
-	case AZO:	return("AZO");
-	case LON:	return("LON");
-	case BER:	return("BER");
-	case ATH:	return("ATH");
-	case MOS:	return("MOS");
-	case DUB:	return("DUB");
-	case KAB:	return("KAB");
-	case KAR:	return("KAR");
-	case BOM:	return("BOM");
-	case KAT:	return("KAT");
-	case DHA:	return("DHA");
-	case BAN:	return("BAN");
-	case HON:	return("HON");
-	case TOK:	return("TOK");
-	case SYD:	return("SYD");
-	case NOU:	return("NOU");
-	case WEL:	return("WEL");
-	}
-
-sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
-return(str);
-}
-			 
-
-/****************************************************************************/
-/* Displays message header information										*/
-/****************************************************************************/
-void viewmsgs(ulong start, ulong count)
-{
-	char when_written[128]
-		,when_imported[128];
-	int i;
-	ulong l=0;
-	smbmsg_t msg;
-	idxrec_t idxrec;
-
-if(!start)
-	start=1;
-fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
-while(l<count) {
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
-		break;
-	i=smb_lockmsghdr(&smb,&msg);
-	if(i) {
-		printf("smb_lockmsghdr returned %d\n",i);
-		break; }
-	i=smb_getmsghdr(&smb,&msg);
-	smb_unlockmsghdr(&smb,&msg);
-	if(i) {
-		printf("smb_getmsghdr returned %d\n",i);
-		break; }
-
-	sprintf(when_written,"%.24s %s"
-		,timestr((time_t *)msg.hdr.when_written.time)
-		,zonestr(msg.hdr.when_written.zone));
-	sprintf(when_imported,"%.24s %s"
-		,timestr((time_t *)msg.hdr.when_imported.time)
-		,zonestr(msg.hdr.when_imported.zone));
-
-	printf( "%-20.20s %s\n"
-			"%-20.20s %s\n"
-            "%-20.20s %s\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %u\n"
-			"%-20.20s %04Xh\n"
-			"%-20.20s %08lXh\n"
-			"%-20.20s %08lXh\n"
-			"%-20.20s %s\n"
-			"%-20.20s %s\n"
-			"%-20.20s %ld (%ld)\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %ld\n"
-			"%-20.20s %s\n"
-			"%-20.20s %06lXh\n"
-			"%-20.20s %u\n",
-
-		"subj",
-		msg.subj,
-
-		"from",
-		msg.from,
-
-		"to",
-		msg.to,
-
-		"type",
-		msg.hdr.type,
-
-		"version",
-		msg.hdr.version,
-
-		"length",
-		msg.hdr.length,
-
-		"attr",
-		msg.hdr.attr,
-
-		"auxattr",
-		msg.hdr.auxattr,
-
-		"netattr",
-		msg.hdr.netattr,
-
-		"when_written",
-		when_written,
-
-		"when_imported",
-		when_imported,
-
-		"number",
-		msg.hdr.number,
-		ftell(smb.sid_fp)/sizeof(idxrec_t),
-
-		"thread_orig",
-		msg.hdr.thread_orig,
-
-		"thread_next",
-		msg.hdr.thread_next,
-
-		"thread_first",
-		msg.hdr.thread_first,
-
-		"reserved[16]",
-		binstr(msg.hdr.reserved,16),
-
-		"offset",
-		msg.hdr.offset,
-
-		"total_dfields",
-		msg.hdr.total_dfields
-		);
-	for(i=0;i<msg.hdr.total_dfields;i++)
-		printf("dfield[%02u].type      %02Xh\n"
-			   "dfield[%02u].offset    %lu\n"
-			   "dfield[%02u].length    %lu\n"
-			   ,i,msg.dfield[i].type
-			   ,i,msg.dfield[i].offset
-			   ,i,msg.dfield[i].length);
-
-	for(i=0;i<msg.total_hfields;i++)
-		printf("hfield[%02u].type      %02Xh\n"
-			   "hfield[%02u].length    %d\n"
-			   "hfield[%02u]_dat       %s\n"
-			   ,i,msg.hfield[i].type
-			   ,i,msg.hfield[i].length
-			   ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
-
-	if(msg.from_net.type)
-		printf("from_net.type        %02Xh\n"
-			   "from_net.addr        %s\n"
-			,msg.from_net.type
-			,msg.from_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
-
-	if(msg.to_net.type)
-		printf("to_net.type          %02Xh\n"
-			   "to_net.addr          %s\n"
-			,msg.to_net.type
-			,msg.to_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-
-	if(msg.replyto_net.type)
-		printf("replyto_net.type     %02Xh\n"
-			   "replyto_net.addr     %s\n"
-			,msg.replyto_net.type
-			,msg.replyto_net.type==NET_FIDO
-			? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
-				: msg.replyto_net.addr);
-
-	printf("from_agent           %02Xh\n"
-		   "to_agent             %02Xh\n"
-		   "replyto_agent        %02Xh\n"
-		   ,msg.from_agent
-		   ,msg.to_agent
-		   ,msg.replyto_agent);
-
-	printf("\n");
-	smb_freemsgmem(&msg);
-	l++; }
-}
-
-/****************************************************************************/
-/* Maintain message base - deletes messages older than max age (in days)	*/
-/* or messages that exceed maximum											*/
-/****************************************************************************/
-void maint(void)
-{
-	int i;
-	ulong l,m,n,f,flagged=0;
-	time_t now;
-	smbmsg_t msg;
-	idxrec_t HUGE16 *idx;
-
-printf("Maintaining %s\r\n",smb.file);
-now=time(NULL);
-i=smb_locksmbhdr(&smb);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&smb);
-if(i) {
-	smb_unlocksmbhdr(&smb);
-	printf("smb_getstatus returned %d\n",i);
-	return; }
-if(!smb.status.total_msgs) {
-	smb_unlocksmbhdr(&smb);
-	printf("Empty\n");
-	return; }
-printf("Loading index...\n");
-if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*smb.status.total_msgs))
-	==NULL) {
-	smb_unlocksmbhdr(&smb);
-	printf("can't allocate %lu bytes of memory\n"
-		,sizeof(idxrec_t)*smb.status.total_msgs);
-	return; }
-fseek(smb.sid_fp,0L,SEEK_SET);
-for(l=0;l<smb.status.total_msgs;l++) {
-	printf("%lu of %lu\r"
-		,l+1,smb.status.total_msgs);
-	if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp))
-		break; }
-printf("\nDone.\n\n");
-
-printf("Scanning for pre-flagged messages...\n");
-for(m=0;m<l;m++) {
-	printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-	if(idx[m].attr&MSG_DELETE)
-		flagged++; }
-printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);
-
-if(smb.status.max_age) {
-	printf("Scanning for messages more than %u days old...\n"
-		,smb.status.max_age);
-	for(m=f=0;m<l;m++) {
-		printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-		if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-			continue;
-		if(now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)
-			>smb.status.max_age) {
-			f++;
-			flagged++;
-			idx[m].attr|=MSG_DELETE; } }  /* mark for deletion */
-	printf("\r100%% (%lu flagged for deletion)\n",f); }
-
-printf("Scanning for read messages to be killed...\n");
-for(m=f=0;m<l;m++) {
-	printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
-	if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-		continue;
-	if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
-		f++;
-		flagged++;
-		idx[m].attr|=MSG_DELETE; } }
-printf("\r100%% (%lu flagged for deletion)\n",f);
-
-if(l-flagged>smb.status.max_msgs) {
-	printf("Flagging excess messages for deletion...\n");
-	for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) {
-		if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
-			continue;
-		printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs);
-		flagged++;
-		idx[m].attr|=MSG_DELETE; }			/* mark for deletion */
-	printf("\nDone.\n\n"); }
-
-if(!flagged) {				/* No messages to delete */
-	LFREE(idx);
-	smb_unlocksmbhdr(&smb);
-	return; }
-
-if(!(mode&NOANALYSIS)) {
-
-	printf("Freeing allocated header and data blocks for deleted messages...\n");
-	if(!(smb.status.attr&SMB_HYPERALLOC)) {
-		i=smb_open_da(&smb);
-		if(i) {
-			smb_unlocksmbhdr(&smb);
-			printf("smb_open_da returned %d\n",i);
-			exit(1); }
-		i=smb_open_ha(&smb);
-		if(i) {
-			smb_unlocksmbhdr(&smb);
-			printf("smb_open_ha returned %d\n",i);
-			exit(1); } }
-
-	for(m=n=0;m<l;m++) {
-		if(idx[m].attr&MSG_DELETE) {
-			printf("%lu of %lu\r",++n,flagged);
-			msg.idx=idx[m];
-			msg.hdr.number=msg.idx.number;
-			if((i=smb_getmsgidx(&smb,&msg))!=0) {
-				printf("\nsmb_getmsgidx returned %d\n",i);
-				continue; }
-			i=smb_lockmsghdr(&smb,&msg);
-			if(i) {
-				printf("\nsmb_lockmsghdr returned %d\n",i);
-				break; }
-			if((i=smb_getmsghdr(&smb,&msg))!=0) {
-				smb_unlockmsghdr(&smb,&msg);
-				printf("\nsmb_getmsghdr returned %d\n",i);
-				break; }
-			msg.hdr.attr|=MSG_DELETE;			/* mark header as deleted */
-			if((i=smb_putmsg(&smb,&msg))!=0) {
-				smb_freemsgmem(&msg);
-				smb_unlockmsghdr(&smb,&msg);
-				printf("\nsmb_putmsg returned %d\n",i);
-				break; }
-			smb_unlockmsghdr(&smb,&msg);
-			if((i=smb_freemsg(&smb,&msg))!=0) {
-				smb_freemsgmem(&msg);
-				printf("\nsmb_freemsg returned %d\n",i);
-				break; }
-			smb_freemsgmem(&msg); } }
-	if(!(smb.status.attr&SMB_HYPERALLOC)) {
-		smb_close_ha(&smb);
-		smb_close_da(&smb); }
-	printf("\nDone.\n\n"); }
-
-printf("Re-writing index...\n");
-rewind(smb.sid_fp);
-if(chsize(fileno(smb.sid_fp),0L))
-	printf("chsize failed!\n");
-for(m=n=0;m<l;m++) {
-	if(idx[m].attr&MSG_DELETE)
-		continue;
-	printf("%lu of %lu\r",++n,l-flagged);
-	fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); }
-printf("\nDone.\n\n");
-fflush(smb.sid_fp);
-
-LFREE(idx);
-smb.status.total_msgs-=flagged;
-smb_putstatus(&smb);
-smb_unlocksmbhdr(&smb);
-}
-
-
-typedef struct {
-	ulong old,new;
-	} datoffset_t;
-
-/****************************************************************************/
-/* Removes all unused blocks from SDT and SHD files 						*/
-/****************************************************************************/
-void packmsgs(ulong packable)
-{
-	uchar str[128],buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
-	int i,file,size;
-	ulong l,m,n,datoffsets=0,length,total,now;
-	FILE *tmp_sdt,*tmp_shd,*tmp_sid;
-	smbhdr_t	hdr;
-	smbmsg_t	msg;
-	datoffset_t *datoffset=NULL;
-
-now=time(NULL);
-printf("Packing %s\n",smb.file);
-i=smb_locksmbhdr(&smb);
-if(i) {
-	printf("smb_locksmbhdr returned %d\n",i);
-	return; }
-i=smb_getstatus(&smb);
-if(i) {
-	smb_unlocksmbhdr(&smb);
-	printf("smb_getstatus returned %d\n",i);
-    return; }
-
-if(!(smb.status.attr&SMB_HYPERALLOC)) {
-	i=smb_open_ha(&smb);
-	if(i) {
-		smb_unlocksmbhdr(&smb);
-		printf("smb_open_ha returned %d\n",i);
-		return; }
-	i=smb_open_da(&smb);
-	if(i) {
-		smb_unlocksmbhdr(&smb);
-		smb_close_ha(&smb);
-		printf("smb_open_da returned %d\n",i);
-		return; } }
-
-if(!smb.status.total_msgs) {
-    printf("Empty\n");
-	rewind(smb.shd_fp);
-	chsize(fileno(smb.shd_fp),smb.status.header_offset);
-	rewind(smb.sdt_fp);
-	chsize(fileno(smb.sdt_fp),0L);
-	rewind(smb.sid_fp);
-	chsize(fileno(smb.sid_fp),0L);
-	if(!(smb.status.attr&SMB_HYPERALLOC)) {
-		rewind(smb.sha_fp);
-		chsize(fileno(smb.sha_fp),0L);
-		rewind(smb.sda_fp);
-		chsize(fileno(smb.sda_fp),0L);
-		smb_close_ha(&smb);
-		smb_close_da(&smb); }
-	smb_unlocksmbhdr(&smb);
-    return; }
-
-
-if(!(smb.status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
-    printf("Analyzing data blocks...\n");
-
-	length=filelength(fileno(smb.sda_fp));
-
-	fseek(smb.sda_fp,0L,SEEK_SET);
-    for(l=m=0;l<length;l+=2) {
-        printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-        i=0;
-		if(!fread(&i,2,1,smb.sda_fp))
-            break;
-        if(!i)
-            m++; }
-
-    printf("\rAnalyzing header blocks...\n");
-
-	length=filelength(fileno(smb.sha_fp));
-
-	fseek(smb.sha_fp,0L,SEEK_SET);
-    for(l=n=0;l<length;l++) {
-        printf("\r%2u%%  ",l ? (long)(100.0/((float)length/l)) : 0);
-		ch=0;
-		if(!fread(&ch,1,1,smb.sha_fp))
-            break;
-		if(!ch)
-            n++; }
-
-    if(!m && !n) {
-		printf("\rAlready compressed.\n\n");
-		smb_close_ha(&smb);
-		smb_close_da(&smb);
-		smb_unlocksmbhdr(&smb);
-        return; }
-
-	if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
-		printf("\rLess than %luk compressable bytes.\n\n",packable);
-		smb_close_ha(&smb);
-		smb_close_da(&smb);
-		smb_unlocksmbhdr(&smb);
-		return; }
-
-	printf("\rCompressing %lu data blocks (%lu bytes)\n"
-			 "        and %lu header blocks (%lu bytes)\n"
-			  ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
-
-if(!(smb.status.attr&SMB_HYPERALLOC)) {
-	rewind(smb.sha_fp);
-	chsize(fileno(smb.sha_fp),0L);		/* Reset both allocation tables */
-	rewind(smb.sda_fp);
-	chsize(fileno(smb.sda_fp),0L); }
-
-if(smb.status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
-	printf("Analyzing %s\n",smb.file);
-
-	length=filelength(fileno(smb.shd_fp));
-	m=n=0;
-	for(l=smb.status.header_offset;l<length;l+=size) {
-		printf("\r%2u%%  ",(long)(100.0/((float)length/l)));
-		msg.idx.offset=l;
-		if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-			printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
-			size=SHD_BLOCK_LEN;
-			continue; }
-		if((i=smb_getmsghdr(&smb,&msg))!=0) {
-			smb_unlockmsghdr(&smb,&msg);
-			m++;
-			size=SHD_BLOCK_LEN;
-			continue; }
-		smb_unlockmsghdr(&smb,&msg);
-		if(msg.hdr.attr&MSG_DELETE) {
-			m+=smb_hdrblocks(msg.hdr.length);
-			total=0;
-			for(i=0;i<msg.hdr.total_dfields;i++)
-				total+=msg.dfield[i].length;
-			n+=smb_datblocks(total); }
-		size=smb_getmsghdrlen(&msg);
-		if(size<1) size=SHD_BLOCK_LEN;
-		while(size%SHD_BLOCK_LEN)
-			size++;
-		smb_freemsgmem(&msg); }
-
-
-    if(!m && !n) {
-		printf("\rAlready compressed.\n\n");
-		smb_unlocksmbhdr(&smb);
-        return; }
-
-	if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
-		printf("\rLess than %luk compressable bytes.\n\n",packable);
-		smb_unlocksmbhdr(&smb);
-		return; }
-
-	printf("\rCompressing %lu data blocks (%lu bytes)\n"
-			 "        and %lu header blocks (%lu bytes)\n"
-			  ,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN); }
-
-sprintf(fname,"%s.SD$",smb.file);
-tmp_sdt=fopen(fname,"wb");
-sprintf(fname,"%s.SH$",smb.file);
-tmp_shd=fopen(fname,"wb");
-sprintf(fname,"%s.SI$",smb.file);
-tmp_sid=fopen(fname,"wb");
-if(!tmp_sdt || !tmp_shd || !tmp_sid) {
-	smb_unlocksmbhdr(&smb);
-	if(!(smb.status.attr&SMB_HYPERALLOC)) {
-		smb_close_ha(&smb);
-		smb_close_da(&smb); }
-	printf("error opening temp file\n");
-	return; }
-setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
-setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
-setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
-if(!(smb.status.attr&SMB_HYPERALLOC)
-	&& (datoffset=(datoffset_t *)LMALLOC(sizeof(datoffset_t)*smb.status.total_msgs))
-	==NULL) {
-	smb_unlocksmbhdr(&smb);
-	smb_close_ha(&smb);
-	smb_close_da(&smb);
-	fclose(tmp_sdt);
-	fclose(tmp_shd);
-	fclose(tmp_sid);
-	printf("error allocating mem\n");
-    return; }
-fseek(smb.shd_fp,0L,SEEK_SET);
-fread(&hdr,1,sizeof(smbhdr_t),smb.shd_fp);
-fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
-fwrite(&(smb.status),1,sizeof(smbstatus_t),tmp_shd);
-for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<smb.status.header_offset;l++) {
-	fread(&ch,1,1,smb.shd_fp);			/* copy additional base header records */
-	fwrite(&ch,1,1,tmp_shd); }
-fseek(smb.sid_fp,0L,SEEK_SET);
-total=0;
-for(l=0;l<smb.status.total_msgs;l++) {
-	printf("%lu of %lu\r",l+1,smb.status.total_msgs);
-	if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
-		break;
-	if(msg.idx.attr&MSG_DELETE) {
-		printf("\nDeleted index.\n");
-		continue; }
-	i=smb_lockmsghdr(&smb,&msg);
-	if(i) {
-		printf("\nsmb_lockmsghdr returned %d\n",i);
-		continue; }
-	i=smb_getmsghdr(&smb,&msg);
-	smb_unlockmsghdr(&smb,&msg);
-	if(i) {
-		printf("\nsmb_getmsghdr returned %d\n",i);
-		continue; }
-	if(msg.hdr.attr&MSG_DELETE) {
-		printf("\nDeleted header.\n");
-		smb_freemsgmem(&msg);
-		continue; }
-	if(msg.expiration.time && msg.expiration.time<=now) {
-		printf("\nExpired message.\n");
-		smb_freemsgmem(&msg);
-		continue; }
-	for(m=0;m<datoffsets;m++)
-		if(msg.hdr.offset==datoffset[m].old)
-			break;
-	if(m<datoffsets) {				/* another index pointed to this data */
-		printf("duplicate index\n");
-		msg.hdr.offset=datoffset[m].new;
-		smb_incdat(&smb,datoffset[m].new,smb_getmsgdatlen(&msg),1); }
-	else {
-
-		if(!(smb.status.attr&SMB_HYPERALLOC))
-			datoffset[datoffsets].old=msg.hdr.offset;
-
-		fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
-
-		m=smb_getmsgdatlen(&msg);
-        if(m>16L*1024L*1024L) {
-            printf("\nInvalid data length (%lu)\n",m);
-            continue; }
-
-		if(!(smb.status.attr&SMB_HYPERALLOC)) {
-			datoffset[datoffsets].new=msg.hdr.offset
-				=smb_fallocdat(&smb,m,1);
-			datoffsets++;
-			fseek(tmp_sdt,msg.hdr.offset,SEEK_SET); }
-		else {
-			fseek(tmp_sdt,0L,SEEK_END);
-			msg.hdr.offset=ftell(tmp_sdt); }
-
-		/* Actually copy the data */
-
-		n=smb_datblocks(m);
-		for(m=0;m<n;m++) {
-			fread(buf,1,SDT_BLOCK_LEN,smb.sdt_fp);
-			if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
-				printf("\nUnsupported translation type (%04X)\n"
-					,*(ushort *)buf);
-				break; }
-			fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); }
-		if(m<n)
-			continue; }
-
-	/* Write the new index entry */
-	length=smb_getmsghdrlen(&msg);
-	if(smb.status.attr&SMB_HYPERALLOC)
-		msg.idx.offset=ftell(tmp_shd);
-	else
-		msg.idx.offset=smb_fallochdr(&smb,length)+smb.status.header_offset;
-	msg.idx.number=msg.hdr.number;
-	msg.idx.attr=msg.hdr.attr;
-	msg.idx.time=msg.hdr.when_imported.time;
-	sprintf(str,"%.128s",msg.subj);
-	strlwr(str);
-	remove_re(str);
-	msg.idx.subj=crc16(str);
-	if(smb.status.attr&SMB_EMAIL) {
-		if(msg.to_ext)
-			msg.idx.to=atoi(msg.to_ext);
-		else
-			msg.idx.to=0;
-		if(msg.from_ext)
-			msg.idx.from=atoi(msg.from_ext);
-		else
-			msg.idx.from=0; }
-	else {
-		sprintf(str,"%.128s",msg.to);
-		strlwr(str);
-		msg.idx.to=crc16(str);
-		sprintf(str,"%.128s",msg.from);
-		strlwr(str);
-		msg.idx.from=crc16(str); }
-	fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
-
-	/* Write the new header entry */
-	fseek(tmp_shd,msg.idx.offset,SEEK_SET);
-	fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
-	for(n=0;n<msg.hdr.total_dfields;n++)
-		fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
-	for(n=0;n<msg.total_hfields;n++) {
-		fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
-		fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
-	while(length%SHD_BLOCK_LEN) {	/* pad with NULLs */
-		fputc(0,tmp_shd);
-		length++; }
-	total++;
-	smb_freemsgmem(&msg); }
-
-if(datoffset)
-	LFREE(datoffset);
-if(!(smb.status.attr&SMB_HYPERALLOC)) {
-	smb_close_ha(&smb);
-	smb_close_da(&smb); }
-
-/* Change *.SH$ into *.SHD */
-fclose(smb.shd_fp);
-fclose(tmp_shd);
-sprintf(fname,"%s.SHD",smb.file);
-remove(fname);
-sprintf(tmpfname,"%s.SH$",smb.file);
-rename(tmpfname,fname);
-
-/* Change *.SD$ into *.SDT */
-fclose(smb.sdt_fp);
-fclose(tmp_sdt);
-sprintf(fname,"%s.SDT",smb.file);
-remove(fname);
-sprintf(tmpfname,"%s.SD$",smb.file);
-rename(tmpfname,fname);
-
-/* Change *.SI$ into *.SID */
-fclose(smb.sid_fp);
-fclose(tmp_sid);
-sprintf(fname,"%s.SID",smb.file);
-remove(fname);
-sprintf(tmpfname,"%s.SI$",smb.file);
-rename(tmpfname,fname);
-
-if((i=smb_open(&smb))!=0) {
-	printf("Error %d reopening %s\n",i,smb.file);
-	return; }
-
-smb.status.total_msgs=total;
-if((i=smb_putstatus(&smb))!=0)
-	printf("\nsmb_putstatus returned %d\n",i);
-printf("\nDone.\n\n");
-}
-
-
-/****************************************************************************/
-/* Read messages in message base											*/
-/****************************************************************************/
-void readmsgs(ulong start)
-{
-	char	str[128],HUGE16 *inbuf,*outbuf;
-	int 	i,ch,done=0,domsg=1,lzh;
-	ushort	xlat;
-	ulong	l,count,outlen;
-	smbmsg_t msg;
-
-if(start)
-	msg.offset=start-1;
-else
-	msg.offset=0;
-while(!done) {
-	if(domsg) {
-		fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
-		if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
-			break;
-		i=smb_lockmsghdr(&smb,&msg);
-		if(i) {
-			printf("smb_lockmsghdr returned %d\n",i);
-			break; }
-		i=smb_getmsghdr(&smb,&msg);
-		if(i) {
-			printf("smb_getmsghdr returned %d\n",i);
-			break; }
-
-		printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
-		printf("Subj : %s\n",msg.subj);
-		printf("To   : %s",msg.to);
-		if(msg.to_net.type)
-			printf(" (%s)",msg.to_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
-		printf("\nFrom : %s",msg.from);
-		if(msg.from_net.type)
-			printf(" (%s)",msg.from_net.type==NET_FIDO
-				? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
-					: msg.from_net.addr);
-#if 1
-		printf("\nDate : %.24s %s"
-			,timestr((time_t *)msg.hdr.when_written.time)
-			,zonestr(msg.hdr.when_written.zone));
-#endif
-		printf("\n\n");
-#if 0
-		for(i=0;i<msg.hdr.total_dfields;i++)
-			switch(msg.dfield[i].type) {
-				case TEXT_BODY:
-				case TEXT_TAIL:
-					fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-						,SEEK_SET);
-					fread(&xlat,2,1,smb.sdt_fp);
-					l=2;
-					lzh=0;
-					while(xlat!=XLAT_NONE) {
-						if(xlat==XLAT_LZH)
-							lzh=1;
-						fread(&xlat,2,1,smb.sdt_fp);
-						l+=2; }
-					if(lzh) {
-						if((inbuf=(char *)LMALLOC(msg.dfield[i].length))
-							==NULL) {
-							printf("Malloc error of %lu\n"
-								,msg.dfield[i].length);
-							exit(1); }
-						fread(inbuf,msg.dfield[i].length-l,1,smb.sdt_fp);
-						outlen=*(long *)inbuf;
-						if((outbuf=(char *)LMALLOC(outlen))==NULL) {
-							printf("Malloc error of lzh %lu\n"
-								,outlen);
-							exit(1); }
-						lzh_decode(inbuf,msg.dfield[i].length-l,outbuf);
-						LFREE(inbuf);
-						for(l=0;l<outlen;l++)
-							putchar(outbuf[l]);
-						LFREE(outbuf); }
-					else {
-						for(;l<msg.dfield[i].length;l++) {
-							ch=fgetc(smb.sdt_fp);
-							if(ch)
-								putchar(ch); } }
-					printf("\n");
-					break; }
-#else
-		if((inbuf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))!=NULL) {
-			printf("%s",inbuf);
-			FREE(inbuf); }
-#endif
-		i=smb_unlockmsghdr(&smb,&msg);
-        if(i) {
-			printf("smb_unlockmsghdr returned %d\n",i);
-			break; }
-		smb_freemsgmem(&msg); }
-	domsg=1;
-	printf("\nReading %s (?=Menu): ",smb.file);
-	switch(toupper(getch())) {
-		case '?':
-			printf("\n"
-				   "\n"
-				   "(R)e-read current message\n"
-				   "(L)ist messages\n"
-				   "(T)en more titles\n"
-				   "(V)iew message headers\n"
-				   "(Q)uit\n"
-				   "(+/-) Forward/Backward\n"
-				   "\n");
-			domsg=0;
-			break;
-		case 'Q':
-			printf("Quit\n");
-			done=1;
-			break;
-		case 'R':
-			printf("Re-read\n");
-			break;
-		case '-':
-			printf("Backwards\n");
-			if(msg.offset)
-				msg.offset--;
-			break;
-		case 'T':
-			printf("Ten titles\n");
-			listmsgs(msg.offset+2,10);
-			msg.offset+=10;
-			domsg=0;
-			break;
-		case 'L':
-			printf("List messages\n");
-			listmsgs(1,-1);
-			domsg=0;
-			break;
-		case 'V':
-			printf("View message headers\n");
-			viewmsgs(1,-1);
-			domsg=0;
-			break;
-		case CR:
-		case '+':
-			printf("Next\n");
-			msg.offset++;
-			break; } }
-}
-
-/***************/
-/* Entry point */
-/***************/
-int main(int argc, char **argv)
-{
-	char cmd[128]="",*p,*s;
-	int i,j,x,y;
-	ulong l;
-
-#ifdef __TURBOC__
-	timezone=0; 		/* Fix for Borland C++ EST default */
-	daylight=0; 		/* Fix for Borland C++ EDT default */
-#elif defined(__WATCOMC__)
-	putenv("TZ=UCT0");  /* Fix for Watcom C++ EDT default */
-#endif
-setvbuf(stdout,0,_IONBF,0);
-
-smb.file[0]=0;
-printf("\nSMBUTIL Version %s (%s) SMBLIB %s � Synchronet Message Base "\
-	"Utility\n\n"
-	,SMBUTIL_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-	,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	,SMBLIB_VERSION
-    );
-for(x=1;x<argc;x++) {
-	if(argv[x][0]=='/') {
-		for(j=1;argv[x][j];j++)
-			switch(toupper(argv[x][j])) {
-				case 'A':
-					mode|=NOANALYSIS;
-					break;
-				case 'Z':
-					if(isdigit(argv[x][j+1]))
-						tzone=atoi(argv[x]+j+1);
-					else if(!stricmp(argv[x]+j+1,"EST"))
-						tzone=EST;
-					else if(!stricmp(argv[x]+j+1,"EDT"))
-						tzone=EDT;
-					else if(!stricmp(argv[x]+j+1,"CST"))
-						tzone=CST;
-					else if(!stricmp(argv[x]+j+1,"CDT"))
-						tzone=CDT;
-					else if(!stricmp(argv[x]+j+1,"MST"))
-						tzone=MST;
-					else if(!stricmp(argv[x]+j+1,"MDT"))
-						tzone=MDT;
-					else if(!stricmp(argv[x]+j+1,"PST"))
-						tzone=PST;
-					else if(!stricmp(argv[x]+j+1,"PDT"))
-						tzone=PDT;
-					j=strlen(argv[x])-1;
-					break;
-				default:
-					printf("\nUnknown opt '%c'\n",argv[x][j]);
-				case '?':
-					printf("%s",usage);
-					exit(1);
-					break; } }
-	else {
-		if(!cmd[0])
-			strcpy(cmd,argv[x]);
-		else {
-			sprintf(smb.file,"%.64s",argv[x]);
-			p=strrchr(smb.file,'.');
-			s=strrchr(smb.file,'\\');
-			if(p>s) *p=0;
-			strupr(smb.file);
-			smb.retry_time=30;
-			printf("Opening %s\r\n",smb.file);
-			if((i=smb_open(&smb))!=0) {
-				printf("error %d opening %s message base\n",i,smb.file);
-				exit(1); }
-			if(!filelength(fileno(smb.shd_fp))) {
-				printf("Empty\n");
-				smb_close(&smb);
-				continue; }
-			for(y=0;cmd[y];y++)
-				switch(toupper(cmd[y])) {
-					case 'I':
-					case 'E':
-					case 'N':
-						strcpy(filein,cmd+1);
-						i=smb_locksmbhdr(&smb);
-						if(i) {
-							printf("smb_locksmbhdr returned %d\n",i);
-							return(1); }
-						postmsg(toupper(cmd[y]));
-						y=strlen(cmd)-1;
-						break;
-					case 'S':
-						showstatus();
-						break;
-					case 'C':
-						config();
-						break;
-					case 'L':
-						listmsgs(atol(cmd+1),-1L);
-						y=strlen(cmd)-1;
-						break;
-					case 'P':
-						packmsgs(atol(cmd+y+1));
-						y=strlen(cmd)-1;
-						break;
-					case 'R':
-						readmsgs(atol(cmd+1));
-						y=strlen(cmd)-1;
-						break;
-					case 'V':
-						viewmsgs(atol(cmd+1),-1L);
-						y=strlen(cmd)-1;
-						break;
-					case 'M':
-						maint();
-						break;
-					default:
-						printf("%s",usage);
-						break; }
-			smb_close(&smb); } } }
-if(!cmd[0])
-	printf("%s",usage);
-return(0);
-}
diff --git a/src/sbbs2/smb/smbutil/smbutil.h b/src/sbbs2/smb/smbutil/smbutil.h
deleted file mode 100644
index 4b5462b12a18e132a3a55b92048d67e2282c5d62..0000000000000000000000000000000000000000
--- a/src/sbbs2/smb/smbutil/smbutil.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SMBUTIL.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#define NOANALYSIS		(1L<<0)
-
-#ifdef __WATCOMC__
-	#define ffblk find_t
-    #define findfirst(x,y,z) _dos_findfirst(x,z,y)
-	#define findnext(x) _dos_findnext(x)
-#endif
-
diff --git a/src/sbbs2/smbactiv/makeall.bat b/src/sbbs2/smbactiv/makeall.bat
deleted file mode 100755
index d68900c3d3397527fe45f8723f77457287880eda..0000000000000000000000000000000000000000
--- a/src/sbbs2/smbactiv/makeall.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-@echo off
-wmake OS=DOS %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=DOSX %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=OS2 %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-wmake OS=NT %1 %2 %3 %4 %5
-if errorlevel 1 goto end
-:end
-
diff --git a/src/sbbs2/smbactiv/makefile b/src/sbbs2/smbactiv/makefile
deleted file mode 100644
index e2a9ad55aa8bd12a022842902e19a26087442c60..0000000000000000000000000000000000000000
--- a/src/sbbs2/smbactiv/makefile
+++ /dev/null
@@ -1,92 +0,0 @@
-############################################
-# Makefile for Synchronet SMBACTIV Utility #
-# For use with Watcom C/C++ 		   #
-############################################
-
-!ifndef OS
-OS	= DOS
-!endif
-
-!ifeq OS DOS
-CC	= *wcc
-!else
-CC	= *wcc386
-!endif
-
-LD	= *wlink
-INCLUDE = \watcom\h;\watcom\h\os2;..;..\smb;..\rio
-
-
-!ifeq OS DOS
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\ -ml
-!else
-CFLAGS	= -I$(INCLUDE) -s -fh=$*.pch -bt=$(OS) -fo=$(OS)\
-!endif
-
-!ifeq OS DOS
-SYSTEM  = DOS
-!endif
-!ifeq OS OS2
-SYSTEM  = OS2V2
-!endif
-!ifeq OS DOSX
-SYSTEM  = DOS4G
-!endif
-!ifeq OS NT
-SYSTEM	= NT
-!endif
-
-LFLAGS  = option stack=16k system $(SYSTEM)
-
-MAIN	= $(OS)\smbactiv.exe
-OBJS	= $(OS)\smbactiv.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj &
-	  $(OS)\ars.obj $(OS)\scfglib2.obj $(OS)\smblib.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\gen_defs.h ..\scfgvars.c &
-	  ..\smb\smbdefs.h ..\smb\smblib.h
-
-# Implicit C Compile Rule
-.c.obj:
-	@echo Compiling (I) $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-#	 @echo Linking $< ...
-	$(LD) $(LFLAGS) file { $(OBJS) }
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# ARS
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-# Shared Functions
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c &
-	..\scfglib.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) &
--DNO_TEXT_CFG &
--DNO_XTRN_CFG &
--DNO_CMDS_CFG &
--DNO_CHAT_CFG &
-$[@
-
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling $[@ to $^@ ...
-	$(CC) $(CFLAGS) $[@
-
diff --git a/src/sbbs2/smbactiv/makefile.bc b/src/sbbs2/smbactiv/makefile.bc
deleted file mode 100644
index 65e62529f4df2aa89b4606d17564a05b576c41a6..0000000000000000000000000000000000000000
--- a/src/sbbs2/smbactiv/makefile.bc
+++ /dev/null
@@ -1,78 +0,0 @@
-############################################
-# Makefile for Synchronet DEADSUBS Utility #
-# For use with Borland C++ for DOS or OS/2 #
-############################################
-
-# Macros
-CC	= bcc
-LD	= tlink
-!ifdef __OS2__
-OS	= OS2
-INCLUDE = c:\bcos2\include;..;..\smb;..\rio
-LIB	= c:\bcos2\lib
-CFLAGS  = -d -C -I$(INCLUDE) -w-pro
-LFLAGS  = -c
-!else
-OS      = DOS
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB	= \bc31\lib
-MODEL	= l
-CFLAGS	= -d -N -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LFLAGS	= -n -c
-!endif
-MAIN	= $(OS)\smbactiv.exe
-OBJS	= $(OS)\smbactiv.obj $(OS)\scfgvars.obj $(OS)\scfglib1.obj \
-	  $(OS)\scfglib2.obj $(OS)\smblib.obj $(OS)\ars.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c \
-	  ..\smb\smbdefs.h ..\smb\smblib.h
-
-# Implicit C Compile Rule
-{.}.c.obj:
-	@echo Compiling (I) $< to $@ ...
-        $(CC) $(CFLAGS) -n$(OS) -c $<
-
-# Main EXE Link Rule
-$(MAIN): $(OBJS) 
-    	@echo Linking $< ...
-!ifdef __OS2__
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c02.obj $(OBJS)
-+, $*, $*, $(LIB)\os2.lib $(LIB)\c2.lib
-!else
-	$(LD) $(LFLAGS) @&&+
-$(LIB)\c0$(MODEL) $(OBJS)   
-+, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-!endif
-
-# Global Variables
-$(OS)\scfgvars.obj: ..\scfgvars.c ..\sbbsdefs.h
-	@echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c -n$(OS) ..\$&.c
-
-# Shared Functions
-$(OS)\scfglib1.obj: ..\scfglib1.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c \
-        ..\scfglib.h
-        $(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_FILE_CFG
--DNO_XTRN_CFG
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-$(OS)\scfglib2.obj: ..\scfglib2.c ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c \
-        ..\scfglib.h
-	$(CC) $(CFLAGS) -c -n$(OS) @&&!
--DNO_FILE_CFG
--DNO_XTRN_CFG
--DNO_CMDS_CFG
--DNO_CHAT_CFG
-! ..\$&.c
-
-$(OS)\smblib.obj: ..\smb\smblib.c ..\smb\smblib.h ..\smb\smbdefs.h
-	@echo Compiling SMBLIB ...
-	$(CC) $(CFLAGS) -n$(OS) -c ..\smb\smblib.c
-
-$(OS)\ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-        $(CC) $(CFLAGS) -n$(OS) -c ..\ars.c
-
diff --git a/src/sbbs2/smbactiv/smbactiv.c b/src/sbbs2/smbactiv/smbactiv.c
deleted file mode 100644
index d932b8c31bcee5fcad3f98e86c191a562583b15a..0000000000000000000000000000000000000000
--- a/src/sbbs2/smbactiv/smbactiv.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* SMBACTIV.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <share.h>
-#include "sbbs.h"
-
-#define SMBACTIV_VER "1.01"
-
-typedef struct {
-	ulong read;
-	ulong firstmsg;
-} sub_status_t;
-
-smb_t smb;
-
-ulong first_msg()
-{
-	smbmsg_t msg;
-
-msg.offset=0;
-msg.hdr.number=0;
-if(smb_getmsgidx(&smb,&msg))			/* Get first message index */
-	return(0);
-return(msg.idx.number);
-}
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-long lputs(char FAR16 *str)
-{
-    char tmp[256];
-    int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)      /* remove CRs */
-    if(str[i]==CR && str[i+1]==LF)
-        continue;
-    else
-        tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stderr));
-}
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access	*/
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(access&O_WRONLY) access|=O_RDWR; 	/* fdopen can't open WRONLY */
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&(O_RDONLY|O_RDWR))
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&(O_WRONLY|O_RDWR))
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[256];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-void bail(int code)
-{
-exit(code);
-}
-
-void main(int argc, char **argv)
-{
-	char str[256],*p;
-	int i,j,file;
-	ulong l,length,max_users=0xffffffff;
-	sub_status_t *sub_status;
-	read_cfg_text_t txt;
-	struct find_t f;
-	FILE *stream;
-
-   _fmode=O_BINARY;
-	txt.openerr="\7\r\nError opening %s for read.\r\n";
-	txt.reading="\r\nReading %s...";
-	txt.readit="\rRead %s       ";
-	txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
-	txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
-
-fprintf(stderr,"\nSMBACTIV Version %s (%s) - Synchronet Message Base Activity "
-	"Monitor\n"
-	,SMBACTIV_VER
-#if defined(__OS2__)
-	,"OS/2"
-#elif defined(__NT__)
-    ,"Win32"
-#elif defined(__DOS4G__)
-	,"DOS4G"
-#elif defined(__FLAT__)
-	,"DOS32"
-#else
-	,"DOS16"
-#endif
-	);
-
-	if(argc>1 && (!stricmp(argv[1],"/?") || !stricmp(argv[1],"?"))) {
-		lprintf("\nusage: SMBACTIV [max_users]\n\n");
-		lprintf("max_users = limit output to subs read by this many users "
-			"or less\n");
-		exit(0); }
-
-	if(argc>1)
-		max_users=atol(argv[1]);
-
-	if(!node_dir[0]) {
-		p=getenv("SBBSNODE");
-		if(p==NULL) {
-			printf("\7\nSBBSNODE environment variable not set.\n");
-			exit(1); }
-		strcpy(node_dir,p); }
-
-	strupr(node_dir);
-
-	if(node_dir[strlen(node_dir)-1]!='\\')
-		strcat(node_dir,"\\");
-
-	read_node_cfg(txt);
-	if(ctrl_dir[0]=='.') {   /* Relative path */
-		strcpy(str,ctrl_dir);
-		sprintf(ctrl_dir,"%s%s",node_dir,str);
-		if(_fullpath(str,ctrl_dir,40))
-			strcpy(ctrl_dir,str); }
-	backslash(ctrl_dir);
-
-	read_main_cfg(txt);
-	if(data_dir[0]=='.') {   /* Relative path */
-		strcpy(str,data_dir);
-		sprintf(data_dir,"%s%s",node_dir,str);
-		if(_fullpath(str,data_dir,40))
-			strcpy(data_dir,str); }
-	backslash(data_dir);
-	if(text_dir[0]=='.') {   /* Relative path */
-		strcpy(str,text_dir);
-		sprintf(text_dir,"%s%s",node_dir,str);
-		if(_fullpath(str,text_dir,40))
-			strcpy(text_dir,str); }
-	backslash(text_dir);
-	read_msgs_cfg(txt);
-
-	if((sub_status=(sub_status_t *)MALLOC
-		(total_subs*sizeof(sub_status_t)))==NULL) {
-		printf("ERROR Allocating memory for sub_status\r\n");
-		exit(1); }
-
-	lprintf("\nReading sub-board ");
-	for(i=0;i<total_subs;i++) {
-		lprintf("%5d of %-5d\b\b\b\b\b\b\b\b\b\b\b\b\b\b",i+1,total_subs);
-		sprintf(smb.file,"%s%s",sub[i]->data_dir,sub[i]->code);
-		if((j=smb_open(&smb))!=0) {
-			lprintf("Error %d opening %s\r\n",j,smb.file);
-			sub_status[i].read=0;
-			sub_status[i].firstmsg=0L;
-            continue; }
-		sub_status[i].read=0;
-		sub_status[i].firstmsg=first_msg();
-		smb_close(&smb); }
-
-	sprintf(str,"%sUSER\\PTRS\\*.IXB",data_dir);
-	if(_dos_findfirst(str,0,&f)) {
-		lprintf("Unable to find any user pointer files.\n");
-		FREE(sub_status);
-		exit(1); }
-
-	j=0;
-	lprintf("\nComparing user pointers ");
-	while(1) {
-		lprintf("%-5d\b\b\b\b\b",++j);
-		sprintf(str,"%sUSER\\PTRS\\%s",data_dir,f.name);
-		if((file=nopen(str,O_RDONLY))==-1) {
-			if(_dos_findnext(&f))
-				break;
-			continue; }
-		length=filelength(file);
-		for(i=0;i<total_subs;i++) {
-			if(sub_status[i].read>max_users)
-				continue;
-			if(length<(sub[i]->ptridx+1)*10L)
-				continue;
-			else {
-				lseek(file,((long)sub[i]->ptridx*10L)+4L,SEEK_SET);
-				read(file,&l,4); }
-			if(l>sub_status[i].firstmsg)
-				sub_status[i].read++; }
-		close(file);
-		if(_dos_findnext(&f))
-			break; }
-
-	printf("NumUsers    Sub-board\n");
-	printf("--------    -------------------------------------------------"
-		"-----------\n");
-	for(i=0;i<total_subs;i++) {
-		if(sub_status[i].read>max_users)
-			continue;
-		printf("%8lu    %-*s %-*s\n"
-			,sub_status[i].read
-			,LEN_GSNAME,grp[sub[i]->grp]->sname
-			,LEN_SLNAME,sub[i]->lname); }
-
-}
diff --git a/src/sbbs2/smbfuncs.c b/src/sbbs2/smbfuncs.c
deleted file mode 100644
index 8c8215138b8f285809e1cb51d226b022ab6d3c71..0000000000000000000000000000000000000000
--- a/src/sbbs2/smbfuncs.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SMBFUNCS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "smbdefs.h"
-
-int 	SMBCALL (smb_ver)(void);
-char *	SMBCALL (smb_lib_ver)(void);
-int 	SMBCALL (smb_open)(smb_t *smb);
-void	SMBCALL (smb_close)(smb_t *smb);
-int 	SMBCALL (smb_open_da)(smb_t *smb);
-void	SMBCALL (smb_close_da)(smb_t *smb);
-int 	SMBCALL (smb_open_ha)(smb_t *smb);
-void	SMBCALL (smb_close_ha)(smb_t *smb);
-int 	SMBCALL (smb_create)(smb_t *smb);
-int 	SMBCALL (smb_stack)(smb_t *smb, int op);
-int 	SMBCALL (smb_trunchdr)(smb_t *smb);
-int 	SMBCALL (smb_locksmbhdr)(smb_t *smb);
-int 	SMBCALL (smb_getstatus)(smb_t *smb);
-int 	SMBCALL (smb_putstatus)(smb_t *smb);
-int 	SMBCALL (smb_unlocksmbhdr)(smb_t *smb);
-int 	SMBCALL (smb_getmsgidx)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_getlastidx)(smb_t *smb, idxrec_t *idx);
-uint	SMBCALL (smb_getmsghdrlen)(smbmsg_t *msg);
-ulong	SMBCALL (smb_getmsgdatlen)(smbmsg_t *msg);
-int 	SMBCALL (smb_lockmsghdr)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_getmsghdr)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_unlockmsghdr)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_addcrc)(smb_t *smb, ulong crc);
-int 	SMBCALL (smb_hfield)(smbmsg_t *msg, ushort type, ushort length
-				,void *data);
-int 	SMBCALL (smb_dfield)(smbmsg_t *msg, ushort type, ulong length);
-int 	SMBCALL (smb_addmsghdr)(smb_t *smb, smbmsg_t *msg,int storage);
-int 	SMBCALL (smb_putmsg)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_putmsgidx)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_putmsghdr)(smb_t *smb, smbmsg_t *msg);
-void	SMBCALL (smb_freemsgmem)(smbmsg_t *msg);
-ulong	SMBCALL (smb_hdrblocks)(ulong length);
-ulong	SMBCALL (smb_datblocks)(ulong length);
-long	SMBCALL (smb_allochdr)(smb_t *smb, ulong length);
-long	SMBCALL (smb_fallochdr)(smb_t *smb, ulong length);
-long	SMBCALL (smb_hallochdr)(smb_t *smb);
-long	SMBCALL (smb_allocdat)(smb_t *smb, ulong length, ushort headers);
-long	SMBCALL (smb_fallocdat)(smb_t *smb, ulong length, ushort headers);
-long	SMBCALL (smb_hallocdat)(smb_t *smb);
-int 	SMBCALL (smb_incdat)(smb_t *smb, ulong offset, ulong length
-				,ushort headers);
-int 	SMBCALL (smb_freemsg)(smb_t *smb, smbmsg_t *msg);
-int 	SMBCALL (smb_freemsgdat)(smb_t *smb, ulong offset, ulong length
-				,ushort headers);
-int 	SMBCALL (smb_freemsghdr)(smb_t *smb, ulong offset, ulong length);
-char HUGE16 * SMBCALL smb_getmsgtxt(smb_t *smb, smbmsg_t *msg, ulong mode);
-void	SMBCALL (smb_freemsgtxt)(char HUGE16 *buf);
-
-/* FILE pointer I/O functions */
-
-int 	SMBCALL (smb_feof(FILE *fp);
-int 	SMBCALL (smb_ferror(FILE *fp);
-int 	SMBCALL (smb_fflush(FILE *fp);
-int 	SMBCALL (smb_fgetc(FILE *fp);
-int 	SMBCALL (smb_fputc(int ch, FILE *fp);
-int 	SMBCALL (smb_fseek(FILE *fp, long offset, int whence);
-long	SMBCALL (smb_ftell(FILE *fp);
-long	SMBCALL (smb_fread(char HUGE16 *buf, long bytes, FILE *fp);
-long	SMBCALL (smb_fwrite(char HUGE16 *buf, long bytes, FILE *fp);
-long	SMBCALL (smb_fgetlength(FILE *fp);
-int 	SMBCALL (smb_fsetlength(FILE *fp, long length);
-void	SMBCALL (smb_rewind(FILE *fp);
-void	SMBCALL (smb_clearerr(FILE *fp);
-
-/* LZH functions */
-
-long	SMBCALL (lzh_encode(uchar *inbuf, long inlen, uchar *outbuf);
-long	SMBCALL (lzh_decode(uchar *inbuf, long inlen, uchar *outbuf);
-
-#endif /* Don't add anything after this #endif statement */
diff --git a/src/sbbs2/smm/addphoto.c b/src/sbbs2/smm/addphoto.c
deleted file mode 100644
index 6f4294579c4e6659c6ad04c88e2f54a9b421208e..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/addphoto.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/* ADDPHOTO.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <io.h>
-#include <dos.h>
-#include <bios.h>
-#include <time.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <share.h>
-#include <conio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <malloc.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "gen_defs.h"
-#include "crc32.h"
-#include "smmdefs.h"
-
-extern int daylight=0;
-extern long timezone=0L;
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC)==0)
-    return(1);
-return(0);
-}
-
-#define MV_BUFLEN	4096
-
-/****************************************************************************/
-/* Moves or copies a file from one dir to another                           */
-/* both 'src' and 'dest' must contain full path and filename                */
-/* returns 0 if successful, -1 if error                                     */
-/****************************************************************************/
-int mv(char *src, char *dest, char copy)
-{
-	char str[256],*buf;
-	int  ind,outd;
-	long length,chunk=MV_BUFLEN,l;
-	struct ftime ftime;
-	FILE *inp,*outp;
-
-if(copy)
-	printf("Copying %s to %s\n",src,dest);
-else
-	printf("Moving %s to %s\n",src,dest);
-if(!stricmp(src,dest))	 /* source and destination are the same! */
-	return(0);
-if(!fexist(src))
-	return(1);
-if(!copy && fexist(dest))
-	return(2);
-if(!copy && ((src[1]!=':' && dest[1]!=':')
-	|| (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
-	if(rename(src,dest))					   /* same drive, so move */
-		return(3);
-	return(0); }
-if((ind=open(src,O_RDONLY|O_BINARY))==-1)
-	return(4);
-if((inp=fdopen(ind,"rb"))==NULL) {
-	close(ind);
-	return(5); }
-setvbuf(inp,NULL,_IOFBF,32*1024);
-if((outd=open(dest,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE|S_IREAD))==-1) {
-	fclose(inp);
-	return(6); }
-if((outp=fdopen(outd,"wb"))==NULL) {
-	close(outd);
-	fclose(inp);
-	return(7); }
-setvbuf(outp,NULL,_IOFBF,8*1024);
-length=filelength(ind);
-if(!length) {
-	fclose(inp);
-	fclose(outp);
-	return(8); }
-if((buf=(char *)MALLOC(MV_BUFLEN))==NULL) {
-	fclose(inp);
-	fclose(outp);
-	return(9); }
-l=0L;
-while(l<length) {
-	if(l+chunk>length)
-		chunk=length-l;
-	if(fread(buf,1,chunk,inp)!=chunk) {
-		FREE(buf);
-		fclose(inp);
-		fclose(outp);
-		return(10); }
-	if(fwrite(buf,1,chunk,outp)!=chunk) {
-		FREE(buf);
-		fclose(inp);
-		fclose(outp);
-		return(11); }
-	l+=chunk; }
-getftime(ind,&ftime);
-setftime(outd,&ftime);
-FREE(buf);
-fclose(inp);
-fclose(outp);
-if(!copy && remove(src))
-	return(12);
-return(0);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-
-int main(int argc, char **argv)
-{
-	char str[128],fname[128],path[128],tmp[128],*p;
-	int i,file;
-	FILE *index, *stream;
-	ulong number,crc;
-	user_t user;
-	ixb_t ixb;
-
-printf("\nADDPHOTO v1.01 - Synchronet Match Maker Photograph Addition\n\n");
-
-if(checktime()) {
-    printf("Time problem!\n");
-	exit(1); }
-
-if(argc<4) {
-	printf("usage: addphoto filename.ext user_number system_name\n");
-	exit(1); }
-
-strupr(argv[1]);
-if(!fexist(argv[1])) {
-	printf("%s doesn't exist\n",argv[1]);
-	exit(1); }
-
-if((file=open("SMM.DAB",O_RDWR|O_BINARY|O_DENYNONE|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	printf("\n\7Error opening/creating SMM.DAB\n");
-    exit(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	printf("\n\7Error converting SMM.DAB file handle to stream\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,4096);
-
-if((file=open("SMM.IXB",O_RDWR|O_BINARY|O_DENYNONE|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	printf("\n\7Error opening/creating SMM.IXB\n");
-    exit(1); }
-if((index=fdopen(file,"w+b"))==NULL) {
-	printf("\n\7Error converting SMM.IXB file handle to stream\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,1024);
-
-number=atol(argv[2]);
-str[0]=0;
-for(i=3;i<argc;i++) {
-	if(str[0])
-		strcat(str," ");
-	strcat(str,argv[i]); }
-
-strupr(str);
-str[25]=0;
-
-crc=crc32(str);
-rewind(index);
-i=0;
-while(!feof(index)) {
-	if(!fread(&ixb,sizeof(ixb_t),1,index))
-		break;
-	if(!ixb.number)    /* DELETED */
-		continue;
-	if(ixb.system!=crc || ixb.number!=number)
-		continue;
-	fseek(stream
-		,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-		*sizeof(user_t),SEEK_SET);
-	if(!fread(&user,sizeof(user_t),1,stream))
-		continue;
-	i=1;
-	break; }
-if(!i) {
-	printf("\7User #%lu @ %s not found!\n",number,str);
-	exit(2); }
-
-for(i=0;user.system[i];i++)
-	if(isalnum(user.system[i]))
-        break;
-if(!user.system[i])
-	fname[0]='~';
-else
-	fname[0]=user.system[i];
-for(i=strlen(user.system)-1;i>0;i--)
-	if(isalnum(user.system[i]))
-		break;
-if(i<=0)
-	fname[1]='~';
-else
-	fname[1]=user.system[i];
-fname[2]=0;
-strupr(user.system);
-strcat(fname,base41(crc16(user.system),tmp));
-strcat(fname,base41(user.number,tmp));
-p=strrchr(argv[1],'.');
-if(p)
-	strcat(fname,p);
-strupr(fname);
-mkdir("PHOTO");
-sprintf(path,"PHOTO\\%s",fname);
-if((i=mv(argv[1],path,1))!=0) {
-	printf("\7ERROR %d copying %s to %s\n",i,argv[1],path);
-	exit(3); }
-
-user.misc|=USER_PHOTO;
-user.updated=time(NULL);
-user.photo=0;
-fseek(stream
-	,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-	*sizeof(user_t),SEEK_SET);
-fwrite(&user,sizeof(user_t),1,stream);
-ixb.updated=user.updated;
-fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-fwrite(&ixb,sizeof(ixb_t),1,index);
-
-printf("%s added successfully!\n",argv[1]);
-return(0);
-}
-
diff --git a/src/sbbs2/smm/delphoto.c b/src/sbbs2/smm/delphoto.c
deleted file mode 100644
index 6934b2d96ecfb964e7d57923ad56b1b1ea3326ba..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/delphoto.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* DELPHOTO.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <io.h>
-#include <dos.h>
-#include <dir.h>
-#include <bios.h>
-#include <time.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <share.h>
-#include <conio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <malloc.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "gen_defs.h"
-#include "crc32.h"
-#include "smmdefs.h"
-
-extern int daylight=0;
-extern long timezone=0L;
-
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-
-int main(int argc, char **argv)
-{
-	char str[128],fname[128],path[128],tmp[128];
-	int i,file;
-	FILE *index, *stream;
-	ulong number,crc;
-	user_t user;
-	ixb_t ixb;
-	struct ffblk ff;
-
-printf("\nDELPHOTO v1.00 - Synchronet Match Maker Photograph Deletion\n\n");
-
-if(checktime()) {
-    printf("Time problem!\n");
-    exit(1); }
-
-if(argc<3) {
-	printf("usage: delphoto user_number system_name\n");
-	exit(1); }
-
-if((file=open("SMM.DAB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	printf("\n\7Error opening/creating SMM.DAB\n");
-    exit(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	printf("\n\7Error converting SMM.DAB file handle to stream\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,4096);
-
-if((file=open("SMM.IXB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	printf("\n\7Error opening/creating SMM.IXB\n");
-    exit(1); }
-if((index=fdopen(file,"w+b"))==NULL) {
-	printf("\n\7Error converting SMM.IXB file handle to stream\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,1024);
-
-number=atol(argv[1]);
-str[0]=0;
-for(i=2;i<argc;i++) {
-	if(str[0])
-		strcat(str," ");
-	strcat(str,argv[i]); }
-
-strupr(str);
-str[25]=0;
-
-crc=crc32(str);
-rewind(index);
-i=0;
-while(!feof(index)) {
-	if(!fread(&ixb,sizeof(ixb_t),1,index))
-		break;
-	if(!ixb.number)    /* DELETED */
-		continue;
-	if(ixb.system!=crc || ixb.number!=number)
-		continue;
-	fseek(stream
-		,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-		*sizeof(user_t),SEEK_SET);
-	if(!fread(&user,sizeof(user_t),1,stream))
-		continue;
-	i=1;
-	break; }
-if(!i) {
-	printf("\7User #%lu @ %s not found!\n",number,str);
-	exit(2); }
-
-if(!(user.misc&USER_PHOTO)) {
-	printf("\7User #%lu @ %s doesn't have a photo attached to their profile.\n"
-		,number,str);
-	exit(3); }
-
-for(i=0;user.system[i];i++)
-	if(isalnum(user.system[i]))
-        break;
-if(!user.system[i])
-	fname[0]='~';
-else
-	fname[0]=user.system[i];
-for(i=strlen(user.system)-1;i>0;i--)
-	if(isalnum(user.system[i]))
-		break;
-if(i<=0)
-	fname[1]='~';
-else
-	fname[1]=user.system[i];
-fname[2]=0;
-strupr(user.system);
-strcat(fname,base41(crc16(user.system),tmp));
-strcat(fname,base41(user.number,tmp));
-strcat(fname,".*");
-strupr(fname);
-sprintf(path,"PHOTO\\%s",fname);
-i=findfirst(path,&ff,0);
-if(i)
-	printf("\7%s doesn't exist!\n",path);
-else {
-	sprintf(path,"PHOTO\\%s",ff.ff_name);
-	if(remove(path))
-		printf("\7%s couldn't be removed!\n",path); }
-
-user.misc&=~USER_PHOTO;
-user.updated=time(NULL);
-user.photo=0;
-fseek(stream
-	,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-	*sizeof(user_t),SEEK_SET);
-fwrite(&user,sizeof(user_t),1,stream);
-ixb.updated=user.updated;
-fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-fwrite(&ixb,sizeof(ixb_t),1,index);
-
-printf("Photo removed successfully from database.\n");
-return(0);
-}
-
diff --git a/src/sbbs2/smm/lstphoto.c b/src/sbbs2/smm/lstphoto.c
deleted file mode 100644
index 3d5a4e908ea3efece8ac09cdb424e3501793c590..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/lstphoto.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* LSTPHOTO.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <io.h>
-#include <dos.h>
-#include <dir.h>
-#include <bios.h>
-#include <time.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <share.h>
-#include <conio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <malloc.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "gen_defs.h"
-#include "crc32.h"
-#include "smmdefs.h"
-
-extern int daylight=0;
-extern long timezone=0L;
-
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct time curtime;
-	struct date date;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-
-int main()
-{
-	char str[128],fname[128],tmp[128];
-	int i,file;
-	FILE *stream;
-	user_t user;
-
-printf("\nLSTPHOTO v1.00 - Synchronet Match Maker Photograph List\n\n");
-
-if(checktime()) {
-    printf("Time problem!\n");
-    exit(1); }
-
-if((file=open("SMM.DAB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	printf("\n\7Error opening/creating SMM.DAB\n");
-    exit(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	printf("\n\7Error converting SMM.DAB file handle to stream\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,4096);
-
-while(!feof(stream)) {
-	if(!fread(&user,sizeof(user_t),1,stream))
-		break;
-	if(!(user.misc&USER_PHOTO) || user.misc&USER_DELETED || !user.number)
-		continue;
-
-	printf("%-25.25s %5lu  %-25.25s %s  ",user.system,user.number,user.name
-		,unixtodstr(user.photo,tmp));
-	for(i=0;user.system[i];i++)
-		if(isalnum(user.system[i]))
-			break;
-	if(!user.system[i])
-		fname[0]='~';
-	else
-		fname[0]=user.system[i];
-	for(i=strlen(user.system)-1;i>0;i--)
-		if(isalnum(user.system[i]))
-			break;
-	if(i<=0)
-		fname[1]='~';
-	else
-		fname[1]=user.system[i];
-	fname[2]=0;
-	strupr(fname);
-	strupr(user.system);
-	strcat(fname,base41(crc16(user.system),tmp));
-	strcat(fname,base41(user.number,tmp));
-	printf("%s\n",fname); }
-
-return(0);
-}
-
diff --git a/src/sbbs2/smm/makefile b/src/sbbs2/smm/makefile
deleted file mode 100644
index af70052dfb57c2746ed40dec40a3d8a9e0bdc7d1..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Macros
-CC	= \bc31\bin\bcc
-LD	= \bc31\bin\tlink
-SDK	= ..\sdk
-MSWAIT	= ..\..\mswait\dos
-INCLUDE = \bc31\include;$(SDK);..\smb
-LIB     = \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -w-prot
-LFLAGS  = /n /c
-OBJS	= xsdk.obj xsdkvars.obj $(MSWAIT)\mswait$(MODEL).obj ..\DOS\rciol.obj
-HEADERS = $(SDK)\xsdk.h $(SDK)\xsdkdefs.h $(SDK)\xsdkvars.c smmdefs.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-smm.exe: $(OBJS) smm.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) smm.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-smm.obj: $(HEADERS)
-
-xsdk.obj: $(SDK)\xsdk.c $(HEADERS)
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c -w+pro $(SDK)\$*.c
-
-xsdkvars.obj: $(SDK)\xsdkvars.c $(SDK)\xsdkdefs.h
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c -w+pro $(SDK)\$*.c
diff --git a/src/sbbs2/smm/makeio.bat b/src/sbbs2/smm/makeio.bat
deleted file mode 100755
index 27cf74041635401a784cbbe809b59b906ad2bc73..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/makeio.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-bcc -w-pro -N -ml -C -n. -DSMB_GETMSGTXT -I..;..\smb smb2smm.c ..\smb\smblib.c ..\smb\lzh.c
-if errorlevel 1 goto end
-bcc -w-pro -N -ml -C -n. -I..;..\smb smm2smb.c ..\smb\smblib.c
-if errorlevel 1 goto end
-bcc -w-pro -N -ml -C -n. -I..;..\smb outphoto.c ..\smb\smblib.c
-:end
diff --git a/src/sbbs2/smm/makemsg.c b/src/sbbs2/smm/makemsg.c
deleted file mode 100644
index b2c00433944db55ee44a11e8d3acedbb4f50f5ad..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/makemsg.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* MAKEMSG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <dos.h>
-#include <stdio.h>
-#include <time.h>
-#include "gen_defs.h"
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	struct date date;
-	struct time curtime;
-
-if(!strcmp(str,"00/00/00") || !str[0])
-	return(NULL);
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-if(str[6]<'7')
-	date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
-else
-	date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
-date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
-return(dostounix(&date,&curtime));
-}
-
-uchar cryptchar(uchar ch, ulong seed)
-{
-if(ch==1)
-	return(0xfe);
-if(ch<0x20 || ch&0x80)	/* Ctrl chars and ex-ASCII are not xlated */
-	return(ch);
-return(ch^(seed&0x1f));
-}
-
-int main(int argc, char **argv)
-{
-	char str[256];
-	FILE *in,*out;
-	int i,j;
-	long l;
-
-if(argc<4) {
-	printf("usage: makemsg infile outfile mm/dd/yy\n");
-	exit(1); }
-
-if((in=fopen(argv[1],"rb"))==NULL) {
-	printf("error opening %s\n",argv[1]);
-	exit(1); }
-
-if((out=fopen(argv[2],"wb"))==NULL) {
-	printf("error opening %s\n",argv[2]);
-	exit(1); }
-
-l=dstrtounix(argv[3]);
-if(!l) {
-	printf("Invalid date %s\n",argv[3]);
-	exit(1); }
-fprintf(out,"%lx\r\n",l^0x305F6C81UL);
-i=ftell(out);
-while(!feof(in)) {
-	if(!fgets(str,128,in))
-		break;
-	for(j=0;str[j];j++,i++)
-		fputc(cryptchar(str[j],l^(i&7)),out); }
-return(0);
-}
diff --git a/src/sbbs2/smm/makephot.bat b/src/sbbs2/smm/makephot.bat
deleted file mode 100755
index 9b6388a531c1721b0e3ce4c59c90b2ad1561df9c..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/makephot.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-bcc -I..;..\smb -w-pro -N -C -ml addphoto.c
-if errorlevel 1 goto end
-bcc -I..;..\smb -w-pro -N -C -ml delphoto.c
-if errorlevel 1 goto end
-bcc -I..;..\smb -w-pro -N -C -ml lstphoto.c
-:end
diff --git a/src/sbbs2/smm/makeutil.bat b/src/sbbs2/smm/makeutil.bat
deleted file mode 100755
index 53649bc7fd0dfe6cf651b550dfeec84e34202899..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/makeutil.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -w-pro -ml -I..;..\smb smmutil.c
diff --git a/src/sbbs2/smm/outphoto.c b/src/sbbs2/smm/outphoto.c
deleted file mode 100644
index 56dd493eb15a8a78fbed510d06e7838020d0f268..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/outphoto.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* OUTPHOTO.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Scans SMM database and posts any photographs into the an SMB base */
-
-#define  uint unsigned int
-
-#include <dos.h>
-#include <share.h>
-#include "smblib.h"
-#include "smmdefs.h"
-#include "crc32.h"
-
-#define DAYS 15L			 // Hatch every 15 days
-
-smb_t smb;
-extern int daylight=0;
-extern long timezone=0L;
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-#define BUF_LEN 8192
-
-int main(int argc, char **argv)
-{
-	uchar	str[128],tmp[128],buf[BUF_LEN],fname[64],path[128],*p,ch;
-	int 	i,j,file,in,linelen,all=0;
-	ushort	xlat;
-	long	length,l;
-	ulong	offset,crc;
-	time_t	now;
-	struct	ffblk ff;
-	user_t	user;
-	smbmsg_t msg;
-	FILE	*stream;
-
-fprintf(stderr,"\nOUTPHOTO %s - Write SMM photos to SMB - Copyright 2002 "
-	"Rob Swindell\n\n",__DATE__);
-
-if(checktime()) {
-    printf("Time problem!\n");
-    return(-1); }
-
-if(argc<3) {
-	fprintf(stderr,"usage: outphoto <smm.dab> <smb_file>\n\n");
-	fprintf(stderr,"example: outphoto c:\\sbbs\\xtrn\\smm\\smm.dab "
-		"c:\\sbbs\\data\\subs\\syncdata\n");
-	return(1); }
-
-for(i=3;i<argc;i++)
-	if(!stricmp(argv[i],"/ALL"))
-		all=1;
-
-strcpy(smb.file,argv[2]);
-strupr(smb.file);
-
-strcpy(str,argv[1]);
-strupr(str);
-if((file=open(str,O_RDWR|O_BINARY|O_DENYNONE))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	printf("error fdopening %s\n",str);
-	return(1); }
-setvbuf(stream,NULL,_IOFBF,4096);
-
-sprintf(str,"%s.SHD",smb.file);
-if(!fexist(str)) {
-	printf("%s doesn't exist\n",smb.file);
-	return(0); }
-fprintf(stderr,"Opening %s\n",smb.file);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	printf("smb_open returned %d\n",i);
-	return(1); }
-
-now=time(NULL);
-while(!feof(stream)) {
-	if(!fread(&user,sizeof(user_t),1,stream))
-		break;
-
-	if(user.misc&(USER_DELETED|USER_FROMSMB) || !(user.misc&USER_PHOTO))
-		continue;
-
-	printf("Photo: %-25.25s  %.24s  "
-		,user.name,ctime(&user.photo));
-
-	if(user.photo && now-user.photo<DAYS*24L*60L*60L && !all) {
-		printf("skipping\n");
-		continue; }
-	printf("hatching\n");
-
-	for(i=0;user.system[i];i++)
-		if(isalnum(user.system[i]))
-			break;
-	if(!user.system[i])
-		fname[0]='~';
-	else
-		fname[0]=user.system[i];
-	for(i=strlen(user.system)-1;i>0;i--)
-		if(isalnum(user.system[i]))
-			break;
-	if(i<=0)
-		fname[1]='~';
-	else
-		fname[1]=user.system[i];
-	fname[2]=0;
-	strcpy(str,user.system);
-	strupr(str);
-	strcat(fname,base41(crc16(str),tmp));
-	strcat(fname,base41(user.number,tmp));
-	strcpy(path,argv[1]);
-	p=strchr(path,'\\');
-	if(p) *(p+1)=0;
-	else path[0]=0;
-	sprintf(str,"%sPHOTO\\%s.*",path,fname);
-	if(findfirst(str,&ff,0)) {
-		printf("%s doesn't exist!\n",str);
-		continue; }
-	strcpy(fname,ff.ff_name);
-	strcpy(path,argv[1]);
-	p=strchr(path,'\\');
-	if(p) *(p+1)=0;
-	else path[0]=0;
-	sprintf(str,"%sPHOTO\\%s",path,fname);
-
-	printf("Exporting %s",str);
-	if((in=open(str,O_RDONLY|O_BINARY|SH_DENYWR))==-1) {
-		printf("\nError opening %s\n",str);
-		continue; }
-
-	memset(buf,0,BUF_LEN);
-	crc=0xffffffffUL;
-	linelen=0;
-	sprintf(buf,"%lx\r\n",filelength(in)^4096);
-	l=strlen(buf);
-	while(l<(BUF_LEN-128)) {
-		if(!read(in,&ch,1))
-			break;
-		crc=ucrc32(ch,crc);
-		if(ch=='`') {
-			buf[l++]='`';
-			buf[l++]='`';
-			linelen++; }
-		else if(ch==0xff)
-			buf[l++]='\xee';
-		else if(ch<0xf)
-			buf[l++]=ch|0xf0;
-		else if(ch<0x20) {
-			buf[l++]='`';
-			buf[l++]=ch+'@';
-			linelen++; }
-		else if(ch>=0xf0) {
-			sprintf(str,"`%x",ch&0xf);
-			buf[l++]=str[0];
-			buf[l++]=str[1];
-			linelen++; }
-		else if(ch==0xe3) {
-			buf[l++]='`';
-			buf[l++]='g';
-			linelen++; }
-		else if(ch==0x8d) {
-			buf[l++]='`';
-			buf[l++]='h';
-			linelen++; }
-		else if(ch==0xee) {
-			buf[l++]='`';
-			buf[l++]='i';
-            linelen++; }
-		else
-			buf[l++]=ch;
-		linelen++;
-		if(linelen>=70) {
-			buf[l++]=CR;
-			buf[l++]=LF;
-			linelen=0; } }
-	buf[l]=0;
-	crc=~crc;
-	sprintf(str,"%lx\r\n--- OUTPHOTO %s",time(NULL),__DATE__);
-	strcat(buf,str);
-	printf("\n");
-
-	length=strlen(buf);   /* +2 for translation string */
-
-	if(smb.status.attr&SMB_HYPERALLOC)
-		offset=smb_hallocdat(&smb);
-	else {
-		i=smb_open_da(&smb);
-		if(i) {
-			printf("smb_open_da returned %d\n",i);
-			exit(1); }
-		offset=smb_allocdat(&smb,length+2,1);
-		fclose(smb.sda_fp); }
-
-	fseek(smb.sdt_fp,offset,SEEK_SET);
-	xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	fwrite(buf,length,1,smb.sdt_fp);
-	length+=2;
-
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=smb_ver();
-	msg.hdr.when_written.time=time(NULL);
-    
-	msg.hdr.offset=offset;
-
-	strcpy(str,"SMM PHOTO");
-	i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.to=crc16(str);
-
-	strcpy(str,"Digital Dynamics");
-	i=smb_hfield(&msg,SENDER,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.from=crc16(str);
-
-	sprintf(tmp,"%.25s",user.system);
-	strupr(tmp);
-	sprintf(str,"%04lx%08lx%08lx%.3s"
-		,user.number^0x191L,crc32(tmp)^0x90120e71L,crc^0x05296328L,fname+9);
-	i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.subj=crc16(str);
-
-	i=smb_dfield(&msg,TEXT_BODY,length);
-	if(i) {
-		printf("smb_dfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-
-	i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-	if(i) {
-		printf("smb_addmsghdr returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	smb_freemsgmem(&msg);
-	fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
-	user.photo=time(NULL);
-	fwrite(&user,sizeof(user_t),1,stream);
-	fseek(stream,ftell(stream),SEEK_SET); }
-return(0);
-}
-
diff --git a/src/sbbs2/smm/smb2smm.c b/src/sbbs2/smm/smb2smm.c
deleted file mode 100644
index de596dd12851e1c9ddebfb7716bd1f899a76d774..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smb2smm.c
+++ /dev/null
@@ -1,970 +0,0 @@
-/* SMB2SMM */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Scans SMB message base for messages to "SMM" and adds them to the SMM    */
-/* database. */
-
-#define  uint unsigned int
-
-#define LOOP_NOPEN 500
-
-#include <dos.h>
-#include "smblib.h"
-#include "smmdefs.h"
-#include "nodedefs.h"
-#include "crc32.h"
-
-#define VERSION "2.01"
-
-extern int daylight=0;
-extern long timezone=0L;
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-char data_dir[128];
-
-smb_t smb;
-FILE *trashfile=NULL;
-
-uchar cryptchar(uchar ch, ulong seed)
-{
-if(ch==0xfe)
-	return(1);
-if(ch<0x20 || ch&0x80)	/* Ctrl chars and ex-ASCII are not xlated */
-	return(ch);
-return(ch^(seed&0x1f));
-}
-
-void decrypt(char *str, ulong seed)
-{
-	char out[1024];
-	int i,j;
-
-j=strlen(str);
-for(i=0;i<j;i++)
-	out[i]=cryptchar(str[i],seed^(i&7));
-out[i]=0;
-strcpy(str,out);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-/***************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first CR  */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\r")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while(*str>' ' && (l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(f.ff_fsize);
-return(-1L);
-}
-
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	struct date date;
-	struct time curtime;
-
-if(!strncmp(str,"00/00/00",8))
-	return(0);
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-if(str[6]<'7')
-	date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
-else
-	date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
-date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
-return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns the age derived from the string 'birth' in the format MM/DD/YY	*/
-/****************************************************************************/
-char getage(char *birth)
-{
-	char age;
-	struct date date;
-
-if(birth[0]<=SP)
-	return(0);
-getdate(&date);
-age=(date.da_year-1900)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
-if(age>90)
-	age-=90;
-if(atoi(birth)>12 || atoi(birth+3)>31)
-	return(0);
-if(((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_mon ||
-	(((birth[0]&0xf)*10)+(birth[1]&0xf)==date.da_mon &&
-	((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_day))
-	age--;
-if(age<0)
-	return(0);
-return(age);
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access&O_DENYNONE) share=O_DENYNONE;
-else if(access==O_RDONLY) share=O_DENYWRITE;
-else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN)
-	if(count>10)
-	   delay(55);
-if(file==-1 && errno==EACCES)
-	puts("\7\nNOPEN: ACCESS DENIED\n\7");
-return(file);
-}
-
-
-/****************************************************************************/
-/* Creates a short message for 'usernumber' than contains 'strin'			*/
-/****************************************************************************/
-void putsmsg(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-	struct ffblk ff;
-    node_t node;
-
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("\7Error opening/creating %s for creat/append access\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-	close(file);
-	printf("\7Error writing %u bytes to %s\n",i,str);
-	return; }
-close(file);
-}
-
-void puttgram(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-	struct ffblk ff;
-    node_t node;
-
-sprintf(str,"%4.4u.MSG",usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("\7Error opening/creating %s for creat/append access\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-	close(file);
-	printf("\7Error writing %u bytes to %s\n",i,str);
-	return; }
-close(file);
-}
-
-int trash(char *instr)
-{
-	char str[1024],word[128];
-
-if(!trashfile)
-	return(0);
-strcpy(str,instr);
-strupr(str);
-rewind(trashfile);
-while(!ferror(trashfile)) {
-	if(!fgets(word,125,trashfile))
-		break;
-	truncsp(word);
-	if(!word[0])
-		continue;
-	strupr(word);
-	if(strstr(str,word))
-		return(1); }
-return(0);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-int main(int argc, char **argv)
-{
-	uchar	str[256],system[128],telegram[1024],HUGE16 *buf,HUGE16 *hp, *p
-			,min_age,fname[64],path[128],tmp[128],ch;
-	int 	i,j,file,out,wallfile,msgfile,tgramonly=0,wallonly=0,esc;
-	ulong	l,m,last,high,system_crc,crc,length;
-	ushort	smm,smm_photo,touser;
-	user_t	user;
-	wall_t	wall;
-	smbmsg_t msg;
-	FILE	*stream,*index,*tmpfile;
-	ixb_t	ixb;
-
-fprintf(stderr,"\nSMB2SMM v%s - Updates SMM via SMB - Developed 1995-1997 "
-	"Rob Swindell\n\n",VERSION);
-
-if(checktime()) {
-    printf("Time problem!\n");
-    return(-1); }
-
-if(argc<3) {
-	fprintf(stderr,"usage: smb2smm <smb_file> <smm.dab>\n\n");
-	fprintf(stderr,"example: smb2smm c:\\sbbs\\data\\subs\\syncdata "
-		"c:\\sbbs\\xtrn\\smm\\smm.dab\n");
-	return(1); }
-
-p=getenv("SBBSNODE");
-if(p==NULL) {
-	printf("\7\nSBBSNODE environment variable not set.\n");
-	exit(1); }
-strcpy(str,p);
-if(str[strlen(str)-1]!='\\')
-	strcat(str,"\\");
-strcat(str,"XTRN.DAT");
-if((file=nopen(str,O_RDONLY))==-1 || (stream=fdopen(file,"rb"))==NULL) {
-	printf("\7\nCan't open %s\n",str);
-	exit(1); }
-fgets(str,81,stream);		/* user name */
-fgets(system,81,stream);	/* system name */
-truncsp(system);
-fgets(str,81,stream);		/* sysop name */
-fgets(str,81,stream);		/* guru name */
-fgets(str,81,stream);		/* ctrl dir */
-fgets(str,81,stream);		/* data dir */
-truncsp(str);
-if(str[0]=='.') {
-	strcpy(data_dir,p); 	/* node dir */
-	if(data_dir[strlen(data_dir)-1]!='\\')
-		strcat(data_dir,"\\");
-	strcat(data_dir,str); }
-else
-	strcpy(data_dir,str);
-fclose(stream);
-
-if(argc>3 && !stricmp(argv[3],"/t"))
-	tgramonly=1;
-
-if(argc>3 && !stricmp(argv[3],"/w"))
-	wallonly=1;
-
-strcpy(smb.file,argv[1]);
-strupr(smb.file);
-
-strcpy(str,argv[2]);
-strupr(str);
-if((file=open(str,O_RDWR|O_BINARY|O_DENYNONE|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if((stream=fdopen(file,"r+b"))==NULL) {
-	printf("error fdopening %s\n",str);
-	return(1); }
-setvbuf(stream,NULL,_IOFBF,4096);
-
-p=strrchr(str,'.');
-if(!p) p=str;
-else p++;
-strcpy(p,"IXB");
-if((file=open(str,O_RDWR|O_BINARY|O_DENYNONE|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if((index=fdopen(file,"r+b"))==NULL) {
-	printf("error fdopening %s\n",str);
-	return(1); }
-setvbuf(index,NULL,_IOFBF,1024);
-
-p=strrchr(str,'.');
-if(!p) p=str;
-else p++;
-strcpy(p,"CAN");
-trashfile=NULL;
-if((file=open(str,O_RDONLY|O_DENYNONE))!=-1) {
-	trashfile=fdopen(file,"rb");
-	setvbuf(trashfile,NULL,_IOFBF,4096); }
-
-p=strrchr(str,'.');
-if(!p) p=str;
-else p++;
-strcpy(p,"CFG");
-if((file=nopen(str,O_RDONLY))==-1) {
-	printf("error opening %s\n",str);
-    return(1); }
-if((tmpfile=fdopen(file,"rb"))==NULL) {
-	printf("error fdopening %s\n",str);
-    return(1); }
-fgets(str,128,tmpfile); /* Min purity age */
-fgets(str,128,tmpfile); /* Min profile age */
-truncsp(str);
-min_age=atoi(str);
-fclose(tmpfile);
-
-sprintf(str,"%s.SMM",smb.file);
-if((file=open(str,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if(read(file,&last,4)!=4)
-	last=0;
-high=last;
-
-sprintf(str,"%s.SHD",smb.file);
-if(!fexist(str)) {
-	printf("%s doesn't exist\n",smb.file);
-	return(0); }
-sprintf(str,"%s.SID",smb.file);
-if(!flength(str)) {
-	printf("%s is empty\n",smb.file);
-    return(0); }
-fprintf(stderr,"Opening %s\n",smb.file);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	printf("smb_open returned %d\n",i);
-	return(1); }
-
-smm=crc16("smm");
-smm_photo=crc16("smm photo");
-
-if((i=smb_locksmbhdr(&smb))!=0) {				/* Be sure noone deletes or */
-	printf("Error locking %d\n",i);             /* adds while we're reading */
-	return(1); }
-
-rewind(smb.sid_fp);
-while(!feof(smb.sid_fp) && !ferror(smb.sid_fp)) {
-	if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-	fprintf(stderr,"\r#%-5lu  ",msg.idx.number);
-	if(msg.idx.to!=smm && msg.idx.to!=smm_photo)
-		continue;
-	if(msg.idx.number<=last || msg.idx.attr&MSG_DELETE)
-		continue;
-	high=msg.idx.number;
-	if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-		printf("\7Error %d locking msg #%lu\n",i,msg.idx.number);
-		continue; }
-	if((i=smb_getmsghdr(&smb,&msg))!=0) {
-		smb_unlockmsghdr(&smb,&msg);
-		printf("\7Error %d reading msg #%lu\n",i,msg.idx.number);
-		continue; }
-
-	smb_unlockmsghdr(&smb,&msg);
-	if(!msg.from_net.type || !strnicmp(msg.from,system,25)) { // ignore local msg
-		smb_freemsgmem(&msg);
-		continue; }
-
-	printf("From: %-25.25s  To: %-25.25s  Subj: %s\n"
-		,msg.from,msg.to,msg.subj);
-
-	if(msg.idx.to==smm_photo) {
-		buf=smb_getmsgtxt(&smb,&msg,0);
-		if(!buf) {
-			smb_freemsgmem(&msg);
-			continue; }
-		sprintf(str,"%.4s",msg.subj);
-		l=ahtoul(str);
-		l^=0x0191;
-		sprintf(str,"%.8s",msg.subj+4);
-		system_crc=ahtoul(str);
-		system_crc^=0x90120e71;
-		fprintf(stderr,"Searching...");
-
-		rewind(index);
-		memset(&user,0,sizeof(user_t));
-		while(1) {
-			if(!fread(&ixb,sizeof(ixb_t),1,index)) {
-				memset(&user,0,sizeof(user_t));
-				break; }
-			if(ixb.number==l && ixb.system==system_crc) {
-				fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-				fseek(stream,(ftell(index)/sizeof(ixb_t))*sizeof(user_t)
-					,SEEK_SET);
-				fread(&user,sizeof(user_t),1,stream);
-				break; } }
-		fprintf(stderr,"\n");
-
-		if(!user.number) {
-			printf("Profile Not found\n");
-			smb_freemsgmem(&msg);
-			continue; }
-
-		for(i=0;user.system[i];i++)
-			if(isalnum(user.system[i]))
-				break;
-		if(!user.system[i])
-			fname[0]='~';
-		else
-			fname[0]=user.system[i];
-		for(i=strlen(user.system)-1;i>0;i--)
-			if(isalnum(user.system[i]))
-				break;
-		if(i<=0)
-			fname[1]='~';
-		else
-			fname[1]=user.system[i];
-		fname[2]=0;
-		strcpy(str,user.system);
-        strupr(str);
-		strcat(fname,base41(crc16(str),tmp));
-		strcat(fname,base41(user.number,tmp));
-		sprintf(str,".%.3s",msg.subj+20);
-		strcat(fname,str);
-		strupr(fname);
-
-		if((out=nopen(fname,O_CREAT|O_WRONLY|O_TRUNC))==-1) {
-			printf("Error opening %s\n",fname);
-			smb_freemsgmem(&msg);
-			continue; }
-		
-		crc=0xffffffffUL;
-		esc=0;
-		for(l=0;buf[l]!=CR;l++)
-			;
-		buf[l]=0;
-		length=ahtoul((char *)buf)^4096;
-		l+=2;	/* Skip CRLF */
-		for(m=0;buf[l] && m<length;l++) {
-			ch=buf[l];
-			if(ch<SP)
-				continue;
-			if(ch=='`') {
-				if(esc) {
-					write(out,&ch,1);
-					m++;
-					crc=ucrc32(ch,crc);
-					esc=0; }
-				else
-					esc=1;
-				continue; }
-			if(esc) {
-				if(isalpha(ch)) {
-					if(isupper(ch))
-						ch-='@';
-					else if(ch=='g')
-						ch=0xe3;
-					else if(ch=='h')
-						ch=0x8d;
-					else if(ch=='i')
-						ch=0xee;
-					else
-						ch=0xfa+(ch-'a'); }
-				else
-					ch=0xf0+(ch-'0');
-				write(out,&ch,1);
-				m++;
-				crc=ucrc32(ch,crc);
-				esc=0;
-				continue; }
-			if(ch>=0xf0)
-				ch&=0xf;
-			if(ch==0xee)
-				ch=0xff;
-			write(out,&ch,1);
-			m++;
-			crc=ucrc32(ch,crc); }
-		close(out);
-		crc=~crc;
-		crc^=0x05296328L;
-		sprintf(str,"%.8s",msg.subj+12);
-		smb_freemsgmem(&msg);
-		if(crc!=ahtoul(str)) {
-			printf("CRC error!\n");
-			remove(fname);
-			continue; }
-		sprintf(path,"PHOTO\\%s",fname);
-        mkdir("PHOTO");
-		if(rename(fname,path)) {
-			printf("Error renaming %s to %s!\n",fname,path);
-			remove(fname);
-			continue; }
-		user.misc|=USER_PHOTO;
-		fseek(stream,(ftell(index)/sizeof(ixb_t))*sizeof(user_t),SEEK_SET);
-		fwrite(&user,sizeof(user_t),1,stream);
-		if(!strnicmp(user.system,system,25))
-			putsmsg(user.number
-				,"\1n\1h\1mYour photo has been imported into "
-					"\1wMatch Maker\1n\7\r\n");
-		continue; }
-
-	if(!stricmp(msg.subj,"->WALL<-")) {
-		buf=smb_getmsgtxt(&smb,&msg,0);
-		smb_freemsgmem(&msg);
-		if(!buf)
-			continue;
-		memset(&wall,0,sizeof(wall_t));
-		hp=buf;
-		while(*hp && *hp<SP) hp++;
-		for(i=0;*hp>=SP && i<25;i++,hp++)
-			wall.name[i]=*hp;
-		wall.name[i]=0;
-		hp+=2;	 /* Skip CRLF */
-		for(i=0;*hp>=SP && i<40;i++,hp++)
-			wall.system[i]=*hp;
-		wall.system[i]=0;
-		hp+=2;	 /* Skip CRLF */
-		for(i=0;i<5;i++) {
-			for(j=0;*hp>=SP && j<70;j++,hp++)
-				wall.text[i][j]=*hp;
-			wall.text[i][j]=0;
-			hp+=2; }
-
-		wall.written=ahtoul((char *)hp);
-		wall.imported=time(NULL);
-		FREE((char *)buf);
-		decrypt(wall.name,wall.written);
-		decrypt(wall.system,wall.written);
-		for(i=0;i<5;i++) {
-			decrypt(wall.text[i],wall.written);
-			if(trash(wall.text[i])) {
-				printf("Rejected: Wall writing found in trash!\n");
-				break; } }
-		if(i<5)
-			continue;
-		if((wallfile=sopen("WALL.DAB",O_WRONLY|O_BINARY|O_CREAT,SH_DENYNO
-			,S_IWRITE|S_IREAD))==-1) {
-			printf("Couldn't open WALL.DAB!\n");
-			continue; }
-		lseek(wallfile,0L,SEEK_END);
-		write(wallfile,&wall,sizeof(wall_t));
-		close(wallfile);
-		continue; }
-
-	if(wallonly) {
-		smb_freemsgmem(&msg);
-		continue; }
-
-	if(!stricmp(msg.subj,"->ALL<-")
-		|| !stricmp(msg.subj,"->SYS<-")
-		|| !stricmp(msg.subj,"->ONE<-")) {
-		sprintf(str,"%.3s%05lu.MSG",msg.subj+2,msg.idx.number);
-		buf=smb_getmsgtxt(&smb,&msg,0);
-		smb_freemsgmem(&msg);
-		if(!buf)
-            continue;
-		l=ahtoul((char *)buf);
-		if(!l)
-            continue;
-		for(i=0;buf[i];i++)
-            if(buf[i]==LF)
-                break;
-        if(buf[i]!=LF)
-            continue;
-		if((msgfile=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-			printf("error opening %s\n",str);
-			continue; }
-		if((tmpfile=fdopen(msgfile,"wb"))==NULL) {
-			close(msgfile);
-			printf("error fdopening %s\n",str);
-			continue; }
-		fprintf(tmpfile,"%08lx\r\n",l);
-		l^=0x305F6C81UL;
-		for(i++;buf[i];i++)
-			fputc(cryptchar(buf[i],l^(i&7)),tmpfile);
-		fclose(tmpfile);
-		putsmsg(1,"\1n\1h\1mNew announcement in \1wMatch Maker\1n\7\r\n");
-		continue; }
-
-
-	j=strlen(msg.subj);
-	for(i=0;i<j;i++)
-		if(!isdigit(msg.subj[i]))
-			break;
-	if(i<j) {				/* at least one non-digit, must be telegram */
-		if(strnicmp(msg.subj,system,25)) {
-			smb_freemsgmem(&msg);
-			continue; }
-		buf=smb_getmsgtxt(&smb,&msg,0);
-		smb_freemsgmem(&msg);
-		if(!buf)
-			continue;
-		l=0;
-		while(buf[l] && buf[l]!='}')         /* Find first text on line */
-			l++;
-		if(!buf[l] || !buf[++l]) {
-			FREE(buf);
-			continue; }
-		touser=ahtoul((char *)buf+l);
-		while(buf[l] && buf[l]>=SP) 	/* Go to end of line */
-			l++;
-		while(buf[l] && buf[l]<=SP) 	/* next line */
-			l++;
-		i=0;
-		while(buf[l]) {
-			if(buf[l]==LF && buf[l+1]==CR) { /* blank line */
-				telegram[i++]=LF;
-				break; }
-			telegram[i++]=buf[l++]; }
-		telegram[i]=0;
-		decrypt(telegram,touser);
-		printf("Telegram to %u\n",touser);
-		if(trash(telegram))
-			printf("Rejected: Contents in trash!\n");
-		else {
-			putsmsg(touser,TGRAM_NOTICE);
-			puttgram(touser,telegram); }
-		FREE(buf);
-		continue;
-		}
-
-	if(tgramonly) {
-		smb_freemsgmem(&msg);
-		continue; }
-
-	if(!msg.from[0]) {
-		smb_freemsgmem(&msg);
-		printf("Blank 'from' field.\n");
-        continue; }
-
-	l=atol(msg.subj);
-	if(!l || l>65535L) {
-		smb_freemsgmem(&msg);
-		printf("Invalid profile.\n");
-		continue; }
-	fprintf(stderr,"Searching for %lu @ %s",l,msg.from);
-	sprintf(str,"%.25s",msg.from);
-	strupr(str);
-	system_crc=crc32(str);
-
-	rewind(index);
-	memset(&user,0,sizeof(user_t));
-	while(1) {
-		if(!fread(&ixb,sizeof(ixb_t),1,index)) {
-			memset(&user,0,sizeof(user_t));
-			break; }
-		if(ixb.number==l && ixb.system==system_crc) {
-			fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-			fseek(stream,(ftell(index)/sizeof(ixb_t))*sizeof(user_t),SEEK_SET);
-			fread(&user,sizeof(user_t),1,stream);
-			if(!(user.misc&USER_FROMSMB)) {
-				memset(&user,0,sizeof(user_t));
-				fread(&ixb,sizeof(ixb_t),1,index);
-				continue; }
-			break; } }
-	fprintf(stderr,"\n");
-
-	if(!user.number) {
-		fprintf(stderr,"Searching for unused record...");
-		rewind(index);
-		while(1) {					/* Find deleted record */
-			if(!fread(&ixb,sizeof(ixb_t),1,index))
-				break;
-			if(ixb.number==0) {
-				fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-				break; } }
-		user.created=time(NULL);
-		user.number=l;
-		sprintf(user.system,"%-.40s",msg.from);
-		fprintf(stderr,"\n"); }
-
-	fseek(stream,(ftell(index)/sizeof(ixb_t))*sizeof(user_t),SEEK_SET);
-	user.updated=time(NULL);
-	user.misc|=USER_FROMSMB;
-	buf=smb_getmsgtxt(&smb,&msg,0);
-	l=0;
-	while(buf[l]) {
-		while(buf[l] && buf[l]<=SP) 		/* Find first text on line */
-			l++;
-		if(!strnicmp((char *)buf+l,"0:",2)) {
-			l+=2;
-			sprintf(user.name,"%-.25s",(char *)buf+l);
-			truncsp(user.name);
-			decrypt(user.name,user.number); }
-		if(!strnicmp((char *)buf+l,"1:",2)) {
-			l+=2;
-			sprintf(user.realname,"%-.25s",(char *)buf+l);
-			truncsp(user.realname);
-			decrypt(user.realname,user.number); }
-		if(!strnicmp((char *)buf+l,"2:",2)) {
-			l+=2;
-			sprintf(user.birth,"%-.8s",(char *)buf+l);
-			decrypt(user.birth,user.number); }
-		if(!strnicmp((char *)buf+l,"3:",2)) {
-			l+=2;
-			sprintf(user.location,"%-.30s",(char *)buf+l);
-			truncsp(user.location);
-			decrypt(user.location,user.number); }
-		if(!strnicmp((char *)buf+l,"4:",2)) {
-            l+=2;
-			sprintf(user.zipcode,"%-.10s",(char *)buf+l);
-            truncsp(user.zipcode);
-			decrypt(user.zipcode,user.number); }
-		if(!strnicmp((char *)buf+l,"5:",2)) {
-			l+=2;
-			sprintf(user.min_zipcode,"%-.10s",(char *)buf+l);
-			truncsp(user.min_zipcode);
-			decrypt(user.min_zipcode,user.number); }
-		if(!strnicmp((char *)buf+l,"6:",2)) {
-			l+=2;
-			sprintf(user.max_zipcode,"%-.10s",(char *)buf+l);
-			truncsp(user.max_zipcode);
-			decrypt(user.max_zipcode,user.number); }
-		if(!strnicmp((char *)buf+l,"7:",2)) {
-			l+=2;
-			sprintf(user.mbtype,"%-.4s",(char *)buf+l);
-			truncsp(user.mbtype);
-			decrypt(user.mbtype,user.number); }
-
-		if(!strnicmp((char *)buf+l,"A:",2)) {
-			l+=2;
-			sprintf(user.note[0],"%-.50s",(char *)buf+l);
-			truncsp(user.note[0]);
-			decrypt(user.note[0],user.number); }
-		if(!strnicmp((char *)buf+l,"B:",2)) {
-			l+=2;
-			sprintf(user.note[1],"%-.50s",(char *)buf+l);
-			truncsp(user.note[1]);
-			decrypt(user.note[1],user.number); }
-		if(!strnicmp((char *)buf+l,"C:",2)) {
-			l+=2;
-			sprintf(user.note[2],"%-.50s",(char *)buf+l);
-			truncsp(user.note[2]);
-			decrypt(user.note[2],user.number); }
-		if(!strnicmp((char *)buf+l,"D:",2)) {
-			l+=2;
-			sprintf(user.note[3],"%-.50s",(char *)buf+l);
-			truncsp(user.note[3]);
-			decrypt(user.note[3],user.number); }
-		if(!strnicmp((char *)buf+l,"E:",2)) {
-			l+=2;
-			sprintf(user.note[4],"%-.50s",(char *)buf+l);
-			truncsp(user.note[4]);
-			decrypt(user.note[4],user.number); }
-
-		if(!strnicmp((char *)buf+l,"F:",2)) {
-			l+=2;
-			user.sex=buf[l];
-			user.pref_sex=buf[l+1]; }
-
-		if(!strnicmp((char *)buf+l,"G:",2)) {
-			l+=2;
-			user.marital=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"H:",2)) {
-			l+=2;
-			user.pref_marital=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"I:",2)) {
-			l+=2;
-			user.race=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"J:",2)) {
-			l+=2;
-			user.pref_race=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"K:",2)) {
-			l+=2;
-			user.hair=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"L:",2)) {
-			l+=2;
-			user.pref_hair=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"M:",2)) {
-			l+=2;
-			user.eyes=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"N:",2)) {
-			l+=2;
-			user.pref_eyes=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"O:",2)) {
-			l+=2;
-			user.weight=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"P:",2)) {
-			l+=2;
-			user.min_weight=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"Q:",2)) {
-			l+=2;
-			user.max_weight=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"R:",2)) {
-			l+=2;
-			user.height=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"S:",2)) {
-			l+=2;
-			user.min_height=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"T:",2)) {
-			l+=2;
-			user.max_height=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"U:",2)) {
-			l+=2;
-			user.min_age=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"V:",2)) {
-			l+=2;
-			user.max_age=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"W:",2)) {
-			l+=2;
-			user.purity=ahtoul((char *)buf+l); }
-
-		if(!strnicmp((char *)buf+l,"X:",2)) {
-			l+=2;
-			user.income=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"Y:",2)) {
-			l+=2;
-			user.min_income=ahtoul((char *)buf+l); }
-		if(!strnicmp((char *)buf+l,"Z:",2)) {
-			l+=2;
-			user.max_income=ahtoul((char *)buf+l); }
-
-		if(toupper(buf[l])=='*' && isdigit(buf[l+1])) {  /* Questionnaires */
-			i=buf[l+1]-'0';
-			l+=2;
-			sprintf(user.queans[i].name,"%-.8s",(char *)buf+l);
-			truncsp(user.queans[i].name);
-			decrypt(user.queans[i].name,user.number);
-			while(buf[l] && buf[l]>=SP) l++;	/* Go to end of line */
-			for(j=0;j<20;j++) {
-				while(buf[l] && buf[l]<=SP) l++;
-				user.queans[i].self[j]=ahtoul((char *)buf+l);
-				l+=5;
-				user.queans[i].pref[j]=ahtoul((char *)buf+l);
-				l+=5; } }
-
-		while(buf[l] && buf[l]>=SP) 	/* Go to end of line */
-			l++; }
-
-	if(getage(user.birth)<min_age)		/* Too young */
-		printf("Rejected: User's age (%u) less than minimum age (%u)\n"
-			,getage(user.birth),min_age);
-	else if(user.name[0]<SP || user.realname[0]<SP || user.system[0]<SP
-		|| user.location[0]<SP || user.zipcode[0]<SP || user.birth[0]<SP)
-		printf("Rejected: Invalid user string\n");
-	else if(trash(user.name))
-		printf("Rejected: User's name (%s) in trash!\n",user.name);
-	else if(trash(user.location))
-		printf("Rejected: User's location (%s) in trash!\n",user.location);
-	else if(trash(user.note[0]) || trash(user.note[1]) || trash(user.note[2])
-		|| trash(user.note[3]) || trash(user.note[4]))
-		printf("Rejected: User's personal text in trash!\n");
-	else {
-		fwrite(&user,sizeof(user_t),1,stream);
-		strupr(user.name);
-		ixb.name=crc32(user.name);
-		strupr(user.system);
-		user.system[25]=0;
-		ixb.system=crc32(user.system);
-		ixb.number=user.number;
-		ixb.updated=user.updated;
-		fwrite(&ixb,sizeof(ixb_t),1,index); }
-	FREE((char *)buf);
-	smb_freemsgmem(&msg);
-	}
-
-lseek(file,0L,SEEK_SET);
-write(file,&high,4);
-close(file);
-return(0);
-}
-
diff --git a/src/sbbs2/smm/smm.c b/src/sbbs2/smm/smm.c
deleted file mode 100644
index d71d05826691f6b6268664d0f8c18317f4a9c590..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smm.c
+++ /dev/null
@@ -1,3993 +0,0 @@
-/* SMM.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet Match Maker */
-
-#include "xsdk.h"
-#include "crc32.h"
-#include "smmdefs.h"
-#include "smmvars.c"
-
-/* RCIOLL.ASM */
-
-int  rioini(int com,int irq);          /* initialize com,irq */
-int  setbaud(int rate);                /* set baud rate */
-int  rioctl(int action);               /* remote i/o control */
-int  dtr(char onoff);                  /* set/reset dtr */
-int  outcom(int ch);                   /* send character */
-int  incom(void);                      /* receive character */
-int  ivhctl(int intcode);              /* local i/o redirection */
-
-/************************/
-/* Remote I/O Constants */
-/************************/
-
-							/* i/o mode and state flags */
-#define CTSCK 0x1000     	/* check cts (mode only) */
-#define RTSCK 0x2000		/* check rts (mode only) */
-#define TXBOF 0x0800		/* transmit buffer overflow (outcom only) */
-#define ABORT 0x0400     	/* check for ^C (mode), aborting (state) */
-#define PAUSE 0x0200     	/* check for ^S (mode), pausing (state) */
-#define NOINP 0x0100     	/* input buffer empty (incom only) */
-
-							/* status flags */
-#define RIODCD	0x80		/* DCD on */
-#define RI		0x40		/* Ring indicate */
-#define DSR 	0x20		/* Dataset ready */
-#define CTS 	0x10       	/* CTS on */
-#define FERR 	0x08		/* Frameing error */
-#define PERR 	0x04		/* Parity error */
-#define OVRR 	0x02		/* Overrun */
-#define RXLOST 	0x01       	/* Receive buffer overflow */
-
-/* rioctl() arguments */
-/* returns mode or state flags in high 8 bits, status flags in low 8 bits */
-
-							/* the following return mode in high 8 bits */
-#define IOMODE 0        	/* no operation */
-#define IOSM 1          	/* i/o set mode flags */
-#define IOCM 2          	/* i/o clear mode flags */
-							/* the following return state in high 8 bits */
-#define IOSTATE 4       	/* no operation */
-#define IOSS 5          	/* i/o set state flags */
-#define IOCS 6          	/* i/o clear state flags */
-#define IOFB 0x308      	/* i/o buffer flush */
-#define IOFI 0x208      	/* input buffer flush */
-#define IOFO 0x108      	/* output buffer flush */
-#define IOCE 9          	/* i/o clear error flags */
-
-							/* return count (16bit)	*/
-#define RXBC	0x0a		/* get receive buffer count */
-#define TXBC	0x0b		/* get transmit buffer count */
-#define TXSYNC  0x0c        /* sync transmition (seconds<<8|0x0c) */
-#define IDLE	0x0d		/* suspend communication routines */
-#define RESUME  0x10d		/* return from suspended state */
-#define RLERC	0x000e		/* read line error count and clear */
-#define CPTON	0x0110		/* set input translation flag for ctrl-p on */
-#define CPTOFF	0x0010		/* set input translation flag for ctrl-p off */
-#define GETCPT	0x8010		/* return the status of ctrl-p translation */
-#define MSR 	0x0011		/* read modem status register */
-#define FIFOCTL 0x0012		/* FIFO UART control */
-#define TSTYPE	0x0013		/* Time-slice API type */
-#define GETTST  0x8013      /* Get Time-slice API type */
-
-
-#define I14DB	0x001d		/* DigiBoard int 14h driver */
-#define I14PC	0x011d		/* PC int 14h driver */
-#define I14PS	0x021d		/* PS/2 int 14h driver */
-#define I14FO   0x031d      /* FOSSIL int 14h driver */
-
-
-							/* ivhctl() arguments */
-#define INT29R 1         	/* copy int 29h output to remote */
-#define INT29L 2			/* Use _putlc for int 29h */
-#define INT16  0x10      	/* return remote chars to int 16h calls */
-#define INTCLR 0            /* release int 16h, int 29h */
-
-#define CLREOL		256 	/* Character to erase to end of line		*/
-#define HIGH        8       /* High intensity for curatr             */
-
-extern uint riobp;
-extern int mswtyp;
-
-unsigned _stklen=16000; 	/* Set stack size in code, not header */
-
-int cbreakh(void);			/* ctrl-break handler */
-
-char getage(char *birth);
-char long_user_info(user_t user);
-void main_user_info(user_t user);
-
-char *nulstr="";
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-char tmp[256],door_sys[128];
-
-char io_int=0;
-struct date date;
-struct time curtime;
-time_t now;
-int smm_pause=1,node_scrnlen;
-questionnaire_t *que[5];
-int total_ques;
-user_t useron,tmpuser;
-ixb_t ixb;
-ulong useron_record,system_crc;
-FILE *stream,*index,*trashfile;
-
-char *PrevReadSendQuitOrMore="\r\n\1n\1b\1h[\1cP\1b]revious screen, "
-	"[\1cR\1b]ead profile, [\1cS\1b]end telegram, [\1cQ\1b]uit, or "
-	"[\1cM\1b]ore: \1w";
-
-int intocm(int in)
-{
-return(in*2.538071);
-}
-
-int cmtoin(int cm)
-{
-	int i;
-
-i=cm*0.394;
-if(((float)cm*0.394)-(float)i>=.5)
-	i++;
-return(i);
-}
-
-int kgtolp(int kg)
-{
-return(kg*2.2046);
-}
-
-int lptokg(int lp)
-{
-	int i;
-
-i=lp*0.453597;
-if(((float)lp*0.453597)-(float)i>=.5)
-	i++;
-return(i);
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...) {
-	char sbuf[256];
-	int chcount;
-
-chcount=vsprintf(sbuf,fmat,_va_ptr);
-lputs(sbuf);
-return(chcount);
-}
-
-/*****************************************************************************/
-/* Returns command line generated from instr with %c replacments             */
-/*****************************************************************************/
-char *cmdstr(char *instr, char *fpath, char *fspec, char *outstr)
-{
-	static char static_cmd[128];
-	char str[256],str2[128],*cmd;
-    int i,j,len;
-
-if(outstr==NULL)
-	cmd=static_cmd;
-else
-	cmd=outstr;
-len=strlen(instr);
-for(i=j=0;i<len && j<128;i++) {
-    if(instr[i]=='%') {
-        i++;
-        cmd[j]=0;
-        switch(toupper(instr[i])) {
-            case 'A':   /* User alias */
-				strcat(cmd,user_name);
-                break;
-            case 'B':   /* Baud (DTE) Rate */
-				strcat(cmd,ultoa(com_rate,str,10));
-                break;
-            case 'C':   /* Connect Description */
-				strcat(cmd,ultoa(user_dce,str,10));
-                break;
-            case 'F':   /* File path */
-                strcat(cmd,fpath);
-                break;
-            case 'G':   /* Temp directory */
-				strcat(cmd,temp_dir);
-                break;
-            case 'I':   /* UART IRQ Line */
-                strcat(cmd,itoa(com_irq,str,10));
-                break;
-            case 'J':
-				strcat(cmd,data_dir);
-                break;
-            case 'K':
-				strcat(cmd,ctrl_dir);
-                break;
-            case 'N':   /* Node Directory (same as SBBSNODE environment var) */
-                strcat(cmd,node_dir);
-                break;
-            case 'O':   /* SysOp */
-                strcat(cmd,sys_op);
-                break;
-            case 'P':   /* COM Port */
-				strcat(cmd,itoa(com_port,str,10));
-                break;
-            case 'Q':   /* QWK ID */
-                strcat(cmd,sys_id);
-                break;
-            case 'R':   /* Rows */
-				strcat(cmd,itoa(user_rows,str,10));
-                break;
-            case 'S':   /* File Spec */
-                strcat(cmd,fspec);
-                break;
-            case 'T':   /* Time left in seconds */
-				strcat(cmd,itoa(time(NULL)-starttime,str,10));
-                break;
-            case 'U':   /* UART I/O Address (in hex) */
-                strcat(cmd,itoa(com_base,str,16));
-                break;
-            case 'W':   /* Time-slice API type (mswtype) */
-#ifndef __OS2__
-                strcat(cmd,itoa(mswtyp,str,10));
-#endif
-                break;
-            case '&':   /* Address of msr */
-				sprintf(str,"%lu",&riobp-1);
-                strcat(cmd,str);
-                break;
-			case 'Z':
-				strcat(cmd,text_dir);
-                break;
-            case '!':   /* EXEC Directory */
-				strcat(cmd,exec_dir);
-                break;
-            case '#':   /* Node number (same as SBBSNNUM environment var) */
-                sprintf(str,"%d",node_num);
-                strcat(cmd,str);
-                break;
-            case '*':
-                sprintf(str,"%03d",node_num);
-                strcat(cmd,str);
-                break;
-            case '$':   /* Credits */
-				strcat(cmd,ultoa(user_cdt,str,10));
-                break;
-            case '%':   /* %% for percent sign */
-                strcat(cmd,"%");
-                break;
-            default:    /* unknown specification */
-                if(isdigit(instr[i])) {
-					sprintf(str,"%0*d",instr[i]&0xf,user_number);
-                    strcat(cmd,str); }
-                break; }
-        j=strlen(cmd); }
-    else
-        cmd[j++]=instr[i]; }
-cmd[j]=0;
-
-return(cmd);
-}
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-int cdt_warning(long cdt)
-{
-if(cdt==0)
-	return(1);
-if(cdt>0) {
-	bprintf("\1m\1hYou will receive \1w%luk\1m in credits for this action!\r\n"
-		,cdt/1024L);
-	return(1); }
-
-bprintf("\1m\1hThis action will cost you \1w%luk\1m in credits.",(-cdt)/1024L);
-if(user_cdt+cdt_adjustment<-cdt) {
-	bprintf("\r\n\r\n\1r\1hSorry, you only have \1w%luk\1m in credits.\r\n"
-		,(user_cdt+cdt_adjustment)/1024L);
-	return(0); }
-return(!noyes(" Continue"));
-}
-
-void adjust_cdt(long cdt)
-{
-if(cdt==0)
-	return;
-cdt_adjustment+=cdt;
-}
-
-int got_flags(char *req, char *got)
-{
-	int i,j;
-
-for(i=0;req[i];i++) {
-	for(j=0;got[j];j++)
-		if(req[i]==got[j])
-			break;
-	if(!got[j])
-		break; }
-if(!req[i])
-	return(1);
-return(0);
-}
-
-int can_add()
-{
-	uchar age=getage(user_birth);
-
-if(user_level<min_level || (age && getage(user_birth)<min_age)
-	|| !got_flags(req_flags1,user_flags1)
-	|| !got_flags(req_flags2,user_flags2)
-	|| !got_flags(req_flags3,user_flags3)
-	|| !got_flags(req_flags4,user_flags4)
-	)
-	return(0);
-return(1);
-}
-
-
-int trash(char *instr)
-{
-	char str[128],word[128];
-
-if(!trashfile)
-	return(0);
-strcpy(str,instr);
-strupr(str);
-rewind(trashfile);
-while(!ferror(trashfile)) {
-	if(!fgets(word,125,trashfile))
-		break;
-	truncsp(word);
-	if(!word[0])
-		continue;
-	strupr(word);
-	if(strstr(str,word))
-		return(1); }
-return(0);
-}
-
-long fdate_dir(char *filespec)
-{
-    struct ffblk f;
-    struct date fd;
-    struct time ft;
-
-if(findfirst(filespec,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC)==NULL) {
-	fd.da_day=f.ff_fdate&0x1f;
-	fd.da_mon=(f.ff_fdate>>5)&0xf;
-	fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
-	ft.ti_hour=(f.ff_ftime>>11)&0x1f;
-	ft.ti_min=(f.ff_ftime>>5)&0x3f;
-	ft.ti_sec=(f.ff_ftime&0xf)*2;
-    return(dostounix(&fd,&ft)); }
-else return(NULL);
-}
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()                                        */
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-    static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-gm=localtime(intime);
-if(gm->tm_hour>=12) {
-    if(gm->tm_hour==12)
-        hour=12;
-    else
-        hour=gm->tm_hour-12;
-    strcpy(mer,"pm"); }
-else {
-    if(gm->tm_hour==0)
-        hour=12;
-    else
-        hour=gm->tm_hour;
-    strcpy(mer,"am"); }
-sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-    ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-    ,hour,gm->tm_min,mer);
-return(str);
-}
-
-
-void puttgram(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-
-sprintf(str,"%4.4u.MSG",usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("\7Error opening/creating %s for creat/append access\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
-	close(file);
-	printf("\7Error writing %u bytes to %s\n",i,str);
-	return; }
-close(file);
-}
-
-
-int send_telegram(user_t user)
-{
-	uchar str[256],line[256],buf[1024];
-	int i;
-
-if(!useron.number) {
-	bputs("\r\n\1h\1rYou must create a profile first.\r\n");
-	pause();
-	return(1); }
-
-if(user_level<telegram_level) {
-	bputs("\r\n\1h\1rYou have insufficient access to send telegrams."
-		"\r\n");
-	pause();
-	return(1); }
-
-main_user_info(user);
-CRLF;
-if(!cdt_warning(telegram_cdt))
-	return(0);
-if(telegram_cdt)
-	CRLF;
-bprintf("\1n\1hSending a telegram to \1y%s\1w:\r\n\r\n"
-	,user.name);
-now=time(NULL);
-memset(buf,0,512);
-sprintf(buf,"\1n\1c\1hMatch Maker\1b telegram from \1c%s\1b "
-	"on %s:\1y\r\n"
-	,useron.name,timestr(&now));
-for(i=0;i<5 && !aborted;i++) {
-	bprintf("\1n\1h\1g%u of 5: \1n\1g",i+1);
-	if(!getstr(line,70,i==4 ? K_MSG:K_MSG|K_WRAP))
-		break;
-	sprintf(str,"\1n\1g%4s%s\r\n",nulstr,line);
-	strcat(buf,str); }
-if(!i || aborted || !yesno("\r\nSave"))
-	return(0);
-if(!(user.misc&USER_FROMSMB)) {
-	putsmsg(user.number,TGRAM_NOTICE);
-	puttgram(user.number,buf); }
-else {
-	if((i=nopen("TELEGRAM.DAB",O_WRONLY|O_CREAT|O_APPEND|SH_DENYNO))
-		==-1) {
-		bprintf("\r\n\1r\1h\1iError writing telegram!\r\n");
-		pause();
-		return(1); }
-	write(i,useron.system,sizeof(useron.system));
-	write(i,user.system,sizeof(user.system));
-	write(i,&user.number,sizeof(user.number));
-	write(i,buf,512);
-	close(i); }
-adjust_cdt(telegram_cdt);
-if(notify_user && notify_user!=user_number) {
-	sprintf(str,"\1n\1hSMM: \1y%s\1m sent a telegram to \1y%s\1m "
-		"from the Match Maker\r\n",user_name,user.name);
-	if(node_dir[0])
-		putsmsg(notify_user,str);
-	else
-		puttgram(notify_user,str); }
-return(1);
-}
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-
-if(!strcmp(str,"00/00/00") || !str[0])
-	return(NULL);
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-if(str[6]<'7')
-	date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
-else
-	date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
-date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
-return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Returns the age derived from the string 'birth' in the format MM/DD/YY	*/
-/****************************************************************************/
-char getage(char *birth)
-{
-	char age;
-
-if(birth[0]<=SP)
-	return(0);
-getdate(&date);
-age=(date.da_year-1900)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
-if(age>90)
-	age-=90;
-if(atoi(birth)>12 || atoi(birth+3)>31)
-	return(0);
-if(((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_mon ||
-	(((birth[0]&0xf)*10)+(birth[1]&0xf)==date.da_mon &&
-	((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_day))
-	age--;
-if(age<0)
-	return(0);
-return(age);
-}
-
-char marital_ch(char user_marital)
-{
-switch(user_marital) {
-	case MARITAL_SINGLE:
-		return('S');
-	case MARITAL_DIVORCED:
-		return('D');
-	case MARITAL_MARRIED:
-		return('M');
-	case MARITAL_WIDOWED:
-		return('W');
-	case MARITAL_OTHER:
-		return('O'); }
-if(user_marital)
-	return('*');
-return(SP);
-}
-
-char race_ch(char user_race)
-{
-switch(user_race) {
-	case RACE_WHITE:
-		return('W');
-	case RACE_BLACK:
-		return('B');
-	case RACE_HISPANIC:
-		return('H');
-	case RACE_AMERINDIAN:
-		return('I');
-	case RACE_ASIAN:
-		return('A');
-	case RACE_MIDEASTERN:
-		return('M');
-	case RACE_OTHER:
-		return('O'); }
-if(user_race)
-	return('*');
-return(SP);
-}
-
-char *hair(char user_hair)
-{
-switch(user_hair) {
-	case HAIR_BLONDE:
-		return("BLN");
-	case HAIR_BROWN:
-		return("BRN");
-	case HAIR_RED:
-		return("RED");
-	case HAIR_BLACK:
-		return("BLK");
-	case HAIR_GREY:
-		return("GRY");
-	case HAIR_OTHER:
-		return("OTH"); }
-if(user_hair)
-	return("*");
-return(nulstr);
-}
-
-char *eyes(char user_eyes)
-{
-switch(user_eyes) {
-	case EYES_BLUE:
-		return("BLU");
-	case EYES_BROWN:
-		return("BRN");
-	case EYES_GREEN:
-		return("GRN");
-	case EYES_HAZEL:
-		return("HAZ");
-	case EYES_OTHER:
-		return("OTH"); }
-if(user_eyes)
-	return("*");
-return(nulstr);
-}
-
-char *marital(char user_marital)
-{
-switch(user_marital) {
-    case MARITAL_SINGLE:
-		return("Single");
-    case MARITAL_MARRIED:
-		return("Married");
-    case MARITAL_DIVORCED:
-		return("Divorced");
-    case MARITAL_WIDOWED:
-		return("Widowed");
-	case MARITAL_OTHER:
-		return("Other"); }
-if(user_marital)
-	return("*");
-return(nulstr);
-}
-
-char *race(char user_race)
-{
-switch(user_race) {
-	case RACE_WHITE:
-		return("White");
-	case RACE_BLACK:
-		return("Black");
-	case RACE_HISPANIC:
-		return("Hispanic");
-	case RACE_ASIAN:
-		return("Asian");
-	case RACE_AMERINDIAN:
-		return("American Indian");
-	case RACE_MIDEASTERN:
-		return("Middle Eastern");
-	case RACE_OTHER:
-		return("Other"); }
-if(user_race)
-	return("*");
-return(nulstr);
-}
-
-ushort getzodiac(char *birth)
-{
-if((!strncmp(birth,"03",2) && atoi(birth+3)>=21)
-	|| (!strncmp(birth,"04",2) && atoi(birth+3)<=19))
-    return(ZODIAC_ARIES);
-if((!strncmp(birth,"04",2) && atoi(birth+3)>=20)
-	|| (!strncmp(birth,"05",2) && atoi(birth+3)<=20))
-	return(ZODIAC_TAURUS);
-if((!strncmp(birth,"05",2) && atoi(birth+3)>=21)
-	|| (!strncmp(birth,"06",2) && atoi(birth+3)<=20))
-	return(ZODIAC_GEMINI);
-if((!strncmp(birth,"06",2) && atoi(birth+3)>=21)
-	|| (!strncmp(birth,"07",2) && atoi(birth+3)<=22))
-	return(ZODIAC_CANCER);
-if((!strncmp(birth,"07",2) && atoi(birth+3)>=23)
-	|| (!strncmp(birth,"08",2) && atoi(birth+3)<=22))
-	return(ZODIAC_LEO);
-if((!strncmp(birth,"08",2) && atoi(birth+3)>=23)
-	|| (!strncmp(birth,"09",2) && atoi(birth+3)<=22))
-	return(ZODIAC_VIRGO);
-if((!strncmp(birth,"09",2) && atoi(birth+3)>=23)
-	|| (!strncmp(birth,"10",2) && atoi(birth+3)<=22))
-	return(ZODIAC_LIBRA);
-if((!strncmp(birth,"10",2) && atoi(birth+3)>=23)
-	|| (!strncmp(birth,"11",2) && atoi(birth+3)<=21))
-	return(ZODIAC_SCORPIO);
-if((!strncmp(birth,"11",2) && atoi(birth+3)>=22)
-	|| (!strncmp(birth,"12",2) && atoi(birth+3)<=21))
-	return(ZODIAC_SAGITTARIUS);
-if((!strncmp(birth,"12",2) && atoi(birth+3)>=22)
-	|| (!strncmp(birth,"01",2) && atoi(birth+3)<=19))
-	return(ZODIAC_CAPRICORN);
-if((!strncmp(birth,"01",2) && atoi(birth+3)>=20)
-	|| (!strncmp(birth,"02",2) && atoi(birth+3)<=18))
-	return(ZODIAC_AQUARIUS);
-if((!strncmp(birth,"02",2) && atoi(birth+3)>=19)
-	|| (!strncmp(birth,"03",2) && atoi(birth+3)<=20))
-	return(ZODIAC_PISCES);
-return(0xff);
-}
-
-char *zodiac(short user_zodiac)
-{
-switch(user_zodiac)
-{
-	case ZODIAC_ARIES:
-		return("Aries");
-	case ZODIAC_TAURUS:
-		return("Taurus");
-	case ZODIAC_GEMINI:
-		return("Gemini");
-	case ZODIAC_CANCER:
-		return("Cancer");
-	case ZODIAC_LEO:
-		return("Leo");
-	case ZODIAC_VIRGO:
-		return("Virgo");
-	case ZODIAC_LIBRA:
-		return("Libra");
-	case ZODIAC_SCORPIO:
-		return("Scorpio");
-	case ZODIAC_SAGITTARIUS:
-		return("Sagittarius");
-	case ZODIAC_CAPRICORN:
-		return("Capricorn");
-	case ZODIAC_AQUARIUS:
-		return("Aquarius");
-	case ZODIAC_PISCES:
-		return("Pisces"); }
-return(nulstr);
-}
-
-short ans2bits(char *str)
-{
-	int i,j;
-	ushort bits=0;
-
-j=strlen(str);
-for(i=0;i<j;i++) {
-	if(str[i]=='*')
-		return(0xffff);
-	bits|=(1<<str[i]-'A'); }
-return(bits);
-}
-
-uchar ans2uchar(char *str)
-{
-	int i,j;
-	uchar bits=0;
-
-j=strlen(str);
-for(i=0;i<j;i++) {
-	if(str[i]=='*')
-		return(0xff);
-	bits|=(1<<str[i]-'A'); }
-return(bits);
-}
-
-
-void bits2ans(ushort bits, char *str)
-{
-	char	tmp[25];
-	int 	i;
-
-str[0]=0;
-if(bits==0xffff) {
-	strcpy(str,"*");
-	return; }
-for(i=0;i<16;i++)
-	if(bits&(1<<i)) {
-		tmp[0]='A'+i;
-		tmp[1]=0;
-		strcat(str,tmp); }
-}
-
-void bits2str(ushort user, char *str)
-{
-	int 	i;
-
-str[0]=0;
-if(user==0xffff) {
-	strcpy(str,"*");
-	return; }
-for(i=0;i<16;i++)
-	if(user&(1<<i))
-		str[i]='A'+i;
-	else
-		str[i]=SP;
-str[i]=0;
-}
-
-void uchar2ans(uchar bits, char *str)
-{
-	char	tmp[25];
-	int 	i;
-
-str[0]=0;
-if(bits==0xff) {
-	strcpy(str,"*");
-	return; }
-for(i=0;i<8;i++)
-	if(bits&(1<<i)) {
-		tmp[0]='A'+i;
-		tmp[1]=0;
-		strcat(str,tmp); }
-}
-
-int basic_match(user_t user, user_t mate)
-{
-	int max=0,match=0,age=getage(mate.birth),zodiac=getzodiac(mate.birth);
-
-if(user.pref_sex!='*' && user.pref_sex!=mate.sex
-	&& !(user.misc&USER_FRIEND))
-	return(0);
-
-if(zodiac&user.pref_zodiac) match++;
-else if(user.misc&USER_REQZODIAC)
-	return(0);
-if(zodiac==user.pref_zodiac) match++;
-max+=2;
-
-if(stricmp(mate.zipcode,user.min_zipcode)>=0
-	&& stricmp(mate.zipcode,user.max_zipcode)<=0) match+=2;
-else if(user.misc&USER_REQZIP) return(0);
-max+=2;
-
-if(mate.marital&user.pref_marital) match++;
-else if(user.misc&USER_REQMARITAL)
-	return(0);
-if(mate.marital==user.pref_marital) match++;
-max+=2;
-
-if(mate.race&user.pref_race) match++;
-else if(user.misc&USER_REQRACE)
-	return(0);
-if(mate.race==user.pref_race) match++;
-max+=2;
-
-if(mate.hair&user.pref_hair) match++;
-else if(user.misc&USER_REQHAIR)
-	return(0);
-if(mate.hair==user.pref_hair) match++;
-max+=2;
-
-if(mate.eyes&user.pref_eyes) match++;
-else if(user.misc&USER_REQEYES)
-	return(0);
-if(mate.eyes==user.pref_eyes) match++;
-max+=2;
-
-if(age>=user.min_age
-	&& (!user.max_age || age<=user.max_age)) match+=2;
-else {
-	if(user.misc&USER_REQAGE) return(0);
-	if(age<user.min_age-((user.max_age-user.min_age)/2)
-		|| (user.max_age && age>user.max_age+((user.max_age-user.min_age)/2)))
-		match-=4;
-	else if(age<user.min_age-((user.max_age-user.min_age)/3)
-		|| (user.max_age && age>user.max_age+((user.max_age-user.min_age)/3)))
-		match-=3;
-	else if(age<user.min_age-((user.max_age-user.min_age)/4)
-		|| (user.max_age && age>user.max_age+((user.max_age-user.min_age)/4)))
-		match-=2;
-	else if(age<user.min_age-((user.max_age-user.min_age)/5)
-		|| (user.max_age && age>user.max_age+((user.max_age-user.min_age)/5)))
-		match--; }
-
-max+=2;
-
-if(mate.weight>=user.min_weight
-	&& (!user.max_weight || mate.weight<=user.max_weight)) match+=2;
-else {
-	if(user.misc&USER_REQWEIGHT) return(0);
-	if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/2)
-		|| (user.max_weight
-		&& mate.weight>user.max_weight+((user.max_weight-user.min_weight)/2)))
-		match-=4;
-	else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/3)
-		|| (user.max_weight
-		&& mate.weight>user.max_weight+((user.max_weight-user.min_weight)/3)))
-		match-=3;
-	else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/4)
-		|| (user.max_weight
-		&& mate.weight>user.max_weight+((user.max_weight-user.min_weight)/4)))
-		match-=2;
-	else if(mate.weight<user.min_weight-((user.max_weight-user.min_weight)/5)
-		|| (user.max_weight
-		&& mate.weight>user.max_weight+((user.max_weight-user.min_weight)/5)))
-		match--; }
-max+=2;
-
-if(mate.height>=user.min_height
-	&& (!user.max_height || mate.height<=user.max_height)) match+=2;
-else {
-	if(user.misc&USER_REQHEIGHT) return(0);
-	if(mate.height<user.min_height-((user.max_height-user.min_height)/2)
-		|| (user.max_height
-		&& mate.height>user.max_height+((user.max_height-user.min_height)/2)))
-		match-=4;
-	else if(mate.height<user.min_height-((user.max_height-user.min_height)/3)
-		|| (user.max_height
-		&& mate.height>user.max_height+((user.max_height-user.min_height)/3)))
-		match-=3;
-	else if(mate.height<user.min_height-((user.max_height-user.min_height)/4)
-		|| (user.max_height
-		&& mate.height>user.max_height+((user.max_height-user.min_height)/4)))
-		match-=2;
-	else if(mate.height<user.min_height-((user.max_height-user.min_height)/5)
-		|| (user.max_height
-		&& mate.height>user.max_height+((user.max_height-user.min_height)/5)))
-		match--; }
-max+=2;
-
-if(mate.income>=user.min_income
-	&& (!user.max_income || mate.income==0xffffffffUL
-	|| mate.income<=user.max_income)) match++;
-else {
-	if(user.misc&USER_REQINCOME) return(0);
-	if(mate.income<user.min_income-((user.max_income-user.min_income)/2)
-		|| (user.max_income
-		&& mate.income>user.max_income+((user.max_income-user.min_income)/2)))
-		match-=4;
-	else if(mate.income<user.min_income-((user.max_income-user.min_income)/3)
-		|| (user.max_income
-		&& mate.income>user.max_income+((user.max_income-user.min_income)/3)))
-		match-=3;
-	else if(mate.income<user.min_income-((user.max_income-user.min_income)/4)
-		|| (user.max_income
-		&& mate.income>user.max_income+((user.max_income-user.min_income)/4)))
-		match-=2;
-	else if(mate.income<user.min_income-((user.max_income-user.min_income)/5)
-		|| (user.max_income
-		&& mate.income>user.max_income+((user.max_income-user.min_income)/5)))
-		match--; }
-max++;
-
-if(match<=0)
-	return(0);
-
-return(((float)match/max)*100.0);
-}
-
-int sys_quenum(char *name)
-{
-	int i;
-
-for(i=0;i<total_ques;i++)
-	if(!stricmp(que[i]->name,name))
-		break;
-if(i<total_ques)
-	return(i);
-return(-1);
-}
-
-int user_quenum(char *name, user_t user)
-{
-	int i;
-
-for(i=0;i<5;i++)
-	if(!stricmp(user.queans[i].name,name))
-		break;
-if(i<5)
-	return(i);
-return(-1);
-}
-
-int total_match(user_t user, user_t mate)
-{
-	int i,j,s,u,match1,match2,quematches=0,quemax=0,quematch;
-
-match1=basic_match(user,mate);
-if(!match1) return(0);
-match2=basic_match(mate,user);
-if(!match2) return(0);
-
-for(i=0;i<5;i++) {
-	if(!user.queans[i].name[0])
-		continue;
-	s=sys_quenum(user.queans[i].name);
-	if(s==-1)
-		continue;
-	u=user_quenum(user.queans[i].name,mate);
-	if(u==-1)
-		continue;
-	for(j=0;j<que[s]->total_ques;j++) {
-		if(user.queans[u].pref[j]&mate.queans[i].self[j]) quematches+=4;
-		if(user.queans[u].pref[j]==mate.queans[i].self[j]) quematches+=2;
-		if(user.queans[u].self[j]&mate.queans[i].pref[j]) quematches+=2;
-		if(user.queans[u].self[j]==mate.queans[i].pref[j]) quematches++;
-		quemax+=9; } }
-
-if(!quemax) 	/* no questionnaires in common */
-	return((match1+match1+match1+match1+match2+match2)/6);
-
-quematch=((float)quematches/quemax)*100.0;
-return((match1+match1+match1+match1+match2+match2+quematch)/7);
-}
-
-
-void main_user_info(user_t user)
-{
-	char str[128],min[64],max[64];
-	int i;
-
-attr(LIGHTGRAY);
-cls();
-if(SYSOP)
-	bprintf("\1n\1gReal: \1h%.25s #%lu (%.40s)\r\n"
-		,user.realname,user.number,user.system);
-bprintf("\1n\1gName: \1h%-25.25s     \1b%-10s   \1c%-15s  \1m%s\r\n"
-	,user.name
-	,marital(user.marital),race(user.race)
-	,user.sex=='M' ? "Male":"Female");
-if(smm_misc&SMM_METRIC)
-	sprintf(str," %-4u",intocm(user.height));
-else
-	sprintf(str,"%2u'%-2u",user.height/12,user.height%12);
-bprintf("\1n\1gHair: \1h%3s  \1n\1gEyes: \1h%3s  \1n\1gHeight:"
-	"\1h%s  \1n\1gWeight: \1h%-3u  \1n\1gAge: \1h%-3u "
-    "\1n\1gZodiac: \1h%s\r\n"
-	,hair(user.hair),eyes(user.eyes),str
-	,smm_misc&SMM_METRIC ? lptokg(user.weight) : user.weight
-	,getage(user.birth),zodiac(getzodiac(user.birth)));
-bprintf("\1n\1gFrom: \1h%-30.30s   \1n\1gZip: \1h%-10.10s    "
-	"\1n\1gIncome: \1h$%sK\1n\1g/year\r\n"
-	,user.location,user.zipcode
-	,user.income==0xffffffffUL ? "?":ultoa(user.income/1000UL,tmp,10));
-if(smm_misc&SMM_METRIC) {
-	sprintf(min,"%u",intocm(user.min_height));
-	sprintf(max,"%u",intocm(user.max_height)); }
-else {
-	sprintf(min,"%u'%u",user.min_height/12,user.min_height%12);
-	sprintf(max,"%u'%u",user.max_height/12,user.max_height%12); }
-bprintf("\1n\1gPref: \1h\1%c%c\1%c%c\1m%c \1%c%3u\1n\1g-\1h\1%c%u\1n\1h  "
-	"\1%c%s \1n\1ghair  \1h\1%c%s \1n\1geyes  \1h\1%c%s\1n\1g-\1h\1%c%s  "
-	"\1%c%u\1n\1g-\1h\1%c%u\1n\1glbs  \1h\1%c$%luK\1n\1g-\1h\1%c%luK\1n\1%c  "
-	"\1h%.3s\r\n"
-	,user.misc&USER_REQMARITAL ? 'w':'b'
-	,marital_ch(user.pref_marital)
-	,user.misc&USER_REQRACE ? 'w':'g'
-	,race_ch(user.pref_race)
-	,user.pref_sex
-	,user.misc&USER_REQAGE	? 'w':'g'
-	,user.min_age
-	,user.misc&USER_REQAGE	? 'w':'g'
-	,user.max_age
-	,user.misc&USER_REQHAIR  ? 'w':'g'
-	,hair(user.pref_hair)
-	,user.misc&USER_REQEYES  ? 'w':'g'
-	,eyes(user.pref_eyes)
-	,user.misc&USER_REQHEIGHT  ? 'w':'g'
-	,min
-	,user.misc&USER_REQHEIGHT  ? 'w':'g'
-	,max
-	,user.misc&USER_REQWEIGHT  ? 'w':'g'
-	,smm_misc&SMM_METRIC ? lptokg(user.min_weight) : user.min_weight
-	,user.misc&USER_REQWEIGHT  ? 'w':'g'
-	,smm_misc&SMM_METRIC ? lptokg(user.max_weight) : user.max_weight
-	,user.misc&USER_REQINCOME  ? 'w':'g'
-	,user.min_income/1000L
-	,user.misc&USER_REQINCOME  ? 'w':'g'
-	,user.max_income/1000L
-	,user.misc&USER_REQZODIAC  ? 'w':'g'
-    ,zodiac(user.pref_zodiac));
-
-bprintf("\1r\1i%s\1n\1w\1h\r\n",user.misc&USER_PHOTO ? "PHOTO":nulstr);
-for(i=0;i<5;i++) {
-    if(!user.note[i][0])
-        break;
-	bprintf("%15s%.50s\r\n",nulstr,user.note[i]); }
-}
-
-char long_user_info(user_t user)
-{
-	char str[128],fname[128],path[128],ch;
-	int i,j,k,s,u,max,match1,match2,user_match,mate_match;
-
-while(1) {
-checkline();
-main_user_info(user);
-
-CRLF;
-/**
-if(user.misc&USER_FROMSMB)
-	bprintf("\1r\1hImported via message base from \1w%s\1r.\r\n"
-		,user.system);
-**/
-bprintf("\1h\1mThis user meets your profile preferences:\1w%3u%%            "
-	,match1=basic_match(useron,user));
-bprintf("\1n\1gCreated: \1h%s\r\n",unixtodstr(user.created,str));
-bprintf("\1h\1mYou meet this user's profile preferences:\1w%3u%%            "
-	,match2=basic_match(user,useron));
-bprintf("\1n\1gUpdated: \1h%s\r\n",unixtodstr(user.updated,str));
-
-if(!smm_pause)
-	lncntr=0;
-
-CRLF;
-bputs("\1n\1b\1hQuestionnaires:\r\n");
-for(i=0;i<5;i++) {
-	max=mate_match=user_match=0;
-	if(!user.queans[i].name[0])
-		continue;
-	s=sys_quenum(user.queans[i].name);
-	if(s==-1)
-		continue;
-	if(que[s]->req_age>getage(useron.birth))
-		continue;
-	if(match1 && match2)
-		u=user_quenum(user.queans[i].name,useron);
-	else
-		u=-1;
-	bprintf("\1h\1c%-25s ",que[s]->desc);
-	if(u==-1) {
-		CRLF;
-		continue; }
-	for(j=0;j<que[s]->total_ques;j++) {
-		if(useron.queans[u].pref[j]&user.queans[i].self[j]) user_match+=2;
-		if(useron.queans[u].pref[j]==user.queans[i].self[j]) user_match++;
-		if(useron.queans[u].self[j]&user.queans[i].pref[j]) mate_match+=2;
-		if(useron.queans[u].self[j]==user.queans[i].pref[j]) mate_match++;
-		max+=3; }
-	bprintf("\1n\1c%s matches your pref:\1h%3u%%  "
-			"\1n\1cYou match %s pref:\1h%3u%%\r\n"
-			,user.sex=='M' ? "He":"She"
-			,(int)(((float)user_match/max)*100.0)
-			,user.sex=='M' ? "his":"her"
-			,(int)(((float)mate_match/max)*100.0)); }
-
-bprintf("\r\n\1r\1hOverall match: \1w%u%%",total_match(useron,user));
-if(user.purity)
-	bprintf("        \1r\1hPurity test: \1w%u%%",user.purity);
-if(user.mbtype[0])
-	bprintf("        \1r\1hPersonality type: \1w%s",user.mbtype);
-CRLF;
-
-if(aborted) {
-	aborted=0;
-	return(0); }
-if(!smm_pause) {
-	if(kbhit())
-		return(0);
-	return(1); }
-nodesync();
-if(lncntr>=user_rows-2)
-    lncntr=0;
-CRLF;
-bputs("\1h\1b[\1cV\1b]iew questionnaires, ");
-if(user.misc&USER_PHOTO)
-	bputs("[\1cD\1b]ownload photo, ");
-bputs("[\1cS\1b]end telegram, [\1cQ\1b]uit, or [Next]: \1c");
-strcpy(str,"VSQN\r");
-if(user.misc&USER_PHOTO)
-	strcat(str,"D");
-if(SYSOP)
-	strcat(str,"+");
-switch(getkeys(str,0)) {
-	case '+':
-		user.misc|=USER_PHOTO;
-		break;
-	case 'Q':
-		return(0);
-	case CR:
-	case 'N':
-		return(1);
-	case 'D':
-		if(!useron.number) {
-			bputs("\r\n\1h\1rYou must create a profile first.\r\n");
-			pause();
-			break; }
-		if(!(useron.misc&USER_PHOTO)) {
-			bputs("\r\n\1h\1rYou cannot download photos until your photo is "
-				"added.\r\n");
-			pause();
-			break; }
-		for(i=0;user.system[i];i++)
-			if(isalnum(user.system[i]))
-				break;
-		if(!user.system[i])
-			fname[0]='~';
-		else
-			fname[0]=user.system[i];
-		for(i=strlen(user.system)-1;i>0;i--)
-			if(isalnum(user.system[i]))
-				break;
-		if(i<=0)
-			fname[1]='~';
-		else
-			fname[1]=user.system[i];
-		fname[2]=0;
-		strupr(user.system);
-		strcat(fname,base41(crc16(user.system),tmp));
-		strcat(fname,base41(user.number,tmp));
-		strcat(fname,".JPG");
-		strupr(fname);
-		sprintf(path,"PHOTO\\%s",fname);
-		if(!fexist(path)) {
-			bputs("\r\n\1n\1hUnpacking...");
-			sprintf(str,"%spkunzip photo %s photo",exec_dir,fname);
-			system(str);
-			bputs("\r\n");
-			if(!fexist(path)) {
-				bputs("\r\n\1n\1h\1i\1rUnpacking failed!\1n\r\n");
-				pause();
-				break; } }
-		if(com_port) {
-			cmdstr(zmodem_send,path,path,str);
-			ivhctl(INTCLR);
-			ivhctl(INT29L);
-			system(str);
-			ivhctl(INTCLR);
-			i=INT29L;
-			i|=(INT29R|INT16);
-			ivhctl(i); }
-		else
-			system(cmdstr(local_view,path,path,str));
-		pause();
-		break;
-
-
-	case 'S':
-		send_telegram(user);
-		break;
-	case 'V':
-
-		if(user_level<que_level) {
-			bputs("\r\n\1h\1rYou have insufficient access to read "
-				"questoinnaires.\r\n");
-			pause();
-            break; }
-
-		for(i=0;i<5;i++) {
-			aborted=0;
-			if(!user.queans[i].name[0])
-				continue;
-			s=sys_quenum(user.queans[i].name);
-			if(s==-1)
-				continue;
-			if(que[s]->req_age>getage(useron.birth))
-				continue;
-			if(match1 && match2)
-				u=user_quenum(user.queans[i].name,useron);
-			else
-				u=-1;
-			sprintf(str,"\r\nDo you wish to view the \1w%s\1b questionnaire"
-				,que[s]->desc);
-			if(!yesno(str))
-				continue;
-			if(!cdt_warning(que_cdt))
-				continue;
-			adjust_cdt(que_cdt);
-			for(j=0;j<que[s]->total_ques && !aborted;) {
-				cls();
-				bprintf("\1n\1m\1hQuestionnaire: \1y%-25s \1mQuestion: "
-					"\1y%d \1mof \1y%d  \1h\1b(Ctrl-C to Abort)\r\n\r\n"
-					,que[s]->desc,j+1,que[s]->total_ques);
-				bprintf("\1w\1h%s\r\n\r\n",que[s]->que[j].txt);
-				for(k=0;k<que[s]->que[j].answers;k++)
-					bprintf("\1h\1b%c\1w) \1g%s\r\n",'A'+k
-						,que[s]->que[j].ans[k]);
-				bits2str(user.queans[i].self[j],str);
-				bprintf("\1n\1g\r\n%25s: \1h%-16s "
-					,user.name,str);
-				bits2str(user.queans[i].pref[j],str);
-				bprintf("\1n\1g %15s: \1h%s","Preferred mate",str);
-				if(u!=-1) {
-					bits2str(useron.queans[u].pref[j],str);
-					bprintf("\1n\1g\r\n%25s: \1h%-16s "
-						,"Your preferred mate",str);
-					bits2str(useron.queans[u].self[j],str);
-					bprintf("\1n\1g %15s: \1h%s","You",str); }
-				CRLF;
-				if(!aborted) {
-					lncntr=0;
-					bputs("\r\n\1h\1b[\1cP\1b]revious, [\1cQ\1b]uit, "
-						"or [Next]: \1c");
-					ch=getkeys("PQN\r",0);
-					if(ch=='P') {
-						if(j) j--;
-						continue; }
-					if(ch=='Q')
-						break;
-					j++; } } }
-		break;
-
-	} }
-return(0);
-}
-
-
-/* Returns 0 if aborted, 1 if continue, negative if previous */
-int short_user_info(user_t user)
-{
-	char str[128],height[64],ch;
-    int i,match;
-    int records;
-    ulong  name_crc;
-	static char name[26],lastname[26],highmatch;
-    static long topixb,topdab,lastixb,lastdab;
-    static int count;
-
-if(!lncntr && smm_pause) {
-	topdab=ftell(stream)-sizeof(user_t);
-	topixb=ftell(index)-sizeof(ixb_t);
-    if(!topdab)
-        lastdab=lastixb=0;
-    count=0;
-	printfile("LIST_HDR.ASC");
-	strcpy(lastname,name);
-	name[0]=highmatch=0; }
-if(user.number) {
-	match=total_match(useron,user);
-    if(!match) str[0]=0;
-    else if(match>=90) sprintf(str,"\1w%u%%",match);
-    else if(match>=80) sprintf(str,"\1c%u%%",match);
-    else if(match>=70) sprintf(str,"\1y%u%%",match);
-    else if(match>=60) sprintf(str,"\1g%u%%",match);
-    else if(match>=50) sprintf(str,"\1m%u%%",match);
-    else if(match>=40) sprintf(str,"\1r%u%%",match);
-    else if(match>=30) sprintf(str,"\1b%u%%",match);
-    else if(match>=20) sprintf(str,"\1n\1g%u%%",match);
-    else if(match>=10) sprintf(str,"\1n\1c%u%%",match);
-    else sprintf(str,"\1n%u%%",match);
-	if(smm_misc&SMM_METRIC)
-		sprintf(height," %-4u",intocm(user.height));
-	else
-		sprintf(height,"%2u'%-2u",user.height/12,user.height%12);
-	bprintf("\1n\1h%c\1n\1g%c\1h\1c%c\1b%3u \1g%3s \1m%3s\1r%s \1y%-3u "
-		"\1n\1g%-25.25s\1r\1h\1i%c\1n\1h%-25.25s%s\r\n"
-        ,user.sex==user.pref_sex ? 'G':user.sex=='*' ? 'B'
-            : marital_ch(user.marital)
-        ,race_ch(user.race)
-        ,user.sex
-        ,getage(user.birth)
-        ,hair(user.hair)
-        ,eyes(user.eyes)
-		,height
-		,smm_misc&SMM_METRIC ? lptokg(user.weight) : user.weight
-        ,user.location
-		,user.misc&USER_PHOTO ? '+':SP
-        ,user.name
-        ,str
-        );
-	if(match &&
-		(!name[0] || !stricmp(name,lastname)
-		|| (stricmp(user.name,lastname) && match>highmatch))) {
-		highmatch=match;
-        sprintf(name,"%.25s",user.name);
-        strupr(name); }
-	}
-
-if(lncntr>=user_rows-2 || !user.number) {
-    lncntr=0;
-	bputs(PrevReadSendQuitOrMore);
-	ch=getkey(K_UPPER);
-	if(ch=='Q') {
-		cls();
-		aborted=1; }
-    else if(ch=='P') {
-		cls();
-        records=((ftell(stream)-topdab)/sizeof(user_t));
-		fseek(stream,lastdab,SEEK_SET);
-		fseek(index,lastixb,SEEK_SET);
-		lastdab-=(records)*sizeof(user_t);
-		lastixb-=(records)*sizeof(ixb_t);
-        if(lastdab<0) lastdab=0;
-        if(lastixb<0) lastixb=0;
-        return(-count); }
-	else if(ch=='R' || ch=='G' || ch=='S') {
-        bprintf("\1n\r\1>\1y\1hUser name: ");
-        if(getstr(name,25,K_NOCRLF|K_LINE|K_EDIT|K_AUTODEL|K_UPPER)) {
-			truncsp(name);
-            name_crc=crc32(name);
-            cls();
-            rewind(index);
-            while(!feof(index)) {
-                if(!fread(&ixb,sizeof(ixb_t),1,index))
-                    break;
-                if(!ixb.number)    /* DELETED */
-                    continue;
-                if(ixb.name!=name_crc)
-                    continue;
-                fseek(stream
-                    ,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-                    *sizeof(user_t),SEEK_SET);
-                if(!fread(&user,sizeof(user_t),1,stream))
-                    continue;
-				if(ch=='S' && send_telegram(user))
-					break;
-				if(ch!='S' && !long_user_info(user))
-                    break; } }
-        fseek(stream,topdab,SEEK_SET);
-        fseek(index,topixb,SEEK_SET);
-		cls();
-		return(-1); }
-    else {
-        lastixb=topixb;
-		lastdab=topdab;
-		cls(); } }
-
-count++;
-if(aborted)
-    return(0);
-return(1);
-}
-
-
-int get_your_det(user_t *user)
-{
-	char	str[128],*p,*hdr;
-	int 	i;
-
-while(1) {
-checkline();
-cls();
-bputs("\1h\0014 Your Detailed Personal Information \1n  \1h\1b"
-    "(Ctrl-C to Abort)\r\n\r\n");
-
-nodesync();
-bputs("\1h\1bPlease enter your name or alias: ");
-strcpy(str,user->name);
-if(!getstr(str,25,K_LINE|K_EDIT|K_AUTODEL|K_UPRLWR))
-	return(0);
-truncsp(str);
-if(trash(str)) {
-	bprintf("\r\n\1h\1rSorry, you can't use that name.\r\n\r\n\1p");
-	continue; }
-strcpy(user->name,str);
-
-CRLF;
-nodesync();
-bprintf("\1h\1gPlease enter your height in %s: "
-	,smm_misc&SMM_METRIC ? "centimeters" : "feet'inches (example: 5'7)");
-if(user->height) {
-	if(smm_misc&SMM_METRIC)
-		sprintf(str,"%u",intocm(user->height));
-	else
-		sprintf(str,"%u'%u",user->height/12,user->height%12); }
-else
-    str[0]=0;
-if(!getstr(str,4,K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->height=cmtoin(atoi(str));
-else {
-	user->height=atoi(str)*12;
-	p=strchr(str,'\'');
-	if(p) user->height+=atoi(p+1); }
-
-CRLF;
-nodesync();
-bprintf("\1h\1mPlease enter your weight (in %s): "
-	,smm_misc&SMM_METRIC ? "kilograms":"pounds");
-if(user->weight)
-	sprintf(str,"%u"
-		,smm_misc&SMM_METRIC ? lptokg(user->weight) : user->weight);
-else
-    str[0]=0;
-if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL|K_LINE))
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->weight=kgtolp(atoi(str));
-else
-	user->weight=atoi(str);
-
-CRLF;
-nodesync();
-bputs("\1h\1rPlease enter your annual income in dollars (ENTER=undisclosed): ");
-if(user->income && user->income!=0xffffffff)
-	sprintf(str,"%luK",user->income/1000);
-else
-    str[0]=0;
-getstr(str,6,K_UPPER|K_EDIT|K_AUTODEL|K_LINE);
-if(aborted)
-	return(0);
-if(strchr(str,'K'))
-	user->income=atol(str)*1000L;
-else if(str[0]==0)
-	user->income=0xffffffffUL;
-else
-	user->income=atol(str);
-
-CRLF;
-nodesync();
-bputs("\1h\1cPlease enter your location (city, state): ");
-strcpy(str,user->location);
-if(!getstr(str,30,K_LINE|K_EDIT|K_AUTODEL|K_UPRLWR))
-	return(0);
-truncsp(str);
-if(trash(str)) {
-	bprintf("\r\n\1r\1hSorry, you can't use that location.\r\n\r\n\1p");
-	continue; }
-strcpy(user->location,str);
-
-
-CRLF;
-nodesync();
-bputs("\1h\1gPlease enter your zip/postal code: ");
-if(!getstr(user->zipcode,10,K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-
-CRLF;
-nodesync();
-for(i=0;i<5;i++) {
-    bprintf("\1n\1gPersonal text - Line %u of 5: ",i+1);
-    if(wordwrap[0])
-        user->note[i][0]=0;
-	strcpy(str,user->note[i]);
-	if(!getstr(str,50,i==4 ? K_LINE|K_EDIT:K_LINE|K_EDIT|K_WRAP))
-		break;
-	if(trash(str)) {
-		bprintf("\r\n\1r\1hSorry, you can't use that text.\r\n\r\n");
-		i--;
-		continue; }
-	strcpy(user->note[i],str); }
-while(i++<5)
-    user->note[i][0]=0;
-aborted=0;
-nodesync();
-if(yesno("\r\nIs the above information correct"))
-    break; }
-return(1);
-}
-
-int get_pref_det(user_t *user)
-{
-	char str[128],*p,*hdr;
-	int i;
-
-while(1) {
-checkline();
-cls();
-bputs("\1h\0014 Detailed Information on Your Preferred Mate \1n  "
-    "\1h\1b(Ctrl-C to Abort)\r\n\r\n");
-
-nodesync();
-bputs("\1n\1cPlease enter the minimum age of your preferred mate: \1h");
-if(user->min_age)
-    sprintf(str,"%u",user->min_age);
-else
-    str[0]=0;
-getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-user->min_age=atoi(str);
-
-nodesync();
-bputs("\1h\1cPlease enter the maximum age of your preferred mate: \1h");
-if(user->max_age)
-    sprintf(str,"%u",user->max_age);
-else
-    str[0]=0;
-getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-user->max_age=atoi(str);
-if(user->min_age) {
-	strcpy(str,"Do you require your mate's age fall within this range");
-	if(user->misc&USER_REQAGE)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQAGE;
-	else
-		user->misc&=~USER_REQAGE; }
-else
-	user->misc&=~USER_REQAGE;
-if(aborted)
-	return(0);
-
-CRLF;
-nodesync();
-bprintf("\1n\1gPlease enter the minimum height of your preferred mate "
-	"in %s: \1w\1h",smm_misc&SMM_METRIC ? "centimeters":"feet'inches");
-if(user->min_height) {
-	if(smm_misc&SMM_METRIC)
-		sprintf(str,"%u",intocm(user->min_height));
-	else
-		sprintf(str,"%u'%u",user->min_height/12,user->min_height%12); }
-else
-    str[0]=0;
-getstr(str,4,K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->min_height=cmtoin(atoi(str));
-else {
-	user->min_height=atoi(str)*12;
-	p=strchr(str,'\'');
-	if(p) user->min_height+=atoi(p+1); }
-nodesync();
-bprintf("\1h\1gPlease enter the maximum height of your preferred mate "
-	"in %s: \1w",smm_misc&SMM_METRIC ? "centimeters":"feet'inches");
-if(user->max_height) {
-	if(smm_misc&SMM_METRIC)
-		sprintf(str,"%u",intocm(user->max_height));
-    else
-		sprintf(str,"%u'%u",user->max_height/12,user->max_height%12); }
-else
-    str[0]=0;
-getstr(str,4,K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->max_height=cmtoin(atoi(str));
-else {
-	user->max_height=atoi(str)*12;
-	p=strchr(str,'\'');
-	if(p) user->max_height+=atoi(p+1); }
-strcpy(str,"Do you require your mate's height fall within this range");
-if(user->misc&USER_REQHEIGHT)
-	i=yesno(str);
-else
-	i=!noyes(str);
-if(i)
-    user->misc|=USER_REQHEIGHT;
-else
-    user->misc&=~USER_REQHEIGHT;
-if(aborted)
-    return(0);
-
-
-CRLF;
-nodesync();
-bprintf("\1n\1mPlease enter the minimum weight of your preferred mate in %s:"
-	" \1w\1h",smm_misc&SMM_METRIC ? "kilograms":"pounds");
-if(user->min_weight) {
-	if(smm_misc&SMM_METRIC)
-		sprintf(str,"%u",lptokg(user->min_weight));
-	else
-		sprintf(str,"%u",user->min_weight); }
-else
-    str[0]=0;
-getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->min_weight=kgtolp(atoi(str));
-else
-	user->min_weight=atoi(str);
-
-nodesync();
-bprintf("\1h\1mPlease enter the maximum weight of your preferred mate in %s:"
-	" \1w",smm_misc&SMM_METRIC ? "kilograms":"pounds");
-if(user->max_weight) {
-	if(smm_misc&SMM_METRIC)
-		sprintf(str,"%u",lptokg(user->max_weight));
-	else
-		sprintf(str,"%u",user->max_weight); }
-else
-    str[0]=0;
-getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted)
-	return(0);
-if(smm_misc&SMM_METRIC)
-	user->max_weight=kgtolp(atoi(str));
-else
-	user->max_weight=atoi(str);
-if(user->max_weight) {
-	strcpy(str,"Do you require your mate's weight fall within this range");
-	if(user->misc&USER_REQWEIGHT)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQWEIGHT;
-	else
-		user->misc&=~USER_REQWEIGHT; }
-else
-	user->misc&=~USER_REQWEIGHT;
-if(aborted)
-    return(0);
-
-
-CRLF;
-nodesync();
-bputs("\1h\1cPlease enter the lowest zip/postal code of your preferred "
-    "mate: \1w");
-getstr(user->min_zipcode,10,K_EDIT|K_AUTODEL|K_UPPER);
-if(aborted)
-	return(0);
-bputs("\1h\1bPlease enter the highest zip/postal code of your preferred "
-    "mate: \1w");
-getstr(user->max_zipcode,10,K_EDIT|K_AUTODEL|K_UPPER);
-if(aborted)
-	return(0);
-strcpy(str,"Do you require your mate's zip/postal code fall within this range");
-if(user->misc&USER_REQZIP)
-	i=yesno(str);
-else
-	i=!noyes(str);
-if(i)
-	user->misc|=USER_REQZIP;
-else
-	user->misc&=~USER_REQZIP;
-if(aborted)
-    return(0);
-
-
-CRLF;
-nodesync();
-bputs("\1h\1gPlease enter the minimum annual income of your "
-    "mate in dollars: \1w");
-if(user->min_income)
-    sprintf(str,"%lu",user->min_income);
-else
-    str[0]=0;
-getstr(str,6,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted) return(0);
-user->min_income=atol(str);
-
-nodesync();
-bputs("\1h\1yPlease enter the maximum annual income of your "
-    "mate in dollars: \1w");
-if(user->max_income)
-    sprintf(str,"%lu",user->max_income);
-else
-    str[0]=0;
-getstr(str,6,K_NUMBER|K_EDIT|K_AUTODEL);
-if(aborted) return(0);
-user->max_income=atol(str);
-if(user->min_income) {
-	strcpy(str,"Do you require that your mate's income fall within this range");
-	if(user->misc&USER_REQINCOME)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQINCOME;
-	else
-		user->misc&=~USER_REQINCOME; }
-else
-	user->misc&=~USER_REQINCOME;
-if(aborted)
-    return(0);
-
-
-nodesync();
-if(yesno("\r\nIs the above information correct"))
-    break; }
-return(1);
-}
-
-int get_your_multi(user_t *user)
-{
-	char str[128],*hdr,*p;
-
-while(1) {
-checkline();
-hdr="\1n\1l\1h\0014 Your Profile \1n  \1h\1b(Ctrl-C to Abort)\r\n\r\n";
-bputs(hdr);
-bputs("\1n\1h\1cYour Marital Status:\r\n\r\n");
-mnemonics("~A) Single\r\n~B) Married\r\n~C) Divorced\r\n~D) Widowed\r\n"
-    "~E) Other\r\n");
-nodesync();
-bputs("\r\n\1y\1hWhich: \1w");
-uchar2ans(user->marital,str);
-if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
-	return(0);
-if(str[0]<='E')
-	break; }
-user->marital=ans2uchar(str);
-
-while(1) {
-checkline();
-bputs(hdr);
-bputs("\1n\1h\1cYour Race:\r\n\r\n");
-mnemonics("~A) White\r\n~B) Black\r\n~C) Hispanic\r\n~D) Asian\r\n"
-	"~E) American Indian\r\n~F) Middle Eastern\r\n~G) Other\r\n");
-nodesync();
-bputs("\r\n\1y\1hWhich: \1w");
-uchar2ans(user->race,str);
-if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
-	return(0);
-if(str[0]<='G')
-    break; }
-user->race=ans2uchar(str);
-
-while(1) {
-checkline();
-bputs(hdr);
-bputs("\1n\1h\1cYour Hair Color:\r\n\r\n");
-mnemonics("~A) Blonde\r\n~B) Brown\r\n~C) Red\r\n~D) Black\r\n"
-    "~E) Grey\r\n~F) Other\r\n");
-nodesync();
-bputs("\r\n\1y\1hWhich: \1w");
-uchar2ans(user->hair,str);
-if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
-	return(0);
-if(str[0]<='F')
-    break; }
-user->hair=ans2uchar(str);
-
-while(1) {
-checkline();
-bputs(hdr);
-bputs("\1n\1h\1cYour Eye Color:\r\n\r\n");
-mnemonics("~A) Blue\r\n~B) Green\r\n~C) Hazel\r\n~D) Brown\r\n"
-    "~E) Other\r\n");
-nodesync();
-bputs("\r\n\1y\1hWhich: \1w");
-uchar2ans(user->eyes,str);
-if(!getstr(str,1,K_ALPHA|K_LINE|K_EDIT|K_AUTODEL|K_UPPER))
-	return(0);
-if(str[0]<='E')
-    break; }
-user->eyes=ans2uchar(str);
-return(1);
-}
-
-int get_pref_multi(user_t *user)
-{
-	char str[128],*hdr,*p;
-	int i;
-
-while(1) {
-checkline();
-hdr="\1n\1l\1h\0014 Profile of Your Preferred Mate \1n  \1h\1b"
-    "(Ctrl-C to Abort)\r\n\r\n";
-bputs(hdr);
-bputs("\1n\1h\1cSex of Your Preferred (Intimate/Romantic) Mate:\r\n\r\n");
-mnemonics("~M) Male\r\n~F) Female\r\n~*) Either\r\n");
-nodesync();
-bputs("\r\n\1y\1hWhich: ");
-str[0]=user->pref_sex;
-str[1]=0;
-if(!getstr(str,1,K_UPPER|K_EDIT|K_AUTODEL|K_LINE))
-    break;
-if(user->sex==str[0] && noyes("\r\nYou are homosexual"))
-	continue;
-if(str[0]=='M' || str[0]=='F' || str[0]=='*')
-    break; }
-user->pref_sex=str[0];
-if(aborted) return(0);
-
-strcpy(str,"\r\nAre you seeking an any-sex (non-romantic) friendship");
-if(user->misc&USER_FRIEND)
-	i=yesno(str);
-else
-	i=!noyes(str);
-if(i)
-	user->misc|=USER_FRIEND;
-else
-	user->misc&=~USER_FRIEND;
-
-bputs(hdr);
-bputs("\1n\1h\1cMarital Status of Your Preferred Mate:\r\n\r\n");
-mnemonics("~A) Single\r\n~B) Married\r\n~C) Divorced\r\n~D) Widowed\r\n"
-    "~E) Other\r\n~*) Any of the above\r\n");
-nodesync();
-bputs("\r\n\1y\1hPlease enter up to 4 answers: ");
-uchar2ans(user->pref_marital,str);
-if(!getstr(str,4,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-user->pref_marital=ans2uchar(str);
-if(user->pref_marital!=0xff) {
-	strcpy(str,"\r\nDo you require your mate have the martial status you "
-		"indicated");
-	if(user->misc&USER_REQMARITAL)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-        user->misc|=USER_REQMARITAL;
-	else
-		user->misc&=~USER_REQMARITAL; }
-else
-	user->misc&=~USER_REQMARITAL;
-if(aborted) return(0);
-
-bputs(hdr);
-bputs("\1n\1h\1cRace of Your Preferred Mate:\r\n\r\n");
-mnemonics("~A) White\r\n~B) Black\r\n~C) Hispanic\r\n~D) Asian\r\n"
-    "~E) American Indian\r\n~F) Middle Eastern\r\n~G) Other\r\n"
-    "~*) Any of the above\r\n");
-nodesync();
-bputs("\r\n\1y\1hPlease enter up to 6 answers: ");
-uchar2ans(user->pref_race,str);
-if(!getstr(str,6,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-user->pref_race=ans2uchar(str);
-if(user->pref_race!=0xff) {
-	strcpy(str,"\r\nDo you require your mate be of the race"
-		" you indicated");
-	if(user->misc&USER_REQRACE)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQRACE;
-	else
-		user->misc&=~USER_REQRACE; }
-else
-	user->misc&=~USER_REQRACE;
-if(aborted) return(0);
-
-bputs(hdr);
-bputs("\1n\1h\1cHair Color of Your Preferred Mate:\r\n\r\n");
-mnemonics("~A) Blonde\r\n~B) Brown\r\n~C) Red\r\n~D) Black\r\n"
-    "~E) Grey\r\n~F) Other\r\n~*) Any of the Above\r\n");
-nodesync();
-bputs("\r\n\1y\1hPlease enter up to 5 answers: ");
-uchar2ans(user->pref_hair,str);
-if(!getstr(str,5,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-user->pref_hair=ans2uchar(str);
-if(user->pref_hair!=0xff) {
-	strcpy(str,"\r\nDo you require your mate have the hair color"
-		" you indicated");
-	if(user->misc&USER_REQHAIR)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQHAIR;
-	else
-		user->misc&=~USER_REQHAIR; }
-else
-	user->misc&=~USER_REQHAIR;
-if(aborted) return(0);
-
-
-bputs(hdr);
-bputs("\1n\1h\1cEye Color of Your Preferred Mate:\r\n\r\n");
-mnemonics("~A) Blue\r\n~B) Green\r\n~C) Hazel\r\n~D) Brown\r\n"
-    "~E) Other\r\n~*) Any of the above\r\n");
-nodesync();
-bputs("\r\n\1y\1hPlease enter up to 4 answers: ");
-uchar2ans(user->pref_eyes,str);
-if(!getstr(str,4,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-user->pref_eyes=ans2uchar(str);
-if(user->pref_eyes!=0xff) {
-	strcpy(str,"\r\nDo you require your mate have the eye color"
-		" you indicated");
-	if(user->misc&USER_REQEYES)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQEYES;
-	else
-		user->misc&=~USER_REQEYES; }
-else
-	user->misc&=~USER_REQEYES;
-if(aborted) return(0);
-
-bputs(hdr);
-bputs("\1n\1h\1cZodiac Sign of Your Preferred Mate:\r\n\r\n");
-mnemonics("~A) Aries\r\n~B) Taurus\r\n~C) Gemini\r\n~D) Cancer\r\n"
-    "~E) Leo\r\n~F) Virgo\r\n~G) Libra\r\n~H) Scorpio\r\n");
-mnemonics("~I) Sagittarius\r\n~J) Capricorn\r\n~K) Aquarius\r\n"
-    "~L) Pisces\r\n~*) Any of the above\r\n");
-nodesync();
-bputs("\r\n\1y\1hPlease enter up to 11 answers: ");
-bits2ans(user->pref_zodiac,str);
-if(!getstr(str,11,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-	return(0);
-user->pref_zodiac=ans2bits(str);
-if(user->pref_zodiac!=0xffff) {
-	strcpy(str,"\r\nDo you require your mate have the zodiac sign"
-		" you indicated");
-	if(user->misc&USER_REQZODIAC)
-		i=yesno(str);
-	else
-		i=!noyes(str);
-	if(i)
-		user->misc|=USER_REQZODIAC;
-	else
-		user->misc&=~USER_REQZODIAC; }
-else
-	user->misc&=~USER_REQZODIAC;
-if(aborted) return(0);
-
-return(1);
-}
-
-void mbtype_desc(char *mbtype)
-{
-	char str[128],type[128];
-
-while(1) {
-	checkline();
-	cls();
-	printfile("MB-TYPE.ASC");
-	nodesync();
-	bprintf("\r\n\1y\1hYour Type: \1w%s\r\n",mbtype);
-	bputs("\1y\1hLetter or Type to define: ");
-	memset(type,0,5);
-	if(!getstr(type,4,K_ALPHA|K_UPPER|K_LINE))
-		break;
-	sprintf(str,"MB-%s.ASC",type);
-	if(!fexist(str)) {
-		bputs("\r\nInvalid Letter or Type!\r\n\r\n");
-		pause();
-		continue; }
-	cls();
-	printfile(str);
-	if(lncntr && !aborted)
-		pause(); }
-}
-
-
-int get_mbtype(user_t *user)
-{
-	char str[256];
-	int file,i=0,e=0,n=0,s=0,f=0,t=0,p=0,j=0,q=0,ch;
-	FILE *stream;
-
-aborted=0;
-cls();
-printfile("MB-INTRO.ASC");
-if(aborted)
-	return(0);
-bputs("\1n\1hYour answers will be kept secret.\r\n\r\n"
-	"Only your personality type will be visible to other users.\r\n\r\n");
-nodesync();
-if(!yesno("Continue with test"))
-    return(0);
-
-if((file=nopen("MB-TYPE.QUE",O_RDONLY))==-1 ||
-	(stream=fdopen(file,"r"))==NULL) {
-	bputs("\7\r\i\hCan't open MBTYPE.QUE\r\n\1p");
-	return(0); }
-while(!feof(stream)) {
-	if(!fgets(str,200,stream))
-        break;
-	str[57]=0;
-	truncsp(str);
-	if(!str[0])
-		break;
-	cls();
-	nodesync();
-	bprintf("\1y\1hMyers-Briggs Personality Test  \1bQuestion #\1w%u  "
-		"\1b(Ctrl-C to Abort)\r\n"
-		"\r\n%s:\r\n\r\n"
-		"[\1wA\1b] %.44s\r\n"
-		"[\1wB\1b] %.44s\r\n"
-		"[\1wC\1b] cannot decide\r\n\r\n"
-		"Which: \1w"
-		,q+1,str,str+58,str+102);
-	ch=getkeys("ABC",0);
-	if(aborted) {
-		fclose(stream);
-		return(0); }
-	if(ch=='C') {
-		q++;
-		continue; }
-
-	if(ch=='A')
-		ch=str[146];
-	else
-		ch=str[147];
-
-	switch(ch) {
-		case 'E':
-			e++;
-			break;
-		case 'I':
-			i++;
-			break;
-		case 'S':
-			s++;
-			break;
-		case 'N':
-			n++;
-			break;
-		case 'T':
-			t++;
-			break;
-		case 'F':
-			f++;
-			break;
-		case 'J':
-			j++;
-			break;
-		case 'P':
-			p++;
-			break; }
-	q++; }
-
-fclose(stream);
-
-if(i>e)
-	user->mbtype[0]='I';
-else if(i==e)
-	user->mbtype[0]='*';
-else
-	user->mbtype[0]='E';
-
-if(s>n)
-	user->mbtype[1]='S';
-else if(s==n)
-	user->mbtype[1]='*';
-else
-	user->mbtype[1]='N';
-
-if(t>f)
-	user->mbtype[2]='T';
-else if(t==f)
-	user->mbtype[2]='*';
-else
-	user->mbtype[2]='F';
-
-if(p>j)
-	user->mbtype[3]='P';
-else if(p==j)
-	user->mbtype[3]='*';
-else
-	user->mbtype[3]='J';
-
-bprintf("\1l\1y\1hYour Myers-Briggs Personality Type is \1w%s\r\n\r\n"
-	,user->mbtype);
-
-if(yesno("Would you like to see the personality type descriptions"))
-	mbtype_desc(user->mbtype);
-return(1);
-}
-
-
-int get_purity(user_t *user)
-{
-	char str[128];
-	int file,no_ans=0,pos_ans=0;
-	FILE *stream;
-
-aborted=0;
-if(!fexist("PURITY.QUE") || purity_age>getage(user->birth))
-	return(0);
-cls();
-printfile("PURITY.ASC");
-if(aborted)
-	return(0);
-bputs("\1n\1hYour answers will be kept secret.\r\n\r\n"
-	"Only your purity score will be visible to other users.\r\n\r\n");
-nodesync();
-if(!yesno("Continue with test"))
-	return(0);
-if((file=nopen("PURITY.QUE",O_RDONLY))==-1 ||
-	(stream=fdopen(file,"r"))==NULL) {
-	bputs("\7\r\i\hCan't open PURITY.QUE\r\n\1p");
-	return(0); }
-while(!feof(stream)) {
-	if(!fgets(str,81,stream))
-		break;
-	truncsp(str);
-	cls();
-	if(str[0]=='*') {
-		printfile(str+1);
-		if(lncntr && !aborted)
-			pause();
-		if(aborted)
-			break;
-		continue; }
-	nodesync();
-	bprintf("\1y\1hPurity Test  \1bQuestion #\1w%u  \1b(Ctrl-C to Abort)\r\n"
-		"\r\nHave you ever:\r\n\r\n"
-		,++pos_ans);
-	if(noyes(str))
-		no_ans++;
-	if(aborted)
-		break; }
-
-fclose(stream);
-if(aborted)
-	return(0);
-
-user->purity=((float)no_ans/pos_ans)*100.0;
-bprintf("\1l\1y\1hCongratulations, you are \1w%u%%\1y pure!\r\n\r\n"
-	,user->purity);
-pause();
-return(1);
-}
-
-int get_que(int i, user_t *inuser)
-{
-	char str[128];
-	int j,k,x,y,u;
-	user_t user=*inuser;
-
-if(que[i]->req_age>getage(inuser->birth))
-	return(0);
-for(j=0;j<que[i]->total_ques && !aborted;j++) {
-
-	u=user_quenum(que[i]->name,user);
-	if(u==-1) { 			/* not already answered */
-		for(u=0;u<5;u++)	/* search for unused questionnaire slot */
-			if(sys_quenum(user.queans[u].name)==-1)
-				break;
-		if(u==5) {		/* All questionnaire slots used!?? */
-			bputs("\r\n\7Questionnaire error, inform sysop!\r\n");
-			pause();
-			return(0); } }
-	strcpy(user.queans[u].name,que[i]->name);
-	cls();
-	bprintf("\1n\1m\1hQuestionnaire: \1y%-25s \1mQuestion: "
-		"\1y%d \1mof \1y%d  \1h\1b(Ctrl-C to Abort)\r\n\r\n"
-		,que[i]->desc,j+1,que[i]->total_ques);
-	bprintf("\1w\1h%s\r\n\r\n",que[i]->que[j].txt);
-	for(k=0;k<que[i]->que[j].answers;k++)
-		bprintf("\1h\1b%c\1w) \1g%s\r\n",'A'+k,que[i]->que[j].ans[k]);
-	nodesync();
-	bprintf("\1n\1g\r\nChoose %s%d answer%s to describe "
-		"\1hyourself\1n\1g%s: "
-		,que[i]->que[j].allowed > 1 ? "up to ":""
-		,que[i]->que[j].allowed,que[i]->que[j].allowed > 1 ? "s":""
-		,j ? " or \1h-\1n\1g to go back" : "");
-	bits2ans(user.queans[u].self[j],str);
-	getstr(str,que[i]->que[j].allowed,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
-	if(aborted)
-		return(0);
-	truncsp(str);
-	if(!str[0]) {
-		j--;
-		continue; }
-	if(str[0]=='-') {
-		if(j) j-=2;
-		else j--;
-		continue; }
-	y=strlen(str);
-	for(x=0;x<y;x++)
-		if(!isalpha(str[x]) || str[x]-'A'>que[i]->que[j].answers-1)
-			break;
-	if(x<y) {
-		j--;
-		continue; }
-	user.queans[u].self[j]=ans2bits(str);
-	nodesync();
-	bprintf("\1n\1g\r\n%s%d answer%s to describe your \1hpreferred mate"
-		"\1n\1g or \1h*\1n\1g for any: "
-		,que[i]->que[j].answers > 1 ? "Up to ":""
-		,que[i]->que[j].answers,que[i]->que[j].answers > 1 ? "s":"");
-	if(user.queans[u].pref[j])
-		bits2ans(user.queans[u].pref[j],str);
-	getstr(str,que[i]->que[j].answers,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
-	if(aborted)
-		return(0);
-	truncsp(str);
-	if(!str[0]) {
-		j--;
-		continue; }
-	y=strlen(str);
-	for(x=0;x<y;x++)
-		if(isalpha(str[x]) && str[x]-'A'>que[i]->que[j].answers-1)
-			break;
-	if(x<y) {
-		j--;
-		continue; }
-	user.queans[u].pref[j]=ans2bits(str); }
-*inuser=user;
-return(1);
-}
-
-/* Gets/updates profile from user. Returns 0 if aborted. */
-
-char get_user_info(user_t *user)
-{
-	char str[128],*p,*hdr;
-	int i,j,k,x,y;
-
-while(1) {
-	checkline();
-	timeleft=0xffff;
-	aborted=0;
-	main_user_info(*user);
-	CRLF;
-	bputs("\1n\1h");
-	bputs("\1b[\1wA\1b] Your name, height, weight, income, location, and "
-			"text\r\n"
-		  "\1b[\1wB\1b] Your marital status, race, hair color, and eye "
-			"color\r\n"
-		  "\1b[\1wC\1b] Preferred age, height, weight, location, and income\r\n"
-		  "\1b[\1wD\1b] Preferred sex, marital status, race, hair color, eye "
-			"color, and zodiac\r\n"
-		  );
-	for(i=0;i<total_ques;i++) {
-		if(que[i]->req_age>getage(user->birth))
-			continue;
-		bprintf("\1b[\1w%u\1b] \1w%s \1bquestionnaire\1b (%u questions) \1w%s\r\n"
-			,i+1,que[i]->desc,que[i]->total_ques
-			,user_quenum(que[i]->name,*user)==-1 ? "[Unanswered]":"[Answered]");
-			}
-	bprintf("\1b[\1wM\1b] Myers-Briggs personality test (70 questions) "
-		"\1w[%s]\r\n",user->mbtype[0] ? user->mbtype : "Unanswered");
-	if(fexist("PURITY.QUE") && purity_age<=getage(user->birth))
-		bprintf("\1b[\1wP\1b] Purity test \1w(%u%% pure)\r\n"
-			,user->purity);
-	bputs("\r\n\1bWhich or [\1wQ\1b]uit: \1w");
-	i=getkeys("ABCDMPQ",total_ques);
-	if(i&0x8000) {
-		i&=~0x8000;
-		i--;
-		get_que(i,user);
-		continue; }
-
-	switch(i) {
-		case 'A':
-			get_your_det(user);
-			break;
-		case 'C':
-			get_pref_det(user);
-			break;
-		case 'B':
-			get_your_multi(user);
-			break;
-		case 'D':
-			get_pref_multi(user);
-			break;
-		case 'M':
-			get_mbtype(user);
-			break;
-		case 'P':
-			get_purity(user);
-			break;
-		case 'Q':
-			return(1); } }
-}
-
-void write_user()
-{
-    char str[256];
-
-if(auto_update && time(NULL)-useron.updated>(long)auto_update*24L*60L*60L)
-	useron.updated=time(NULL);
-fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
-fwrite(&useron,sizeof(user_t),1,stream);
-fflush(stream);
-
-ixb.updated=useron.updated;
-if(useron.misc&USER_DELETED)
-    ixb.number=0;
-else
-    ixb.number=useron.number;
-strcpy(str,useron.name);
-strupr(str);
-ixb.name=crc32(str);
-ixb.system=system_crc;
-fseek(index,useron_record*sizeof(ixb_t),SEEK_SET);
-fwrite(&ixb,sizeof(ixb_t),1,index);
-fflush(index);
-if(!ixb.number) {
-	sprintf(str,"%04u.MSG",useron.number);
-	remove(str); }
-}
-
-
-void add_userinfo()
-{
-	static user_t user;
-	char str[128];
-	ushort tleft=timeleft;
-	int i;
-
-if(!cdt_warning(profile_cdt))
-	return;
-timeleft=0xffff;
-user.number=user_number;
-user.sex=user_sex;
-strcpy(user.name,user_name);
-strcpy(user.realname,user_name);
-strcpy(user.system,system_name);
-strcpy(user.birth,user_birth);
-strcpy(user.zipcode,user_zipcode);
-sprintf(user.min_zipcode,"%c0000",user_zipcode[0]);
-sprintf(user.max_zipcode,"%c9999",user_zipcode[0]);
-strcpy(user.location,user_location);
-if(user.sex!='M' && user.sex!='F') {
-	if(yesno("Are you of male gender"))
-		user.sex='M';
-	else
-		user.sex='F'; }
-if(!getage(user.birth))
-	while(1) {
-		checkline();
-		cls();
-		bputs("\1l\1y\1hYour birthdate (MM/DD/YY): ");
-		if(!getstr(user.birth,8,K_UPPER|K_LINE))
-			return;
-		if(getage(user.birth))
-			break; }
-
-user.pref_sex=user.sex=='M' ? 'F' : 'M';
-user.created=time(NULL);
-if(!get_your_det(&user) || !get_your_multi(&user) || !get_pref_multi(&user)
-	|| !get_pref_det(&user)) {
-	timeleft=tleft;
-	return; }
-for(i=0;i<total_ques;i++) {
-	aborted=0;
-	if(que[i]->req_age>getage(user.birth))
-		continue;
-	timeleft=0xffff;
-	cls();
-	bprintf("\1w\1h%s Questionnaire: \1y%u questions\r\n\r\n"
-		"\1cAnswers will be viewable by other users.\r\n\r\n"
-		,que[i]->desc,que[i]->total_ques);
-	if(yesno("Continue with questionnaire"))
-		get_que(i,&user); }
-timeleft=0xffff;
-get_mbtype(&user);
-timeleft=0xffff;
-get_purity(&user);
-if(!get_user_info(&user)) {
-	timeleft=tleft;
-	return; }
-user.updated=time(NULL);
-useron=user;
-bputs("\1n\1h\r\nSaving...");
-rewind(index);
-while(!feof(index)) {
-	if(!fread(&ixb,sizeof(ixb_t),1,index))
-		break;
-	if(!ixb.number) {	  /* Deleted User */
-		fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-		break; } }
-
-useron_record=ftell(index)/sizeof(ixb_t);
-
-write_user();
-adjust_cdt(profile_cdt);
-
-if(notify_user && notify_user!=user_number) {
-	sprintf(str,"\1n\1hSMM: \1y%s \1madded %s profile to the Match Maker.\r\n"
-		,user_name,user_sex=='M' ? "his":"her");
-	if(node_dir[0])
-		putsmsg(notify_user,str);
-	else
-		puttgram(notify_user,str); }
-
-timeleft=tleft;
-}
-
-void delphoto(user_t user)
-{
-	char fname[64],path[128];
-	int i;
-	struct ffblk ff;
-
-if(!(user.misc&USER_PHOTO))
-	return;
-for(i=0;user.system[i];i++)
-	if(isalnum(user.system[i]))
-        break;
-if(!user.system[i])
-	fname[0]='~';
-else
-	fname[0]=user.system[i];
-for(i=strlen(user.system)-1;i>0;i--)
-	if(isalnum(user.system[i]))
-		break;
-if(i<=0)
-	fname[1]='~';
-else
-	fname[1]=user.system[i];
-fname[2]=0;
-strupr(user.system);
-strcat(fname,base41(crc16(user.system),tmp));
-strcat(fname,base41(user.number,tmp));
-strcat(fname,".*");
-strupr(fname);
-sprintf(path,"PHOTO\\%s",fname);
-i=findfirst(path,&ff,0);
-if(i)
-	return;
-sprintf(path,"PHOTO\\%s",ff.ff_name);
-if(remove(path))
-	bprintf("\1r\1h\7%s couldn't be removed!\1n\r\n",path);
-else
-	bprintf("\1r\1hPhoto removed.\r\n");
-}
-
-
-void smm_exit()
-{
-	char str[128];
-	int i;
-	FILE *in,*out;
-
-if(io_int) {
-	io_int=0;
-	ivhctl(0); }
-if(com_port) {
-	for(i=0;i<5;i++)
-		if(!rioctl(TXBC))		/* wait for rest of output */
-			break;
-		else
-			mswait(1000);
-    rioini(0,0); }
-if(useron.number) {
-	useron.lastin=time(NULL);
-	write_user(); }
-if(stream)
-	fclose(stream);
-if(cdt_adjustment) {
-	if(node_dir[0]) {
-		sprintf(str,"%sMODUSER.DAT",node_dir);
-		if((out=fopen(str,"wt"))==NULL) {
-			bprintf("Error opening %s for write\r\n",str);
-			return; }
-		fprintf(out,"%ld",cdt_adjustment);
-		fclose(out); }
-	else {							/* Write back credits to DOOR.SYS */
-		strcpy(str,door_sys);
-		str[strlen(str)-1]='_';
-		remove(str);
-		rename(door_sys,str);
-		if((in=fopen(str,"rb"))==NULL) {
-			bprintf("Error opening %s for read\r\n",str);
-            return; }
-		if((out=fopen(door_sys,"wb"))==NULL) {
-			bprintf("Error opening %s for write\r\n",door_sys);
-			return; }
-		for(i=0;!feof(in);i++) {
-			if(!fgets(tmp,128,in))
-				break;
-			if(i+1==30)
-				fprintf(out,"%ld\r\n",-(cdt_adjustment/1024L));
-			else if(i+1==31)
-				fprintf(out,"%ld\r\n",(user_cdt+cdt_adjustment)/1024L);
-			else
-				fprintf(out,"%s",tmp); }
-		fclose(in);
-		fclose(out);
-		remove(str);
-		} }
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-void statusline(void)
-{
-	int col,row;
-
-col=lclwx();
-row=lclwy();
-lclxy(1,node_scrnlen);
-lclatr(CYAN|HIGH|(BLUE<<4));
-lputs("  ");
-lprintf("%-25.25s %02d %-25.25s  %02d %c %s"
-    ,user_name,user_level,user_realname[0] ? user_realname : user_location
-    ,getage(user_birth)
-    ,user_sex ? user_sex : SP
-    ,user_phone);
-lputc(CLREOL);
-lclatr(LIGHTGRAY);
-lclxy(col,row);
-}
-
-
-int minor_protection(user_t user)
-{
-if(!user_number || !age_split || SYSOP)
-	return(0);
-if(getage(user_birth)<age_split && getage(user.birth)>=age_split)
-	return(1);
-if(getage(user_birth)>=age_split && getage(user.birth)<age_split)
-	return(1);
-return(0);
-}
-
-void main(int argc, char **argv)
-{
-	char	str[512],name[128],desc[128],gotoname[128],*p,ext,ch;
-	int 	i,j,k,file,match,found;
-	uint	base=0xffff;
-	ushort	tleft;
-	long	l,offset;
-	ulong	name_crc,sys_crc,*crc_lst,ul;
-	FILE	*fp,*que_lst;
-	user_t	user;
-	wall_t	wall;
-	struct	ffblk ff;
-
-nodefile=-1;
-node_misc=NM_LOWPRIO;
-com_port=-1;
-com_base=0;
-com_irq=com_rate=0;
-node_dir[0]=exec_dir[0]=temp_dir[0]=ctrl_dir[0]=door_sys[0]=system_name[0]=0;
-sys_name[0]=0;
-
-p=getenv("SBBSNODE");
-if(p) {
-	strcpy(node_dir,p);
-	if(node_dir[strlen(node_dir)-1]!='\\')
-		strcat(node_dir,"\\");
-	initdata(); }
-
-gotoname[0]=0;
-for(i=1;i<argc;i++) {
-	if(argv[i][0]=='/') {
-		switch(toupper(argv[i][1])) {
-			case 'P':
-				com_port=atoi(argv[i]+2);
-				break;
-			case 'I':
-				com_irq=atoi(argv[i]+2);
-				break;
-			case 'C':
-				com_base=ahtoul(argv[i]+2);
-				break;
-			case 'R':
-				com_rate=atol(argv[i]+2);
-				break;
-			case 'T':
-				mswtyp=atoi(argv[i]+2);
-				break;
-			case 'N':
-				node_dir[0]=0;
-				break;
-			default:
-				printf("\nusage: SMM [DOOR.SYS] [/option] [/option] [...] [user name]\n");
-				printf("\n");
-				printf("where:\n");
-				printf("       DOOR.SYS is the path and filename of DOOR.SYS\n");
-				printf("\n");
-				printf("       /p# sets com port\n");
-				printf("       /i# sets com irq\n");
-				printf("       /c# sets com I/O address (or DIGI or FOSSIL)\n");
-				printf("       /r# sets com rate\n");
-				printf("       /t# sets time-slice API support\n");
-				printf("\n");
-				printf("       user name (if specified) is user to look-up\n");
-				exit(1); }
-		continue; }
-	if(!node_dir[0] && !door_sys[0]) {
-		strcpy(door_sys,argv[i]);
-		continue; }
-	if(gotoname[0])
-		strcat(gotoname," ");
-	strcat(gotoname,argv[i]); }
-
-if(!node_dir[0] && !door_sys[0]) {
-	printf("\n\7SBBSNODE environment variable not set and DOOR.SYS not "
-		"specified.\n");
-	exit(1); }
-
-if(door_sys[0]) {
-	#ifdef __TURBOC__
-		ctrlbrk(cbreakh);
-	#endif
-
-	#ifdef __WATCOMC__
-		putenv("TZ=UCT0");
-		setvbuf(stdout,NULL,_IONBF,0);
-		setvbuf(stderr,NULL,_IONBF,0);
-	#endif
-
-	if(setmode(fileno(stderr),O_BINARY)==-1) {	 /* eliminate LF expansion */
-		printf("\n\7Can't set stderr to BINARY\n");
-		exit(1); }
-
-	starttime=time(NULL);			/* initialize start time stamp */
-	wordwrap[0]=0;					/* set wordwrap to null */
-	attr(LIGHTGRAY);				/* initialize color and curatr to plain */
-	mnehigh=LIGHTGRAY|HIGH; 		/* mnemonics highlight color */
-	mnelow=GREEN;					/* mnemonics normal text color */
-	sec_warn=180;					/* seconds till inactivity warning */
-	sec_timeout=300;				/* seconds till inactivity timeout */
-	tos=lncntr=0;					/* init topofscreen and linecounter to 0 */
-	lastnodemsg=0;					/* Last node to send message to */
-	aborted=0;						/* Ctrl-C hit flag */
-
-	fp=fopen(door_sys,"rb");
-	if(!fp) {
-		printf("\n\7ERROR opening %s\n",door_sys);
-		exit(2); }
-	user_misc=user_flags2[0]=user_flags3[0]=user_flags4[0]=0;
-	user_rest[0]=user_exempt[0]=0;
-	user_sex=user_address[0]=user_zipcode[0]=user_realname[0]=0;
-	str[0]=0;
-	fgets(str,81,fp);				// 01: COM port - if local
-	if(com_port==-1)
-		com_port=atoi(str+3);
-	str[0]=0;
-	fgets(str,81,fp);				// 02: DCE Rate
-	user_dce=atoi(str);
-	fgets(str,81,fp);				// 03: Data bits
-	str[0]=0;
-	fgets(str,81,fp);				// 04: Node num
-	node_num=atoi(str);
-	str[0]=0;
-	fgets(str,81,fp);				// 05: DTE rate
-	if(!com_rate)
-		com_rate=atol(str);
-	fgets(str,81,fp);				// 06: Screen display
-	fgets(str,81,fp);				// 07: Printer toggle
-	fgets(str,81,fp);				// 08: Page bell
-	fgets(str,81,fp);				// 09: Caller alarm
-	str[0]=0;
-	fgets(str,81,fp);				// 10: User name
-	sprintf(user_name,"%.25s",str);
-	truncsp(user_name);
-	str[0]=0;
-	fgets(str,81,fp);				// 11: User location
-	sprintf(user_location,"%.30s",str);
-	truncsp(user_location);
-	str[0]=0;
-	fgets(str,81,fp);				// 12: Home phone
-	sprintf(user_phone,"%.12s",str);
-	truncsp(user_phone);
-	fgets(str,81,fp);				// 13: Work phone
-	fgets(str,81,fp);				// 14: Password
-	str[0]=0;
-	fgets(str,81,fp);				// 15: Security Level
-	user_level=atoi(str);
-	fgets(str,81,fp);				// 16: Total logons
-	fgets(str,81,fp);				// 17: Last on date
-	str[0]=0;
-	fgets(str,81,fp);				// 18: Time left in seconds
-	timeleft=atoi(str);
-	fgets(str,81,fp);				// 19: Time left in minutes
-	str[0]=0;
-	fgets(str,81,fp);				// 20: Graphics
-	if(!strnicmp(str,"GR",2))
-		user_misc|=(COLOR|ANSI);
-	str[0]=0;
-	fgets(str,81,fp);				// 21: Screen length
-	user_rows=atoi(str);
-	if(user_rows<10)
-		user_rows=24;
-	fgets(str,81,fp);				// 22: Expert?
-	str[0]=0;
-	fgets(str,81,fp);				// 23: Registered conferences
-	sprintf(user_flags1,"%.26s",str);
-	truncsp(user_flags1);
-	fgets(str,81,fp);				// 24: Conference came from
-	str[0]=0;
-	fgets(str,81,fp);				// 25: User's expiration date
-	user_expire=dstrtounix(str);
-	str[0]=0;
-	fgets(str,81,fp);				// 26: User's number
-	user_number=atoi(str);
-	fgets(str,81,fp);				// 27: Default protocol
-	fgets(str,81,fp);				// 28: Total uploads
-	fgets(str,81,fp);				// 29: Total downloads
-	fgets(str,81,fp);				// 30: Kbytes downloaded today
-	str[0]=0;
-	fgets(str,81,fp);				// 31: Max Kbytes to download today
-	user_cdt=atol(str)*1024UL;
-	str[0]=0;
-	fgets(str,81,fp);				// 32: Birthday
-	truncsp(str);
-	sprintf(user_birth,"%.8s",str);
-	fgets(str,81,fp);				// 33: Path to MAIN
-	fgets(str,81,fp);				// 34: Path to GEN
-	str[0]=0;
-	fgets(str,81,fp);				 // 35: Sysop's name
-	sprintf(sys_op,"%.40s",str);
-	truncsp(sys_op);
-	fclose(fp);
-	con_fp=stderr;
-	if(setmode(fileno(con_fp),O_BINARY)==-1) {	 /* eliminate LF expansion */
-		printf("Can't set console output to BINARY\n");
-		exit(1); }
-	}
-
-if(!user_number) {
-	printf("\7\nERROR: Invalid user number (%u)\n",user_number);
-	exit(5); }
-
-if(*(&riobp-1)!=23) {
-    printf("Wrong rciol.obj\n");
-    exit(1); }
-
-node_scrnlen=lclini(0xd<<8);	  /* Tab expansion, no CRLF expansion */
-lclini(node_scrnlen-1);
-
-if(com_port) {
-	lprintf("\r\nInitializing COM port %u: ",com_port);
-	switch(com_base) {
-		case 0xb:
-			lputs("PC BIOS");
-			rioctl(I14PC);
-			if(!com_irq) com_irq=com_port-1;
-			break;
-		case 0xffff:
-		case 0xd:
-			lputs("DigiBoard");
-			rioctl(I14DB);
-			if(!com_irq) com_irq=com_port-1;
-			break;
-		case 0xe:
-			lputs("PS/2 BIOS");
-			rioctl(I14PS);
-			if(!com_irq) com_irq=com_port-1;
-			break;
-		case 0xf:
-			lputs("FOSSIL");
-			rioctl(I14FO);
-			if(!com_irq) com_irq=com_port-1;
-			break;
-		case 0:
-			base=com_port;
-			lputs("UART I/O (BIOS), ");
-			if(com_irq)
-				lprintf("IRQ %d",com_irq);
-			else lputs("default IRQ");
-			break;
-		default:
-			base=com_base;
-			lprintf("UART I/O %Xh, ",com_base);
-			if(com_irq)
-				lprintf("IRQ %d",com_irq);
-			else lputs("default IRQ");
-			break; }
-
-	if(base==0xffff)
-		lprintf(" channel %u",com_irq);
-	i=rioini(base,com_irq);
-	if(i) {
-		lprintf(" - Failed! (%d)\r\n",i);
-		exit(1); }
-	if(mdm_misc&MDM_FLOWCTRL)
-		rioctl(IOSM|CTSCK|RTSCK); /* set rts/cts chk */
-	if(com_rate)
-		setbaud((uint)(com_rate&0xffffL));
-	msr=&riobp-1; }
-
-/* STATUS LINE */
-statusline();
-
-rioctl(TSTYPE|mswtyp);	 /* set time-slice API type */
-
-rioctl(CPTON);			/* ctrl-p translation */
-
-i=INT29L;
-if(com_port)
-	i|=(INT29R|INT16);
-ivhctl(i);
-io_int=1;
-
-atexit(smm_exit);
-
-printf("\r\nSynchronet Match Maker  v%s  Developed 1995-1997 Rob Swindell\n\n"
-    ,SMM_VER);
-
-if(checktime()) {
-    printf("Time problem!\n");
-    return; }
-
-if((file=nopen("SMM.CFG",O_RDONLY))==-1) {
-	bprintf("\r\n\7Error opening/creating SMM.DAB\r\n");
-    exit(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	bprintf("\r\n\7Error converting SMM.DAB file handle to stream\r\n");
-    exit(1); }
-str[0]=0;
-fgets(str,128,stream);
-purity_age=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-min_age=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-min_level=atoi(str);
-
-req_flags1[0]=0;
-fgets(req_flags1,128,stream);
-req_flags1[27]=0;
-truncsp(req_flags1);
-
-req_flags2[0]=0;
-fgets(req_flags2,128,stream);
-req_flags2[27]=0;
-truncsp(req_flags2);
-
-req_flags3[0]=0;
-fgets(req_flags3,128,stream);
-req_flags3[27]=0;
-truncsp(req_flags3);
-
-req_flags4[0]=0;
-fgets(req_flags4,128,stream);
-req_flags4[27]=0;
-truncsp(req_flags4);
-
-str[0]=0;
-fgets(str,128,stream);
-profile_cdt=atol(str);
-str[0]=0;
-fgets(str,128,stream);
-telegram_cdt=atol(str);
-str[0]=0;
-fgets(str,128,stream);
-auto_update=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-notify_user=atoi(str);
-
-fgets(str,128,stream);		// regnum
-
-str[0]=0;
-fgets(str,128,stream);
-telegram_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-que_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-wall_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-wall_cdt=atol(str);
-
-str[0]=0;
-fgets(str,128,stream);
-que_cdt=atol(str);
-
-fgets(zmodem_send,128,stream);
-if(!zmodem_send[0])
-    strcpy(zmodem_send,DEFAULT_ZMODEM_SEND);
-truncsp(zmodem_send);
-
-str[0]=0;
-fgets(str,128,stream);
-smm_misc=atol(str);
-
-fgets(str,128,stream);
-sprintf(system_name,"%.40s",str);
-truncsp(system_name);
-
-fgets(local_view,128,stream);
-truncsp(local_view);
-
-str[0]=0;
-fgets(str,128,stream);
-sysop_level=atoi(str);
-if(!sysop_level)
-    sysop_level=90;
-
-str[0]=0;
-fgets(str,128,stream);
-wall_age=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-age_split=atoi(str);
-
-fclose(stream);
-
-if(!system_name[0] && sys_name[0])
-	strcpy(system_name,sys_name);
-if(!system_name[0]) {
-    printf("\7\nERROR: System name not specified\n");
-    exit(3) ; }
-
-sprintf(str,"%.25s",system_name);
-strupr(str);
-system_crc=crc32(str);
-
-if((file=open("SMM.DAB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	bprintf("\r\n\7Error opening/creating SMM.DAB\r\n");
-    exit(1); }
-if((stream=fdopen(file,"w+b"))==NULL) {
-	bprintf("\r\n\7Error converting SMM.DAB file handle to stream\r\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,4096);
-
-if((file=open("SMM.IXB",O_RDWR|O_BINARY|SH_DENYNO|O_CREAT
-    ,S_IWRITE|S_IREAD))==-1) {
-	bprintf("\r\n\7Error opening/creating SMM.IXB\r\n");
-    exit(1); }
-if((index=fdopen(file,"w+b"))==NULL) {
-	bprintf("\r\n\7Error converting SMM.IXB file handle to stream\r\n");
-    exit(1); }
-setvbuf(stream,0L,_IOFBF,1024);
-
-trashfile=NULL;
-if((file=open("SMM.CAN",O_RDONLY|SH_DENYNO))!=-1) {
-	trashfile=fdopen(file,"rb");
-	setvbuf(trashfile,NULL,_IOFBF,4096); }
-
-total_ques=0;
-i=nopen("QUE.LST",O_RDONLY);
-if(i!=-1)
-	que_lst=fdopen(i,"rb");
-else
-	que_lst=NULL;
-i=0;
-while(que_lst && !feof(que_lst) && i<5) {
-	if(!fgets(name,81,que_lst))
-		break;
-	truncsp(name);
-	strupr(name);
-	sprintf(str,"%s.QUE",name);
-	if(!fgets(desc,81,que_lst))
-		break;
-	truncsp(desc);
-	if(!fgets(tmp,81,que_lst))
-		break;
-	truncsp(tmp);
-	if((file=nopen(str,O_RDONLY))!=-1) {
-		fp=fdopen(file,"rb");
-		total_ques++;
-		if((que[i]=(questionnaire_t *)MALLOC(sizeof(questionnaire_t)))==NULL) {
-			bprintf("Can't malloc questionnaires!\r\n");
-			exit(1); }
-		sprintf(que[i]->name,"%.8s",name);
-		sprintf(que[i]->desc,"%.25s",desc);
-		que[i]->req_age=atoi(tmp);
-		fgets(str,128,fp);
-		que[i]->total_ques=atoi(str);
-		if(que[i]->total_ques<1 || que[i]->total_ques>20) {
-			bprintf("Invalid number of questions (%d) in questionnaire #%d\r\n"
-				,que[i]->total_ques,i+1);
-			exit(1); }
-		for(j=0;j<que[i]->total_ques;j++) {
-			if(!fgets(str,128,fp))
-				break;
-			truncsp(str);
-			if(!str[0])
-				break;
-			str[80]=0;
-			strcpy(que[i]->que[j].txt,str);
-			fgets(str,128,fp);
-			que[i]->que[j].answers=atoi(str);
-			if(que[i]->que[j].answers<1 || que[i]->que[j].answers>16) {
-				bprintf("Invalid number of answers (%d) in question #%d "
-					"of questionnaire #%d\r\n"
-					,que[i]->que[j].answers,j+1,i+1);
-				exit(1); }
-			fgets(str,128,fp);
-			que[i]->que[j].allowed=atoi(str);
-			for(k=0;k<que[i]->que[j].answers;k++) {
-				if(!fgets(str,128,fp))
-					break;
-				truncsp(str);
-				if(!str[0])
-					break;
-				str[60]=0;
-				strcpy(que[i]->que[j].ans[k],str); }
-			que[i]->que[j].answers=k; }
-
-		que[i]->total_ques=j; }
-	fclose(fp);
-	i++; }
-fclose(que_lst);
-
-lncntr=0;
-getsmsg(user_number);
-if(lncntr)
-	pause();
-
-memset(&useron,0,sizeof(user_t));
-
-atexit(smm_exit);
-
-bputs("\1n\1hSearching for your profile...");
-rewind(index);
-while(!feof(index)) {
-	if(!fread(&ixb,sizeof(ixb_t),1,index))
-		break;
-	if(ixb.system==system_crc && ixb.number==user_number) {
-		useron_record=(ftell(index)-sizeof(ixb_t))/sizeof(ixb_t);
-		fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
-		fread(&user,sizeof(user_t),1,stream);
-		if(stricmp(user.realname,user_name)) {	/* new name, so delete it */
-			user.misc|=USER_DELETED;
-			fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
-			fwrite(&user,sizeof(user_t),1,stream);
-			fseek(stream,0,SEEK_CUR);
-			fseek(index,ftell(index)-sizeof(ixb_t),SEEK_SET);
-			ixb.number=0;
-			fwrite(&ixb,sizeof(ixb_t),1,index);
-			sprintf(str,"%04u.MSG",user_number);
-			remove(str);
-			continue; }
-		useron=user;		/* name matches, same user */
-		break; } }
-fflush(stream);
-fflush(index);
-CRLF;
-
-if(useron.number && useron.sex!='M' && useron.sex!='F') {
-	if(yesno("Are you of male gender"))
-		useron.sex='M';
-	else
-		useron.sex='F';
-	write_user();
-	user_sex=useron.sex; }
-
-if(!useron.number && user_sex!='M' && user_sex!='F' && can_add()) {
-	if(yesno("Are you of male gender"))
-		user_sex='M';
-	else
-		user_sex='F'; }
-
-if(!useron.number && can_add()) {
-	sprintf(str,"%04u.MSG",user_number);
-	remove(str);
-	printfile("SMM_LOGO.ASC");
-	if(yesno("\r\nYour profile doesn't exist. Create it now"))
-		add_userinfo(); }
-
-if(gotoname[0]) {
-	strupr(gotoname);
-	name_crc=crc32(gotoname);
-	rewind(index);
-	i=0;
-	while(!feof(index)) {
-		if(!fread(&ixb,sizeof(ixb_t),1,index))
-			break;
-		if(!ixb.number)    /* DELETED */
-			continue;
-		if(ixb.name!=name_crc)
-			continue;
-		fseek(stream
-			,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-			*sizeof(user_t),SEEK_SET);
-		if(!fread(&user,sizeof(user_t),1,stream))
-			continue;
-		if(minor_protection(user))
-			continue;
-		i=1;
-		if(!long_user_info(user))
-			break; }
-	if(!i) {
-		bprintf("\r\n\1n\1h%s \1rnot found.\r\n",gotoname);
-		pause(); }
-	return; }
-
-/*********************************************/
-/* ALL User Messages (from Digital Dynamics) */
-/*********************************************/
-for(i=findfirst("ALL*.MSG",&ff,0);!i;i=findnext(&ff)) {
-	if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
-		bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	if((fp=fdopen(j,"rb"))==NULL) {
-		bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	str[0]=0;
-	fgets(str,128,fp);
-	truncsp(str);
-	ul=ahtoul(str);    /* Expiration date */
-	ul^=0x305F6C81UL;
-	attr(LIGHTGRAY);
-	cls();
-	while(!feof(fp)) {
-		if(!fgets(str,128,fp))
-			break;
-		bputs(str); }
-	fclose(fp);
-	CRLF;
-	if(ul<=time(NULL))
-		remove(ff.ff_name); }
-
-/**************************************************/
-/* One-time User Messages (from Digital Dynamics) */
-/**************************************************/
-for(i=findfirst("ONE*.MSG",&ff,0);!i;i=findnext(&ff)) {
-	if(fdate_dir(ff.ff_name)<useron.lastin)
-		continue;
-	if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
-		bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	if((fp=fdopen(j,"rb"))==NULL) {
-		bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	str[0]=0;
-	fgets(str,128,fp);
-	truncsp(str);
-	ul=ahtoul(str);    /* Expiration date */
-	ul^=0x305F6C81UL;
-	attr(LIGHTGRAY);
-	cls();
-	while(!feof(fp)) {
-		if(!fgets(str,128,fp))
-			break;
-		bputs(str); }
-	fclose(fp);
-	CRLF;
-	if(ul<=time(NULL))
-        remove(ff.ff_name); }
-
-/******************************************/
-/* Sysop Messages (from Digital Dynamics) */
-/******************************************/
-for(i=findfirst("SYS*.MSG",&ff,0);SYSOP && !i;i=findnext(&ff)) {
-	if((j=nopen(ff.ff_name,O_RDONLY))==-1) {
-		bprintf("\1n\1r\1hCan't open \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	if((fp=fdopen(j,"rb"))==NULL) {
-		bprintf("\1n\1r\1hCan't fdopen \1w%s\r\n",ff.ff_name);
-		pause();
-		continue; }
-	str[0]=0;
-	fgets(str,128,fp);
-	truncsp(str);
-	ul=ahtoul(str);    /* Expiration date */
-	ul^=0x305F6C81UL;
-	attr(LIGHTGRAY);
-	cls();
-	while(!feof(fp)) {
-		if(!fgets(str,128,fp))
-			break;
-		bputs(str); }
-	fclose(fp);
-	CRLF;
-	if(ul<=time(NULL) || !noyes("Delete message"))
-        remove(ff.ff_name); }
-
-statusline();
-while(1) {
-	checkline();
-	aborted=0;
-	attr(LIGHTGRAY);
-	cls();
-
-	bprintf("\1n  \1b\1hSynchronet \1cMatch Maker  \1bv%s (XSDK v%s)  "
-		"Developed 1995-1997 Rob Swindell\1n\r\n\r\n",SMM_VER,xsdk_ver);
-	printfile("SMM_LOGO.ASC");
-	CRLF;
-
-	l=filelength(fileno(stream));
-	if(l<0) l=0;
-	sprintf(str,"\1n\1cThere are \1h%lu\1n\1c entries in the user profile "
-		"database.\r\n",l/(long)sizeof(user_t));
-	center(str);
-
-	sprintf(str,"%04u.MSG",user_number);
-	if(fexist(str))
-		center("\1h\1mYou have awaiting telegrams!\r\n");
-
-	if(flength("WALL.DAB")>0)
-		center("\1h\1cThere is writing on the Wall.\r\n");
-
-	if(!useron.number)
-		center("\1h\1rYou have not yet created a profile!\r\n");
-
-	printfile("SMM_MAIN.ASC");
-
-	nodesync(); 			/* Display any waiting messages */
-
-	bprintf("\r\n%32s\1b\1hWhich or [\1wQ\1b]uit: \1h\1w",nulstr);
-	ch=getkey(K_UPPER);
-//	  bprintf("%c\r\n",ch);
-	bputs("\r\1>");
-	switch(ch) {
-		case '?':
-			break;
-		case '*':
-			if(!SYSOP)
-				break;
-			bputs("\1n\1hSearching...");
-			rewind(stream);
-			while(!feof(stream) && !aborted) {
-				if(!fread(&user,sizeof(user_t),1,stream))
-					break;
-				if(user.misc&USER_DELETED) {
-					sprintf(str,"\r\nUndelete \1c%s \1b(\1c%s@%s\1b)"
-						,user.name,user.realname,user.system);
-					if(!yesno(str))
-						continue;
-					fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
-					user.misc&=~USER_DELETED;
-					fwrite(&user,sizeof(user_t),1,stream);
-					fseek(stream,0,SEEK_CUR);
-					fseek(index
-						,((ftell(stream)-sizeof(user_t))/sizeof(user_t))
-						*sizeof(ixb_t),SEEK_SET);
-					strcpy(str,user.name);
-					strupr(str);
-					ixb.name=crc32(str);
-					sprintf(str,"%.25s",user.system);
-					strupr(str);
-					ixb.system=crc32(str);
-					ixb.updated=user.updated;
-					ixb.number=user.number;
-					fwrite(&ixb,sizeof(ixb_t),1,index);
-					} }
-			fflush(stream);
-			fflush(index);
-			break;
-		case '!':
-			if(!SYSOP)
-				break;
-			cls();
-			bputs("\1n\1hSystems Participating in Your Database:\r\n\r\n\1m");
-			crc_lst=NULL;
-			j=0;
-			rewind(stream);
-			while(!feof(stream) && !aborted) {
-				if(!fread(&user,sizeof(user_t),1,stream))
-                    break;
-				if(user.misc&USER_DELETED || !(user.misc&USER_FROMSMB))
-					continue;
-				if(!smm_pause)
-					lncntr=0;
-				sprintf(str,"%.25s",user.system);
-				strupr(str);
-				sys_crc=crc32(str);
-				for(i=0;i<j;i++)
-					if(sys_crc==crc_lst[i])
-						break;
-				if(i==j) {
-					crc_lst=REALLOC(crc_lst,(j+1)*sizeof(ulong));
-					if(crc_lst==NULL) {
-						printf("REALLOC error!\n");
-						pause();
-						break; }
-					crc_lst[j++]=sys_crc;
-					bprintf("%s\r\n",user.system); } }
-			if(crc_lst)
-				FREE(crc_lst);
-			if(j)
-				bprintf("\1n\r\n\1h%u systems listed.\r\n",j);
-			pause();
-			break;
-		case '\\':
-			if(!SYSOP)
-				break;
-			bprintf("Rebuilding Index...");
-			rewind(stream);
-			rewind(index);
-			while(!feof(stream)) {
-				if(!fread(&user,sizeof(user_t),1,stream))
-					break;
-				if(user.misc&USER_DELETED)
-					ixb.number=0;
-				else
-					ixb.number=user.number;
-				strupr(user.name);
-				ixb.name=crc32(user.name);
-				strupr(user.system);
-				user.system[25]=0;
-				ixb.system=crc32(user.system);
-				ixb.updated=user.updated;
-				fwrite(&ixb,sizeof(ixb_t),1,index); }
-			break;
-		case 'R':
-			if(useron.number) {
-				bputs("\1y\1hMinimum match percentage: \1w");
-				sprintf(str,"%u",useron.min_match);
-				if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
-					break;
-				useron.min_match=atoi(str);
-				if(useron.min_match>100)
-					useron.min_match=100; }
-			rewind(stream);
-			bprintf("\1n\1l\1hSearching...");
-			while(!feof(stream) && !aborted) {
-				if(!fread(&user,sizeof(user_t),1,stream))
-					break;
-				if(user.misc&USER_DELETED)
-					continue;
-				if(minor_protection(user))
-					continue;
-				if(useron.min_match && useron.number) {
-					match=total_match(useron,user);
-					if(match<useron.min_match)
-						continue; }
-				if(!long_user_info(user))
-					break;
-				if(!smm_pause)
-					lncntr=0;
-				bprintf("\1n\1l\1hSearching..."); }
-			break;
-		case 'F':
-			bputs("\1y\1hText to search for: ");
-			if(!getstr(str,25,K_UPPER|K_LINE))
-                break;
-			ext=yesno("\r\nDisplay extended profiles");
-			cls();
-			if(!smm_pause && !ext)
-				printfile("LIST_HDR.ASC");
-			rewind(stream);
-			i=0;
-			while(!aborted) {
-				bprintf("\1n\1l\1hSearching...");
-				while(!feof(stream) && !aborted) {
-					if(!fread(&user,sizeof(user_t),1,stream))
-						break;
-					if(user.misc&USER_DELETED)
-						continue;
-					if(minor_protection(user))
-						continue;
-					tmpuser=user;
-					sprintf(tmp,"%lu",user.number);
-					strupr(user.name);
-					strupr(user.realname);
-					strupr(user.system);
-					strupr(user.location);
-					strupr(user.note[0]);
-					strupr(user.note[1]);
-					strupr(user.note[2]);
-					strupr(user.note[3]);
-					strupr(user.note[4]);
-					if(strstr(user.name,str)
-						|| strstr(user.location,str)
-						|| strstr(user.mbtype,str)
-						|| strstr(user.note[0],str)
-						|| strstr(user.note[1],str)
-						|| strstr(user.note[2],str)
-						|| strstr(user.note[3],str)
-						|| strstr(user.note[4],str)
-						|| (SYSOP && strstr(user.realname,str))
-						|| (SYSOP && strstr(user.system,str))
-						|| (SYSOP && !strcmp(tmp,str))
-						) {
-						i=1;
-						if(ext && !long_user_info(tmpuser))
-							break;
-						if(!ext && short_user_info(tmpuser)==0)
-							break;
-						if(!smm_pause)
-							lncntr=0; } }
-				if(aborted || ext || !lncntr)
-					break;
-				user.number=0;
-				if(short_user_info(user)>=0)
-					break; }
-			if(!i)
-				bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
-            break;
-		case 'G':
-			bputs("\1y\1hUser name: ");
-			if(!getstr(str,25,K_UPPER|K_LINE))
-                break;
-			truncsp(str);
-			name_crc=crc32(str);
-			rewind(index);
-			i=0;
-			while(!feof(index)) {
-				if(!fread(&ixb,sizeof(ixb_t),1,index))
-					break;
-				if(!ixb.number)    /* DELETED */
-					continue;
-				if(ixb.name!=name_crc)
-					continue;
-				fseek(stream
-					,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-					*sizeof(user_t),SEEK_SET);
-				if(!fread(&user,sizeof(user_t),1,stream))
-					continue;
-				if(minor_protection(user))
-                    continue;
-				i=1;
-				if(!long_user_info(user))
-					break; }
-			if(!i)
-				bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
-            break;
-		case 'L':
-			if(useron.number) {
-				bputs("\1y\1hMinimum match percentage: \1w");
-				sprintf(str,"%u",useron.min_match);
-				if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
-					break;
-				useron.min_match=atoi(str);
-				if(useron.min_match>100)
-					useron.min_match=100; }
-			cls();
-			if(!smm_pause)
-				printfile("LIST_HDR.ASC");
-			rewind(stream);
-			while(!aborted) {
-				while(!feof(stream) && !aborted) {
-					if(!fread(&user,sizeof(user_t),1,stream))
-						break;
-					if(user.misc&USER_DELETED)
-						continue;
-					if(minor_protection(user))
-						continue;
-					if(useron.min_match && useron.number) {
-						match=total_match(useron,user);
-						if(match<useron.min_match)
-							continue; }
-					if(!short_user_info(user))
-						break;
-					if(!smm_pause)
-						lncntr=0; }
-				if(aborted || !lncntr)
-					break;
-				user.number=0;
-				if(short_user_info(user)>=0)
-					break; }
-            break;
-
-		case 'N':
-			while(1) {
-				checkline();
-				bputs("\1y\1hLast update (MM/DD/YY): ");
-				if(useron.number)
-					unixtodstr(useron.lastin,str);
-				else
-					str[0]=0;
-				if(!getstr(str,8,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-					break;
-				if(isdigit(str[0]) && isdigit(str[1]) && str[2]=='/'
-					&& isdigit(str[3]) && isdigit(str[4]) && str[5]=='/'
-					&& isdigit(str[6]) && isdigit(str[7]))
-					break;
-				bputs("\r\n\1h\1rInvalid date!\r\n\r\n"); }
-			if(!str[0] || aborted)
-				break;
-			l=dstrtounix(str);
-			if(useron.number) {
-				bputs("\1y\1h\r\nMinimum match percentage: \1w");
-				sprintf(str,"%u",useron.min_match);
-				if(!getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL) || aborted)
-					break;
-				useron.min_match=atoi(str);
-				if(useron.min_match>100)
-					useron.min_match=100; }
-			ext=!noyes("\r\nDisplay extended profiles");
-			if(aborted)
-				break;
-			cls();
-			if(!ext && !smm_pause)
-				printfile("LIST_HDR.ASC");
-			rewind(index);
-			while(!aborted) {
-				while(!feof(index) && !aborted) {
-					if(!smm_pause)
-						lncntr=0;
-					if(!fread(&ixb,sizeof(ixb_t),1,index))
-						break;
-					if(!ixb.number) 	/* DELETED */
-						continue;
-					if(ixb.updated>=l) {
-						fseek(stream
-							,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-							*sizeof(user_t),SEEK_SET);
-						if(!fread(&user,sizeof(user_t),1,stream))
-							continue;
-						if(minor_protection(user))
-							continue;
-						if(useron.min_match && useron.number) {
-							match=total_match(useron,user);
-							if(match<useron.min_match)
-								continue; }
-						if(ext && !long_user_info(user))
-							break;
-						if(!ext && short_user_info(user)==0)
-							break;
-						continue; } }
-				if(aborted || ext || !lncntr)
-					break;
-				user.number=0;
-				if(short_user_info(user)>=0)
-					break; }
-            break;
-
-		case 'U':
-		case 'W':       /* Create/Edit Profile */
-			if(!can_add()) {
-				bprintf("\1h\1rYou have insufficient access to create a "
-					"profile.\r\n\r\n");
-				break; }
-
-			if(!useron.number) {
-				add_userinfo();
-				break; }
-
-			user=useron;
-			tleft=timeleft;
-			if(!get_user_info(&user)) {
-				timeleft=tleft;
-				break; }
-
-			if(!memcmp(&user,&useron,sizeof(user_t))) {
-				timeleft=tleft;
-				break; }
-
-			if(!yesno("Save changes")) {
-				timeleft=tleft;
-				break; }
-			timeleft=tleft;
-			user.updated=time(NULL);
-			useron=user;
-			write_user();
-            break;
-
-		case 'D':
-			if(SYSOP) {
-				bputs("Name to Delete: ");
-				if(useron.number) {
-					strcpy(str,useron.name);
-					strupr(str); }
-				else
-					str[0]=0;
-				getstr(str,25,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
-				rewind(stream);
-				while(!feof(stream)) {
-					if(!fread(&user,sizeof(user_t),1,stream))
-						break;
-					strcpy(tmp,user.name);
-					strupr(tmp);
-					if(!(user.misc&USER_DELETED) && strstr(tmp,str)) {
-						sprintf(tmp,"Delete %s (%s@%s)"
-							,user.name,user.realname,user.system);
-						i=noyes(tmp);
-						if(aborted)
-							break;
-						if(i)
-							continue;
-						fseek(stream,ftell(stream)-sizeof(user_t),SEEK_SET);
-						fseek(index
-							,((ftell(stream)-sizeof(user_t))/sizeof(user_t))
-							*sizeof(ixb_t),SEEK_SET);
-						user.misc|=USER_DELETED;
-						fwrite(&user,sizeof(user_t),1,stream);
-						fseek(stream,0,SEEK_CUR);
-						memset(&ixb,0,sizeof(ixb_t));
-						fwrite(&ixb,sizeof(ixb_t),1,index);
-						fflush(stream);
-						fflush(index);
-						delphoto(user);
-						if(user.number==user_number
-							&& !stricmp(user.system,system_name))
-							useron.number=0;
-						break; } }
-				if(aborted)
-					break;
-				break; }
-			if(!useron.number) {
-				bputs("\1h\1rYour profile doesn't exist.\r\n\r\n");
-                break; }
-			if(noyes("Are you sure you want to delete your profile"))
-                break;
-			if(!cdt_warning(-profile_cdt))
-				break;
-			sprintf(str,"%04u.MSG",user_number);
-			remove(str);
-			fseek(stream,useron_record*sizeof(user_t),SEEK_SET);
-			useron.misc|=USER_DELETED;
-			fwrite(&useron,sizeof(user_t),1,stream);
-			fflush(stream);
-			memset(&ixb,0,sizeof(ixb_t));
-			fseek(index,useron_record*sizeof(ixb_t),SEEK_SET);
-			fwrite(&ixb,sizeof(ixb_t),1,index);
-			fflush(index);
-			delphoto(user);
-			useron.number=0;
-			aborted=0;
-			bputs("\r\n\1h\1r\1iProfile deleted.\r\n");
-			adjust_cdt(-profile_cdt);
-            break;
-		case 'P':
-			smm_pause=!smm_pause;
-			bprintf("\1r\1hScreen pause is now \1w%s\r\n\r\n"
-				,smm_pause ? "ON":"OFF");
-            break;
-		case 'M':
-			mbtype_desc(useron.mbtype);
-			break;
-		case 'H':
-			cls();
-			printfile("SMM_HELP.ASC");
-			break;
-		case 'O':
-			if(noyes("Hang-up now"))
-				break;
-			dtr(5);
-			if(node_dir) {
-				sprintf(str,"%sHANGUP.NOW",node_dir);
-				fopen(str,"wb");
-				nodesync(); }
-			return;
-		case 'S':
-			bputs("\1y\1hUser name: ");
-			if(!getstr(str,25,K_UPPER|K_LINE))
-                break;
-			truncsp(str);
-			name_crc=crc32(str);
-			rewind(index);
-			i=0;
-			while(!feof(index)) {
-				if(!fread(&ixb,sizeof(ixb_t),1,index))
-					break;
-				if(!ixb.number)    /* DELETED */
-					continue;
-				if(ixb.name!=name_crc)
-					continue;
-                fseek(stream
-					,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-					*sizeof(user_t),SEEK_SET);
-				if(!fread(&user,sizeof(user_t),1,stream))
-					continue;
-				if(minor_protection(user))
-                    continue;
-				i=1;
-				if(send_telegram(user))
-					break; }
-			if(!i)
-				bprintf("\r\n\1n\1h%s \1rnot found.\r\n",str);
-            break;
-		case 'T':
-			sprintf(str,"%04u.MSG",user_number);
-			if(!fexist(str)) {
-				bputs("\1r\1hYou have no telegrams waiting.\r\n\r\n");
-				break; }
-			cls();
-			printfile(str);
-			if(noyes("\r\nDelete all telegrams waiting for you"))
-				break;
-			remove(str);
-			break;
-		case 'V':   /* Visit the wall */
-			if(getage(user_birth)<wall_age && !SYSOP) {
-				bputs("\1r\1hSorry, you're too young to view the wall.\r\n");
-				pause();
-				break; }
-			while(1) {
-				checkline();
-				bputs("\1y\1hView writing since (MM/DD/YY): ");
-                if(useron.number)
-                    unixtodstr(useron.lastin,str);
-                else
-                    str[0]=0;
-                if(!getstr(str,8,K_UPPER|K_LINE|K_EDIT|K_AUTODEL))
-                    break;
-                if(isdigit(str[0]) && isdigit(str[1]) && str[2]=='/'
-                    && isdigit(str[3]) && isdigit(str[4]) && str[5]=='/'
-                    && isdigit(str[6]) && isdigit(str[7]))
-                    break;
-                bputs("\r\n\1h\1rInvalid date!\r\n\r\n"); }
-			if(aborted)
-                break;
-			l=dstrtounix(str);
-			ext=yesno("\r\nDisplay extended information when available");
-			if(aborted)
-                break;
-			strcpy(str,"WALL.DAB");
-			if((file=sopen(str,O_RDWR|O_BINARY|O_CREAT,SH_DENYNO
-				,S_IREAD|S_IWRITE))==-1) {
-				bprintf("\r\nError opening %s\r\n",str);
-				break; }
-			cls();
-			offset=0L;
-			while(!eof(file) && !aborted) {
-				if(read(file,&wall,sizeof(wall_t))!=sizeof(wall_t))
-					break;
-				if(wall.imported<l)
-					continue;
-				strcpy(str,wall.name);
-				strupr(str);
-				name_crc=crc32(str);
-				sprintf(str,"%.25s",wall.system);
-				strupr(str);
-				sys_crc=crc32(str);
-				rewind(index);
-				i=0;
-				user.sex=0;
-				while(ext && !feof(index) && !aborted) {
-					if(!fread(&ixb,sizeof(ixb_t),1,index))
-						break;
-					if(!ixb.number)    /* DELETED */
-						continue;
-					if(ixb.name!=name_crc || ixb.system!=sys_crc)
-						continue;
-					fseek(stream
-						,((ftell(index)-sizeof(ixb_t))/sizeof(ixb_t))
-						*sizeof(user_t),SEEK_SET);
-					if(!fread(&user,sizeof(user_t),1,stream))
-						continue;
-					if(minor_protection(user))
-						break;
-					main_user_info(user);
-					if(useron.number) {
-						CRLF;
-						bprintf("\1h\1mThis user meets your profile "
-							"preferences:\1w%3u%%            "
-							,basic_match(useron,user));
-						bprintf("\1n\1gCreated: \1h%s\r\n"
-							,unixtodstr(user.created,str));
-						bprintf("\1h\1mYou meet this user's profile "
-							"preferences:\1w%3u%%            "
-							,basic_match(user,useron));
-						bprintf("\1n\1gUpdated: \1h%s\r\n"
-							,unixtodstr(user.updated,str)); }
-
-					i=1;
-					CRLF;
-					break; }
-				if(!i) {
-					if(ext)
-						cls();
-					bprintf("\1n\1h%s ",wall.name); }
-				bprintf("\1n\1h\1cWrote on %s:\r\n"
-					,timestr(&wall.written));
-				for(j=0;j<5;j++) {
-					if(!wall.text[j][0])
-						break;
-					bprintf("\1n\1%c%5s%s\r\n"
-						,user.sex=='F'?'m':'g',"",wall.text[j]); }
-				if(aborted)
-					break;
-				if(ext) {
-					nodesync();
-					if(i) {
-						bputs(PrevReadSendQuitOrMore);
-						ch=getkey(K_UPPER);
-						if(ch=='R')
-							long_user_info(user);
-						if(ch=='S')
-							send_telegram(user);
-						if(ch=='R' || ch=='S')  /* Don't move forward */
-							lseek(file,tell(file)-sizeof(wall_t),SEEK_SET); }
-					else {
-						bputs("\r\n\1n\1hProfile not found.\r\n\r\n");
-						bputs("\1b[\1cP\1b]revious, [\1cQ\1b]uit, "
-							"or [\1cM\1b]ore: \1c");
-						ch=getkey(K_UPPER); }
-					if(ch=='P') {
-						lseek(file,offset,SEEK_SET);
-						if(tell(file))
-							lseek(file,tell(file)-sizeof(wall_t),SEEK_SET);
-						offset=tell(file);
-						continue; }
-					if(ch=='Q') {
-						cls();
-						break; }
-					offset=tell(file); }
-				else if(lncntr+7>=user_rows || eof(file)) {
-					lncntr=0;
-					bputs(PrevReadSendQuitOrMore);
-					ch=getkey(K_UPPER);
-					if(ch=='Q')
-						break;
-					else if(ch=='S' || ch=='R') {
-						bprintf("\1n\r\1>\1y\1hUser name: ");
-						if(getstr(name,25,K_UPPER|K_LINE|K_NOCRLF)) {
-							truncsp(name);
-							name_crc=crc32(name);
-							rewind(index);
-							i=0;
-							while(!feof(index)) {
-								if(!fread(&ixb,sizeof(ixb_t),1,index))
-									break;
-								if(!ixb.number)    /* DELETED */
-									continue;
-								if(ixb.name!=name_crc)
-									continue;
-								fseek(stream
-									,((ftell(index)
-										-sizeof(ixb_t))/sizeof(ixb_t))
-									*sizeof(user_t),SEEK_SET);
-								if(!fread(&user,sizeof(user_t),1,stream))
-									continue;
-								if(minor_protection(user))
-									continue;
-								i=1;
-								if(ch=='S' && send_telegram(user))
-									break;
-								if(ch=='R' && !long_user_info(user))
-									break;	}
-							if(!i)
-								bprintf("\r\n\1n\1h%s \1rnot found.\r\n",name);
-								}
-						lseek(file,offset,SEEK_SET); }
-					else if(ch=='P') {
-						lseek(file,offset,SEEK_SET);
-						for(i=0;i<4;i++)
-							if(tell(file))
-								lseek(file,tell(file)-sizeof(wall_t),SEEK_SET);
-						}
-					cls();
-					offset=tell(file); } }
-			cls();
-			if(user_level<wall_level) {
-				close(file);
-                bputs("\r\n\1h\1rYou have insufficient access to write on the "
-                    "wall.\r\n");
-                pause();
-                break; }
-			if(aborted || noyes("Write on the Wall")) {
-				close(file);
-				break; }
-			if(!useron.number) {
-				bputs("\r\n\1h\1rYou must create a profile first.\r\n");
-				close(file);
-				break; }
-			if(!cdt_warning(wall_cdt)) {
-				close(file);
-				break; }
-			memset(&wall,0,sizeof(wall_t));
-			strcpy(wall.name,useron.name);
-			strcpy(wall.system,system_name);
-			wall.written=wall.imported=time(NULL);
-			bputs("\1l\1n\1hWriting on the Wall:\r\n\r\n");
-			for(i=0;i<5 && !aborted;i++) {
-				bprintf("\1n\1h\1%c%u of 5: \1n\1%c"
-					,useron.sex=='F'?'m':'g',i+1,useron.sex=='F'?'m':'g');
-				if(!getstr(wall.text[i],70,i==4 ? K_MSG:K_MSG|K_WRAP))
-					break;
-				if(trash(wall.text[i])) {
-					bprintf("\r\n\1r\1hSorry, you can't use that text."
-						"\r\n\r\n");
-					i--;
-					continue; } }
-			if(!i || aborted || !yesno("\r\nSave")) {
-				close(file);
-				break; }
-			lseek(file,0L,SEEK_END);
-			write(file,&wall,sizeof(wall_t));
-			close(file);
-			adjust_cdt(wall_cdt);
-			if(notify_user && notify_user!=user_number) {
-				sprintf(str,"\1n\1hSMM: \1y%s\1m wrote on the Match Maker "
-					"Wall\r\n",user_name);
-				if(node_dir[0])
-					putsmsg(notify_user,str);
-				else
-					puttgram(notify_user,str); }
-			break;
-		case 'Q':
-			return; } }
-}
-
-/* End of SMM.C */
diff --git a/src/sbbs2/smm/smm2msg.c b/src/sbbs2/smm/smm2msg.c
deleted file mode 100644
index 6e9a05da3ccde266f7de3f90778989a0d8585c26..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smm2msg.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/* SMM2MSG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Scans SMM database and posts any additions/updates into an MSG file */
-
-#define  uint unsigned int
-
-#include <dos.h>
-#include "smblib.h"
-#include "smmdefs.h"
-
-#define VERSION "1.00�"
-
-smb_t smb;
-extern int daylight=0;
-extern long timezone=0L;
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-uchar cryptchar(uchar ch, ulong seed)
-{
-if(ch==1)
-	return(0xfe);
-if(ch<0x20 || ch&0x80)	/* Ctrl chars and ex-ASCII are not xlated */
-	return(ch);
-return(ch^(seed&0x1f));
-}
-
-char *encrypt(uchar *str, ulong seed)
-{
-	static uchar out[1024];
-	int i,j;
-
-j=strlen(str);
-for(i=0;i<j;i++)
-	out[i]=cryptchar(str[i],seed^(i&7));
-out[i]=0;
-return(out);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct time curtime;
-	struct date date;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-#define BUF_LEN 8192
-
-int main(int argc, char **argv)
-{
-	uchar	str[128],tmp[128],msg_dir[128],buf[BUF_LEN],telegram[513],*p;
-	int 	i,j,file;
-	ushort	xlat;
-	long	length;
-	ulong	offset;
-	time_t	last,t;
-	user_t	user,from;
-	wall_t	wall;
-    smbmsg_t msg;
-	FILE	*stream;
-
-fprintf(stderr,"\nSMM2MSG v%s - Write SMM data to MSG - Developed 1995-1997 "
-	"Rob Swindell\n\n",VERSION);
-
-if(checktime()) {
-    printf("Time problem!\n");
-    return(-1); }
-
-if(argc<3) {
-	fprintf(stderr,"usage: smm2msg <smm.dab> <msg_dir>\n\n");
-	fprintf(stderr,"example: smm2msg c:\\sbbs\\xtrn\\smm\\smm.dab "
-		"c:\\im\\mail\n");
-	return(1); }
-
-
-strcpy(msg_dir,argv[2]);
-strupr(msg_dir);
-
-strcpy(str,argv[1]);
-strupr(str);
-if((file=open(str,O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if((stream=fdopen(file,"rb"))==NULL) {
-	printf("error fdopening %s\n",str);
-	return(1); }
-setvbuf(stream,NULL,_IOFBF,4096);
-
-strcpy(tmp,str);
-p=strrchr(tmp,'.');
-if(p) {
-	(*p)=0;
-	strcat(tmp,"2MSG.DAB");
-	if((file=open(tmp,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-		printf("error opening %s\n",str);
-		return(1); }
-	t=time(NULL);
-	if(read(file,&last,sizeof(time_t))!=sizeof(time_t))
-		last=0;
-	lseek(file,0L,SEEK_SET);
-	write(file,&t,sizeof(time_t));
-	close(file); }
-
-//sprintf(str,"%s.SHD",smb.file);
-//if(!fexist(str)) {
-//	  printf("%s doesn't exist\n",smb.file);
-//	  return(0); }
-//fprintf(stderr,"Opening %s\n",smb.file);
-//smb.retry_time=30;
-//if((i=smb_open(&smb))!=0) {
-//	  printf("smb_open returned %d\n",i);
-//	  return(1); }
-
-strcpy(str,argv[1]);
-strupr(str);
-p=strrchr(str,'\\');
-if(p) p++;
-else p=str;
-strcpy(p,"TELEGRAM.DAB");
-if((file=open(str,O_RDWR|O_DENYNONE|O_BINARY))!=-1) {
-	while(!eof(file)) {
-		read(file,from.system,sizeof(user.system));
-		read(file,user.system,sizeof(user.system));
-        read(file,&user.number,sizeof(user.number));
-		printf("Telegram to: %lu@%s\n",user.number,user.system);
-		read(file,telegram,512);
-		telegram[512]=0;
-		sprintf(buf,"}%lx\r\n%s",user.number,encrypt(telegram,user.number));
-		strcat(buf,"\r\n"); /* blank line terminates telegram */
-		strcat(buf,"\r\n--- SMM2MSG v");
-		strcat(buf,VERSION);
-
-		length=strlen(buf);   /* +2 for translation string */
-
-		if(smb.status.attr&SMB_HYPERALLOC)
-			offset=smb_hallocdat(&smb);
-		else {
-			i=smb_open_da(&smb);
-			if(i) {
-				printf("smb_open_da returned %d\n",i);
-				exit(1); }
-			offset=smb_allocdat(&smb,length+2,1);
-			fclose(smb.sda_fp); }
-
-		fseek(smb.sdt_fp,offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,smb.sdt_fp);
-		fwrite(buf,length,1,smb.sdt_fp);
-		length+=2;
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=SMB_VERSION;
-		msg.hdr.when_written.time=time(NULL);
-
-		msg.hdr.offset=offset;
-
-		strcpy(str,"SMM");
-		i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.to=crc16(str);
-
-		strcpy(str,from.system);
-		i=smb_hfield(&msg,SENDER,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.from=crc16(str);
-
-		strcpy(str,user.system);
-		i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-
-		i=smb_dfield(&msg,TEXT_BODY,length);
-		if(i) {
-			printf("smb_dfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-
-		i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-		if(i) {
-			printf("smb_addmsghdr returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		smb_freemsgmem(&msg); }
-	chsize(file,0L);
-	close(file); }
-
-strcpy(str,argv[1]);
-strupr(str);
-p=strrchr(str,'\\');
-if(p) p++;
-else p=str;
-strcpy(p,"WALL.DAB");
-if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYNO))!=-1) {
-	while(!eof(file)) {
-		if(!read(file,&wall,sizeof(wall_t)))
-			break;
-		if(last && wall.imported<last)
-			continue;
-
-		if(wall.imported!=wall.written) 	/* Imported from SMB */
-			continue;
-
-		printf("Wall writing from: %s\n",wall.name);
-		sprintf(buf,"%s\r\n",encrypt(wall.name,wall.written));
-		sprintf(str,"%s\r\n",encrypt(wall.system,wall.written));
-		strcat(buf,str);
-		for(i=0;i<5;i++) {
-			sprintf(str,"%s\r\n",encrypt(wall.text[i],wall.written));
-			strcat(buf,str); }
-		sprintf(str,"%lx\r\n",wall.written);
-		strcat(buf,str);
-		strcat(buf,"\r\n--- SMM2SMB v");
-		strcat(buf,VERSION);
-
-		length=strlen(buf);   /* +2 for translation string */
-
-		if(smb.status.attr&SMB_HYPERALLOC)
-			offset=smb_hallocdat(&smb);
-		else {
-			i=smb_open_da(&smb);
-			if(i) {
-				printf("smb_open_da returned %d\n",i);
-				exit(1); }
-			offset=smb_allocdat(&smb,length+2,1);
-			fclose(smb.sda_fp); }
-
-		fseek(smb.sdt_fp,offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,smb.sdt_fp);
-		fwrite(buf,length,1,smb.sdt_fp);
-		length+=2;
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=SMB_VERSION;
-		msg.hdr.when_written.time=time(NULL);
-
-		msg.hdr.offset=offset;
-
-		strcpy(str,"SMM");
-		i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.to=crc16(str);
-
-		strcpy(str,wall.system);
-		i=smb_hfield(&msg,SENDER,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.from=crc16(str);
-
-		strcpy(str,"->WALL<-");
-		i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-
-		i=smb_dfield(&msg,TEXT_BODY,length);
-		if(i) {
-			printf("smb_dfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-
-		i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-		if(i) {
-			printf("smb_addmsghdr returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		smb_freemsgmem(&msg); }
-    close(file); }
-
-
-while(!feof(stream)) {
-	if(!fread(&user,sizeof(user_t),1,stream))
-		break;
-	if(user.misc&(USER_FROMSMB|USER_DELETED)
-		|| (last && user.updated<last && user.created<last)
-		|| user.number&0xffff0000L
-		|| user.number==0
-		|| user.system[0]<SP
-		|| user.name[0]<SP
-		|| user.realname[0]<SP
-		|| user.location[0]<SP
-		|| user.zipcode[0]<SP
-		|| user.birth[0]<SP)
-		continue;
-
-	printf("Profile: %s\n",user.name);
-	memset(buf,0,BUF_LEN);
-
-	sprintf(str,"0:%.25s\r\n",encrypt(user.name,user.number));
-	strcat(buf,str);
-	sprintf(str,"1:%.25s\r\n",encrypt(user.realname,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"2:%.8s\r\n",encrypt(user.birth,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"3:%.30s\r\n",encrypt(user.location,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"4:%.10s\r\n",encrypt(user.zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"5:%.10s\r\n",encrypt(user.min_zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"6:%.10s\r\n",encrypt(user.max_zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"7:%.4s\r\n",encrypt(user.mbtype,user.number));
-	strcat(buf,str);
-
-	sprintf(str,"A:%.50s\r\n",encrypt(user.note[0],user.number));
-	strcat(buf,str);
-	sprintf(str,"B:%.50s\r\n",encrypt(user.note[1],user.number));
-    strcat(buf,str);
-	sprintf(str,"C:%.50s\r\n",encrypt(user.note[2],user.number));
-    strcat(buf,str);
-	sprintf(str,"D:%.50s\r\n",encrypt(user.note[3],user.number));
-    strcat(buf,str);
-	sprintf(str,"E:%.50s\r\n",encrypt(user.note[4],user.number));
-    strcat(buf,str);
-
-	sprintf(str,"F:%c%c\r\n",user.sex,user.pref_sex);
-	strcat(buf,str);
-
-	sprintf(str,"G:%x\r\n",user.marital);
-	strcat(buf,str);
-	sprintf(str,"H:%x\r\n",user.pref_marital);
-	strcat(buf,str);
-
-	sprintf(str,"I:%x\r\n",user.race);
-	strcat(buf,str);
-	sprintf(str,"J:%x\r\n",user.pref_race);
-    strcat(buf,str);
-
-	sprintf(str,"K:%x\r\n",user.hair);
-	strcat(buf,str);
-	sprintf(str,"L:%x\r\n",user.pref_hair);
-    strcat(buf,str);
-
-	sprintf(str,"M:%x\r\n",user.eyes);
-	strcat(buf,str);
-	sprintf(str,"N:%x\r\n",user.pref_eyes);
-    strcat(buf,str);
-
-	sprintf(str,"O:%x\r\nP:%x\r\nQ:%x\r\n"
-		,user.weight,user.min_weight,user.max_weight);
-	strcat(buf,str);
-
-	sprintf(str,"R:%x\r\nS:%x\r\nT:%x\r\n"
-		,user.height,user.min_height,user.max_height);
-    strcat(buf,str);
-
-	sprintf(str,"U:%x\r\nV:%x\r\nW:%x\r\n"
-		,user.min_age,user.max_age,user.purity);
-	strcat(buf,str);
-
-	sprintf(str,"X:%lx\r\nY:%lx\r\nZ:%lx\r\n!:%lx\r\n"
-		,user.income,user.min_income,user.max_income,time(NULL));
-	strcat(buf,str);
-
-	for(i=0;i<5;i++) {
-		if(!user.queans[i].name[0])
-			continue;
-		sprintf(str,"*%d%.8s\r\n",i,encrypt(user.queans[i].name,user.number));
-		strcat(buf,str);
-		for(j=0;j<20;j++) {
-			sprintf(str," %04x %04x"
-				,user.queans[i].self[j]
-				,user.queans[i].pref[j]);
-			strcat(buf,str);
-			if(!((j+1)%7))
-				strcat(buf,"\r\n"); }
-		strcat(buf,"\r\n"); }
-
-	strcat(buf,"\r\n--- SMM2MSG v");
-	strcat(buf,VERSION);
-
-	length=strlen(buf);   /* +2 for translation string */
-
-	if(smb.status.attr&SMB_HYPERALLOC)
-		offset=smb_hallocdat(&smb);
-	else {
-		i=smb_open_da(&smb);
-		if(i) {
-			printf("smb_open_da returned %d\n",i);
-			exit(1); }
-		offset=smb_allocdat(&smb,length+2,1);
-		fclose(smb.sda_fp); }
-
-	fseek(smb.sdt_fp,offset,SEEK_SET);
-	xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	fwrite(buf,length,1,smb.sdt_fp);
-	length+=2;
-
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=SMB_VERSION;
-	msg.hdr.when_written.time=time(NULL);
-    
-	msg.hdr.offset=offset;
-
-	strcpy(str,"SMM");
-	i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.to=crc16(str);
-
-	strcpy(str,user.system);
-	i=smb_hfield(&msg,SENDER,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.from=crc16(str);
-
-	sprintf(str,"%lu",user.number);
-	i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.subj=crc16(str);
-
-	i=smb_dfield(&msg,TEXT_BODY,length);
-	if(i) {
-		printf("smb_dfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-
-	i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-	if(i) {
-		printf("smb_addmsghdr returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	smb_freemsgmem(&msg); }
-return(0);
-}
-
diff --git a/src/sbbs2/smm/smm2smb.c b/src/sbbs2/smm/smm2smb.c
deleted file mode 100644
index ffb670a48a8baa7a688b0f93a74a4a8c5fcc153c..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smm2smb.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/* SMM2SMB.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Scans SMM database and posts any additions/updates into the an SMB base */
-
-#define  uint unsigned int
-
-#include <dos.h>
-#include "smblib.h"
-#include "smmdefs.h"
-
-#define VERSION "2.01"
-
-smb_t smb;
-extern int daylight=0;
-extern long timezone=0L;
-
-unsigned _stklen=16000;
-
-uchar cryptchar(uchar ch, ulong seed)
-{
-if(ch==1)
-	return(0xfe);
-if(ch<0x20 || ch&0x80)	/* Ctrl chars and ex-ASCII are not xlated */
-	return(ch);
-return(ch^(seed&0x1f));
-}
-
-char *encrypt(uchar *str, ulong seed)
-{
-	static uchar out[1024];
-	int i,j;
-
-j=strlen(str);
-for(i=0;i<j;i++)
-	out[i]=cryptchar(str[i],seed^(i&7));
-out[i]=0;
-return(out);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==0)
-    return(1);
-return(0);
-}
-
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct time curtime;
-	struct date date;
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-#define BUF_LEN 8192
-
-int main(int argc, char **argv)
-{
-	uchar	str[128],tmp[128],buf[BUF_LEN],telegram[513],*p;
-	int 	i,j,file;
-	ushort	xlat;
-	long	length;
-	ulong	offset;
-	time_t	last,t;
-	user_t	user,from;
-	wall_t	wall;
-	smbmsg_t msg;
-	FILE	*stream;
-
-fprintf(stderr,"\nSMM2SMB v%s - Write SMM data to SMB - Developed 1994-1997 "
-	"Rob Swindell\n\n",VERSION);
-
-if(checktime()) {
-    printf("Time problem!\n");
-    return(-1); }
-
-if(argc<3) {
-	fprintf(stderr,"usage: smm2smb <smm.dab> <smb_file>\n\n");
-	fprintf(stderr,"example: smm2smb c:\\sbbs\\xtrn\\smm\\smm.dab "
-		"c:\\sbbs\\data\\subs\\syncdata\n");
-	return(1); }
-
-
-strcpy(smb.file,argv[2]);
-strupr(smb.file);
-
-strcpy(str,argv[1]);
-strupr(str);
-if((file=open(str,O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-	printf("error opening %s\n",str);
-	return(1); }
-if((stream=fdopen(file,"rb"))==NULL) {
-	printf("error fdopening %s\n",str);
-	return(1); }
-setvbuf(stream,NULL,_IOFBF,4096);
-
-strcpy(tmp,str);
-p=strrchr(tmp,'.');
-if(p) {
-	(*p)=0;
-	strcat(tmp,"2SMB.DAB");
-	if((file=open(tmp,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-		printf("error opening %s\n",str);
-		return(1); }
-	t=time(NULL);
-	if(read(file,&last,sizeof(time_t))!=sizeof(time_t))
-		last=0;
-	lseek(file,0L,SEEK_SET);
-	write(file,&t,sizeof(time_t));
-	close(file); }
-
-sprintf(str,"%s.SHD",smb.file);
-if(!fexist(str)) {
-	printf("%s doesn't exist\n",smb.file);
-	return(0); }
-fprintf(stderr,"Opening %s\n",smb.file);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	printf("smb_open returned %d\n",i);
-	return(1); }
-
-strcpy(str,argv[1]);
-strupr(str);
-p=strrchr(str,'\\');
-if(p) p++;
-else p=str;
-strcpy(p,"TELEGRAM.DAB");
-if((file=open(str,O_RDWR|O_DENYNONE|O_BINARY))!=-1) {
-	while(!eof(file)) {
-		read(file,from.system,sizeof(user.system));
-		read(file,user.system,sizeof(user.system));
-        read(file,&user.number,sizeof(user.number));
-		printf("Telegram to: %lu@%s\n",user.number,user.system);
-		read(file,telegram,512);
-		telegram[512]=0;
-		sprintf(buf,"}%lx\r\n%s",user.number,encrypt(telegram,user.number));
-		strcat(buf,"\r\n"); /* blank line terminates telegram */
-		strcat(buf,"\r\n--- SMM2SMB v");
-		strcat(buf,VERSION);
-
-		length=strlen(buf);   /* +2 for translation string */
-
-		if(smb.status.attr&SMB_HYPERALLOC)
-			offset=smb_hallocdat(&smb);
-		else {
-			i=smb_open_da(&smb);
-			if(i) {
-				printf("smb_open_da returned %d\n",i);
-				exit(1); }
-			offset=smb_allocdat(&smb,length+2,1);
-			fclose(smb.sda_fp); }
-
-		fseek(smb.sdt_fp,offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,smb.sdt_fp);
-		fwrite(buf,length,1,smb.sdt_fp);
-		length+=2;
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=SMB_VERSION;
-		msg.hdr.when_written.time=time(NULL);
-
-		msg.hdr.offset=offset;
-
-		strcpy(str,"SMM");
-		i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.to=crc16(str);
-
-		strcpy(str,from.system);
-		i=smb_hfield(&msg,SENDER,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.from=crc16(str);
-
-		strcpy(str,user.system);
-		i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-
-		i=smb_dfield(&msg,TEXT_BODY,length);
-		if(i) {
-			printf("smb_dfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-
-		i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-		if(i) {
-			printf("smb_addmsghdr returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		smb_freemsgmem(&msg); }
-	chsize(file,0L);
-	close(file); }
-
-strcpy(str,argv[1]);
-strupr(str);
-p=strrchr(str,'\\');
-if(p) p++;
-else p=str;
-strcpy(p,"WALL.DAB");
-if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYNO))!=-1) {
-	while(!eof(file)) {
-		if(!read(file,&wall,sizeof(wall_t)))
-			break;
-		if(last && wall.imported<last)
-			continue;
-
-		if(wall.imported!=wall.written) 	/* Imported from SMB */
-			continue;
-
-		printf("Wall writing from: %s\n",wall.name);
-		sprintf(buf,"%s\r\n",encrypt(wall.name,wall.written));
-		sprintf(str,"%s\r\n",encrypt(wall.system,wall.written));
-		strcat(buf,str);
-		for(i=0;i<5;i++) {
-			sprintf(str,"%s\r\n",encrypt(wall.text[i],wall.written));
-			strcat(buf,str); }
-		sprintf(str,"%lx\r\n",wall.written);
-		strcat(buf,str);
-		strcat(buf,"\r\n--- SMM2SMB v");
-		strcat(buf,VERSION);
-
-		length=strlen(buf);   /* +2 for translation string */
-
-		if(smb.status.attr&SMB_HYPERALLOC)
-			offset=smb_hallocdat(&smb);
-		else {
-			i=smb_open_da(&smb);
-			if(i) {
-				printf("smb_open_da returned %d\n",i);
-				exit(1); }
-			offset=smb_allocdat(&smb,length+2,1);
-			fclose(smb.sda_fp); }
-
-		fseek(smb.sdt_fp,offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,smb.sdt_fp);
-		fwrite(buf,length,1,smb.sdt_fp);
-		length+=2;
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=SMB_VERSION;
-		msg.hdr.when_written.time=time(NULL);
-
-		msg.hdr.offset=offset;
-
-		strcpy(str,"SMM");
-		i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.to=crc16(str);
-
-		strcpy(str,wall.system);
-		i=smb_hfield(&msg,SENDER,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.from=crc16(str);
-
-		strcpy(str,"->WALL<-");
-		i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-
-		i=smb_dfield(&msg,TEXT_BODY,length);
-		if(i) {
-			printf("smb_dfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-
-		i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-		if(i) {
-			printf("smb_addmsghdr returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		smb_freemsgmem(&msg); }
-    close(file); }
-
-
-while(!feof(stream)) {
-	if(!fread(&user,sizeof(user_t),1,stream))
-		break;
-	if(user.misc&(USER_FROMSMB|USER_DELETED)
-		|| (last && user.updated<last && user.created<last)
-		|| user.number&0xffff0000L
-		|| user.number==0
-		|| user.system[0]<SP
-		|| user.name[0]<SP
-		|| user.realname[0]<SP
-		|| user.location[0]<SP
-		|| user.zipcode[0]<SP
-		|| user.birth[0]<SP)
-		continue;
-
-	printf("Profile: %s\n",user.name);
-	memset(buf,0,BUF_LEN);
-
-	sprintf(str,"0:%.25s\r\n",encrypt(user.name,user.number));
-	strcat(buf,str);
-	sprintf(str,"1:%.25s\r\n",encrypt(user.realname,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"2:%.8s\r\n",encrypt(user.birth,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"3:%.30s\r\n",encrypt(user.location,user.number));
-    strcat(buf,str);
-
-	sprintf(str,"4:%.10s\r\n",encrypt(user.zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"5:%.10s\r\n",encrypt(user.min_zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"6:%.10s\r\n",encrypt(user.max_zipcode,user.number));
-    strcat(buf,str);
-	sprintf(str,"7:%.4s\r\n",encrypt(user.mbtype,user.number));
-	strcat(buf,str);
-
-	sprintf(str,"A:%.50s\r\n",encrypt(user.note[0],user.number));
-	strcat(buf,str);
-	sprintf(str,"B:%.50s\r\n",encrypt(user.note[1],user.number));
-    strcat(buf,str);
-	sprintf(str,"C:%.50s\r\n",encrypt(user.note[2],user.number));
-    strcat(buf,str);
-	sprintf(str,"D:%.50s\r\n",encrypt(user.note[3],user.number));
-    strcat(buf,str);
-	sprintf(str,"E:%.50s\r\n",encrypt(user.note[4],user.number));
-    strcat(buf,str);
-
-	sprintf(str,"F:%c%c\r\n",user.sex,user.pref_sex);
-	strcat(buf,str);
-
-	sprintf(str,"G:%x\r\n",user.marital);
-	strcat(buf,str);
-	sprintf(str,"H:%x\r\n",user.pref_marital);
-	strcat(buf,str);
-
-	sprintf(str,"I:%x\r\n",user.race);
-	strcat(buf,str);
-	sprintf(str,"J:%x\r\n",user.pref_race);
-    strcat(buf,str);
-
-	sprintf(str,"K:%x\r\n",user.hair);
-	strcat(buf,str);
-	sprintf(str,"L:%x\r\n",user.pref_hair);
-    strcat(buf,str);
-
-	sprintf(str,"M:%x\r\n",user.eyes);
-	strcat(buf,str);
-	sprintf(str,"N:%x\r\n",user.pref_eyes);
-    strcat(buf,str);
-
-	sprintf(str,"O:%x\r\nP:%x\r\nQ:%x\r\n"
-		,user.weight,user.min_weight,user.max_weight);
-	strcat(buf,str);
-
-	sprintf(str,"R:%x\r\nS:%x\r\nT:%x\r\n"
-		,user.height,user.min_height,user.max_height);
-    strcat(buf,str);
-
-	sprintf(str,"U:%x\r\nV:%x\r\nW:%x\r\n"
-		,user.min_age,user.max_age,user.purity);
-	strcat(buf,str);
-
-	sprintf(str,"X:%lx\r\nY:%lx\r\nZ:%lx\r\n!:%lx\r\n"
-		,user.income,user.min_income,user.max_income,time(NULL));
-	strcat(buf,str);
-
-	for(i=0;i<5;i++) {
-		if(!user.queans[i].name[0])
-			continue;
-		sprintf(str,"*%d%.8s\r\n",i,encrypt(user.queans[i].name,user.number));
-		strcat(buf,str);
-		for(j=0;j<20;j++) {
-			sprintf(str," %04x %04x"
-				,user.queans[i].self[j]
-				,user.queans[i].pref[j]);
-			strcat(buf,str);
-			if(!((j+1)%7))
-				strcat(buf,"\r\n"); }
-		strcat(buf,"\r\n"); }
-
-	strcat(buf,"\r\n--- SMM2SMB v");
-	strcat(buf,VERSION);
-
-	length=strlen(buf);   /* +2 for translation string */
-
-	if(smb.status.attr&SMB_HYPERALLOC)
-		offset=smb_hallocdat(&smb);
-	else {
-		i=smb_open_da(&smb);
-		if(i) {
-			printf("smb_open_da returned %d\n",i);
-			exit(1); }
-		offset=smb_allocdat(&smb,length+2,1);
-		fclose(smb.sda_fp); }
-
-	fseek(smb.sdt_fp,offset,SEEK_SET);
-	xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	fwrite(buf,length,1,smb.sdt_fp);
-	length+=2;
-
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=SMB_VERSION;
-	msg.hdr.when_written.time=time(NULL);
-    
-	msg.hdr.offset=offset;
-
-	strcpy(str,"SMM");
-	i=smb_hfield(&msg,RECIPIENT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.to=crc16(str);
-
-	strcpy(str,user.system);
-	i=smb_hfield(&msg,SENDER,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.from=crc16(str);
-
-	sprintf(str,"%lu",user.number);
-	i=smb_hfield(&msg,SUBJECT,strlen(str),str);
-	if(i) {
-		printf("smb_hfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	strlwr(str);
-	msg.idx.subj=crc16(str);
-
-	i=smb_dfield(&msg,TEXT_BODY,length);
-	if(i) {
-		printf("smb_dfield returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-
-	i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-	if(i) {
-		printf("smb_addmsghdr returned %d\n",i);
-		smb_freemsgdat(&smb,offset,length,1);
-		exit(1); }
-	smb_freemsgmem(&msg); }
-return(0);
-}
-
-/* End of SMM2SMB.C */
diff --git a/src/sbbs2/smm/smmcfg.c b/src/sbbs2/smm/smmcfg.c
deleted file mode 100644
index b4e5003e0712c9283f53da2e164d8ccce527f65f..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smmcfg.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* SMMCFG.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <uifc.h>
-#include <sys\stat.h>
-#include "gen_defs.h"
-#include "smmdefs.h"
-#include "smmvars.c"
-
-char **opt;
-
-void bail(int code);
-void main();
-char fexist(char *filespec);
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-void bail(int code)
-{
-
-if(code)
-	getch();
-uifcbail();
-exit(code);
-}
-
-void main()
-{
-	char str[256];
-	int i,j,k,file,dflt,sysop_level;
-	FILE *stream;
-
-savnum=0;
-if((opt=(char **)MALLOC(sizeof(char *)*300))==NULL) {
-	cputs("memory allocation error\r\n");
-	bail(1); }
-for(i=0;i<300;i++)
-	if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL) {
-		cputs("memory allocation error\r\n");
-        bail(1); }
-uifcini();
-sprintf(str,"Synchronet Match Maker v%s",SMM_VER);
-uscrn(str);
-
-if((file=open("SMM.CFG",O_RDONLY|O_BINARY|O_DENYNONE))==-1) {
-	textattr(LIGHTGRAY);
-	clrscr();
-	lprintf("Error opening SMM.CFG\r\n");
-	bail(1); }
-if((stream=fdopen(file,"rb"))==NULL) {
-	textattr(LIGHTGRAY);
-	clrscr();
-	lprintf("Error fdopen SMM.CFG\r\n");
-	bail(1); }
-
-str[0]=0;
-fgets(str,128,stream);
-purity_age=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-min_age=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-min_level=atoi(str);
-
-req_flags1[0]=0;
-fgets(req_flags1,128,stream);
-req_flags1[27]=0;
-truncsp(req_flags1);
-
-req_flags2[0]=0;
-fgets(req_flags2,128,stream);
-req_flags2[27]=0;
-truncsp(req_flags2);
-
-req_flags3[0]=0;
-fgets(req_flags3,128,stream);
-req_flags3[27]=0;
-truncsp(req_flags3);
-
-req_flags4[0]=0;
-fgets(req_flags4,128,stream);
-req_flags4[27]=0;
-truncsp(req_flags4);
-
-str[0]=0;
-fgets(str,128,stream);
-profile_cdt=atol(str);
-str[0]=0;
-fgets(str,128,stream);
-telegram_cdt=atol(str);
-str[0]=0;
-fgets(str,128,stream);
-auto_update=atoi(str);
-str[0]=0;
-fgets(str,128,stream);
-notify_user=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);	// regnum
-
-str[0]=0;
-fgets(str,128,stream);
-telegram_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-que_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-wall_level=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-wall_cdt=atol(str);
-
-str[0]=0;
-fgets(str,128,stream);
-que_cdt=atol(str);
-
-zmodem_send[0]=0;
-fgets(zmodem_send,128,stream);
-if(!zmodem_send[0])
-	strcpy(zmodem_send,DEFAULT_ZMODEM_SEND);
-truncsp(zmodem_send);
-
-str[0]=0;
-fgets(str,128,stream);
-smm_misc=atol(str);
-
-str[0]=0;
-fgets(str,128,stream);
-sprintf(system_name,"%.25s",str);
-truncsp(system_name);
-
-local_view[0]=0;
-fgets(local_view,128,stream);
-truncsp(local_view);
-
-str[0]=0;
-fgets(str,128,stream);
-sysop_level=atoi(str);
-if(!sysop_level)
-	sysop_level=90;
-
-str[0]=0;
-fgets(str,128,stream);
-wall_age=atoi(str);
-
-str[0]=0;
-fgets(str,128,stream);
-age_split=atoi(str);
-
-fclose(stream);
-
-
-dflt=0;
-while(1) {
-	helpbuf=
-" Synchronet Match Maker Configuration \r\n\r\n"
-"Move through the various options using the arrow keys.  Select the\r\n"
-"highlighted options by pressing ENTER.\r\n\r\n";
-	j=0;
-	sprintf(opt[j++],"%-40.40s %s","System Name",system_name);
-	sprintf(opt[j++],"Wall Security...");
-	sprintf(opt[j++],"Profile Database Security...");
-	sprintf(str,"Credit %s for Adding Profile"
-		,profile_cdt>0 ? "Bonus":"Cost");
-	sprintf(opt[j++],"%-40.40s %ldk",str
-		,profile_cdt>0 ? profile_cdt/1024L : (-profile_cdt)/1024L);
-	sprintf(str,"Credit %s for Sending Telegram"
-		,telegram_cdt>0 ? "Bonus":"Cost");
-	sprintf(opt[j++],"%-40.40s %ldk",str
-		,telegram_cdt>0 ? telegram_cdt/1024L : (-telegram_cdt)/1024L);
-	sprintf(str,"Credit %s for Writing on the Wall"
-		,wall_cdt>0 ? "Bonus":"Cost");
-	sprintf(opt[j++],"%-40.40s %ldk",str
-		,wall_cdt>0 ? wall_cdt/1024L : (-wall_cdt)/1024L);
-	sprintf(str,"Credit %s for Reading Questionnaire"
-		,que_cdt>0 ? "Bonus":"Cost");
-	sprintf(opt[j++],"%-40.40s %ldk",str
-		,que_cdt>0 ? que_cdt/1024L : (-que_cdt)/1024L);
-	sprintf(opt[j++],"%-40.40s %u","Minimum Level to Send Telegrams"
-		,telegram_level);
-	sprintf(opt[j++],"%-40.40s %u","Minimum Level to Read Questionnaires"
-		,que_level);
-	sprintf(opt[j++],"%-40.40s %s","Minor Segregation (Protection) Age"
-		,age_split ? itoa(age_split,str,10):"Disabled");
-	sprintf(opt[j++],"%-40.40s %u","Sysop Level",sysop_level);
-	sprintf(opt[j++],"%-40.40s %s","Auto-Update Profiles"
-		,auto_update ? itoa(auto_update,str,10):"Disabled");
-	sprintf(opt[j++],"%-40.40s %s","Notify User of Activity"
-		,notify_user ? itoa(notify_user,str,10):"Disabled");
-	sprintf(opt[j++],"%-40.40s %s","Use Metric System"
-		,smm_misc&SMM_METRIC ? "Yes":"No");
-	sprintf(opt[j++],"%-40.40s %.25s","Zmodem Send Command"
-		,zmodem_send);
-	sprintf(opt[j++],"%-40.40s %.25s","Local Photo Viewer"
-		,local_view);
-	opt[j][0]=NULL;
-	switch(ulist(WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC,0,0,60,&dflt,0
-	,"Synchronet Match Maker Configuration",opt)) {
-		case 0:
-helpbuf=
-" System Name \r\n\r\n"
-"This is your BBS name. Once you have configured your BBS name here, you\r\n"
-"will not be able to change it, without losing all of your local users'\r\n"
-"profiles in your database.\r\n"
-"\r\n"
-"It is highly recommended that you do not change your BBS name here,\r\n"
-"even if you decide to change your actual BBS name in the future.\r\n"
-"\r\n"
-"All BBS names in a match maker network must be unique.";
-			uinput(WIN_MID,0,0,"System Name"
-				,system_name,40,K_EDIT|K_UPPER);
-            break;
-		case 1:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-40.40s  %u"
-					,"Minimum User Age to Access Wall"
-					,wall_age);
-				sprintf(opt[k++],"%-40.40s  %u"
-					,"Minimum Security Level to Write on Wall"
-					,wall_level);
-				opt[k][0]=NULL;
-helpbuf=
-" Wall Security \r\n\r\n"
-"This menu allows you to specify which users can access the wall.\r\n";
-
-				j=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,0,&j,0
-					,"Wall Security",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-helpbuf=
-" Minimum User Age \r\n\r\n"
-"This is the minimum user age that will be allowed to access (read or\r\n"
-"write) the wall.";
-						sprintf(str,"%u",wall_age);
-						uinput(WIN_L2R|WIN_SAV,0,0,
-							"Minimum Age to Access Wall"
-							,str,2,K_EDIT|K_NUMBER);
-						wall_age=atoi(str);
-                        break;
-					case 1:
-helpbuf=
-" Minimum User Level \r\n\r\n"
-"This is the minimum user level required to write on the wall.\r\n";
-						sprintf(str,"%u",wall_level);
-						uinput(WIN_L2R|WIN_SAV,0,0,
-							"Minimum Level to Write on Wall"
-							,str,2,K_EDIT|K_NUMBER);
-						wall_level=atoi(str);
-						break; } }
-			break;
-		case 2:
-			j=0;
-			while(1) {
-				k=0;
-				sprintf(opt[k++],"%-40.40s  %u"
-					,"Minimum User Age to Add Profile"
-					,min_age);
-				sprintf(opt[k++],"%-40.40s  %u"
-					,"Minimum User Age to Take Purity Test"
-					,purity_age);
-				sprintf(opt[k++],"%-40.40s  %u"
-					,"Minimum Security Level to Add Profile"
-					,min_level);
-				sprintf(opt[k++],"%-40.40s  %s"
-					,"Required Flags (Set 1) to Add Profile"
-					,req_flags1);
-				sprintf(opt[k++],"%-40.40s  %s"
-					,"Required Flags (Set 2) to Add Profile"
-					,req_flags2);
-				sprintf(opt[k++],"%-40.40s  %s"
-					,"Required Flags (Set 3) to Add Profile"
-					,req_flags3);
-				sprintf(opt[k++],"%-40.40s  %s"
-					,"Required Flags (Set 4) to Add Profile"
-					,req_flags4);
-				opt[k][0]=NULL;
-helpbuf=
-" Profile Security \r\n\r\n"
-"This menu allows you to specify which users can create profiles\r\n"
-"and take the purity test.";
-
-				j=ulist(WIN_ACT|WIN_SAV|WIN_RHT|WIN_BOT,0,0,0,&j,0
-					,"Profile Database Security",opt);
-				if(j==-1)
-					break;
-				switch(j) {
-					case 0:
-helpbuf=
-" Minimum User Age \r\n\r\n"
-"This is the minimum user age that will be allowed to add a profile to\r\n"
-"the database.";
-						sprintf(str,"%u",min_age);
-						uinput(WIN_L2R|WIN_SAV,0,0,
-							"Minimum Age",str,2,K_EDIT|K_NUMBER);
-						min_age=atoi(str);
-						break;
-					case 1:
-helpbuf=
-" Minimum User Age for Purity Test\r\n\r\n"
-"This is the minimum user age that will be allowed to take the purity\r\n"
-"test.";
-						sprintf(str,"%u",purity_age);
-						uinput(WIN_L2R|WIN_SAV,0,0,
-							"Minimum Age for Purity Test"
-							,str,2,K_EDIT|K_NUMBER);
-						purity_age=atoi(str);
-						break;
-					case 2:
-helpbuf=
-" Minimum Security Level \r\n\r\n"
-"This is the minimum security level that is required to add a profile\r\n"
-"to the database.";
-						sprintf(str,"%u",min_level);
-						uinput(WIN_L2R|WIN_SAV,0,0,
-							"Security Level",str,3,K_EDIT|K_NUMBER);
-						min_level=atoi(str);
-                        break;
-					case 3:
-helpbuf=
-" Required Flags from Flag Set 1 \r\n\r\n"
-"These are the flags that a required for the user to add a profile\r\n"
-"to the database.";
-						uinput(WIN_L2R|WIN_SAV,0,0,"Flag Set 1"
-							,req_flags1
-							,26,K_EDIT|K_UPPER|K_ALPHA);
-                        break;
-					case 4:
-helpbuf=
-" Required Flags from Flag Set 2 \r\n\r\n"
-"These are the flags that a required for the user to add a profile\r\n"
-"to the database.";
-						uinput(WIN_L2R|WIN_SAV,0,0,"Flag Set 2"
-							,req_flags2
-							,26,K_EDIT|K_UPPER|K_ALPHA);
-                        break;
-					case 5:
-helpbuf=
-" Required Flags from Flag Set 3 \r\n\r\n"
-"These are the flags that a required for the user to add a profile\r\n"
-"to the database.";
-						uinput(WIN_L2R|WIN_SAV,0,0,"Flag Set 3"
-							,req_flags3
-							,26,K_EDIT|K_UPPER|K_ALPHA);
-                        break;
-					case 6:
-helpbuf=
-" Required Flags from Flag Set 4 \r\n\r\n"
-"These are the flags that a required for the user to add a profile\r\n"
-"to the database.";
-						uinput(WIN_L2R|WIN_SAV,0,0,"Flag Set 4"
-							,req_flags4
-							,26,K_EDIT|K_UPPER|K_ALPHA);
-						break; } }
-            break;
-		case 3:
-helpbuf=
-" Credit Adjustment for Adding Profile \r\n\r\n"
-"You can have Synchronet Match Maker either give credits to or take\r\n"
-"credits from the user for adding a profile to the database.";
-			strcpy(opt[0],"Add Credits");
-			strcpy(opt[1],"Remove Credits");
-			opt[2][0]=0;
-			i=1;
-			i=ulist(WIN_L2R|WIN_BOT|WIN_ACT,0,0,0,&i,0
-				,"Credit Adjustment for Adding Profile",opt);
-			if(i==-1)
-				break;
-			sprintf(str,"%ld",profile_cdt<0 ? -profile_cdt:profile_cdt);
-			uinput(WIN_MID,0,0,"Credits (K=1024)"
-				,str,10,K_EDIT|K_UPPER);
-			if(strchr(str,'K'))
-				profile_cdt=atol(str)*1024L;
-			else
-				profile_cdt=atol(str);
-			if(i==1)
-				profile_cdt=-profile_cdt;
-			break;
-		case 4:
-helpbuf=
-" Credit Adjustment for Sending Telegram \r\n\r\n"
-"You can have Synchronet Match Maker either give credits to or take\r\n"
-"credits from the user for sending a telegram to another user in SMM.";
-			strcpy(opt[0],"Add Credits");
-			strcpy(opt[1],"Remove Credits");
-			opt[2][0]=0;
-			i=1;
-			i=ulist(WIN_L2R|WIN_BOT|WIN_ACT,0,0,0,&i,0
-				,"Credit Adjustment for Sending Telegram",opt);
-			if(i==-1)
-				break;
-			sprintf(str,"%ld",telegram_cdt<0 ? -telegram_cdt:telegram_cdt);
-			uinput(WIN_MID,0,0,"Credits (K=1024)"
-				,str,10,K_EDIT|K_UPPER);
-			if(strchr(str,'K'))
-				telegram_cdt=atol(str)*1024L;
-			else
-				telegram_cdt=atol(str);
-			if(i==1)
-				telegram_cdt=-telegram_cdt;
-            break;
-		case 5:
-helpbuf=
-" Credit Adjustment for Writing on the Wall \r\n\r\n"
-"You can have Synchronet Match Maker either give credits to or take\r\n"
-"credits from the user for writing on the wall.";
-			strcpy(opt[0],"Add Credits");
-			strcpy(opt[1],"Remove Credits");
-			opt[2][0]=0;
-			i=1;
-			i=ulist(WIN_L2R|WIN_BOT|WIN_ACT,0,0,0,&i,0
-				,"Credit Adjustment for Writing on the Wall",opt);
-			if(i==-1)
-				break;
-			sprintf(str,"%ld",wall_cdt<0 ? -wall_cdt:wall_cdt);
-			uinput(WIN_MID,0,0,"Credits (K=1024)"
-				,str,10,K_EDIT|K_UPPER);
-			if(strchr(str,'K'))
-				wall_cdt=atol(str)*1024L;
-			else
-				wall_cdt=atol(str);
-			if(i==1)
-				wall_cdt=-wall_cdt;
-            break;
-		case 6:
-helpbuf=
-" Credit Adjustment for Reading Questionnaire \r\n\r\n"
-"You can have Synchronet Match Maker either give credits to or take\r\n"
-"credits from the user when reading another user's questionnaire";
-			strcpy(opt[0],"Add Credits");
-			strcpy(opt[1],"Remove Credits");
-			opt[2][0]=0;
-			i=1;
-			i=ulist(WIN_L2R|WIN_BOT|WIN_ACT,0,0,0,&i,0
-				,"Credit Adjustment for Reading Questionnaire",opt);
-			if(i==-1)
-				break;
-			sprintf(str,"%ld",que_cdt<0 ? -que_cdt:que_cdt);
-			uinput(WIN_MID,0,0,"Credits (K=1024)"
-				,str,10,K_EDIT|K_UPPER);
-			if(strchr(str,'K'))
-				que_cdt=atol(str)*1024L;
-			else
-				que_cdt=atol(str);
-			if(i==1)
-				que_cdt=-que_cdt;
-            break;
-		case 7:
-helpbuf=
-" Minimum Level to Send Telegrams \r\n\r\n"
-"Use this option to restrict the sending of telegrams to users of a\r\n"
-"specific security level or higher.";
-			sprintf(str,"%u",telegram_level);
-			uinput(WIN_MID,0,0,"Minimum Level to Send Telegrams"
-				,str,3,K_EDIT|K_NUMBER);
-			telegram_level=atoi(str);
-            break;
-		case 8:
-helpbuf=
-" Minimum Level to Read Questionnaires \r\n\r\n"
-"Users will only be allowed to read other users' questionnaires if\r\n"
-"their security level is this value or higher.";
-			sprintf(str,"%u",que_level);
-			uinput(WIN_MID,0,0,"Minimum Level to Read Questionnaires"
-				,str,3,K_EDIT|K_NUMBER);
-			que_level=atoi(str);
-            break;
-		case 9:
-helpbuf=
-" Minor Segregation (Protection) Age \r\n\r\n"
-"This option (if enabled) separates all users into two groups:\r\n"
-"\r\n"
-"Minors: Those users below the specified age (normally 18)\r\n"
-"Adults: Those users at or above the specified age\r\n"
-"\r\n"
-"If enabled, adults cannot see minors' profiles or send telegrams to\r\n"
-"minors and vice versa.\r\n"
-"\r\n"
-"If disabled, all users can see eachother's profiles regardless of age.\r\n";
-			sprintf(str,"%u",age_split);
-			uinput(WIN_MID,0,0,"Minor Segregation Age (0=Disabled)"
-				,str,2,K_EDIT|K_NUMBER);
-			age_split=atoi(str);
-			break;
-		case 10:
-helpbuf=
-" Sysop Level \r\n\r\n"
-"Every user of this level or higher will be given access to sysop\r\n"
-"commands in the match maker.";
-			sprintf(str,"%u",sysop_level);
-			uinput(WIN_MID,0,0,"Sysop Level",str,3,K_EDIT|K_NUMBER);
-			sysop_level=atoi(str);
-            break;
-
-		case 11:
-helpbuf=
-" Auto-Update Profiles \r\n\r\n"
-"If you would like to have Synchronet Match Maker automatically send\r\n"
-"a network update message for a user that is active in SMM, but hasn't\r\n"
-"actually made any changes to his or her profile, set this option to the\r\n"
-"number of days between Auto-Updates (e.g. 30 days is a good value).\r\n"
-"\r\n"
-"Setting this option to 0 disables this feature.";
-			sprintf(str,"%u",auto_update);
-			uinput(WIN_MID,0,0,"Auto-Update Profiles (in Days)"
-				,str,3,K_EDIT|K_NUMBER);
-			auto_update=atoi(str);
-			break;
-		case 12:
-helpbuf=
-" Notify User of Activity \r\n\r\n"
-"If you would like to have Synchronet Match Maker automatically send\r\n"
-"a message to a specific user (most commonly the sysop) whenever a user\r\n"
-"adds a profile to the database or sends a telegram from SMM, set this\r\n"
-"option to the number of that user (e.g. 1 would indicate user #1).\r\n"
-"\r\n"
-"Setting this option to 0 disables this feature.";
-			sprintf(str,"%u",notify_user);
-			uinput(WIN_MID,0,0,"Notify User Number (0=disabled)"
-				,str,5,K_EDIT|K_NUMBER);
-			notify_user=atoi(str);
-            break;
-		case 13:
-helpbuf=
-" Use Metric System \r\n\r\n"
-"If you wish to use centimeters and kilograms instead of inches and\r\n"
-"pounds for height and weight measurements, set this option to Yes.";
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			i=1;
-			i=ulist(WIN_MID|WIN_ACT,0,0,0,&i,0
-				,"Use Metric Measurement System",opt);
-			if(i==-1)
-                break;
-			if(i==1)
-				smm_misc&=~SMM_METRIC;
-			else
-				smm_misc|=SMM_METRIC;
-			break;
-
-		case 14:
-helpbuf=
-" Zmodem Send Command \r\n\r\n"
-"This is the command line to execute to send files to remote user.\r\n";
-			uinput(WIN_MID,0,0,"Zmodem Send"
-				,zmodem_send,50,K_EDIT);
-            break;
-		case 15:
-helpbuf=
-" Local Photo Viewer \r\n\r\n"
-"This is the command line to execute to view photos when logged on\r\n"
-"locally.\r\n";
-			uinput(WIN_MID,0,0,"Local Viewer"
-				,local_view,50,K_EDIT);
-            break;
-		case -1:
-helpbuf=
-" Save Configuration File \r\n\r\n"
-"Select Yes to save the config file, No to quit without saving,\r\n"
-"or hit  ESC  to go back to the menu.\r\n\r\n";
-			i=0;
-			strcpy(opt[0],"Yes");
-			strcpy(opt[1],"No");
-			opt[2][0]=0;
-			i=ulist(WIN_MID,0,0,0,&i,0,"Save Config File",opt);
-			if(i==-1) break;
-			if(i) bail(0);
-			if((file=open("SMM.CFG"
-				,O_WRONLY|O_BINARY|O_CREAT|O_DENYALL|O_TRUNC,S_IWRITE))==-1) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error opening SMM.CFG\r\n");
-				bail(1); }
-			if((stream=fdopen(file,"wb"))==NULL) {
-				textattr(LIGHTGRAY);
-				clrscr();
-				lprintf("Error fdopen SMM.CFG\r\n");
-				bail(1); }
-			fprintf(stream,"%u\r\n%u\r\n%u\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-				,purity_age,min_age,min_level
-				,req_flags1,req_flags2,req_flags3,req_flags4);
-			fprintf(stream,"%ld\r\n%ld\r\n%u\r\n%u\r\n%s\r\n%u\r\n%u\r\n"
-				,profile_cdt,telegram_cdt,auto_update,notify_user,""
-				,telegram_level,que_level);
-			fprintf(stream,"%u\r\n%ld\r\n%ld\r\n%s\r\n%ld\r\n%s\r\n"
-				,wall_level,wall_cdt,que_cdt,zmodem_send,smm_misc,system_name);
-			fprintf(stream,"%s\r\n%u\r\n%u\r\n%u\r\n"
-				,local_view,sysop_level,wall_age,age_split);
-			fclose(stream);
-			bail(0);
-	}
-}
-}
-/****************************************************************************/
-/* Checks the disk drive for the existance of a file. Returns 1 if it 		*/
-/* exists, 0 if it doesn't.													*/
-/* Called from upload														*/
-/****************************************************************************/
-char fexist(char *filespec)
-{
-	struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-	return(1);
-return(0);
-}
diff --git a/src/sbbs2/smm/smmcfg.mak b/src/sbbs2/smm/smmcfg.mak
deleted file mode 100644
index eeb956f5cbb2b9882aeb89fd32eded0af62d1e3b..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smmcfg.mak
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# Macros
-CC	= bcc
-LD	= tlink
-SDK	= ..\sdk
-UIFC	= ..\..\uifc
-MSWAIT	= ..\..\mswait
-INCLUDE = \bc45\include;$(UIFC);..
-LIB	= \bc45\lib
-MODEL	= l
-CFLAGS  = -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LDFLAGS = /n /c
-OBJS	= $(MSWAIT)\dos\mswait$(MODEL).obj uifc.obj
-HEADERS = $(UIFC)\uifc.h smmdefs.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-smmcfg.exe: $(OBJS) smmcfg.obj
-    	@echo Linking $< ...
-	$(LD) $(LDFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) smmcfg.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-
-# All .obj modules
-smmcfg.obj: $(HEADERS)
-
-uifc.obj: $(UIFC)\uifc.h $(UIFC)\uifc.c
-	@echo Compiling $(UIFC)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c -DSCFG $(UIFC)\$*.c
-
diff --git a/src/sbbs2/smm/smmdefs.h b/src/sbbs2/smm/smmdefs.h
deleted file mode 100644
index 5d88b9d8f1785a916639502cd4098897aebdb44c..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smmdefs.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* SMMDEFS.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#define SMM_VER "2.10"
-
-#define SMM_METRIC			(1<<0)	/* Use metric measurements */
-
-#define USER_DELETED		(1<<0)	/* Bits for user.misc field */
-#define USER_FROMSMB		(1<<1)	/* Imported from SMB */
-#define USER_REQZIP 		(1<<2)	/* Require mate in zip range */
-#define USER_REQAGE 		(1<<3)	/* Require mate in age range */
-#define USER_REQWEIGHT		(1<<4)	/* Require mate in weight range */
-#define USER_REQHEIGHT		(1<<5)	/* Require mate in height range */
-#define USER_REQINCOME		(1<<6)	/* Require mate in income range */
-#define USER_REQMARITAL 	(1<<7)	/* Require marital status */
-#define USER_REQZODIAC		(1<<8)	/* Require zodiac */
-#define USER_REQRACE		(1<<9)	/* Require race */
-#define USER_REQHAIR		(1<<10) /* Require hair */
-#define USER_REQEYES		(1<<11) /* Require eyes */
-#define USER_FRIEND 		(1<<12) /* Seeking same-sex friendship */
-#define USER_PHOTO			(1<<13) /* Photo attached to profile */
-
-
-#define ZODIAC_ARIES		(1<<0)	/* Mar 21 - Apr 19 */
-#define ZODIAC_TAURUS		(1<<1)	/* Apr 20 - May 20 */
-#define ZODIAC_GEMINI		(1<<2)	/* May 21 - Jun 20 */
-#define ZODIAC_CANCER		(1<<3)	/* Jun 21 - Jul 22 */
-#define ZODIAC_LEO			(1<<4)	/* Jul 23 - Aug 22 */
-#define ZODIAC_VIRGO		(1<<5)	/* Aug 23 - Sep 22 */
-#define ZODIAC_LIBRA		(1<<6)	/* Sep 23 - Oct 22 */
-#define ZODIAC_SCORPIO		(1<<7)	/* Oct 23 - Nov 21 */
-#define ZODIAC_SAGITTARIUS	(1<<8)	/* Nov 22 - Dec 21 */
-#define ZODIAC_CAPRICORN	(1<<9)	/* Dec 22 - Jan 19 */
-#define ZODIAC_AQUARIUS 	(1<<10) /* Jan 20 - Feb 18 */
-#define ZODIAC_PISCES		(1<<11) /* Feb 19 - Mar 20 */
-
-#define HAIR_BLONDE 		(1<<0)
-#define HAIR_BROWN			(1<<1)
-#define HAIR_RED			(1<<2)
-#define HAIR_BLACK			(1<<3)
-#define HAIR_GREY			(1<<4)
-#define HAIR_OTHER			(1<<5)
-
-#define EYES_BLUE			(1<<0)
-#define EYES_GREEN			(1<<1)
-#define EYES_HAZEL			(1<<2)
-#define EYES_BROWN			(1<<3)
-#define EYES_OTHER			(1<<4)
-
-#define RACE_WHITE			(1<<0)
-#define RACE_BLACK			(1<<1)
-#define RACE_HISPANIC		(1<<2)
-#define RACE_ASIAN			(1<<3)
-#define RACE_AMERINDIAN 	(1<<4)
-#define RACE_MIDEASTERN 	(1<<5)
-#define RACE_OTHER			(1<<6)
-
-#define MARITAL_SINGLE		(1<<0)
-#define MARITAL_MARRIED 	(1<<1)
-#define MARITAL_DIVORCED	(1<<2)
-#define MARITAL_WIDOWED 	(1<<3)
-#define MARITAL_OTHER		(1<<4)
-
-typedef struct {
-
-	uchar	txt[82];
-	uchar	answers;		/* Total answers */
-	uchar	allowed;		/* number of answers allowed for self */
-	uchar	ans[16][62];	/* Answers */
-
-	} question_t;
-
-typedef struct {
-
-	uchar	name[9];
-	uchar	desc[26];
-	uchar	req_age;
-	uchar	total_ques;
-	question_t	que[20];
-
-	} questionnaire_t;
-
-typedef struct {
-
-	uchar	name[9];	   /* Name of questionnaire */
-	ushort	self[20];	   /* Answers to questions */
-	ushort	pref[20];	   /* Preferred partner's answer(s) */
-
-	} queans_t;
-
-typedef struct {
-
-	ulong	number; 		/* User's number on BBS */
-	ulong	system; 		/* CRC-32 of system name */
-	ulong	name;
-	ulong	updated;
-
-	} ixb_t;
-
-typedef struct {
-
-	uchar	name[26];		/* User's name or alias */
-	uchar	realname[26];	/* User's name or alias on the BBS */
-	uchar	system[41]; 	/* BBS name */
-	ulong	number; 		/* User's number on BBS */
-	uchar	birth[9];		/* MM/DD/YY format */
-	uchar	zipcode[11];	/* Zip code */
-	uchar	location[31];	/* City, state */
-	ushort	pref_zodiac;	/* Preferred zodiac sign */
-	uchar	sex;			/* 'M' or 'F' */
-	uchar	pref_sex;
-	uchar	marital;
-	uchar	pref_marital;
-	uchar	race;
-	uchar	pref_race;
-	uchar	hair;			/* hair color */
-	uchar	pref_hair;		/* preferred hair color */
-	uchar	eyes;			/* eye color */
-	uchar	pref_eyes;		/* preferred eye color */
-	ushort	weight; 		/* Sad, we have to use 16-bits! */
-	uchar	height; 		/* in inches */
-	ushort	min_weight;
-	ushort	max_weight;
-	uchar	min_height;
-	uchar	max_height;
-	uchar	min_age;
-	uchar	max_age;
-	uchar	min_zipcode[11];
-	uchar	max_zipcode[11];
-	ulong	income;
-	ulong	min_income;
-	ulong	max_income;
-	time_t	created;
-	time_t	updated;
-	uchar	note[5][51];
-	ulong	misc;
-	time_t	lastin;
-	uchar	min_match;
-	uchar	purity; 		/* Purity % */
-	uchar	mbtype[5];		/* Myers-Briggs personality type */
-	time_t	photo;			/* Date last photo hatched */
-	uchar	filler[60]; 	/* Available for future use */
-	queans_t   queans[5];
-
-	} user_t;
-
-typedef struct {
-
-	uchar	name[26];		/* User's name or alias */
-    uchar   system[41];     /* BBS name */
-	uchar	text[5][71];	/* Writing */
-	time_t	written;		/* Date/time created */
-	time_t	imported;
-
-	} wall_t;
-
-#define TGRAM_NOTICE "\1n\1h\1mNew telegram in \1wMatch Maker \1mfor you!" \
-                "\7\1n\r\n"
-#define DEFAULT_ZMODEM_SEND "%!dsz portx %u,%i sz %f"
diff --git a/src/sbbs2/smm/smmutil.c b/src/sbbs2/smm/smmutil.c
deleted file mode 100644
index d2c5eaa695b4c8b5de4b7b04710093a81a21a5fe..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smmutil.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/* SMMUTIL.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-#include <io.h>
-#include <dos.h>
-#include <fcntl.h>
-#include <sys\stat.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include "gen_defs.h"
-#include "smmdefs.h"
-#include "crc32.h"
-
-struct date date;
-struct time curtime;
-
-FILE *log=NULL;
-
-/****************************************************************************/
-/* Returns 32-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ulong crc32(char *str)
-{
-	int i=0;
-	ulong crc=0xffffffffUL;
-
-	while(str[i])
-		crc=ucrc32(str[i++],crc);
-	crc=~crc;
-	return(crc);
-}
-
-/****************************************************************************/
-/* Returns the age derived from the string 'birth' in the format MM/DD/YY	*/
-/****************************************************************************/
-char getage(char *birth)
-{
-	char age;
-
-if(birth[0]<=SP)
-	return(0);
-getdate(&date);
-age=(date.da_year-1900)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
-if(age>90)
-	age-=90;
-if(atoi(birth)>12 || atoi(birth+3)>31)
-	return(0);
-if(((birth[0]&0xf)*10)+(birth[1]&0xf)>date.da_mon ||
-	(((birth[0]&0xf)*10)+(birth[1]&0xf)==date.da_mon &&
-	((birth[3]&0xf)*10)+(birth[4]&0xf)>date.da_day))
-	age--;
-if(age<0)
-	return(0);
-return(age);
-}
-
-/**********************/
-/* Log print function */
-/**********************/
-void logprintf(char *str, ...)
-{
-    va_list argptr;
-    char buf[256];
-    time_t now;
-    struct tm *gm;
-
-va_start(argptr,str);
-vsprintf(buf,str,argptr);
-va_end(argptr);
-fprintf(stderr,"\n%s",buf);
-if(!log) return;
-now=time(NULL);
-gm=localtime(&now);
-fseek(log,0L,SEEK_END);
-fprintf(log,"%02u/%02u/%02u %02u:%02u:%02u %s\r\n"
-    ,gm->tm_mon+1,gm->tm_mday,TM_YEAR(gm->tm_year),gm->tm_hour,gm->tm_min,gm->tm_sec
-    ,buf);
-fflush(log);
-}
-
-
-char *base41(unsigned int i, char *str)
-{
-	char c;
-	unsigned int j=41*41,k;
-
-for(c=0;c<3;c++) {
-	k=i/j;
-	str[c]='0'+k;
-	i-=(k*j);
-	j/=41;
-	if(str[c]>=':')
-		str[c]='A'+(str[c]-':');
-	if(str[c]>='[')
-		str[c]='#'+(str[c]-'['); }
-str[c]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-    ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL)                 */
-/****************************************************************************/
-ushort crc16(char *str)
-{
-    int     i=0;
-    ushort  crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-    ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-void delphoto(user_t user)
-{
-	char fname[64],path[128],tmp[128];
-	int i;
-	struct ffblk ff;
-
-if(!(user.misc&USER_PHOTO))
-	return;
-for(i=0;user.system[i];i++)
-	if(isalnum(user.system[i]))
-        break;
-if(!user.system[i])
-	fname[0]='~';
-else
-	fname[0]=user.system[i];
-for(i=strlen(user.system)-1;i>0;i--)
-	if(isalnum(user.system[i]))
-		break;
-if(i<=0)
-	fname[1]='~';
-else
-	fname[1]=user.system[i];
-fname[2]=0;
-strupr(user.system);
-strcat(fname,base41(crc16(user.system),tmp));
-strcat(fname,base41(user.number,tmp));
-strcat(fname,".*");
-strupr(fname);
-sprintf(path,"PHOTO\\%s",fname);
-i=findfirst(path,&ff,0);
-if(i)
-	return;
-sprintf(path,"PHOTO\\%s",ff.ff_name);
-if(remove(path))
-	logprintf("Photo (%s) couldn't be removed!",path);
-else
-	logprintf("Photo (%s) removed",path);
-}
-
-
-int main(int argc, char **argv)
-{
-	int  i,file,max_age=0,max_wall=0,age;
-	long l,m,total_ixbs=0
-		,users=0,photos=0,networked=0
-		,male_straight=0
-		,male_gay=0
-		,male_bi=0
-		,female_straight=0
-		,female_gay=0
-		,female_bi=0
-		,age12=0
-		,age15=0
-		,age20=0,age25=0
-		,age30=0,age35=0
-		,age40=0,age45=0
-		,age50=0,age55=0
-		,age60=0,age65=0
-		,age70=0,age71=0
-		,zodiac_aries=0
-		,zodiac_taurus=0
-		,zodiac_gemini=0
-		,zodiac_cancer=0
-		,zodiac_leo=0
-		,zodiac_virgo=0
-		,zodiac_libra=0
-		,zodiac_scorpio=0
-		,zodiac_sagittarius=0
-		,zodiac_capricorn=0
-		,zodiac_aquarius=0
-		,zodiac_pisces=0
-		,hair_blonde=0
-		,hair_brown=0
-		,hair_red=0
-		,hair_black=0
-		,hair_grey=0
-		,hair_other=0
-		,eyes_blue=0
-		,eyes_green=0
-		,eyes_hazel=0
-		,eyes_brown=0
-		,eyes_other=0
-		,race_white=0
-		,race_black=0
-		,race_hispanic=0
-		,race_asian=0
-		,race_amerindian=0
-		,race_mideastern=0
-		,race_other=0
-		,marital_single=0
-		,marital_married=0
-		,marital_divorced=0
-		,marital_widowed=0
-		,marital_other=0
-		;
-	FILE *ixb_fp,*dab_fp,*tmp_fp;
-	ixb_t huge *ixb=NULL,ixbrec;
-	user_t user;
-	wall_t wall;
-	time_t now;
-
-fprintf(stderr,"\nSMMUTIL � Synchronet Match Maker Utility � v2.01�\n\n");
-
-for(i=1;i<argc;i++)
-	if(isdigit(argv[i][0])) {
-		if(max_age)
-			max_wall=atoi(argv[i]);
-		else
-			max_age=atoi(argv[i]); }
-	else {
-		printf("usage: SMMUTIL max_profile_age_in_days "
-			"max_wall_writing_age_in_days\n");
-		printf("\n");
-		printf("example: SMMUTIL 90 7\n");
-		exit(1); }
-
-if((file=open("SMM.IXB",O_RDWR|O_BINARY|O_CREAT|O_DENYNONE
-	,S_IWRITE|S_IREAD))==-1
-	|| (ixb_fp=fdopen(file,"r+b"))==NULL) {
-	printf("Error opening SMM.IXB\n");
-	exit(1); }
-
-if((file=open("SMM.DAB",O_RDWR|O_BINARY|O_DENYNONE))==-1
-	|| (dab_fp=fdopen(file,"r+b"))==NULL) {
-	printf("Error opening SMM.DAB\n");
-    exit(1); }
-
-if((file=open("SMM.TMP",O_WRONLY|O_CREAT|O_TRUNC|O_BINARY|O_DENYALL
-	,S_IWRITE|S_IREAD))==-1
-	|| (tmp_fp=fdopen(file,"r+b"))==NULL) {
-	printf("Error opening SMM.TMP\n");
-    exit(1); }
-
-if((file=open("SMMUTIL.LOG",O_WRONLY|O_CREAT|O_APPEND|O_BINARY|O_DENYALL
-	,S_IWRITE|S_IREAD))==-1
-	|| (log=fdopen(file,"w+b"))==NULL) {
-	printf("Error opening SMMUTIL.LOG\n");
-	exit(1); }
-
-fprintf(stderr,"Reading profile data...");
-rewind(dab_fp);
-while(!feof(dab_fp)) {
-	if(!fread(&user,sizeof(user_t),1,dab_fp))
-		break;
-	if((ixb=REALLOC(ixb,sizeof(ixb_t)*(total_ixbs+1)))==NULL) {
-		printf("Malloc error\n");
-		exit(1); }
-	user.name[25]=0;
-	strupr(user.name);
-	ixb[total_ixbs].name=crc32(user.name);
-	user.system[25]=0;
-	strupr(user.system);
-	ixb[total_ixbs].system=crc32(user.system);
-	ixb[total_ixbs].updated=user.updated;
-	if(user.misc&USER_DELETED)
-		ixb[total_ixbs].number=0;
-	else
-		ixb[total_ixbs].number=user.number;
-	total_ixbs++; }
-fprintf(stderr,"\n");
-
-now=time(NULL);
-fprintf(stderr,"Creating new profile index and data files...");
-chsize(fileno(ixb_fp),0);
-rewind(ixb_fp);
-rewind(tmp_fp);
-for(l=0;l<total_ixbs;l++) {
-	fseek(dab_fp,l*sizeof(user_t),SEEK_SET);
-    if(!fread(&user,sizeof(user_t),1,dab_fp)) {
-		logprintf("%04lX Couldn't read user record",l);
-        continue; }
-
-	/* Make sure all strings are NULL terminated */
-	user.name[25]=user.realname[25]=user.system[40]=user.birth[8]=0;
-	user.zipcode[10]=user.location[30]=0;
-	user.min_zipcode[10]=user.max_zipcode[10]=0;
-	for(i=0;i<5;i++)
-		user.note[i][50]=0;
-
-	if(!ixb[l].number) {
-		logprintf("%04lX %5lu %-25s Deleted user"
-			,l,user.number,user.system);
-		delphoto(user);
-		continue; }
-	if(ixb[l].number&0xffff0000UL) {
-		logprintf("%04lX %5lu %-25s Invalid user number"
-			,l,ixb[l].number,user.system);
-		delphoto(user);
-		continue; }
-	if(max_age
-		&& now>ixb[l].updated	// Not in the future
-		&& (now-ixb[l].updated)/(24UL*60UL*60UL)>max_age) {
-		logprintf("%04lX %5lu %-25s Not updated in %lu days"
-			,l,user.number,user.system,(now-ixb[l].updated)/(24UL*60UL*60UL));
-		delphoto(user);
-		continue; }
-	for(m=l+1;m<total_ixbs;m++)
-		if(ixb[l].number
-			&& ixb[l].number==ixb[m].number && ixb[l].system==ixb[m].system)
-			break;
-	if(m<total_ixbs) {		/* Duplicate found! */
-		logprintf("%04lX %5lu %-25s Duplicate user"
-			,l,user.number,user.system);
-		delphoto(user);
-		continue; }
-
-	if(user.name[0]<SP || user.realname[0]<SP || user.system[0]<SP
-		|| user.location[0]<SP || user.zipcode[0]<SP || user.birth[0]<SP) {
-		logprintf("%04lX %5lu %-25s Invalid user string"
-			,l,user.number,user.system);
-		delphoto(user);
-		continue; }
-	if(!user.sex || !user.marital || !user.race || !user.hair || !user.eyes) {
-		logprintf("%04lX %5lu %-25s Null field"
-			,l,user.number,user.system);
-		delphoto(user);
-		continue; }
-	if(user.sex=='M') {
-		if(user.pref_sex=='F')
-			male_straight++;
-		else if(user.pref_sex=='M')
-			male_gay++;
-		else
-			male_bi++; }
-	else if(user.sex=='F') {
-		if(user.pref_sex=='M')
-			female_straight++;
-		else if(user.pref_sex=='F')
-			female_gay++;
-		else
-			female_bi++; }
-	else {
-		logprintf("%04lX %5lu %-25s Invalid sex (%02X)"
-			,l,user.number,user.system,user.sex);
-		delphoto(user);
-		continue; }
-	users++;
-	if(user.misc&USER_PHOTO)
-		photos++;
-	if(user.misc&USER_FROMSMB)
-		networked++;
-	age=getage(user.birth);
-	if(age<13) age12++;
-	else if(age<16) age15++;
-	else if(age<21) age20++;
-	else if(age<26) age25++;
-	else if(age<31) age30++;
-	else if(age<36) age35++;
-	else if(age<41) age40++;
-	else if(age<46) age45++;
-	else if(age<51) age50++;
-	else if(age<56) age55++;
-	else if(age<61) age60++;
-	else if(age<66) age65++;
-	else if(age<71) age70++;
-	else age71++;
-	switch(user.hair) {
-		case HAIR_BLONDE:
-			hair_blonde++;
-			break;
-		case HAIR_BROWN:
-			hair_brown++;
-			break;
-		case HAIR_RED:
-			hair_red++;
-			break;
-		case HAIR_BLACK:
-			hair_black++;
-			break;
-		case HAIR_GREY:
-			hair_grey++;
-			break;
-		default:
-			hair_other++;
-			break; }
-
-	switch(user.eyes) {
-		case EYES_BLUE:
-			eyes_blue++;
-			break;
-        case EYES_BROWN:
-			eyes_brown++;
-			break;
-        case EYES_GREEN:
-			eyes_green++;
-            break;
-        case EYES_HAZEL:
-			eyes_hazel++;
-            break;
-		default:
-			eyes_other++;
-			break; }
-	switch(user.marital) {
-		case MARITAL_SINGLE:
-			marital_single++;
-			break;
-		case MARITAL_MARRIED:
-			marital_married++;
-            break;
-        case MARITAL_DIVORCED:
-			marital_divorced++;
-            break;
-        case MARITAL_WIDOWED:
-			marital_widowed++;
-            break;
-        default:
-			marital_other++;
-			break; }
-
-	switch(user.race) {
-		case RACE_WHITE:
-			race_white++;
-			break;
-		case RACE_BLACK:
-			race_black++;
-			break;
-		case RACE_HISPANIC:
-			race_hispanic++;
-			break;
-		case RACE_ASIAN:
-			race_asian++;
-			break;
-		case RACE_AMERINDIAN:
-			race_amerindian++;
-			break;
-		case RACE_MIDEASTERN:
-			race_mideastern++;
-			break;
-		default:
-			race_other++;
-			break; }
-
-	if((!strncmp(user.birth,"03",2) && atoi(user.birth+3)>=21)
-		|| (!strncmp(user.birth,"04",2) && atoi(user.birth+3)<=19))
-		zodiac_aries++;
-	else if((!strncmp(user.birth,"04",2) && atoi(user.birth+3)>=20)
-		|| (!strncmp(user.birth,"05",2) && atoi(user.birth+3)<=20))
-		zodiac_taurus++;
-	else if((!strncmp(user.birth,"05",2) && atoi(user.birth+3)>=21)
-		|| (!strncmp(user.birth,"06",2) && atoi(user.birth+3)<=20))
-		zodiac_gemini++;
-	else if((!strncmp(user.birth,"06",2) && atoi(user.birth+3)>=21)
-		|| (!strncmp(user.birth,"07",2) && atoi(user.birth+3)<=22))
-		zodiac_cancer++;
-	else if((!strncmp(user.birth,"07",2) && atoi(user.birth+3)>=23)
-		|| (!strncmp(user.birth,"08",2) && atoi(user.birth+3)<=22))
-		zodiac_leo++;
-	else if((!strncmp(user.birth,"08",2) && atoi(user.birth+3)>=23)
-		|| (!strncmp(user.birth,"09",2) && atoi(user.birth+3)<=22))
-		zodiac_virgo++;
-	else if((!strncmp(user.birth,"09",2) && atoi(user.birth+3)>=23)
-		|| (!strncmp(user.birth,"10",2) && atoi(user.birth+3)<=22))
-		zodiac_libra++;
-	else if((!strncmp(user.birth,"10",2) && atoi(user.birth+3)>=23)
-		|| (!strncmp(user.birth,"11",2) && atoi(user.birth+3)<=21))
-		zodiac_scorpio++;
-	else if((!strncmp(user.birth,"11",2) && atoi(user.birth+3)>=22)
-		|| (!strncmp(user.birth,"12",2) && atoi(user.birth+3)<=21))
-		zodiac_sagittarius++;
-	else if((!strncmp(user.birth,"12",2) && atoi(user.birth+3)>=22)
-		|| (!strncmp(user.birth,"01",2) && atoi(user.birth+3)<=19))
-		zodiac_capricorn++;
-	else if((!strncmp(user.birth,"01",2) && atoi(user.birth+3)>=20)
-		|| (!strncmp(user.birth,"02",2) && atoi(user.birth+3)<=18))
-		zodiac_aquarius++;
-	else if((!strncmp(user.birth,"02",2) && atoi(user.birth+3)>=19)
-		|| (!strncmp(user.birth,"03",2) && atoi(user.birth+3)<=20))
-		zodiac_pisces++;
-
-	fwrite(&ixb[l],sizeof(ixb_t),1,ixb_fp);
-	fwrite(&user,sizeof(user_t),1,tmp_fp);
-	}
-fprintf(stderr,"\n");
-fcloseall();
-remove("SMM.DAB");
-rename("SMM.TMP","SMM.DAB");
-
-printf("Synchronet Match Maker Statistics\n");
-printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
-printf("\n");
-printf("%-25s         : %lu\n","Total",users);
-printf("%-25s         : %lu\n","Photos",photos);
-printf("%-25s         : %lu\n","Networked",networked);
-// if(male_straight)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: male (hetero)"
-		,(((float)male_straight/users)*100.0),male_straight);
-// if(male_gay)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: male (gay)"
-		,(((float)male_gay/users)*100.0),male_gay);
-// if(male_bi)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: male (bi)"
-		,(((float)male_bi/users)*100.0),male_bi);
-// if(female_straight)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: female (hetero)"
-		,(((float)female_straight/users)*100.0),female_straight);
-// if(female_gay)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: female (gay)"
-		,(((float)female_gay/users)*100.0),female_gay);
-// if(female_bi)
-	printf("%-25s (%4.1f%%) : %lu\n","Sex: female (bi)"
-		,(((float)female_bi/users)*100.0),female_bi);
-// if(age12)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 12 and younger"
-		,(((float)age12/users)*100.0),age12);
-// if(age15)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 13 to 15 years old"
-		,(((float)age15/users)*100.0),age15);
-// if(age20)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 16 to 20 years old"
-		,(((float)age20/users)*100.0),age20);
-// if(age25)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 21 to 25 years old"
-		,(((float)age25/users)*100.0),age25);
-// if(age30)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 26 to 30 years old"
-		,(((float)age30/users)*100.0),age30);
-// if(age35)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 31 to 35 years old"
-		,(((float)age35/users)*100.0),age35);
-// if(age40)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 36 to 40 years old"
-		,(((float)age40/users)*100.0),age40);
-// if(age45)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 41 to 45 years old"
-		,(((float)age45/users)*100.0),age45);
-// if(age50)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 46 to 50 years old"
-		,(((float)age50/users)*100.0),age50);
-// if(age55)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 51 to 55 years old"
-		,(((float)age55/users)*100.0),age55);
-// if(age60)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 56 to 60 years old"
-		,(((float)age60/users)*100.0),age60);
-// if(age65)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 61 to 65 years old"
-		,(((float)age65/users)*100.0),age65);
-// if(age70)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 66 to 70 years old"
-		,(((float)age70/users)*100.0),age70);
-// if(age71)
-	printf("%-25s (%4.1f%%) : %lu\n","Age: 71 and older"
-		,(((float)age71/users)*100.0),age71);
-// if(hair_blonde)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: blonde"
-		,(((float)hair_blonde/users)*100.0),hair_blonde);
-// if(hair_brown)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: brown"
-		,(((float)hair_brown/users)*100.0),hair_brown);
-// if(hair_black)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: black"
-		,(((float)hair_black/users)*100.0),hair_black);
-// if(hair_red)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: red"
-		,(((float)hair_red/users)*100.0),hair_red);
-// if(hair_grey)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: grey"
-		,(((float)hair_grey/users)*100.0),hair_grey);
-// if(hair_other)
-	printf("%-25s (%4.1f%%) : %lu\n","Hair: other"
-		,(((float)hair_other/users)*100.0),hair_other);
-// if(eyes_blue)
-	printf("%-25s (%4.1f%%) : %lu\n","Eyes: blue"
-		,(((float)eyes_blue/users)*100.0),eyes_blue);
-// if(eyes_brown)
-	printf("%-25s (%4.1f%%) : %lu\n","Eyes: brown"
-        ,(((float)eyes_brown/users)*100.0),eyes_brown);
-// if(eyes_green)
-	printf("%-25s (%4.1f%%) : %lu\n","Eyes: green"
-		,(((float)eyes_green/users)*100.0),eyes_green);
-// if(eyes_hazel)
-	printf("%-25s (%4.1f%%) : %lu\n","Eyes: hazel"
-		,(((float)eyes_hazel/users)*100.0),eyes_hazel);
-// if(eyes_other)
-	printf("%-25s (%4.1f%%) : %lu\n","Eyes: other"
-		,(((float)eyes_other/users)*100.0),eyes_other);
-// if(race_white)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: white"
-		,(((float)race_white/users)*100.0),race_white);
-// if(race_black)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: black"
-		,(((float)race_black/users)*100.0),race_black);
-// if(race_asian)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: asian"
-		,(((float)race_asian/users)*100.0),race_asian);
-// if(race_amerindian)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: amerindian"
-		,(((float)race_amerindian/users)*100.0),race_amerindian);
-// if(race_mideastern)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: mideastern"
-		,(((float)race_mideastern/users)*100.0),race_mideastern);
-// if(race_hispanic)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: hispanic"
-		,(((float)race_hispanic/users)*100.0),race_hispanic);
-// if(race_other)
-	printf("%-25s (%4.1f%%) : %lu\n","Race: other"
-		,(((float)race_other/users)*100.0),race_other);
-// if(marital_single)
-	printf("%-25s (%4.1f%%) : %lu\n","Marital: single"
-        ,(((float)marital_single/users)*100.0),marital_single);
-// if(marital_married)
-	printf("%-25s (%4.1f%%) : %lu\n","Marital: married"
-		,(((float)marital_married/users)*100.0),marital_married);
-// if(marital_divorced)
-	printf("%-25s (%4.1f%%) : %lu\n","Marital: divorced"
-		,(((float)marital_divorced/users)*100.0),marital_divorced);
-// if(marital_widowed)
-	printf("%-25s (%4.1f%%) : %lu\n","Marital: widowed"
-		,(((float)marital_widowed/users)*100.0),marital_widowed);
-// if(marital_other)
-	printf("%-25s (%4.1f%%) : %lu\n","Marital: other"
-		,(((float)marital_other/users)*100.0),marital_other);
-// if(zodiac_aries)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: aries"
-		,(((float)zodiac_aries/users)*100.0),zodiac_aries);
-// if(zodiac_taurus)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: taurus"
-		,(((float)zodiac_taurus/users)*100.0),zodiac_taurus);
-// if(zodiac_gemini)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: gemini"
-		,(((float)zodiac_gemini/users)*100.0),zodiac_gemini);
-// if(zodiac_cancer)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: cancer"
-		,(((float)zodiac_cancer/users)*100.0),zodiac_cancer);
-// if(zodiac_leo)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: leo"
-		,(((float)zodiac_leo/users)*100.0),zodiac_leo);
-// if(zodiac_virgo)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: virgo"
-		,(((float)zodiac_virgo/users)*100.0),zodiac_virgo);
-// if(zodiac_libra)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: libra"
-		,(((float)zodiac_libra/users)*100.0),zodiac_libra);
-// if(zodiac_scorpio)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: scorpio"
-		,(((float)zodiac_scorpio/users)*100.0),zodiac_scorpio);
-// if(zodiac_sagittarius)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: sagittarius"
-		,(((float)zodiac_sagittarius/users)*100.0),zodiac_sagittarius);
-// if(zodiac_capricorn)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: capricorn"
-		,(((float)zodiac_capricorn/users)*100.0),zodiac_capricorn);
-// if(zodiac_aquarius)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: aquarius"
-		,(((float)zodiac_aquarius/users)*100.0),zodiac_aquarius);
-// if(zodiac_pisces)
-	printf("%-25s (%4.1f%%) : %lu\n","Zodiac: pisces"
-		,(((float)zodiac_pisces/users)*100.0),zodiac_pisces);
-
-if(!max_wall)
-	return(0);
-
-if((file=open("WALL.DAB",O_RDWR|O_BINARY|O_DENYNONE))==-1
-	|| (dab_fp=fdopen(file,"r+b"))==NULL) {
-	printf("Error opening WALL.DAB\n");
-    exit(1); }
-
-if((file=open("WALL.TMP",O_WRONLY|O_CREAT|O_TRUNC|O_BINARY|O_DENYALL
-	,S_IWRITE|S_IREAD))==-1
-	|| (tmp_fp=fdopen(file,"r+b"))==NULL) {
-	printf("Error opening WALL.TMP\n");
-    exit(1); }
-
-fprintf(stderr,"Reading wall data...");
-rewind(dab_fp);
-while(!feof(dab_fp)) {
-	if(!fread(&wall,sizeof(wall_t),1,dab_fp))
-        break;
-	if((now-wall.imported)/(24UL*60UL*60UL)<=max_wall)
-		fwrite(&wall,sizeof(wall_t),1,tmp_fp); }
-
-fprintf(stderr,"\n");
-fcloseall();
-remove("WALL.DAB");
-rename("WALL.TMP","WALL.DAB");
-
-return(0);
-}
diff --git a/src/sbbs2/smm/smmvars.c b/src/sbbs2/smm/smmvars.c
deleted file mode 100644
index 0e828145b47872cfe91a13cf3e5b26e69654e616..0000000000000000000000000000000000000000
--- a/src/sbbs2/smm/smmvars.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SMMVARS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-uchar purity_age=18;
-uchar min_age=15;
-uint  min_level=0;
-uchar req_flags1[128]="";
-uchar req_flags2[128]="";
-uchar req_flags3[128]="";
-uchar req_flags4[128]="";
-uchar zmodem_send[128]="";
-uchar local_view[128]="";
-uint  auto_update=0;
-long  profile_cdt=0;
-long  telegram_cdt=0;
-uint  telegram_level=0;
-long  wall_cdt=0;
-uint  wall_level=0;
-uchar wall_age=0;
-uchar age_split=0;
-uint  que_level=0;
-long  que_cdt=0;
-long  cdt_adjustment=0;
-uint  notify_user=0;
-ulong smm_misc=0;
-uchar system_name[41]="";
diff --git a/src/sbbs2/str.c b/src/sbbs2/str.c
deleted file mode 100644
index 6d4e2ade02e8377f346e98829bc1876020a4b982..0000000000000000000000000000000000000000
--- a/src/sbbs2/str.c
+++ /dev/null
@@ -1,1080 +0,0 @@
-#line 1 "STR.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*****************************************************/
-/* Functions that perform lengthy string i/o rotines */
-/*****************************************************/
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Lists all users who have access to the current sub.                      */
-/****************************************************************************/
-void userlist(char mode)
-{
-	uchar name[256],sort=0;
-	int i,j,k,users=0;
-	uchar *line[1000];
-	user_t user;
-
-if(lastuser()<=1000)
-	sort=yesno(text[SortAlphaQ]);
-if(sort) {
-	bputs(text[CheckingSlots]); }
-else {
-	CRLF; }
-j=0;
-k=lastuser();
-for(i=1;i<=k && !msgabort();i++) {
-	if(sort && (online==ON_LOCAL || !rioctl(TXBC)))
-		bprintf("%-4d\b\b\b\b",i);
-	user.number=i;
-	getuserdat(&user);
-	if(user.misc&(DELETED|INACTIVE))
-		continue;
-	users++;
-	if(mode==UL_SUB) {
-		if(!usrgrps)
-			continue;
-		if(!chk_ar(grp[usrgrp[curgrp]]->ar,user))
-			continue;
-		if(!chk_ar(sub[usrsub[curgrp][cursub[curgrp]]]->ar,user)
-			|| (sub[usrsub[curgrp][cursub[curgrp]]]->read_ar[0]
-			&& !chk_ar(sub[usrsub[curgrp][cursub[curgrp]]]->read_ar,user)))
-			continue; }
-	else if(mode==UL_DIR) {
-		if(user.rest&FLAG('T'))
-			continue;
-		if(!usrlibs)
-			continue;
-		if(!chk_ar(lib[usrlib[curlib]]->ar,user))
-			continue;
-		if(!chk_ar(dir[usrdir[curlib][curdir[curlib]]]->ar,user))
-			continue; }
-	if(sort) {
-		if((line[j]=(char *)MALLOC(128))==0) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,83);
-			for(i=0;i<j;i++)
-				FREE(line[i]);
-			return; }
-		sprintf(name,"%s #%d",user.alias,i);
-		sprintf(line[j],text[UserListFmt],name
-			,sys_misc&SM_LISTLOC ? user.location : user.note
-			,unixtodstr(user.laston,tmp)
-			,user.modem); }
-	else {
-		sprintf(name,"%s #%u",user.alias,i);
-		bprintf(text[UserListFmt],name
-			,sys_misc&SM_LISTLOC ? user.location : user.note
-			,unixtodstr(user.laston,tmp)
-			,user.modem); }
-	j++; }
-if(i<=k) {	/* aborted */
-	if(sort)
-		for(i=0;i<j;i++)
-			FREE(line[i]);
-	return; }
-if(!sort) {
-	CRLF; }
-bprintf(text[NTotalUsers],users);
-if(mode==UL_SUB)
-	bprintf(text[NUsersOnCurSub],j);
-else if(mode==UL_DIR)
-	bprintf(text[NUsersOnCurDir],j);
-if(!sort)
-	return;
-CRLF;
-qsort((void *)line,j,sizeof(line[0])
-	,(int(*)(const void*, const void*))pstrcmp);
-for(i=0;i<j && !msgabort();i++)
-	bputs(line[i]);
-for(i=0;i<j;i++)
-	FREE(line[i]);
-}
-
-/****************************************************************************/
-/* SIF input function. See SIF.DOC for more info        					*/
-/****************************************************************************/
-void sif(char *fname, char *answers, long len)
-{
-	char str[256],template[256],HUGE16 *buf,t,max,min,mode,cr;
-	int file;
-	ulong length,l=0,m,top,a=0;
-
-sprintf(str,"%s%s.SIF",text_dir,strupr(fname));
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	answers[0]=0;
-	return; }
-length=filelength(file);
-if((buf=(char *)MALLOC(length))==0) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length);
-	answers[0]=0;
-	return; }
-if(lread(file,buf,length)!=length) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str,length);
-	answers[0]=0;
-	return; }
-close(file);
-while(l<length && online) {
-	mode=min=max=t=cr=0;
-	top=l;
-	while(l<length && buf[l++]!=STX);
-	for(m=l;m<length;m++)
-		if(buf[m]==ETX || !buf[m]) {
-			buf[m]=0;
-			break; }
-	if(l>=length) break;
-	if(online==ON_REMOTE) {
-		rioctl(IOCM|ABORT);
-		rioctl(IOCS|ABORT); }
-	putmsg(buf+l,P_SAVEATR);
-	m++;
-	if(toupper(buf[m])!='C' && toupper(buf[m])!='S')
-        continue;
-	SYNC;
-	if(online==ON_REMOTE)
-		rioctl(IOSM|ABORT);
-	if(a>=len) {
-		errormsg(WHERE,ERR_LEN,fname,len);
-		break; }
-	if((buf[m]&0xdf)=='C') {
-    	if((buf[m+1]&0xdf)=='U') {		/* Uppercase only */
-			mode|=K_UPPER;
-			m++; }
-		else if((buf[m+1]&0xdf)=='N') {	/* Numbers only */
-			mode|=K_NUMBER;
-			m++; }
-		if((buf[m+1]&0xdf)=='L') {		/* Draw line */
-        	if(useron.misc&COLOR)
-				attr(color[clr_inputline]);
-			else
-				attr(BLACK|(LIGHTGRAY<<4));
-			bputs(" \b");
-			m++; }
-		if((buf[m+1]&0xdf)=='R') {		/* Add CRLF */
-			cr=1;
-			m++; }
-		if(buf[m+1]=='"') {
-			m+=2;
-			for(l=m;l<length;l++)
-				if(buf[l]=='"') {
-					buf[l]=0;
-					break; }
-			answers[a++]=getkeys((char *)buf+m,0); }
-		else {
-			answers[a]=getkey(mode);
-			outchar(answers[a++]);
-			attr(LIGHTGRAY);
-			CRLF; }
-		if(cr) {
-			answers[a++]=CR;
-			answers[a++]=LF; } }
-	else if((buf[m]&0xdf)=='S') {		/* String */
-		if((buf[m+1]&0xdf)=='U') {		/* Uppercase only */
-			mode|=K_UPPER;
-			m++; }
-		else if((buf[m+1]&0xdf)=='F') { /* Force Upper/Lowr case */
-			mode|=K_UPRLWR;
-			m++; }
-		else if((buf[m+1]&0xdf)=='N') {	/* Numbers only */
-			mode|=K_NUMBER;
-			m++; }
-		if((buf[m+1]&0xdf)=='L') {		/* Draw line */
-			mode|=K_LINE;
-			m++; }
-		if((buf[m+1]&0xdf)=='R') {		/* Add CRLF */
-			cr=1;
-			m++; }
-		if(isdigit(buf[m+1])) {
-			max=buf[++m]&0xf;
-			if(isdigit(buf[m+1]))
-				max=max*10+(buf[++m]&0xf); }
-		if(buf[m+1]=='.' && isdigit(buf[m+2])) {
-			m++;
-			min=buf[++m]&0xf;
-			if(isdigit(buf[m+1]))
-				min=min*10+(buf[++m]&0xf); }
-		if(buf[m+1]=='"') {
-			m++;
-			mode&=~K_NUMBER;
-			while(buf[++m]!='"' && t<80)
-				template[t++]=buf[m];
-			template[t]=0;
-			max=strlen(template); }
-		if(t) {
-			if(gettmplt(str,template,mode)<min) {
-				l=top;
-				continue; } }
-		else {
-			if(!max)
-				continue;
-			if(getstr(str,max,mode)<min) {
-				l=top;
-				continue; } }
-		if(!cr) {
-			for(cr=0;str[cr];cr++)
-				answers[a+cr]=str[cr];
-			while(cr<max)
-				answers[a+cr++]=ETX;
-			a+=max; }
-		else {
-			putrec(answers,a,max,str);
-			putrec(answers,a+max,2,crlf);
-			a+=max+2; } } }
-answers[a]=0;
-FREE((char *)buf);
-}
-
-/****************************************************************************/
-/* SIF output function. See SIF.DOC for more info        					*/
-/****************************************************************************/
-void sof(char *fname, char *answers, long len)
-{
-	char str[256],HUGE16 *buf,max,min,cr;
-	int file;
-	ulong length,l=0,m,a=0;
-
-sprintf(str,"%s%s.SIF",text_dir,strupr(fname));
-if((file=nopen(str,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	answers[0]=0;
-	return; }
-length=filelength(file);
-if((buf=(char *)MALLOC(length))==0) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,str,length);
-	answers[0]=0;
-	return; }
-if(lread(file,buf,length)!=length) {
-	close(file);
-	errormsg(WHERE,ERR_READ,str,length);
-	answers[0]=0;
-	return; }
-close(file);
-while(l<length && online) {
-	min=max=cr=0;
-	while(l<length && buf[l++]!=STX);
-	for(m=l;m<length;m++)
-		if(buf[m]==ETX || !buf[m]) {
-			buf[m]=0;
-			break; }
-	if(l>=length) break;
-	if(online==ON_REMOTE) {
-		rioctl(IOCM|ABORT);
-		rioctl(IOCS|ABORT); }
-	putmsg(buf+l,P_SAVEATR);
-	m++;
-	if(toupper(buf[m])!='C' && toupper(buf[m])!='S')
-		continue;
-	SYNC;
-	if(online==ON_REMOTE)
-		rioctl(IOSM|ABORT);
-	if(a>=len) {
-		bprintf("\r\nSOF: %s defined more data than buffer size "
-			"(%lu bytes)\r\n",fname,len);
-		break; }
-	if((buf[m]&0xdf)=='C') {
-		if((buf[m+1]&0xdf)=='U')  		/* Uppercase only */
-			m++;
-		else if((buf[m+1]&0xdf)=='N')  	/* Numbers only */
-			m++;
-		if((buf[m+1]&0xdf)=='L') {		/* Draw line */
-        	if(useron.misc&COLOR)
-				attr(color[clr_inputline]);
-			else
-				attr(BLACK|(LIGHTGRAY<<4));
-			bputs(" \b");
-			m++; }
-		if((buf[m+1]&0xdf)=='R') {		/* Add CRLF */
-			cr=1;
-			m++; }
-		outchar(answers[a++]);
-		attr(LIGHTGRAY);
-		CRLF;
-		if(cr)
-			a+=2; }
-	else if((buf[m]&0xdf)=='S') {		/* String */
-		if((buf[m+1]&0xdf)=='U')
-			m++;
-		else if((buf[m+1]&0xdf)=='F')
-			m++;
-		else if((buf[m+1]&0xdf)=='N')   /* Numbers only */
-			m++;
-		if((buf[m+1]&0xdf)=='L') {
-        	if(useron.misc&COLOR)
-				attr(color[clr_inputline]);
-			else
-				attr(BLACK|(LIGHTGRAY<<4));
-			m++; }
-		if((buf[m+1]&0xdf)=='R') {
-			cr=1;
-			m++; }
-		if(isdigit(buf[m+1])) {
-			max=buf[++m]&0xf;
-			if(isdigit(buf[m+1]))
-				max=max*10+(buf[++m]&0xf); }
-		if(buf[m+1]=='.' && isdigit(buf[m+2])) {
-			m++;
-			min=buf[++m]&0xf;
-			if(isdigit(buf[m+1]))
-				min=min*10+(buf[++m]&0xf); }
-		if(buf[m+1]=='"') {
-			max=0;
-			m++;
-			while(buf[++m]!='"' && max<80)
-				max++; }
-		if(!max)
-			continue;
-		getrec(answers,a,max,str);
-		bputs(str);
-		attr(LIGHTGRAY);
-		CRLF;
-		if(!cr)
-			a+=max;
-		else
-			a+=max+2; } }
-FREE((char *)buf);
-}
-
-/****************************************************************************/
-/* Creates data file 'datfile' from input via sif file 'siffile'            */
-/****************************************************************************/
-void create_sif_dat(char *siffile, char *datfile)
-{
-	char *buf;
-	int file;
-
-if((buf=(char *)MALLOC(SIF_MAXBUF))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,siffile,SIF_MAXBUF);
-	return; }
-memset(buf,SIF_MAXBUF,0);	 /* initialize to null */
-sif(siffile,buf,SIF_MAXBUF);
-if((file=nopen(datfile,O_WRONLY|O_TRUNC|O_CREAT))==-1) {
-	FREE(buf);
-	errormsg(WHERE,ERR_OPEN,datfile,O_WRONLY|O_TRUNC|O_CREAT);
-	return; }
-write(file,buf,strlen(buf));
-close(file);
-FREE(buf);
-}
-
-/****************************************************************************/
-/* Reads data file 'datfile' and displays output via sif file 'siffile'     */
-/****************************************************************************/
-void read_sif_dat(char *siffile, char *datfile)
-{
-	char *buf;
-	int file;
-	long length;
-
-if((file=nopen(datfile,O_RDONLY))==-1) {
-	errormsg(WHERE,ERR_OPEN,datfile,O_RDONLY);
-	return; }
-length=filelength(file);
-if(!length) {
-	close(file);
-	return; }
-if((buf=(char *)MALLOC(length))==NULL) {
-	close(file);
-	errormsg(WHERE,ERR_ALLOC,datfile,length);
-	return; }
-read(file,buf,length);
-close(file);
-sof(siffile,buf,length);
-FREE(buf);
-}
-
-/****************************************************************************/
-/* Get string by template. A=Alpha, N=Number, !=Anything                    */
-/* First character MUST be an A,N or !.                                     */
-/* Modes - K_LINE and K_UPPER are supported.                                */
-/****************************************************************************/
-char gettmplt(char *strout,char *template,int mode)
-{
-	uchar t=strlen(template),c=0,ch,str[256];
-
-sys_status&=~SS_ABORT;
-strupr(template);
-if(useron.misc&ANSI) {
-	if(mode&K_LINE) {
-		if(useron.misc&COLOR)
-            attr(color[clr_inputline]);
-		else
-			attr(BLACK|(LIGHTGRAY<<4)); }
-	while(c<t) {
-		if(template[c]=='N' || template[c]=='A' || template[c]=='!')
-			outchar(SP);
-		else
-			outchar(template[c]);
-		c++; }
-	bprintf("\x1b[%dD",t); }
-c=0;
-if(mode&K_EDIT) {
-	strcpy(str,strout);
-	bputs(str);
-	c=strlen(str); }
-while((ch=getkey(mode))!=CR && online && !(sys_status&SS_ABORT)) {
-	if(ch==BS) {
-		if(!c)
-			continue;
-		for(ch=1,c--;c;c--,ch++)
-			if(template[c]=='N' || template[c]=='A' || template[c]=='!')
-				break;
-		if(useron.misc&ANSI)
-			bprintf("\x1b[%dD",ch);
-		else while(ch--)
-			outchar(BS);
-		bputs(" \b");
-		continue; }
-	if(ch==24) {	/* Ctrl-X */
-		for(c--;c!=0xff;c--) {
-			outchar(BS);
-			if(template[c]=='N' || template[c]=='A' || template[c]=='!')
-				bputs(" \b"); }
-		c=0; }
-	else if(c<t) {
-		if(template[c]=='N' && !isdigit(ch))
-			continue;
-		if(template[c]=='A' && !isalpha(ch))
-			continue;
-		outchar(ch);
-		str[c++]=ch;
-		while(c<t && template[c]!='N' && template[c]!='A' && template[c]!='!'){
-			str[c]=template[c];
-			outchar(template[c++]); } } }
-str[c]=0;
-attr(LIGHTGRAY);
-CRLF;
-if(!(sys_status&SS_ABORT))
-	strcpy(strout,str);
-return(c);
-}
-
-/*****************************************************************************/
-/* Accepts a user's input to change a new-scan time pointer                  */
-/* Returns 0 if input was aborted or invalid, 1 if complete					 */
-/*****************************************************************************/
-char inputnstime(time_t *dt)
-{
-	int hour;
-	struct date tmpdate;
-	struct time tmptime;
-	char pm,str[256];
-
-bputs(text[NScanDate]);
-bputs(timestr(dt));
-CRLF;
-unixtodos(*dt,&tmpdate,&tmptime);
-bputs(text[NScanYear]);
-itoa(tmpdate.da_year,str,10);
-if(!getstr(str,4,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
-	CRLF;
-	return(0); }
-tmpdate.da_year=atoi(str);
-if(tmpdate.da_year<1970) {
-	CRLF;
-	return(0); }
-bputs(text[NScanMonth]);
-itoa(tmpdate.da_mon,str,10);
-if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
-	CRLF;
-	return(0); }
-tmpdate.da_mon=atoi(str);
-if(tmpdate.da_mon<1 || tmpdate.da_mon>12) {
-	CRLF;
-	return(0); }
-bputs(text[NScanDay]);
-itoa(tmpdate.da_day,str,10);
-if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
-	CRLF;
-	return(0); }
-tmpdate.da_day=atoi(str);
-if(tmpdate.da_day<1 || tmpdate.da_day>31) {
-	CRLF;
-	return(0); }
-bputs(text[NScanHour]);
-if(sys_misc&SM_MILITARY)
-	hour=tmptime.ti_hour;
-else {
-	if(tmptime.ti_hour==0) {	/* 12 midnite */
-		pm=0;
-		hour=12; }
-	else if(tmptime.ti_hour>12) {
-		hour=tmptime.ti_hour-12;
-		pm=1; }
-	else {
-		hour=tmptime.ti_hour;
-		pm=0; } }
-itoa(hour,str,10);
-if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
-	CRLF;
-	return(0); }
-
-tmptime.ti_hour=atoi(str);
-if(tmptime.ti_hour>24) {
-	CRLF;
-	return(0); }
-bputs(text[NScanMinute]);
-itoa(tmptime.ti_min,str,10);
-if(!getstr(str,2,K_EDIT|K_AUTODEL|K_NUMBER|K_NOCRLF) || sys_status&SS_ABORT) {
-	CRLF;
-	return(0); }
-
-tmptime.ti_min=atoi(str);
-if(tmptime.ti_min>59) {
-	CRLF;
-	return(0); }
-tmptime.ti_sec=0;
-if(!(sys_misc&SM_MILITARY) && tmptime.ti_hour && tmptime.ti_hour<13) {
-	if(pm && yesno(text[NScanPmQ])) {
-			if(tmptime.ti_hour<12)
-				tmptime.ti_hour+=12; }
-	else if(!pm && !yesno(text[NScanAmQ])) {
-			if(tmptime.ti_hour<12)
-				tmptime.ti_hour+=12; }
-	else if(tmptime.ti_hour==12)
-		tmptime.ti_hour=0; }
-else {
-	CRLF; }
-*dt=dostounix(&tmpdate,&tmptime);
-return(1);
-}
-
-/*****************************************************************************/
-/* Checks a password for uniqueness and validity                              */
-/*****************************************************************************/
-char chkpass(char *pass, user_t user)
-{
-	char c,d,first[128],last[128],sysop[41],sysname[41],*p;
-
-if(strlen(pass)<4) {
-	bputs(text[PasswordTooShort]);
-	return(0); }
-if(!strcmp(pass,user.pass)) {
-	bputs(text[PasswordNotChanged]);
-	return(0); }
-d=strlen(pass);
-for(c=1;c<d;c++)
-	if(pass[c]!=pass[c-1])
-		break;
-if(c==d) {
-	bputs(text[PasswordInvalid]);
-	return(0); }
-for(c=0;c<3;c++)	/* check for 1234 and ABCD */
-	if(pass[c]!=pass[c+1]+1)
-		break;
-if(c==3) {
-	bputs(text[PasswordObvious]);
-	return(0); }
-for(c=0;c<3;c++)	/* check for 4321 and ZYXW */
-	if(pass[c]!=pass[c+1]-1)
-		break;
-if(c==3) {
-	bputs(text[PasswordObvious]);
-    return(0); }
-strupr(user.name);
-strupr(user.alias);
-strcpy(first,user.alias);
-p=strchr(first,SP);
-if(p) {
-	*p=0;
-	strcpy(last,p+1); }
-else
-	last[0]=0;
-strupr(user.handle);
-strcpy(sysop,sys_op);
-strupr(sysop);
-strcpy(sysname,sys_name);
-strupr(sysname);
-if((user.pass[0]
-		&& (strstr(pass,user.pass) || strstr(user.pass,pass)))
-	|| (user.name[0]
-		&& (strstr(pass,user.name) || strstr(user.name,pass)))
-	|| strstr(pass,user.alias) || strstr(user.alias,pass)
-	|| strstr(pass,first) || strstr(first,pass)
-	|| (last[0]
-		&& (strstr(pass,last) || strstr(last,pass)))
-	|| strstr(pass,user.handle) || strstr(user.handle,pass)
-	|| (user.zipcode[0]
-		&& (strstr(pass,user.zipcode) || strstr(user.zipcode,pass)))
-	|| (sysname[0]
-		&& (strstr(pass,sysname) || strstr(sysname,pass)))
-	|| (sysop[0]
-		&& (strstr(pass,sysop) || strstr(sysop,pass)))
-	|| (sys_id[0]
-		&& (strstr(pass,sys_id) || strstr(sys_id,pass)))
-	|| (node_phone[0] && strstr(pass,node_phone))
-	|| (user.phone[0] && strstr(user.phone,pass))
-	|| !strncmp(pass,"QWER",3)
-	|| !strncmp(pass,"ASDF",3)
-	|| !strncmp(pass,"!@#$",3)
-	)
-	{
-	bputs(text[PasswordObvious]);
-	return(0); }
-return(1);
-}
-
-/****************************************************************************/
-/* Prompts user for detailed information regarding their computer 			*/
-/* and places that information into 'computer'								*/
-/* Called from function newuser												*/
-/****************************************************************************/
-void getcomputer(char *computer)
-{
-	char str[256];
-
-if(!(uq&UQ_MC_COMP)) {
-	while(online) {
-		bputs(text[EnterYourComputer]);
-		if(getstr(computer,LEN_COMP,K_LINE))
-			break; }
-	return; }
-bputs(text[ComputerTypeMenu]);
-bputs(text[ComputerTypePrompt]);
-switch(getkeys("ABCDE",0)) {
-	case 'A':
-		sif("COMPUTER",str,8);
-		if(!online) return;
-		switch(str[0]) {
-			case 'A':
-				strcpy(computer,"XT");
-				break;
-			case 'B':
-				strcpy(computer,"286");
-				break;
-			case 'C':
-				strcpy(computer,"386SX");
-				break;
-			case 'D':
-				strcpy(computer,"386DX");
-				break;
-			case 'E':
-				strcpy(computer,"486");
-				break; }
-		switch(str[1]) {
-			case 'A':
-				strcat(computer,"-4 ");
-				break;
-			case 'B':
-				strcat(computer,"-6 ");
-				break;
-			case 'C':
-				strcat(computer,"-8 ");
-				break;
-			case 'D':
-				strcat(computer,"-10 ");
-				break;
-			case 'E':
-				strcat(computer,"-12 ");
-				break;
-			case 'F':
-				strcat(computer,"-16 ");
-				break;
-			case 'G':
-				strcat(computer,"-20 ");
-				break;
-			case 'H':
-				strcat(computer,"-25 ");
-				break;
-			case 'I':
-				strcat(computer,"-33 ");
-				break;
-			case 'J':
-				strcat(computer,"-40 ");
-				break;
-			case 'K':
-				strcat(computer,"-50 ");
-				break; }
-		switch(str[2]) {
-			case 'A':
-				strcat(computer,"8bit ");
-				break;
-			case 'B':
-				strcat(computer,"ISA ");
-				break;
-			case 'C':
-				strcat(computer,"MCA ");
-				break;
-			case 'D':
-				strcat(computer,"EISA ");
-				break; }
-		switch(str[3]) {
-			case 'A':
-				strcat(computer,"MDA ");
-				break;
-			case 'B':
-				strcat(computer,"HERC ");
-				break;
-			case 'C':
-				strcat(computer,"CGA ");
-				break;
-			case 'D':
-				strcat(computer,"EGA ");
-				break;
-			case 'E':
-				strcat(computer,"MCGA ");
-				break;
-			case 'F':
-				strcat(computer,"VGA ");
-				break;
-			case 'G':
-				strcat(computer,"SVGA ");
-				break;
-			case 'H':
-				strcat(computer,"MVGA ");
-				break;
-			case 'I':
-				strcat(computer,"8514 ");
-				break;
-			case 'J':
-				strcat(computer,"XGA ");
-				break;
-			case 'K':
-				strcat(computer,"TIGA ");
-				break; }
-		switch(str[4]) {
-			case 'A':
-				strcat(computer,"<1 ");
-				break;
-			case 'B':
-				strcat(computer,"1 ");
-				break;
-			case 'C':
-				strcat(computer,"2 ");
-				break;
-			case 'D':
-				strcat(computer,"3 ");
-				break;
-			case 'E':
-				strcat(computer,"4 ");
-				break;
-			case 'F':
-				strcat(computer,"5 ");
-				break;
-			case 'G':
-				strcat(computer,"6 ");
-				break;
-			case 'H':
-				strcat(computer,"8 ");
-				break;
-			case 'I':
-				strcat(computer,"10 ");
-				break;
-			case 'J':
-				strcat(computer,"12 ");
-				break;
-			case 'K':
-				strcat(computer,"16 ");
-				break;
-			case 'L':
-				strcat(computer,"18 ");
-				break;
-			case 'M':
-				strcat(computer,"24 ");
-				break;
-			case 'N':
-				strcat(computer,"32 ");
-				break;
-			case 'O':
-				strcat(computer,"64 ");
-				break; }
-		switch(str[5]) {
-			case 'A':
-				strcat(computer,"0 ");
-				break;
-			case 'B':
-				strcat(computer,"10 ");
-				break;
-			case 'C':
-				strcat(computer,"20 ");
-				break;
-			case 'D':
-				strcat(computer,"30 ");
-				break;
-			case 'E':
-				strcat(computer,"40 ");
-				break;
-			case 'F':
-				strcat(computer,"60 ");
-				break;
-			case 'G':
-				strcat(computer,"80 ");
-				break;
-			case 'H':
-				strcat(computer,"100 ");
-				break;
-			case 'I':
-				strcat(computer,"120 ");
-				break;
-			case 'J':
-				strcat(computer,"150 ");
-				break;
-			case 'K':
-				strcat(computer,"200 ");
-				break;
-			case 'L':
-				strcat(computer,"250 ");
-				break;
-			case 'M':
-				strcat(computer,"300 ");
-				break;
-			case 'N':
-				strcat(computer,"400 ");
-				break;
-			case 'O':
-				strcat(computer,"500 ");
-				break;
-			case 'P':
-				strcat(computer,"600 ");
-				break;
-			case 'Q':
-				strcat(computer,"700 ");
-				break;
-			case 'R':
-				strcat(computer,"800 ");
-				break;
-			case 'S':
-				strcat(computer,"900 ");
-				break;
-			case 'T':
-				strcat(computer,"1GB ");
-				break; }
-		switch(str[6]) {
-			case 'A':
-				strcat(computer,"ST506");
-				break;
-			case 'B':
-				strcat(computer,"SCSI");
-				break;
-			case 'C':
-				strcat(computer,"SCSI2");
-				break;
-			case 'D':
-				strcat(computer,"ESDI");
-				break;
-			case 'E':
-				strcat(computer,"IDE"); }
-		break;
-	case 'B':
-		sprintf(computer,"%.*s",LEN_COMP,text[ComputerTypeB]);
-		return;
-	case 'C':
-		sprintf(computer,"%.*s",LEN_COMP,text[ComputerTypeC]);
-		return;
-	case 'D':
-		sprintf(computer,"%.*s",LEN_COMP,text[ComputerTypeD]);
-		return;
-	case 'E':
-		sprintf(computer,"%.*s",LEN_COMP,text[ComputerTypeE]);
-		return; }
-}
-
-/****************************************************************************/
-/* Displays information about sub-board subnum								*/
-/****************************************************************************/
-void subinfo(uint subnum)
-{
-	char str[256];
-
-bputs(text[SubInfoHdr]);
-bprintf(text[SubInfoLongName],sub[subnum]->lname);
-bprintf(text[SubInfoShortName],sub[subnum]->sname);
-bprintf(text[SubInfoQWKName],sub[subnum]->qwkname);
-bprintf(text[SubInfoMaxMsgs],sub[subnum]->maxmsgs);
-if(sub[subnum]->misc&SUB_QNET)
-	bprintf(text[SubInfoTagLine],sub[subnum]->tagline);
-if(sub[subnum]->misc&SUB_FIDO)
-	bprintf(text[SubInfoFidoNet]
-		,sub[subnum]->origline
-		,faddrtoa(sub[subnum]->faddr));
-sprintf(str,"%s%s.MSG",sub[subnum]->data_dir,sub[subnum]->code);
-if(fexist(str) && yesno(text[SubInfoViewFileQ]))
-	printfile(str,0);
-}
-
-/****************************************************************************/
-/* Displays information about transfer directory dirnum 					*/
-/****************************************************************************/
-void dirinfo(uint dirnum)
-{
-	char str[256];
-
-bputs(text[DirInfoHdr]);
-bprintf(text[DirInfoLongName],dir[dirnum]->lname);
-bprintf(text[DirInfoShortName],dir[dirnum]->sname);
-if(dir[dirnum]->exts[0])
-	bprintf(text[DirInfoAllowedExts],dir[dirnum]->exts);
-bprintf(text[DirInfoMaxFiles],dir[dirnum]->maxfiles);
-sprintf(str,"%s%s.MSG",dir[dirnum]->data_dir,dir[dirnum]->code);
-if(fexist(str) && yesno(text[DirInfoViewFileQ]))
-	printfile(str,0);
-}
-
-/****************************************************************************/
-/* Searches the file <name>.CAN in the TEXT directory for matches			*/
-/* Returns 1 if found in list, 0 if not.									*/
-/****************************************************************************/
-char trashcan(char *insearch, char *name)
-{
-	char str[256],search[256],c,found=0;
-	int file;
-	FILE *stream;
-
-sprintf(str,"%s%s.CAN",text_dir,name);
-if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-	if(fexist(str))
-		errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return(0); }
-strcpy(search,insearch);
-strupr(search);
-while(!feof(stream) && !ferror(stream) && !found) {
-	if(!fgets(str,81,stream))
-		break;
-	truncsp(str);
-	c=strlen(str);
-	if(c) {
-		c--;
-		strupr(str);
-		if(str[c]=='~') {
-			str[c]=0;
-			if(strstr(search,str))
-				found=1; }
-
-		else if(str[c]=='^') {
-			str[c]=0;
-			if(!strncmp(str,search,c))
-				found=1; }
-
-		else if(!strcmp(str,search))
-			found=1; } }
-fclose(stream);
-if(found) {
-	sprintf(str,"%sBAD%s.MSG",text_dir,name);
-	if(fexist(str))
-		printfile(str,0);
-	return(1); }
-return(0);
-}
-
-/****************************************************************************/
-/* Error handling routine. Prints to local and remote screens the error     */
-/* information, function, action, object and access and then attempts to    */
-/* write the error information into the file ERROR.LOG and NODE.LOG         */
-/****************************************************************************/
-void errormsg(int line, char *source, char action, char *object, ulong access)
-{
-    char str[512];
-    char actstr[256];
-
-switch(action) {
-    case ERR_OPEN:
-        strcpy(actstr,"opening");
-        break;
-    case ERR_CLOSE:
-		strcpy(actstr,"closing");
-        break;
-    case ERR_FDOPEN:
-        strcpy(actstr,"fdopen");
-        break;
-    case ERR_READ:
-        strcpy(actstr,"reading");
-        break;
-    case ERR_WRITE:
-        strcpy(actstr,"writing");
-        break;
-    case ERR_REMOVE:
-        strcpy(actstr,"removing");
-        break;
-    case ERR_ALLOC:
-        strcpy(actstr,"allocating memory");
-        break;
-    case ERR_CHK:
-        strcpy(actstr,"checking");
-        break;
-    case ERR_LEN:
-        strcpy(actstr,"checking length");
-        break;
-    case ERR_EXEC:
-        strcpy(actstr,"executing");
-        break;
-    case ERR_CHDIR:
-        strcpy(actstr,"changing directory");
-        break;
-	case ERR_CREATE:
-		strcpy(actstr,"creating");
-		break;
-	case ERR_LOCK:
-		strcpy(actstr,"locking");
-		break;
-	case ERR_UNLOCK:
-		strcpy(actstr,"unlocking");
-        break;
-    default:
-        strcpy(actstr,"UNKNOWN"); }
-bprintf("\7\r\nERROR -   action: %s",actstr);   /* tell user about error */
-bprintf("\7\r\n          object: %s",object);
-bprintf("\7\r\n          access: %ld",access);
-if(access>9 && (long)access!=-1 && (short)access!=-1 && (char)access!=-1)
-	bprintf(" (%lXh)",access);
-if(sys_misc&SM_ERRALARM) {
-	beep(500,220); beep(250,220);
-	beep(500,220); beep(250,220);
-	beep(500,220); beep(250,220);
-	nosound(); }
-bputs("\r\n\r\nThe sysop has been notified. <Hit a key>");
-getkey(0);
-CRLF;
-sprintf(str,"\r\n      file: %s\r\n      line: %d\r\n    action: %s\r\n"
-	"    object: %s\r\n    access: %ld"
-	,source,line,actstr,object,access);
-if(access>9 && (long)access!=-1 && (short)access!=-1 && (char)access!=-1) {
-	sprintf(tmp," (%lXh)",access);
-	strcat(str,tmp); }
-if(errno) {
-	sprintf(tmp,"\r\n     errno: %d",errno);
-    strcat(str,tmp); }
-if(_doserrno && _doserrno!=errno) {
-	sprintf(tmp,"\r\n  doserrno: %d",_doserrno);
-    strcat(str,tmp); }
-errno=_doserrno=0;
-errorlog(str);
-}
-
-/*****************************************************************************/
-/* Error logging to NODE.LOG and DATA\ERROR.LOG function                     */
-/*****************************************************************************/
-void errorlog(char *text)
-{
-	static char inside;
-    char hdr[256],str[256],tmp2[256];
-    int file;
-
-if(inside)		/* let's not go recursive on this puppy */
-	return;
-inside=1;
-getnodedat(node_num,&thisnode,1);
-criterrs=++thisnode.errors;
-putnodedat(node_num,thisnode);
-now=time(NULL);
-logline("!!",text);
-sprintf(str,"%sERROR.LOG",data_dir);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-    sprintf(tmp2,"ERROR opening/creating %s",str);
-    logline("!!",tmp2);
-	inside=0;
-    return; }
-sprintf(hdr,"%s Node %2d: %s #%d"
-    ,timestr(&now),node_num,useron.alias,useron.number);
-write(file,hdr,strlen(hdr));
-write(file,crlf,2);
-write(file,text,strlen(text));
-write(file,"\r\n\r\n",4);
-close(file);
-inside=0;
-}
-
diff --git a/src/sbbs2/text.h b/src/sbbs2/text.h
deleted file mode 100644
index c1b29aa404540d72fd1f4b5dfe966de43cc1d4fd..0000000000000000000000000000000000000000
--- a/src/sbbs2/text.h
+++ /dev/null
@@ -1,737 +0,0 @@
-/* TEXT.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/****************************************************************************/
-/* Macros for elements of the array of pointers (text[]) to static text		*/
-/* Should correlate with CTRL\TEXT.DAT										*/
-/****************************************************************************/
-
-#ifndef _TEXT_H
-#define _TEXT_H
-
-enum {
- MsgSubj
-,MsgAttr
-,MsgTo
-,MsgToExt
-,MsgToNet
-,MsgFrom
-,MsgFromExt
-,MsgFromNet
-,MsgDate
-,Email
-,Post
-,TooManyEmailsToday
-,TooManyPostsToday
-,CantAddToQueue
-,R_Email
-,R_Post
-,R_Feedback
-,Emailing
-,Posting
-,NewFile
-,TitlePrompt
-,EnterMsgNow
-,EnterMsgNowRaw
-,NoMoreLines
-,OnlyNLinesLeft
-,OutOfBytes
-,InvalidLineNumber
-,MsgCleared
-,WithLineNumbers
-,Aborted
-,AnonymousQ
-,Anonymous
-,Saving
-,SavedNBytes
-,WritingIndx
-,Emailed
-,Posted
-,EmailNodeMsg
-,R_Forward
-,ForwardedFrom
-,Forwarded
-,AutoMsgBy
-,AutoMsg
-,R_AutoMsg
-,NoMailWaiting
-,MailWaitingLstHdr
-,MailWaitingLstFmt
-,StartWithN
-,ReadingMail
-,CantReplyToAnonMsg
-,Regarding
-,RegardingBy
-,RegardingByTo
-,DeleteMailQ
-,OK
-,ForwardMailTo
-,SaveMsgToFile
-,FileToWriteTo
-,NoMailSent
-,MailSentLstHdr
-,ReadingSentMail
-,CantDelForwardedMail
-,NoMailOnSystem
-,ReadingAllMail
-,MailOnSystemLstHdr
-,MailOnSystemLstFmt
-,NScanStatusFmt
-,SearchSubFmt
-,NoMsgsOnSub
-,ZScanPostHdr
-,ReadingSub
-,YouDidntPostMsgN
-,DeletePostQ
-,DeletingPost
-,DeletedPost
-,SearchStringPrompt
-,SubMsgLstHdr
-,SubMsgLstFmt
-,ChangeMsgPurgeQ
-,NoTextSections
-,TextSectionLstHdr
-,TextSectionLstFmt
-,WhichTextSection
-,TextFilesLstHdr
-,TextFilesLstFmt
-,WhichTextFileSysop
-,WhichTextFile
-,AddTextFileBeforeWhich
-,AddTextFilePath
-,AddTextFileDesc
-,RemoveWhichTextFile
-,DeleteTextFileQ
-,EditWhichTextFile
-,NScanAllGrpsQ
-,SScanAllGrpsQ
-,AreYouSureQ
-,R_Chat
-,ReFeedback
-,SiHdr
-,SiSysName
-,SiSysID
-,SiSysFaddr
-,SiSysPsite
-,SiSysLocation
-,SiSysop
-,SiSysNodes
-,SiNodeNumberName
-,SiNodePhone
-,SiTotalLogons
-,SiLogonsToday
-,SiTotalTime
-,SiTimeToday
-,ViewSysInfoFileQ
-,ViewLogonMsgQ
-,R_ReadSentMail
-,MessageScan
-,MessageScanComplete
-,MessageScanAborted
-,LogOffQ
-,CantPostOnSub
-,R_TransferSection
-,NoOtherActiveNodes
-,R_ExternalPrograms
-,UserStats
-,SubLstHdr
-,SubLstFmt
-,GrpLstHdr
-,GrpLstFmt
-,NScanCfgWhichGrp
-,SScanCfgWhichGrp
-,CfgSubLstHdr
-,CfgSubLstFmt
-,CfgGrpLstHdr
-,CfgGrpLstFmt
-,NScanCfgWhichSub
-,SScanCfgWhichSub
-,SubPtrLstFmt
-,WhichOrAll
-,RawMsgInputModeIsNow
-,OFF
-,ON
-,LineStatus
-,SystemStatsHdr
-,NodeStatsHdr
-,StatsTotalLogons
-,StatsLogonsToday
-,StatsTotalTime
-,StatsTimeToday
-,StatsUploadsToday
-,StatsDownloadsToday
-,StatsPostsToday
-,StatsEmailsToday
-,StatsFeedbacksToday
-,ChUserPrompt
-,ChUserPwPrompt
-,NBytesFreeMemory
-,ErrorLogHdr
-,DeleteErrorLogQ
-,NoErrorLogExists
-,ClearErrCounter
-,InvalidNode
-,RerunThisNodeNowQ
-,DeleteGuruLogQ
-,NScanAllLibsQ
-,R_Download
-,SearchingAllDirs
-,SearchingAllLibs
-,NFilesListed
-,EmptyDir
-,NScanHdr
-,R_RemoveFiles
-,DirFull
-,R_Upload
-,CantUploadHere
-,FileSpec
-,UserTransferStats
-,NoSysopDir
-,CantUploadToSysop
-,DirLstHdr
-,DirLstFmt
-,LibLstHdr
-,LibLstFmt
-,BatDownloadFlagIsNow
-,TransferPolicyHdr
-,TpCreditValue
-,TpUpload
-,TpDownload
-,NoUserDir
-,NoFilesForYou
-,UserDirFull
-,CantUploadToUser
-,BoxHdrLib
-,BoxHdrDir
-,BoxHdrFiles
-,ShortHdrLib
-,ShortHdrDir
-,BatchDlFlags
-,BatchDlQueueIsFull
-,FileSpecStarDotStar
-,LowDiskSpace
-,DiskNBytesFree
-,Filename
-,BadFilename
-,UploadToSysopDirQ
-,UploadToUserDirQ
-,UploadToCurDirQ
-,FileAlreadyThere
-,FileOnDiskAddQ
-,FileNotOnDisk
-,TheseFileExtsOnly
-,FileAlreadyOnline
-,EnterAfterLastDestUser
-,SendFileToUser
-,DuplicateUser
-,UserWontBeAbleToDl
-,CantSendYourselfFiles
-,UserAddedToDestList
-,RateThisFile
-,Rated
-,MultipleDiskQ
-,HowManyDisksTotal
-,NumberOfFile
-,FileOneOfTen
-,FileOneOfTwo
-,EnterDescNow
-,NoDescription
-,ProtocolOrQuit
-,ProtocolBatchOrQuit
-,BatchUlQueueIsFull
-,FileAddedToUlQueue
-,UserToUserXferNodeMsg
-,FileInfoPrompt
-,QuitOrNext
-,RExemptRemoveFilePrompt
-,MoveToLibLstFmt
-,MoveToLibPrompt
-,MoveToDirLstFmt
-,MoveToDirPrompt
-,MovedFile
-,CloseFileRecordQ
-,SysopRemoveFilePrompt
-,UserRemoveFilePrompt
-,FileNotThere
-,CouldntRemoveFile
-,DeleteFileQ
-,AddToOfflineDirQ
-,RemoveCreditsQ
-,UserNotFound
-,CreditsToRemove
-,FileRemovedUserMsg
-,EditFilename
-,CouldntRenameFile
-,FileRenamed
-,EditDescription
-,DeleteExtDescriptionQ
-,EditUploader
-,EditCreditValue
-,EditTimesDownloaded
-,EditOpenCount
-,EditAltPath
-,YouOnlyHaveNCredits
-,NotEnoughCredits
-,NotEnoughTimeToDl
-,ProtocolBatchQuitOrNext
-,BulkUpload
-,BulkUploadDescPrompt
-,NoFilesInBatchQueue
-,BatchMenuPrompt
-,ClearUploadQueueQ
-,UploadQueueCleared
-,ClearDownloadQueueQ
-,DownloadQueueCleared
-,DownloadQueueIsEmpty
-,UploadQueueLstHdr
-,UploadQueueLstFmt
-,DownloadQueueLstHdr
-,DownloadQueueLstFmt
-,DownloadQueueTotals
-,RemoveWhichFromUlQueue
-,RemoveWhichFromDlQueue
-,UploadQueueIsEmpty
-,HangUpAfterXferQ
-,StartXferNow
-,Disconnecting
-,Disconnected
-,FileNotSent
-,RemovingTempFiles
-,ExtractFrom
-,UnextractableFile
-,FileNotFound
-,ExtractFilesPrompt
-,TempDirPrompt
-,TempFileNotCreatedYet
-,TempFileInfo
-,TempDirTotal
-,NFilesRemoved
-,ResortWarning
-,ResortLineFmt
-,ResortEmptyDir
-,Sorting
-,Sorted
-,Compressed
-,FileAlreadyInQueue
-,FileIsNotOnline
-,FileAddedToBatDlQueue
-,NonviewableFile
-,FileNotReceived
-,FileHadErrors
-,FileZeroLength
-,FileNBytesReceived
-,FileNBytesSent
-,DownloadUserMsg
-,Partially
-,FiLib
-,FiDir
-,FiFilename
-,FiFileSize
-,FiCredits
-,FiDescription
-,FiUploadedBy
-,FiFileDate
-,FiDateUled
-,FiDateDled
-,FiTimesDled
-,FiTransferTime
-,FiAlternatePath
-,InvalidAlternatePathN
-,FileIsOpen
-,HappyBirthday
-,TimeToChangePw
-,NewPasswordQ
-,NewPassword
-,VerifyPassword
-,Wrong
-,PasswordChanged
-,NoMoreLogons
-,R_Logons
-,EnterYourAlias
-,EnterYourRealName
-,EnterYourCompany
-,EnterYourHandle
-,EnterYourSex
-,EnterYourAddress
-,EnterYourPhoneNumber
-,EnterYourBirthday
-,EnterYourCityState
-,EnterYourZipCode
-,EnterYourComputer
-,CallingFromNorthAmericaQ
-,UserInfoCorrectQ
-,LiUserNumberName
-,LiLogonsToday
-,LiTimeonToday
-,LiMailWaiting
-,LiSysopIs
-,LiSysopAvailable
-,LiSysopNotAvailable
-,UserOnTwoNodes
-,CriticalErrors
-,UserXferForYou
-,UnreceivedUserXfer
-,ReadYourMailNowQ
-,NoNewUsers
-,NewUserPasswordPrompt
-,AutoTerminalQ
-,AnsiTerminalQ
-,ColorTerminalQ
-,RipTerminalQ
-,ExAsciiTerminalQ
-,YouCantUseThatName
-,YourPasswordIs
-,NewUserPasswordVerify
-,IncorrectPassword
-,MagicWordPrompt
-,FailedMagicWord
-,SystemFull
-,NewUserFeedbackHdr
-,NoFeedbackWarning
-,NoXtrnPrograms
-,XtrnProgLstHdr
-,XtrnProgLstTitles
-,XtrnProgLstUnderline
-,XtrnProgLstFmt
-,WhichXtrnProg
-,UserRunningXtrn
-,RemoveNodeLockQ
-,MinimumModemSpeed
-,NoNodeAccess
-,NodeLocked
-,UnknownUser
-,InvalidLogon
-,SlogFmt
-,Locally
-,SortAlphaQ
-,CheckingSlots
-,UserListFmt
-,NTotalUsers
-,NUsersOnCurSub
-,NUsersOnCurDir
-,NScanDate
-,NScanYear
-,NScanMonth
-,NScanDay
-,NScanHour
-,NScanMinute
-,NScanPmQ
-,NScanAmQ
-,PasswordTooShort
-,PasswordNotChanged
-,PasswordInvalid
-,PasswordObvious
-,ComputerTypeMenu
-,ComputerTypePrompt
-,ComputerTypeB
-,ComputerTypeC
-,ComputerTypeD
-,ComputerTypeE
-,NoUserData
-,Deleted
-,Inactive
-,UeditAliasPassword
-,UeditRealNamePhone
-,UeditAddressBirthday
-,UeditLocationZipcode
-,UeditNoteHandle
-,UeditComputerModem
-,UeditCommentLine
-,UserDates
-,UserTimes
-,UserLogons
-,UserEmails
-,UserNetMail
-,UserUploads
-,UserDownloads
-,UserLeech
-,UserCredits
-,UserMinutes
-,UeditSecLevel
-,UeditFlags
-,UeditExempts
-,UeditPrompt
-,UeditRestoreQ
-,UeditActivateQ
-,UeditDeleteQ
-,UeditReadUserMailWQ
-,UeditReadUserMailSQ
-,UeditDeactivateUserQ
-,ChangeExemptionQ
-,FlagEditing
-,GoToUser
-,UeditLastOn
-,UeditFirstOn
-,UeditExpire
-,UeditPwModDate
-,UeditML
-,UeditNote
-,UeditComment
-,UeditUlBytes
-,UeditUploads
-,UeditDlBytes
-,UeditDownloads
-,UeditLeech
-,QuickValidateFmt
-,QuickValidatePrompt
-,UeditPassword
-,UeditCredits
-,UeditMinutes
-,UeditCopyUserQ
-,UeditCopyUserToSlot
-,ChangeRestrictsQ
-,ModifyCredits
-,ModifyMinutes
-,DeleteQuestionaireQ
-,UserDefaultsHdr
-,UserDefaultsTerminal
-,UserDefaultsXeditor
-,UserDefaultsRows
-,UserDefaultsMenuMode
-,UserDefaultsPause
-,UserDefaultsHotKey
-,UserDefaultsCursor
-,UserDefaultsCLS
-,UserDefaultsAskNScan
-,UserDefaultsAskSScan
-,UserDefaultsANFS
-,UserDefaultsRemember
-,UserDefaultsBatFlag
-,UserDefaultsNetMail
-,UserDefaultsCommandSet
-,UserDefaultsQuiet
-,UserDefaultsPassword
-,UserDefaultsArcType
-,UserDefaultsProtocol
-,UserDefaultsWhich
-,On
-,Off
-,HowManyRows
-,CurrentPassword
-,ForwardMailQ
-,EnterNetMailAddress
-,SelectItemHdr
-,SelectItemFmt
-,SelectItemWhich
-,SysopIsHere
-,EndOfChat
-,ChatPrompt
-,AnonUserChatHandle
-,WelcomeToMultiChat
-,WelcomeToChannelN
-,NodeInMultiChatLocally
-,YoureOnTheAir
-,NodeJoinedMultiChat
-,NodeLeftMultiChat
-,MultiChatCommandPrompt
-,PasswordProtected
-,CorrectPassword
-,WrongPassword
-,PasswordProtectChanQ
-,PasswordPrompt
-,ChatLineFmt
-,SysopPageIsNow
-,SysopIsNotAvailable
-,ChatWithGuruInsteadQ
-,PrivateMsgPrompt
-,NodeToPrivateChat
-,NodeNAlreadyInPChat
-,NodeNIsNotInUse
-,NoNeedToPageSelf
-,CantPageNode
-,NodePageMsg
-,AllNodePageMsg
-,NodePChatPageMsg
-,R_SendMessages
-,NodeToSendMsgTo
-,NoNeedToSendMsgToSelf
-,NodeMsgPrompt
-,NodeMsgFmt
-,AllNodeMsgFmt
-,PagingGuru
-,WaitingForNodeInPChat
-,NodeJoinedPrivateChat
-,NodeLeftPrivateChat
-,NoOneHasLoggedOnToday
-,LastFewCallers
-,LastFewCallersFmt
-,CallersToday
-,DoYouMeanThisUserQ
-,UNKNOWN_USER
-,TimesUp
-,NodeLoggedOff
-,NodeLoggedOnAtNbps
-,TiLogon
-,TiNow
-,TiTimeon
-,TiTimeLeft
-,ControlKeyMenu
-,TakenTooLongToLogon
-,CallBackWhenYoureThere
-,YesNoQuestion
-,Yes
-,No
-,NoYesQuestion
-,Pause
-,Wait
-,SysStatsLogHdr
-,NodeStatsLogHdr
-,ReducedTime
-,EventInfo
-,UploadBeforeEvent
-,QWKPrompt
-,QWKCtrlACodes
-,QWKPackingSubboard
-,QWKPackedSubboard
-,QWKPackingEmail
-,QWKPackedEmail
-,QWKUnpacking
-,QWKUnpacked
-,QWKNoNewMessages
-,QWKCompressionFailed
-,QWKExtractionFailed
-,QWKReplyNotReceived
-,QWKInvalidConferenceN
-,CreatingFileList
-,CreatedFileList
-,NoFiles
-,MsgPtrsInitialized
-,ConversionRate
-,CreditsToMin
-,YouHaveTooManyMinutes
-,BillingNodeMsg
-,Convert100ktoNminQ
-,CreditedAccount
-,ANSICaptureIsNow
-,RetrievingFile
-,AltULPathIsNow
-,PrivatePostQ
-,PostTo
-,NoToUser
-,UsingRealName
-,PostingPrivately
-,PostingAnonymously
-,CantDeletePosts
-,SubInfoHdr
-,SubInfoLongName
-,SubInfoShortName
-,SubInfoQWKName
-,SubInfoMaxMsgs
-,SubInfoTagLine
-,SubInfoFidoNet
-,SubInfoViewFileQ
-,DirInfoHdr
-,DirInfoLongName
-,DirInfoShortName
-,DirInfoAllowedExts
-,DirInfoMaxFiles
-,DirInfoViewFileQ
-,NoNetMailAllowed
-,NetMailCostContinueQ
-,NetMailing
-,RemoveFromNewScanQ
-,SubGroupOrAll
-,DirLibOrAll
-,EnterPath
-,SearchExtendedQ
-,DisplayTitlesOnlyQ
-,EchoIsNow
-,WelcomeToPrivateChat
-,UploadingREP
-,ReceivedFileViaQWK
-,QWKmsgLimitReached
-,PrivatePostsNotAllowed
-,LoadingMsgPtrs
-,LoadedMsgPtrs
-,QuoteMessageQ
-,QuoteLinesPrompt
-,ChatChanLstHdr
-,ChatChanLstTitles
-,ChatChanLstUnderline
-,ChatChanLstFmt
-,CantAccessThatChannel
-,CantDownloadFromDir
-,SearchingForDupes
-,SearchedForDupes
-,AccountWillExpireInNDays
-,AccountHasExpired
-,DownloadBatchQ
-,WaitingForDeviceN
-,UserSentYouMail
-,UserSentYouFile
-,UserReadYourMail
-,UserReadYourMailNodeMsg
-,JoinWhichGrp
-,JoinWhichSub
-,JoinWhichLib
-,JoinWhichDir
-,CfgDirLstHdr
-,CfgDirLstFmt
-,CfgLibLstHdr
-,CfgLibLstFmt
-,BatchFlagPrompt
-,FileListBatchCommands
-,DownloadAttachedFileQ
-,FreeMinLeft
-,FreeMinToDeposit
-,EmailFilesNotAllowed
-,CantRunThatProgram
-,OnlyXminutesLeft
-,AreYouThere
-,NoAccessLevel
-,NoAccessAge
-,NoAccessBPS
-,NoAccessCredit
-,NoAccessNode
-,NoAccessUser
-,NoAccessExpire
-,NoAccessTimeLeft
-,NoAccessTimeUsed
-,NoAccessTime
-,NoAccessPCR
-,NoAccessUDR
-,NoAccessUDFR
-,NoAccessFlag1
-,NoAccessFlag2
-,NoAccessFlag3
-,NoAccessFlag4
-,NoAccessSex
-,NoAccessExempt
-,NoAccessRest
-,NoAccessDay
-,NoAccessGroup
-,NoAccessSub
-,NoAccessLib
-,NoAccessDir
-,NodeLstHdr
-,NodeActionMain
-,NodeActionReadMsgs
-,NodeActionReadMail
-,NodeActionSendMail
-,NodeActionReadTxt
-,NodeActionReadSentMail
-,NodeActionPostMsg
-,NodeActionAutoMsg
-,NodeActionXtrn
-,NodeActionDefaults
-,NodeActionXfer
-,NodeActionDLing
-,NodeActionULing
-,NodeActionBiXfer
-,NodeActionListFiles
-,NodeActionLoggingOn
-,NodeActionLocalChat
-,NodeActionMultiChat
-,NodeActionGuruChat
-,NodeActionChatSec
-,NodeActionSysopAct
-,NodeActionQWK
-,NodeActionPrivateChat
-,NodeActionPaging
-,NodeActionRetrieving
-,YN
-
-,TOTAL_TEXT };
-
-#endif
diff --git a/src/sbbs2/text_sec.c b/src/sbbs2/text_sec.c
deleted file mode 100644
index a63c2689449fc7bf9efe00be4a9038bae294a599..0000000000000000000000000000000000000000
--- a/src/sbbs2/text_sec.c
+++ /dev/null
@@ -1,200 +0,0 @@
-#line 1 "TEXT_SEC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-#define MAX_TXTSECS 	500 /* Maximum number of text file sections 	*/
-#define MAX_TXTFILES    500 /* Maximum number of text files per section */
-
-/****************************************************************************/
-/* General Text File Section.                                               */
-/* Called from function main_sec                                            */
-/* Returns 1 if no text sections available, 0 otherwise.                    */
-/****************************************************************************/
-char text_sec()
-{
-	char	str[256],usrsec[MAX_TXTSECS],usrsecs,cursec,usemenu
-			,*file[MAX_TXTFILES],addpath[83],addstr[83],*buf,ch;
-	long	i,j;
-    long    l,length;
-    FILE    *stream;
-
-// ch=getage(useron.birth); Removed 05/19/96
-for(i=j=0;i<total_txtsecs;i++) {
-    if(!chk_ar(txtsec[i]->ar,useron))
-        continue;
-    usrsec[j++]=i; }
-usrsecs=j;
-if(!usrsecs) {
-    bputs(text[NoTextSections]);
-    return(1); }
-action=NODE_RTXT;
-while(online) {
-	sprintf(str,"%sMENU\\TEXT_SEC.*",text_dir);
-    if(fexist(str))
-        menu("TEXT_SEC");
-    else {
-        bputs(text[TextSectionLstHdr]);
-        for(i=0;i<usrsecs && !msgabort();i++) {
-            sprintf(str,text[TextSectionLstFmt],i+1,txtsec[usrsec[i]]->name);
-            if(i<9) outchar(SP);
-            bputs(str); } }
-    ASYNC;
-    mnemonics(text[WhichTextSection]);
-    if((cursec=getnum(usrsecs))<1)
-        break;
-    cursec--;
-    while(online) {
-		sprintf(str,"%sMENU\\TEXT%u.*",text_dir,cursec+1);
-        if(fexist(str)) {
-            sprintf(str,"TEXT%u",cursec+1);
-            menu(str);
-            usemenu=1; }
-        else {
-            bprintf(text[TextFilesLstHdr],txtsec[usrsec[cursec]]->name);
-            usemenu=0; }
-        sprintf(str,"%sTEXT\\%s.IXT",data_dir,txtsec[usrsec[cursec]]->code);
-        j=0;
-        if(fexist(str)) {
-			if((stream=fnopen((int *)&i,str,O_RDONLY))==NULL) {
-                errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-                return(0); }
-            while(!ferror(stream) && !msgabort()) {  /* file open too long */
-                if(!fgets(str,81,stream))
-                    break;
-                str[strlen(str)-2]=0;   /* chop off CRLF */
-                if((file[j]=MALLOC(strlen(str)+1))==NULL) {
-                    errormsg(WHERE,ERR_ALLOC,nulstr,strlen(str)+1);
-                    continue; }
-                strcpy(file[j],str);
-                fgets(str,81,stream);
-                if(!usemenu) bprintf(text[TextFilesLstFmt],j+1,str);
-                j++; }
-            fclose(stream); }
-        ASYNC;
-        if(SYSOP) {
-            strcpy(str,"QARE?");
-            mnemonics(text[WhichTextFileSysop]); }
-        else {
-            strcpy(str,"Q?");
-            mnemonics(text[WhichTextFile]); }
-        i=getkeys(str,j);
-		if(!(i&0x80000000L)) {		  /* no file number */
-            for(l=0;l<j;l++)
-                FREE(file[l]);
-            if((i=='E' || i=='R') && !j)
-                continue; }
-        if(i=='Q' || !i)
-            break;
-        if(i==-1) {  /* ctrl-c */
-            for(i=0;i<j;i++)
-                FREE(file[i]);
-            return(0); }
-        if(i=='?')  /* ? means re-list */
-            continue;
-        if(i=='A') {    /* Add text file */
-            if(j) {
-                bputs(text[AddTextFileBeforeWhich]);
-                i=getnum(j+1);
-                if(i<1)
-                    continue;
-                i--;    /* number of file entries to skip */ }
-            else
-                i=0;
-            bprintf(text[AddTextFilePath]
-                ,data_dir,txtsec[usrsec[cursec]]->code);
-            if(!getstr(addpath,80,K_UPPER))
-                continue;
-            strcat(addpath,crlf);
-            bputs(text[AddTextFileDesc]);
-            if(!getstr(addstr,74,0))
-                continue;
-            strcat(addstr,crlf);
-            sprintf(str,"%sTEXT\\%s.IXT"
-                ,data_dir,txtsec[usrsec[cursec]]->code);
-            if(i==j) {  /* just add to end */
-                if((i=nopen(str,O_WRONLY|O_APPEND|O_CREAT))==-1) {
-                    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_APPEND|O_CREAT);
-                    return(0); }
-                write(i,addpath,strlen(addpath));
-                write(i,addstr,strlen(addstr));
-                close(i);
-                continue; }
-            j=i; /* inserting in middle of file */
-			if((stream=fnopen((int *)&i,str,O_RDWR))==NULL) {
-                errormsg(WHERE,ERR_OPEN,str,O_RDWR);
-                return(0); }
-            length=filelength(i);
-            for(i=0;i<j;i++) {  /* skip two lines for each entry */
-                fgets(tmp,81,stream);
-                fgets(tmp,81,stream); }
-            l=ftell(stream);
-            if((buf=(char *)MALLOC(length-l))==NULL) {
-                fclose(stream);
-                errormsg(WHERE,ERR_ALLOC,str,length-l);
-                return(0); }
-            fread(buf,1,length-l,stream);
-            fseek(stream,l,SEEK_SET); /* go back to where we need to insert */
-            fputs(addpath,stream);
-            fputs(addstr,stream);
-            fwrite(buf,1,length-l,stream);
-            fclose(stream);
-            FREE(buf);
-            continue; }
-        if(i=='R' || i=='E') {   /* Remove or Edit text file */
-            ch=i;
-            if(ch=='R')
-                bputs(text[RemoveWhichTextFile]);
-            else
-                bputs(text[EditWhichTextFile]);
-            i=getnum(j);
-            if(i<1)
-                continue;
-            sprintf(str,"%sTEXT\\%s.IXT"
-                ,data_dir,txtsec[usrsec[cursec]]->code);
-            j=i-1;
-			if((stream=fnopen((int *)&i,str,O_RDONLY))==NULL) {
-                errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-                return(0); }
-			// length=filelength(i); Removed 05/19/96
-            for(i=0;i<j;i++) {  /* skip two lines for each entry */
-                fgets(tmp,81,stream);
-                fgets(tmp,81,stream); }
-            fgets(addpath,81,stream);
-            truncsp(addpath);
-            fclose(stream);
-            if(!strchr(addpath,'\\'))
-                sprintf(tmp,"%sTEXT\\%s\\%s"
-                    ,data_dir,txtsec[usrsec[cursec]]->code,addpath);
-            else
-                strcpy(tmp,addpath);
-            if(ch=='R') {               /* Remove */
-                if(fexist(tmp)) {
-                    sprintf(str,text[DeleteTextFileQ],tmp);
-                    if(!noyes(str))
-                        if(remove(tmp)) errormsg(WHERE,ERR_REMOVE,tmp,0); }
-                sprintf(str,"%sTEXT\\%s.IXT"
-                    ,data_dir,txtsec[usrsec[cursec]]->code);
-				removeline(str,addpath,2,0); }
-            else {                      /* Edit */
-                strcpy(str,tmp);
-                editfile(str); }
-            continue; }
-		i=(i&~0x80000000L)-1;
-        if(!strchr(file[i],'\\'))
-            sprintf(str,"%sTEXT\\%s\\%s"
-                ,data_dir,txtsec[usrsec[cursec]]->code,file[i]);
-        else
-            strcpy(str,file[i]);
-        attr(LIGHTGRAY);
-        printfile(str,0);
-        sprintf(str,"Read Text File: %s",file[i]);
-        logline("T-",str);
-        pause();
-        sys_status&=~SS_ABORT;
-        for(i=0;i<j;i++)
-            FREE(file[i]); } }
-return(0);
-}
-
diff --git a/src/sbbs2/un_qwk.c b/src/sbbs2/un_qwk.c
deleted file mode 100644
index d8cfe2b6c70b3f1e0aa158c707d6c648fb97af05..0000000000000000000000000000000000000000
--- a/src/sbbs2/un_qwk.c
+++ /dev/null
@@ -1,200 +0,0 @@
-#line 1 "UN_QWK.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-
-/****************************************************************************/
-/* Unpacks .QWK packet, hubnum is the number of the QWK net hub 			*/
-/****************************************************************************/
-void unpack_qwk(char *packet,uint hubnum)
-{
-	uchar	str[256],fname[128],block[128],ch;
-	int 	k,file;
-	uint	i,j,n,msgs,lastsub=INVALID_SUB;
-	long	l,size,misc;
-	time_t	t;
-    struct  ffblk ff;
-	FILE	*qwk;
-
-useron.number=1;
-getuserdat(&useron);
-console=CON_L_ECHO;
-i=external(cmdstr(qhub[hubnum]->unpack,packet,"*.*",NULL),EX_OUTL);
-if(i) {
-	errormsg(WHERE,ERR_EXEC,cmdstr(qhub[hubnum]->unpack,packet,"*.*",NULL),i);
-	return; }
-sprintf(str,"%sMESSAGES.DAT",temp_dir);
-if(!fexist(str)) {
-	sprintf(str,"%s.QWK doesn't contain MESSAGES.DAT",qhub[hubnum]->id);
-	errorlog(str);
-	return; }
-if((qwk=fnopen(&file,str,O_RDONLY))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-size=filelength(file);
-/********************/
-/* Process messages */
-/********************/
-bputs(text[QWKUnpacking]);
-
-for(l=128;l<size;l+=i*128) {
-	fseek(qwk,l,SEEK_SET);
-	fread(block,128,1,qwk);
-	sprintf(tmp,"%.6s",block+116);
-	i=atoi(tmp);  /* i = number of 128 byte records */
-	if(i<2) {
-		i=1;
-		continue; }
-	/*********************************/
-	/* public message on a sub-board */
-	/*********************************/
-	n=(uint)block[123]|(((uint)block[124])<<8);  /* conference number */
-
-	if(!n) {		/* NETMAIL */
-		sprintf(str,"%25.25s",block+21);
-		truncsp(str);
-		if(!stricmp(str,"NETMAIL")) {  /* QWK to FidoNet NetMail */
-			qwktonetmail(qwk,block,NULL,hubnum+1);
-            continue; }
-		if(strchr(str,'@')) {
-			qwktonetmail(qwk,block,str,hubnum+1);
-            continue; }
-		j=atoi(str);
-		if(j && j>lastuser())
-			j=0;
-		if(!j && !stricmp(str,"SYSOP"))
-			j=1;
-		if(!j)
-			j=matchuser(str);
-		if(!j && !stricmp(str,sys_id))
-			j=1;
-		if(!j) {
-			bputs(text[UnknownUser]);
-            continue; }
-
-		getuserrec(j,U_MISC,8,str);
-		misc=ahtoul(str);
-		if(misc&NETMAIL && sys_misc&SM_FWDTONET) {
-			getuserrec(j,U_NETMAIL,LEN_NETMAIL,str);
-			qwktonetmail(qwk,block,str,hubnum+1);
-            continue; }
-
-		smb_stack(&smb,SMB_STACK_PUSH);
-		sprintf(smb.file,"%sMAIL",data_dir);
-		smb.retry_time=smb_retry_time;
-		if((k=smb_open(&smb))!=0) {
-			errormsg(WHERE,ERR_OPEN,smb.file,k);
-			smb_stack(&smb,SMB_STACK_POP);
-			continue; }
-		if(!filelength(fileno(smb.shd_fp))) {
-			smb.status.max_crcs=mail_maxcrcs;
-			smb.status.max_msgs=MAX_SYSMAIL;
-			smb.status.max_age=mail_maxage;
-			smb.status.attr=SMB_EMAIL;
-			if((k=smb_create(&smb))!=0) {
-				smb_close(&smb);
-				errormsg(WHERE,ERR_CREATE,smb.file,k);
-				smb_stack(&smb,SMB_STACK_POP);
-				continue; } }
-		if((k=smb_locksmbhdr(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_LOCK,smb.file,k);
-			smb_stack(&smb,SMB_STACK_POP);
-			continue; }
-		if((k=smb_getstatus(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_READ,smb.file,k);
-			smb_stack(&smb,SMB_STACK_POP);
-            continue; }
-		smb_unlocksmbhdr(&smb);
-		qwktomsg(qwk,block,hubnum+1,INVALID_SUB,j);
-		smb_close(&smb);
-		smb_stack(&smb,SMB_STACK_POP);
-		sprintf(tmp,"%-25.25s",block+46);
-		truncsp(tmp);
-		sprintf(str,text[UserSentYouMail],tmp);
-		putsmsg(j,str);
-		continue;
-		}
-
-	for(j=0;j<qhub[hubnum]->subs;j++)
-		if(qhub[hubnum]->conf[j]==n)
-			break;
-	if(j>=qhub[hubnum]->subs)	/* ignore messages for subs not in config */
-		continue;
-
-	j=qhub[hubnum]->sub[j];
-
-	if(j!=lastsub) {
-		if(lastsub!=INVALID_SUB)
-			smb_close(&smb);
-		lastsub=INVALID_SUB;
-		sprintf(smb.file,"%s%s",sub[j]->data_dir,sub[j]->code);
-		smb.retry_time=smb_retry_time;
-		if((k=smb_open(&smb))!=0) {
-			errormsg(WHERE,ERR_OPEN,smb.file,k);
-			continue; }
-		if(!filelength(fileno(smb.shd_fp))) {
-			smb.status.max_crcs=sub[j]->maxcrcs;
-			smb.status.max_msgs=sub[j]->maxmsgs;
-			smb.status.max_age=sub[j]->maxage;
-			smb.status.attr=sub[j]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
-			if((k=smb_create(&smb))!=0) {
-				smb_close(&smb);
-				errormsg(WHERE,ERR_CREATE,smb.file,k);
-				continue; } }
-		if((k=smb_locksmbhdr(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_LOCK,smb.file,k);
-			continue; }
-		if((k=smb_getstatus(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_READ,smb.file,k);
-			continue; }
-		smb_unlocksmbhdr(&smb);
-		lastsub=j; }
-
-	if(!qwktomsg(qwk,block,hubnum+1,j,0))
-		continue;
-
-	if(sub[j]->misc&SUB_FIDO && sub[j]->echomail_sem[0]) /* update semaphore */
-		if((file=nopen(sub[j]->echomail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-			close(file);
-	bprintf(text[Posted],grp[sub[j]->grp]->sname,sub[j]->lname); }
-
-update_qwkroute(NULL);		/* Write ROUTE.DAT */
-
-fclose(qwk);
-if(lastsub!=INVALID_SUB)
-	smb_close(&smb);
-
-delfiles(temp_dir,"*.NDX");
-sprintf(str,"%sMESSAGES.DAT",temp_dir);
-remove(str);
-sprintf(str,"%sDOOR.ID",temp_dir);
-remove(str);
-sprintf(str,"%sCONTROL.DAT",temp_dir);
-remove(str);
-sprintf(str,"%sNETFLAGS.DAT",temp_dir);
-remove(str);
-
-sprintf(str,"%s*.*",temp_dir);
-i=findfirst(str,&ff,0);
-if(!i) {
-	sprintf(str,"%sQNET\\%s.IN",data_dir,qhub[hubnum]->id);
-	mkdir(str); }
-while(!i) {
-	sprintf(str,"%s%s",temp_dir,ff.ff_name);
-	sprintf(fname,"%sQNET\\%s.IN\\%s",data_dir,qhub[hubnum]->id,ff.ff_name);
-	mv(str,fname,1);
-	sprintf(str,text[ReceivedFileViaQWK],ff.ff_name,qhub[hubnum]->id);
-	putsmsg(1,str);
-	i=findnext(&ff); }
-
-bputs(text[QWKUnpacked]);
-CRLF;
-remove(packet);
-
-}
diff --git a/src/sbbs2/un_rep.c b/src/sbbs2/un_rep.c
deleted file mode 100644
index c26bc8ca3421163f86b4e831ebfa99f13471e041..0000000000000000000000000000000000000000
--- a/src/sbbs2/un_rep.c
+++ /dev/null
@@ -1,382 +0,0 @@
-#line 1 "UN_REP.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "qwk.h"
-
-/****************************************************************************/
-/* Unpacks .REP packet, 'repname' is the path and filename of the packet    */
-/****************************************************************************/
-void unpack_rep()
-{
-	uchar	ch,str[256],fname[128],block[128]
-			,*AttemptedToUploadREPpacket="Attempted to upload REP packet";
-	int 	file;
-	uint	h,i,j,k,msgs,lastsub=INVALID_SUB;
-	ulong	n;
-	long	l,size,misc,crc;
-	node_t	node;
-	time_t	t;
-	file_t	f;
-    struct  ffblk ff;
-	FILE	*rep;
-
-sprintf(str,"%s%s.REP",temp_dir,sys_id);
-if(!fexist(str)) {
-	bputs(text[QWKReplyNotReceived]);
-	logline("U!",AttemptedToUploadREPpacket);
-	logline(nulstr,"REP file not received");
-	return; }
-for(k=0;k<total_fextrs;k++)
-	if(!stricmp(fextr[k]->ext,useron.tmpext) && chk_ar(fextr[k]->ar,useron))
-		break;
-if(k>=total_fextrs)
-	k=0;
-i=external(cmdstr(fextr[k]->cmd,str,"*.*",NULL),EX_OUTL|EX_OUTR);
-if(i) {
-	bputs(text[QWKExtractionFailed]);
-	logline("U!",AttemptedToUploadREPpacket);
-	logline(nulstr,"Extraction failed");
-	return; }
-sprintf(str,"%s%s.MSG",temp_dir,sys_id);
-if(!fexist(str)) {
-	bputs(text[QWKReplyNotReceived]);
-	logline("U!",AttemptedToUploadREPpacket);
-	logline(nulstr,"MSG file not received");
-	return; }
-if((rep=fnopen(&file,str,O_RDONLY))==NULL) {
-	errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-	return; }
-size=filelength(file);
-fread(block,128,1,rep);
-if(strncmpi(block,sys_id,strlen(sys_id))) {
-	fclose(rep);
-	bputs(text[QWKReplyNotReceived]);
-	logline("U!",AttemptedToUploadREPpacket);
-	logline(nulstr,"Incorrect BBSID");
-	return; }
-logline("U+","Uploaded REP packet");
-/********************/
-/* Process messages */
-/********************/
-bputs(text[QWKUnpacking]);
-
-for(l=128;l<size;l+=i*128) {
-	lncntr=0;					/* defeat pause */
-	fseek(rep,l,SEEK_SET);
-	fread(block,128,1,rep);
-	sprintf(tmp,"%.6s",block+116);
-	i=atoi(tmp);  /* i = number of 128 byte records */
-	if(i<2) {
-		sprintf(tmp,"%s blocks",str);
-		errormsg(WHERE,ERR_CHK,tmp,i);
-		i=1;
-		continue; }
-	if(atoi(block+1)==0) {					/**********/
-		if(useron.rest&FLAG('E')) {         /* E-mail */
-			bputs(text[R_Email]);			/**********/
-			continue; }
-
-        sprintf(str,"%25.25s",block+21);
-		truncsp(str);
-		if(!stricmp(str,"NETMAIL")) {  /* QWK to FidoNet NetMail */
-			qwktonetmail(rep,block,NULL,0);
-			continue; }
-		if(strchr(str,'@')) {
-			qwktonetmail(rep,block,str,0);
-			continue; }
-		if(!stricmp(str,"SBBS")) {    /* to SBBS, config stuff */
-			qwkcfgline(block+71,INVALID_SUB);
-            continue; }
-
-		if(useron.etoday>=level_emailperday[useron.level]
-			&& !(useron.rest&FLAG('Q'))) {
-			bputs(text[TooManyEmailsToday]);
-			continue; }
-		j=atoi(str);
-		if(j && j>lastuser())
-			j=0;
-		if(!j &&
-			(!stricmp(str,"SYSOP")
-			|| !stricmp(str,sys_id)
-			|| !stricmp(str,sys_op)))
-			j=1;
-		if(!j)
-			j=matchuser(str);
-		if(!j) {
-			bputs(text[UnknownUser]);
-			continue; }
-		if(j==1 && useron.rest&FLAG('S')) {
-			bprintf(text[R_Feedback],sys_op);
-			continue; }
-
-		getuserrec(j,U_MISC,8,str);
-		misc=ahtoul(str);
-		if(misc&NETMAIL && sys_misc&SM_FWDTONET) {
-			getuserrec(j,U_NETMAIL,LEN_NETMAIL,str);
-			qwktonetmail(rep,block,str,0);
-			continue; }
-
-		sprintf(smb.file,"%sMAIL",data_dir);
-		smb.retry_time=smb_retry_time;
-
-		if(lastsub!=INVALID_SUB) {
-			smb_close(&smb);
-			lastsub=INVALID_SUB; }
-
-		if((k=smb_open(&smb))!=0) {
-			errormsg(WHERE,ERR_OPEN,smb.file,k);
-			continue; }
-
-		if(!filelength(fileno(smb.shd_fp))) {
-			smb.status.max_crcs=mail_maxcrcs;
-			smb.status.max_msgs=MAX_SYSMAIL;
-			smb.status.max_age=mail_maxage;
-			smb.status.attr=SMB_EMAIL;
-			if((k=smb_create(&smb))!=0) {
-				smb_close(&smb);
-				errormsg(WHERE,ERR_CREATE,smb.file,k);
-				continue; } }
-
-		if((k=smb_locksmbhdr(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_LOCK,smb.file,k);
-			continue; }
-
-		if((k=smb_getstatus(&smb))!=0) {
-			smb_close(&smb);
-			errormsg(WHERE,ERR_READ,smb.file,k);
-			continue; }
-
-		smb_unlocksmbhdr(&smb);
-
-		if(!qwktomsg(rep,block,0,INVALID_SUB,j)) {
-			smb_close(&smb);
-			continue; }
-		smb_close(&smb);
-
-		if(j==1) {
-			useron.fbacks++;
-			logon_fbacks++;
-			putuserrec(useron.number,U_FBACKS,5
-				,itoa(useron.fbacks,tmp,10)); }
-		else {
-			useron.emails++;
-			logon_emails++;
-			putuserrec(useron.number,U_EMAILS,5
-				,itoa(useron.emails,tmp,10)); }
-		useron.etoday++;
-		putuserrec(useron.number,U_ETODAY,5
-			,itoa(useron.etoday,tmp,10));
-		bprintf(text[Emailed],username(j,tmp),j);
-		sprintf(str,"E-mailed %s #%d",username(j,tmp),j);
-		logline("E+",str);
-		if(useron.rest&FLAG('Q')) {
-			sprintf(tmp,"%-25.25s",block+46);
-			truncsp(tmp); }
-		else
-			strcpy(tmp,useron.alias);
-		for(k=1;k<=sys_nodes;k++) { /* Tell user, if online */
-			getnodedat(k,&node,0);
-			if(node.useron==j && !(node.misc&NODE_POFF)
-				&& (node.status==NODE_INUSE
-				|| node.status==NODE_QUIET)) {
-				sprintf(str,text[EmailNodeMsg]
-					,node_num,tmp);
-				putnmsg(k,str);
-				break; } }
-		if(k>sys_nodes) {
-			sprintf(str,text[UserSentYouMail],tmp);
-			putsmsg(j,str); } }    /* end of email */
-
-			/**************************/
-	else {	/* message on a sub-board */
-			/**************************/
-		n=atol((char *)block+1); /* conference number */
-		for(j=0;j<usrgrps;j++) {
-			for(k=0;k<usrsubs[j];k++)
-				if(sub[usrsub[j][k]]->qwkconf==n)
-					break;
-			if(k<usrsubs[j])
-				break; }
-
-		if(j>=usrgrps) {
-			if(n<1000) {			 /* version 1 method, start at 101 */
-				j=n/100;
-				k=n-(j*100); }
-			else {					 /* version 2 method, start at 1001 */
-				j=n/1000;
-				k=n-(j*1000); }
-			j--;	/* j is group */
-			k--;	/* k is sub */
-			if(j>=usrgrps || k>=usrsubs[j]) {
-				bprintf(text[QWKInvalidConferenceN],n);
-				sprintf(str,"Invalid conference number %d",n);
-				logline("P!",str);
-				continue; } }
-
-		n=usrsub[j][k];
-
-		/* if posting, add to new-scan config for QWKnet nodes automatically */
-        if(useron.rest&FLAG('Q'))
-			sub[n]->misc|=SUB_NSCAN;
-
-		sprintf(str,"%-25.25s","SBBS");
-		if(!strnicmp((char *)block+21,str,25)) {	/* to SBBS, config stuff */
-			qwkcfgline((char *)block+71,n);
-			continue; }
-
-		if(!SYSOP && sub[n]->misc&SUB_QNET) {	/* QWK Netted */
-			sprintf(str,"%-25.25s","DROP");         /* Drop from new-scan? */
-			if(!strnicmp((char *)block+71,str,25))	/* don't allow post */
-				continue;
-			sprintf(str,"%-25.25s","ADD");          /* Add to new-scan? */
-			if(!strnicmp((char *)block+71,str,25))	/* don't allow post */
-				continue; }
-
-		if(useron.rest&FLAG('Q') && !(sub[n]->misc&SUB_QNET)) {
-			bputs(text[CantPostOnSub]);
-			logline("P!","Attempted to post on non-QWKnet sub");
-			continue; }
-
-        if(useron.rest&FLAG('P')) {
-            bputs(text[R_Post]);
-			logline("P!","Post attempted");
-            continue; }
-
-		if(useron.ptoday>=level_postsperday[useron.level]
-			&& !(useron.rest&FLAG('Q'))) {
-			bputs(text[TooManyPostsToday]);
-			continue; }
-
-		if(useron.rest&FLAG('N')
-			&& sub[n]->misc&(SUB_FIDO|SUB_PNET|SUB_QNET|SUB_INET)) {
-			bputs(text[CantPostOnSub]);
-			logline("P!","Networked post attempted");
-			continue; }
-
-		if(!chk_ar(sub[n]->post_ar,useron)) {
-			bputs(text[CantPostOnSub]);
-			logline("P!","Post attempted");
-			continue; }
-
-		if((block[0]=='*' || block[0]=='+')
-			&& !(sub[n]->misc&SUB_PRIV)) {
-			bputs(text[PrivatePostsNotAllowed]);
-			logline("P!","Private post attempt");
-			continue; }
-
-		if(block[0]=='*' || block[0]=='+'           /* Private post */
-			|| sub[n]->misc&SUB_PONLY) {
-			sprintf(str,"%-25.25s",nulstr);
-			sprintf(tmp,"%-25.25s","ALL");
-			if(!strnicmp((char *)block+21,str,25)
-				|| !strnicmp((char *)block+21,tmp,25)) {	/* to blank */
-				bputs(text[NoToUser]);						/* or all */
-				continue; } }
-
-		if(!SYSOP && !(useron.rest&FLAG('Q'))) {
-			sprintf(str,"%-25.25s","SYSOP");
-			if(!strnicmp((char *)block+21,str,25)) {
-				sprintf(str,"%-25.25s",username(1,tmp));
-				memcpy((char *)block+21,str,25); } }	/* change from sysop */
-														/* to user #1 */
-
-#if 0	/* TWIT FILTER */
-		sprintf(str,"%25.25s",block+46);  /* From user */
-		truncsp(str);
-
-		if(!stricmp(str,"Lee Matherne")
-			|| !stricmp(str,"Big Joe")
-			) {
-			bprintf(text[Posted],grp[sub[n]->grp]->sname
-				,sub[n]->lname);
-			continue; }
-#endif
-
-		if(n!=lastsub) {
-			if(lastsub!=INVALID_SUB)
-				smb_close(&smb);
-			lastsub=INVALID_SUB;
-			sprintf(smb.file,"%s%s",sub[n]->data_dir,sub[n]->code);
-			smb.retry_time=smb_retry_time;
-			if((j=smb_open(&smb))!=0) {
-				errormsg(WHERE,ERR_OPEN,smb.file,j);
-				continue; }
-
-			if(!filelength(fileno(smb.shd_fp))) {
-				smb.status.max_crcs=sub[n]->maxcrcs;
-				smb.status.max_msgs=sub[n]->maxmsgs;
-				smb.status.max_age=sub[n]->maxage;
-				smb.status.attr=sub[n]->misc&SUB_HYPER ? SMB_HYPERALLOC:0;
-				if((j=smb_create(&smb))!=0) {
-					smb_close(&smb);
-					lastsub=INVALID_SUB;
-					errormsg(WHERE,ERR_CREATE,smb.file,j);
-					continue; } }
-
-			if((j=smb_locksmbhdr(&smb))!=0) {
-				smb_close(&smb);
-				lastsub=INVALID_SUB;
-				errormsg(WHERE,ERR_LOCK,smb.file,j);
-				continue; }
-			if((j=smb_getstatus(&smb))!=0) {
-				smb_close(&smb);
-				lastsub=INVALID_SUB;
-				errormsg(WHERE,ERR_READ,smb.file,j);
-				continue; }
-			smb_unlocksmbhdr(&smb);
-			lastsub=n; }
-
-		if(!qwktomsg(rep,block,0,n,0))
-			continue;
-
-		useron.ptoday++;
-		useron.posts++;
-//		  if(!(useron.rest&FLAG('Q')))
-		logon_posts++;
-		putuserrec(useron.number,U_POSTS,5,itoa(useron.posts,str,10));
-		putuserrec(useron.number,U_PTODAY,5,itoa(useron.ptoday,str,10));
-		bprintf(text[Posted],grp[sub[n]->grp]->sname
-			,sub[n]->lname);
-		sprintf(str,"Posted on %s %s",grp[sub[n]->grp]->sname
-			,sub[n]->lname);
-		if(sub[n]->misc&SUB_FIDO && sub[n]->echomail_sem[0])  /* semaphore */
-			if((file=nopen(sub[n]->echomail_sem,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
-				close(file);
-        logline("P+",str); } }         /* end of public message */
-
-update_qwkroute(NULL);			/* Write ROUTE.DAT */
-
-if(lastsub!=INVALID_SUB)
-	smb_close(&smb);
-fclose(rep);
-
-if(useron.rest&FLAG('Q')) {             /* QWK Net Node */
-	sprintf(str,"%s%s.MSG",temp_dir,sys_id);
-	remove(str);
-	sprintf(str,"%s%s.REP",temp_dir,sys_id);
-    remove(str);
-
-	sprintf(str,"%s*.*",temp_dir);
-	i=findfirst(str,&ff,0);
-	if(!i) {
-		sprintf(str,"%sQNET\\%s.IN",data_dir,useron.alias);
-		mkdir(str); }
-	while(!i) { 						/* Extra files */
-		sprintf(str,"%s%s",temp_dir,ff.ff_name);
-		sprintf(fname,"%sQNET\\%s.IN\\%s",data_dir,useron.alias,ff.ff_name);
-		mv(str,fname,1);
-		sprintf(str,text[ReceivedFileViaQWK],ff.ff_name,useron.alias);
-		putsmsg(1,str);
-		i=findnext(&ff); } }
-
-bputs(text[QWKUnpacked]);
-CRLF;
-/**********************************************/
-/* Hang-up now if that's what the user wanted */
-/**********************************************/
-autohangup();
-
-}
diff --git a/src/sbbs2/useredit.c b/src/sbbs2/useredit.c
deleted file mode 100644
index 0b3c4fbd9f7134658a43237b9ae04cfb39fe48d5..0000000000000000000000000000000000000000
--- a/src/sbbs2/useredit.c
+++ /dev/null
@@ -1,966 +0,0 @@
-#line 1 "USEREDIT.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*******************************************************************/
-/* The function useredit(), and functions that are closely related */
-/*******************************************************************/
-
-#include "sbbs.h"
-
-#define SEARCH_TXT 0
-#define SEARCH_ARS 1
-
-int searchup(char *search,int usernum);
-int searchdn(char *search,int usernum);
-
-/****************************************************************************/
-/* Edits user data. Can only edit users with a Main Security Level less 	*/
-/* than or equal to the current user's Main Security Level					*/
-/* Called from functions waitforcall, main_sec, xfer_sec and inkey			*/
-/****************************************************************************/
-void useredit(int usernumber, int local)
-{
-	uchar str[256],tmp2[256],tmp3[256],c,stype=SEARCH_TXT;
-	uchar search[256]={""},artxt[128]={""},*ar=NULL;
-	int i,j,k;
-	long l;
-	user_t user;
-
-if(online==ON_REMOTE && console&(CON_R_ECHO|CON_R_INPUT) && !chksyspass(local))
-	return;
-if(online==ON_LOCAL) {
-	if(!(sys_misc&SM_L_SYSOP))
-		return;
-	if(node_misc&NM_SYSPW && !chksyspass(local))
-		return; }
-if(usernumber)
-	user.number=usernumber;
-else
-	user.number=useron.number;
-action=NODE_SYSP;
-if(sys_status&SS_INUEDIT)
-	return;
-sys_status|=SS_INUEDIT;
-while(online) {
-	CLS;
-	attr(LIGHTGRAY);
-	getuserdat(&user);
-	if(!user.number) {
-		user.number=1;
-		getuserdat(&user);
-		if(!user.number) {
-			bputs(text[NoUserData]);
-			getkey(0);
-			sys_status&=~SS_INUEDIT;
-			return; } }
-	unixtodstr(time(NULL),str);
-	unixtodstr(user.laston,tmp);
-	if(strcmp(str,tmp) && user.ltoday) {
-		user.ltoday=user.ttoday=user.ptoday=user.etoday=user.textra=0;
-		user.freecdt=level_freecdtperday[user.level];
-		putuserdat(user); }	/* Leave alone */
-	if(user.misc&DELETED)
-		bputs(text[Deleted]);
-	else if(user.misc&INACTIVE)
-		bputs(text[Inactive]);
-	bprintf(text[UeditAliasPassword]
-		,user.alias, (user.level>useron.level && console&CON_R_ECHO)
-		|| !(sys_misc&SM_ECHO_PW) ? "XXXXXXXX" : user.pass
-		, unixtodstr(user.pwmod,tmp));
-	bprintf(text[UeditRealNamePhone]
-		,user.level>useron.level && console&CON_R_ECHO
-		? "XXXXXXXX" : user.name
-		,user.level>useron.level && console&CON_R_ECHO
-		? "XXX-XXX-XXXX" : user.phone);
-	bprintf(text[UeditAddressBirthday]
-		,user.address,getage(user.birth),user.sex,user.birth);
-	bprintf(text[UeditLocationZipcode],user.location,user.zipcode);
-	bprintf(text[UeditNoteHandle],user.note,user.handle);
-	bprintf(text[UeditComputerModem],user.comp,user.modem);
-	sprintf(str,"%sUSER\\%4.4u.MSG",data_dir,user.number);
-	i=fexist(str);
-	if(user.comment[0] || i)
-		bprintf(text[UeditCommentLine],i ? '+' : SP
-			,user.comment);
-	else
-		CRLF;
-	unixtodos(user.laston,&date,&curtime);
-	bprintf(text[UserDates]
-		,unixtodstr(user.firston,str),unixtodstr(user.expire,tmp)
-		,unixtodstr(user.laston,tmp2),curtime.ti_hour,curtime.ti_min);
-	bprintf(text[UserTimes]
-		,user.timeon,user.ttoday,level_timeperday[user.level]
-		,user.tlast,level_timepercall[user.level],user.textra);
-	if(user.posts)
-		i=user.logons/user.posts;
-	else
-		i=0;
-	bprintf(text[UserLogons]
-		,user.logons,user.ltoday,level_callsperday[user.level],user.posts
-		,i ? 100/i : user.posts>user.logons ? 100 : 0
-		,user.ptoday);
-	bprintf(text[UserEmails]
-		,user.emails,user.fbacks,getmail(user.number,0),user.etoday);
-	if(user.misc&NETMAIL)
-		bprintf(text[UserNetMail],user.netmail);
-	else
-		CRLF;
-	bprintf(text[UserUploads],ultoac(user.ulb,tmp),user.uls);
-	if(user.leech)
-		sprintf(str,text[UserLeech],user.leech);
-	else
-		str[0]=0;
-	bprintf(text[UserDownloads],ultoac(user.dlb,tmp),user.dls,str);
-	bprintf(text[UserCredits],ultoac(user.cdt,tmp)
-		,ultoac(user.freecdt,tmp2),ultoac(level_freecdtperday[user.level],str));
-	bprintf(text[UserMinutes],ultoac(user.min,tmp));
-	bprintf(text[UeditSecLevel],user.level);
-	bprintf(text[UeditFlags],ltoaf(user.flags1,tmp),ltoaf(user.flags3,tmp2)
-		,ltoaf(user.flags2,tmp3),ltoaf(user.flags4,str));
-	bprintf(text[UeditExempts],ltoaf(user.exempt,tmp),ltoaf(user.rest,tmp2));
-	l=lastuser();
-	ASYNC;
-	if(lncntr>=rows-2)
-        lncntr=0;
-	bprintf(text[UeditPrompt],user.number,l);
-	if(user.level>useron.level && console&CON_R_INPUT)
-		strcpy(str,"QG[]?/{},");
-	else
-		strcpy(str,"ABCDEFGHIJKLMNOPQRSTUVWXYZ+[]?/{}~*$#");
-	l=getkeys(str,l);
-	if(l&0x80000000L) {
-		user.number=l&~0x80000000L;
-		continue; }
-	switch(l) {
-		case 'A':
-			bputs(text[EnterYourAlias]);
-			getstr(user.alias,LEN_ALIAS,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_ALIAS,LEN_ALIAS,user.alias);
-			if(!(user.misc&DELETED))
-				putusername(user.number,user.alias);
-			bputs(text[EnterYourHandle]);
-			getstr(user.handle,LEN_HANDLE,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_HANDLE,LEN_HANDLE,user.handle);
-			break;
-		case 'B':
-			bputs(text[EnterYourBirthday]);
-			gettmplt(user.birth,"nn/nn/nn",K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_BIRTH,LEN_BIRTH,user.birth);
-			break;
-		case 'C':
-			bputs(text[EnterYourComputer]);
-			getstr(user.comp,LEN_COMP,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_COMP,LEN_COMP,user.comp);
-			break;
-		case 'D':
-			if(user.misc&DELETED) {
-				if(!noyes(text[UeditRestoreQ])) {
-					putuserrec(user.number,U_MISC,8
-						,ultoa(user.misc&~DELETED,str,16));
-					putusername(user.number,user.alias); }
-				break; }
-			if(user.misc&INACTIVE) {
-				if(!noyes(text[UeditActivateQ]))
-					putuserrec(user.number,U_MISC,8
-						,ultoa(user.misc&~INACTIVE,str,16));
-				break; }
-			if(!noyes(text[UeditDeleteQ])) {
-				getsmsg(user.number);
-				if(getmail(user.number,0)) {
-					if(yesno(text[UeditReadUserMailWQ]))
-						readmail(user.number,MAIL_YOUR); }
-				if(getmail(user.number,1)) {
-					if(yesno(text[UeditReadUserMailSQ]))
-						readmail(user.number,MAIL_SENT); }
-				putuserrec(user.number,U_MISC,8
-					,ultoa(user.misc|DELETED,str,16));
-				putusername(user.number,nulstr);
-				break; }
-			if(!noyes(text[UeditDeactivateUserQ])) {
-				if(getmail(user.number,0)) {
-					if(yesno(text[UeditReadUserMailWQ]))
-						readmail(user.number,MAIL_YOUR); }
-				if(getmail(user.number,1)) {
-					if(yesno(text[UeditReadUserMailSQ]))
-						readmail(user.number,MAIL_SENT); }
-				putuserrec(user.number,U_MISC,8
-					,ultoa(user.misc|INACTIVE,str,16));
-				break; }
-			break;
-		case 'E':
-			if(!yesno(text[ChangeExemptionQ]))
-				break;
-			while(online) {
-				bprintf(text[FlagEditing],ltoaf(user.exempt,tmp));
-				c=getkeys("ABCDEFGHIJKLMNOPQRSTUVWXYZ?\r",0);
-                if(sys_status&SS_ABORT)
-					break;
-				if(c==CR) break;
-				if(c=='?') {
-					menu("EXEMPT");
-					continue; }
-				if(!(useron.exempt&FLAG(c)) && console&CON_R_INPUT)
-					continue;
-                user.exempt^=FLAG(c);
-				putuserrec(user.number,U_EXEMPT,8,ultoa(user.exempt,tmp,16)); }
-			break;
-		case 'F':
-			i=1;
-			while(online) {
-				bprintf("\r\nFlag Set #%d\r\n",i);
-				switch(i) {
-					case 1:
-						bprintf(text[FlagEditing],ltoaf(user.flags1,tmp));
-						break;
-					case 2:
-						bprintf(text[FlagEditing],ltoaf(user.flags2,tmp));
-                        break;
-					case 3:
-						bprintf(text[FlagEditing],ltoaf(user.flags3,tmp));
-                        break;
-					case 4:
-						bprintf(text[FlagEditing],ltoaf(user.flags4,tmp));
-						break; }
-				c=getkeys("ABCDEFGHIJKLMNOPQRSTUVWXYZ?1234\r",0);
-				if(sys_status&SS_ABORT)
-					break;
-				if(c==CR) break;
-				if(c=='?') {
-					sprintf(str,"FLAGS%d",i);
-					menu(str);
-					continue; }
-				if(isdigit(c)) {
-					i=c&0xf;
-					continue; }
-				if(console & CON_R_INPUT)
-					switch(i) {
-						case 1:
-							if(!(useron.flags1&FLAG(c)))
-								continue;
-							break;
-						case 2:
-							if(!(useron.flags2&FLAG(c)))
-								continue;
-                            break;
-						case 3:
-							if(!(useron.flags3&FLAG(c)))
-								continue;
-                            break;
-						case 4:
-							if(!(useron.flags4&FLAG(c)))
-								continue;
-							break; }
-				switch(i) {
-					case 1:
-						user.flags1^=FLAG(c);
-						putuserrec(user.number,U_FLAGS1,8
-							,ultoa(user.flags1,tmp,16));
-						break;
-					case 2:
-						user.flags2^=FLAG(c);
-						putuserrec(user.number,U_FLAGS2,8
-							,ultoa(user.flags2,tmp,16));
-						break;
-					case 3:
-						user.flags3^=FLAG(c);
-						putuserrec(user.number,U_FLAGS3,8
-							,ultoa(user.flags3,tmp,16));
-                        break;
-					case 4:
-						user.flags4^=FLAG(c);
-						putuserrec(user.number,U_FLAGS4,8
-							,ultoa(user.flags4,tmp,16));
-						break; } }
-			break;
-		case 'G':
-			bputs(text[GoToUser]);
-			if(getstr(str,LEN_ALIAS,K_UPPER|K_LINE)) {
-				if(isdigit(str[0])) {
-					i=atoi(str);
-					if(i>lastuser())
-						break;
-					if(i) user.number=i; }
-				else {
-					i=finduser(str);
-					if(i) user.number=i; } }
-			break;
-		case 'H': /* edit user's information file */
-			attr(LIGHTGRAY);
-            sprintf(str,"%sUSER\\%4.4u.MSG",data_dir,user.number);
-            editfile(str);
-            break;
-		case 'I':
-			maindflts(user);
-			break;
-		case 'J':   /* Edit Minutes */
-			bputs(text[UeditMinutes]);
-			ultoa(user.min,str,10);
-            if(getstr(str,10,K_NUMBER|K_LINE))
-				putuserrec(user.number,U_MIN,10,str);
-            break;
-		case 'K':	/* date changes */
-			bputs(text[UeditLastOn]);
-			unixtodstr(user.laston,str);
-			gettmplt(str,"nn/nn/nn",K_LINE|K_EDIT);
-			if(sys_status&SS_ABORT)
-				break;
-			user.laston=dstrtounix(str);
-			putuserrec(user.number,U_LASTON,8,ultoa(user.laston,tmp,16));
-			bputs(text[UeditFirstOn]);
-			unixtodstr(user.firston,str);
-			gettmplt(str,"nn/nn/nn",K_LINE|K_EDIT);
-			if(sys_status&SS_ABORT)
-				break;
-			user.firston=dstrtounix(str);
-			putuserrec(user.number,U_FIRSTON,8,ultoa(user.firston,tmp,16));
-			bputs(text[UeditExpire]);
-			unixtodstr(user.expire,str);
-			gettmplt(str,"nn/nn/nn",K_LINE|K_EDIT);
-			if(sys_status&SS_ABORT)
-				break;
-			user.expire=dstrtounix(str);
-			putuserrec(user.number,U_EXPIRE,8,ultoa(user.expire,tmp,16));
-			bputs(text[UeditPwModDate]);
-			unixtodstr(user.pwmod,str);
-			gettmplt(str,"nn/nn/nn",K_LINE|K_EDIT);
-			if(sys_status&SS_ABORT)
-				break;
-			user.pwmod=dstrtounix(str);
-			putuserrec(user.number,U_PWMOD,8,ultoa(user.pwmod,tmp,16));
-			break;
-		case 'L':
-			bputs(text[EnterYourAddress]);
-			getstr(user.address,LEN_ADDRESS,K_LINE|K_EDIT|K_AUTODEL);
-			if(sys_status&SS_ABORT)
-				break;
-			putuserrec(user.number,U_ADDRESS,LEN_ADDRESS,user.address);
-			bputs(text[EnterYourCityState]);
-			getstr(user.location,LEN_LOCATION,K_LINE|K_EDIT|K_AUTODEL);
-			if(sys_status&SS_ABORT)
-				break;
-			putuserrec(user.number,U_LOCATION,LEN_LOCATION,user.location);
-			bputs(text[EnterYourZipCode]);
-			getstr(user.zipcode,LEN_ZIPCODE,K_LINE|K_EDIT|K_AUTODEL|K_UPPER);
-			if(sys_status&SS_ABORT)
-				break;
-			putuserrec(user.number,U_ZIPCODE,LEN_ZIPCODE,user.zipcode);
-			break;
-		case 'M':
-			bputs(text[UeditML]);
-			itoa(user.level,str,10);
-			if(getstr(str,2,K_NUMBER|K_LINE))
-				if(!(atoi(str)>useron.level && console&CON_R_INPUT))
-					putuserrec(user.number,U_LEVEL,2,str);
-			break;
-		case 'N':
-			bputs(text[UeditNote]);
-			getstr(user.note,LEN_NOTE,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_NOTE,LEN_NOTE,user.note);
-			break;
-		case 'O':
-			bputs(text[UeditComment]);
-			getstr(user.comment,60,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_COMMENT,60,user.comment);
-			break;
-		case 'P':
-			bputs(text[EnterYourPhoneNumber]);
-			getstr(user.phone,LEN_PHONE,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_PHONE,LEN_PHONE,user.phone);
-			break;
-		case 'Q':
-			CLS;
-			sys_status&=~SS_INUEDIT;
-			if(ar)
-				FREE(ar);
-			return;
-		case 'R':
-			bputs(text[EnterYourRealName]);
-			getstr(user.name,LEN_NAME,K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_NAME,LEN_NAME,user.name);
-			break;
-		case 'S':
-			bputs(text[EnterYourSex]);
-			if(getstr(str,1,K_UPPER|K_LINE))
-				putuserrec(user.number,U_SEX,1,str);
-			break;
-		case 'T':   /* Text Search */
-			bputs(text[SearchStringPrompt]);
-			if(getstr(search,30,K_UPPER|K_LINE))
-				stype=SEARCH_TXT;
-			break;
-		case 'U':
-			bputs(text[UeditUlBytes]);
-			ultoa(user.ulb,str,10);
-			if(getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-				putuserrec(user.number,U_ULB,10,str);
-			if(sys_status&SS_ABORT)
-				break;
-			bputs(text[UeditUploads]);
-			sprintf(str,"%u",user.uls);
-			if(getstr(str,5,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-				putuserrec(user.number,U_ULS,5,str);
-            if(sys_status&SS_ABORT)
-				break;
-			bputs(text[UeditDlBytes]);
-			ultoa(user.dlb,str,10);
-			if(getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-				putuserrec(user.number,U_DLB,10,str);
-            if(sys_status&SS_ABORT)
-				break;
-			bputs(text[UeditDownloads]);
-			sprintf(str,"%u",user.dls);
-			if(getstr(str,5,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL))
-				putuserrec(user.number,U_DLS,5,str);
-			break;
-		case 'V':
-			CLS;
-			attr(LIGHTGRAY);
-			for(i=0;i<10;i++) {
-				bprintf(text[QuickValidateFmt]
-					,i,val_level[i],ltoaf(val_flags1[i],str)
-					,ltoaf(val_exempt[i],tmp)
-					,ltoaf(val_rest[i],tmp3)); }
-			ASYNC;
-			bputs(text[QuickValidatePrompt]);
-			c=getkey(0);
-			if(!isdigit(c))
-				break;
-			i=c&0xf;
-			user.level=val_level[i];
-			user.flags1=val_flags1[i];
-			user.flags2=val_flags2[i];
-			user.flags3=val_flags3[i];
-			user.flags4=val_flags4[i];
-			user.exempt=val_exempt[i];
-			user.rest=val_rest[i];
-			user.cdt+=val_cdt[i];
-			now=time(NULL);
-			if(val_expire[i]) {
-				if(user.expire<now)
-					user.expire=now+((long)val_expire[i]*24L*60L*60L);
-				else
-					user.expire+=((long)val_expire[i]*24L*60L*60L); }
-			putuserdat(user);
-			break;
-		case 'W':
-			bputs(text[UeditPassword]);
-			getstr(user.pass,LEN_PASS,K_UPPER|K_LINE|K_EDIT|K_AUTODEL);
-			putuserrec(user.number,U_PASS,LEN_PASS,user.pass);
-			break;
-		case 'X':
-			attr(LIGHTGRAY);
-            sprintf(str,"%sUSER\\%4.4u.MSG",data_dir,user.number);
-			printfile(str,0);
-			pause();
-			break;
-        case 'Y':
-			if(!noyes(text[UeditCopyUserQ])) {
-				bputs(text[UeditCopyUserToSlot]);
-				i=getnum(lastuser());
-				if(i>0) {
-					user.number=i;
-					putusername(user.number,user.alias);
-					putuserdat(user); } }
-			break;
-		case 'Z':
-			if(!yesno(text[ChangeRestrictsQ]))
-				break;
-			while(online) {
-				bprintf(text[FlagEditing],ltoaf(user.rest,tmp));
-				c=getkeys("ABCDEFGHIJKLMNOPQRSTUVWXYZ?\r",0);
-                if(sys_status&SS_ABORT)
-					break;
-				if(c==CR) break;
-				if(c=='?') {
-					menu("RESTRICT");
-					continue; }
-				user.rest^=FLAG(c);
-				putuserrec(user.number,U_REST,8,ultoa(user.rest,tmp,16)); }
-			break;
-		case '?':
-			CLS;
-			menu("UEDIT");  /* Sysop Uedit Edit Menu */
-			pause();
-			break;
-		case '~':
-			bputs(text[UeditLeech]);
-			if(getstr(str,2,K_NUMBER|K_LINE))
-				putuserrec(user.number,U_LEECH,2,itoa(atoi(str),tmp,16));
-            break;
-		case '+':
-			bputs(text[ModifyCredits]);
-			getstr(str,10,K_UPPER|K_LINE);
-			l=atol(str);
-			if(strstr(str,"M"))
-				l*=0x100000L;
-			else if(strstr(str,"K"))
-				l*=1024;
-			else if(strstr(str,"$"))
-				l*=cdt_per_dollar;
-			if(l<0L && l*-1 > user.cdt)
-				user.cdt=0L;
-			else
-				user.cdt+=l;
-			putuserrec(user.number,U_CDT,10,ultoa(user.cdt,tmp,10));
-			break;
-		case '*':
-			bputs(text[ModifyMinutes]);
-			getstr(str,10,K_UPPER|K_LINE);
-			l=atol(str);
-			if(strstr(str,"H"))
-				l*=60L;
-			if(l<0L && l*-1 > user.min)
-				user.min=0L;
-			else
-				user.min+=l;
-			putuserrec(user.number,U_MIN,10,ultoa(user.min,tmp,10));
-			break;
-		case '#': /* read new user questionaire */
-			sprintf(str,"%sUSER\\%4.4u.DAT",data_dir,user.number);
-			if(!new_sof[0] || !fexist(str))
-				break;
-			read_sif_dat(new_sof,str);
-			if(!noyes(text[DeleteQuestionaireQ]))
-				remove(str);
-			break;
-		case '$':
-			bputs(text[UeditCredits]);
-            ultoa(user.cdt,str,10);
-            if(getstr(str,10,K_NUMBER|K_LINE))
-                putuserrec(user.number,U_CDT,10,str);
-            break;
-		case '/':
-			bputs(text[SearchStringPrompt]);
-			if(getstr(artxt,40,K_UPPER|K_LINE))
-				stype=SEARCH_ARS;
-			if(ar && ar[0])
-				FREE(ar);
-			ar=arstr(0,artxt);
-            break;
-		case '{':
-			if(stype==SEARCH_TXT)
-				user.number=searchdn(search,user.number);
-			else {
-				if(!ar)
-					break;
-				k=user.number;
-				for(i=k-1;i;i--) {
-					user.number=i;
-					getuserdat(&user);
-					if(chk_ar(ar,user)) {
-						outchar(7);
-						break; } }
-				if(!i)
-					user.number=k; }
-			break;
-		case '}':
-			if(stype==SEARCH_TXT)
-				user.number=searchup(search,user.number);
-			else {
-				if(!ar)
-					break;
-				j=lastuser();
-				k=user.number;
-				for(i=k+1;i<=j;i++) {
-					user.number=i;
-					getuserdat(&user);
-					if(chk_ar(ar,user)) {
-						outchar(7);
-						break; } }
-				if(i>j)
-                    user.number=k; }
-			break;
-		case ']':
-			if(user.number==lastuser())
-				user.number=1;
-			else user.number++;
-			break;
-		case '[':
-			if(user.number==1)
-				user.number=lastuser();
-			else user.number--;
-			break; } }
-sys_status&=~SS_INUEDIT;
-}
-
-/****************************************************************************/
-/* Seaches forward through the USER.DAT file for the ocurrance of 'search'  */
-/* starting at the offset for usernum+1 and returning the usernumber of the */
-/* record where the string was found or the original usernumber if the 		*/
-/* string wasn't found														*/
-/* Called from the function useredit										*/
-/****************************************************************************/
-int searchup(char *search,int usernum)
-{
-	char userdat[U_LEN+1];
-	int file,count;
-	uint i=usernum+1;
-
-if(!search[0])
-	return(usernum);
-sprintf(userdat,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(userdat,O_RDONLY|O_DENYNONE))==-1)
-	return(usernum);
-lseek(file,(long)((long)usernum*U_LEN),0);
-
-while(!eof(file)) {
-	count=0;
-	while(count<LOOP_NODEDAB
-		&& lock(file,(long)((long)(i-1)*U_LEN),U_LEN)==-1) {
-		if(count>10)
-			mswait(55);
-		count++; }
-
-	if(count>=LOOP_NODEDAB) {
-		close(file);
-		errormsg(WHERE,ERR_LOCK,"USER.DAT",i);
-		return(usernum); }
-
-	if(read(file,userdat,U_LEN)!=U_LEN) {
-		unlock(file,(long)((long)(i-1)*U_LEN),U_LEN);
-		close(file);
-		errormsg(WHERE,ERR_READ,"USER.DAT",U_LEN);
-		return(usernum); }
-
-	unlock(file,(long)((long)(i-1)*U_LEN),U_LEN);
-	userdat[U_LEN]=0;
-	strupr(userdat);
-	if(strstr(userdat,search)) {
-		outchar(7);
-		close(file);
-		return(i); }
-	i++; }
-close(file);
-return(usernum);
-}
-
-/****************************************************************************/
-/* Seaches backward through the USER.DAT file for the ocurrance of 'search' */
-/* starting at the offset for usernum-1 and returning the usernumber of the */
-/* record where the string was found or the original usernumber if the 		*/
-/* string wasn't found														*/
-/* Called from the function useredit										*/
-/****************************************************************************/
-int searchdn(char *search,int usernum)
-{
-	char userdat[U_LEN+1];
-	int file,count;
-	uint i=usernum-1;
-
-if(!search[0])
-	return(usernum);
-sprintf(userdat,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(userdat,O_RDONLY))==-1)
-	return(usernum);
-while(i) {
-	lseek(file,(long)((long)(i-1)*U_LEN),0);
-	count=0;
-	while(count<LOOP_NODEDAB
-		&& lock(file,(long)((long)(i-1)*U_LEN),U_LEN)==-1) {
-		if(count>10)
-			mswait(55);
-		count++; }
-
-	if(count>=LOOP_NODEDAB) {
-		close(file);
-		errormsg(WHERE,ERR_LOCK,"USER.DAT",i);
-        return(usernum); }
-
-	if(read(file,userdat,U_LEN)==-1) {
-		unlock(file,(long)((long)(i-1)*U_LEN),U_LEN);
-		close(file);
-		errormsg(WHERE,ERR_READ,"USER.DAT",U_LEN);
-		return(usernum); }
-	unlock(file,(long)((long)(i-1)*U_LEN),U_LEN);
-	userdat[U_LEN]=0;
-	strupr(userdat);
-	if(strstr(userdat,search)) {
-		outchar(7);
-		close(file);
-		return(i); }
-	i--; }
-close(file);
-return(usernum);
-}
-
-/****************************************************************************/
-/* This function view/edits the users main default settings.				*/
-/****************************************************************************/
-void maindflts(user_t user)
-{
-	char str[256],ch;
-	int i;
-
-action=NODE_DFLT;
-while(online) {
-	CLS;
-/*
-	if(user.number==useron.number && useron.rest&FLAG('G')) /* Guest */
-		user=useron;
-	else
-*/
-		getuserdat(&user);
-    if(user.rows)
-		rows=user.rows;
-	bprintf(text[UserDefaultsHdr],user.alias,user.number);
-	sprintf(str,"%s%s%s%s%s"
-						,user.misc&AUTOTERM ? "Auto Detect ":nulstr
-						,user.misc&ANSI ? "ANSI ":"TTY "
-						,user.misc&COLOR ? "(Color) ":"(Mono) "
-						,user.misc&WIP	? "WIP" : user.misc&RIP ? "RIP "
-							:nulstr
-						,user.misc&NO_EXASCII ? "ASCII Only":nulstr);
-	bprintf(text[UserDefaultsTerminal],str);
-	if(total_xedits)
-		bprintf(text[UserDefaultsXeditor]
-			,user.xedit ? xedit[user.xedit-1]->name : "None");
-	if(user.rows)
-		itoa(user.rows,tmp,10);
-	else
-		sprintf(tmp,"Auto Detect (%d)",rows);
-	bprintf(text[UserDefaultsRows],tmp);
-	if(total_shells>1)
-		bprintf(text[UserDefaultsCommandSet]
-			,shell[user.shell]->name);
-	bprintf(text[UserDefaultsArcType]
-		,user.tmpext);
-	bprintf(text[UserDefaultsMenuMode]
-		,user.misc&EXPERT ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsPause]
-		,user.misc&UPAUSE ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsHotKey]
-		,user.misc&COLDKEYS ? text[Off] : text[On]);
-	bprintf(text[UserDefaultsCursor]
-		,user.misc&SPIN ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsCLS]
-		,user.misc&CLRSCRN ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsAskNScan]
-		,user.misc&ASK_NSCAN ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsAskSScan]
-        ,user.misc&ASK_SSCAN ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsANFS]
-		,user.misc&ANFSCAN ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsRemember]
-		,user.misc&CURSUB ? text[On] : text[Off]);
-	bprintf(text[UserDefaultsBatFlag]
-		,user.misc&BATCHFLAG ? text[On] : text[Off]);
-	if(sys_misc&SM_FWDTONET)
-		bprintf(text[UserDefaultsNetMail]
-			,user.misc&NETMAIL ? text[On] : text[Off]);
-	if(useron.exempt&FLAG('Q') || user.misc&QUIET)
-		bprintf(text[UserDefaultsQuiet]
-			,user.misc&QUIET ? text[On] : text[Off]);
-	if(user.prot!=SP)
-		sprintf(str,"%c",user.prot);
-	else
-		strcpy(str,"None");
-	bprintf(text[UserDefaultsProtocol],str
-        ,user.misc&AUTOHANG ? "(Hang-up After Xfer)":nulstr);
-	if(sys_misc&SM_PWEDIT && !(user.rest&FLAG('G')))
-		bputs(text[UserDefaultsPassword]);
-
-	ASYNC;
-	bputs(text[UserDefaultsWhich]);
-	strcpy(str,"HTBALPRSYFNCQXZ\r");
-	if(sys_misc&SM_PWEDIT && !(user.rest&FLAG('G')))
-		strcat(str,"W");
-	if(useron.exempt&FLAG('Q') || user.misc&QUIET)
-		strcat(str,"D");
-	if(total_xedits)
-		strcat(str,"E");
-	if(sys_misc&SM_FWDTONET)
-		strcat(str,"M");
-	if(total_shells>1)
-		strcat(str,"K");
-	ch=getkeys(str,0);
-	switch(ch) {
-		case 'T':
-			if(yesno(text[AutoTerminalQ])) {
-				user.misc|=AUTOTERM;
-				user.misc&=~(ANSI|RIP|WIP);
-				user.misc|=autoterm; }
-			else
-				user.misc&=~AUTOTERM;
-			if(!(user.misc&AUTOTERM)) {
-				if(yesno(text[AnsiTerminalQ]))
-					user.misc|=ANSI;
-				else
-					user.misc&=~(ANSI|COLOR); }
-			if(user.misc&ANSI) {
-				if(yesno(text[ColorTerminalQ]))
-					user.misc|=COLOR;
-				else
-					user.misc&=~COLOR; }
-			if(!yesno(text[ExAsciiTerminalQ]))
-				user.misc|=NO_EXASCII;
-			else
-				user.misc&=~NO_EXASCII;
-			if(!(user.misc&AUTOTERM)) {
-				if(!noyes(text[RipTerminalQ]))
-					user.misc|=RIP;
-				else
-					user.misc&=~RIP; }
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'B':
-			user.misc^=BATCHFLAG;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'E':
-			if(noyes("Use an external editor")) {
-				putuserrec(user.number,U_XEDIT,8,nulstr);
-				break; }
-			if(user.xedit)
-				user.xedit--;
-			for(i=0;i<total_xedits;i++)
-				uselect(1,i,"External Editor",xedit[i]->name,xedit[i]->ar);
-			if((i=uselect(0,user.xedit,0,0,0))>=0)
-				putuserrec(user.number,U_XEDIT,8,xedit[i]->code);
-			break;
-		case 'K':   /* Command shell */
-			for(i=0;i<total_shells;i++)
-				uselect(1,i,"Command Shell",shell[i]->name,shell[i]->ar);
-			if((i=uselect(0,user.shell,0,0,0))>=0)
-				putuserrec(user.number,U_SHELL,8,shell[i]->code);
-			break;
-		case 'A':
-			for(i=0;i<total_fcomps;i++)
-				uselect(1,i,"Archive Type",fcomp[i]->ext,fcomp[i]->ar);
-			if((i=uselect(0,0,0,0,0))>=0)
-				putuserrec(user.number,U_TMPEXT,3,fcomp[i]->ext);
-			break;
-		case 'L':
-			bputs(text[HowManyRows]);
-			if((ch=getnum(99))!=-1)
-				putuserrec(user.number,U_ROWS,2,itoa(ch,tmp,10));
-			break;
-		case 'P':
-			user.misc^=UPAUSE;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'H':
-			user.misc^=COLDKEYS;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-            break;
-		case 'S':
-			user.misc^=SPIN;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'F':
-			user.misc^=ANFSCAN;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'X':
-			user.misc^=EXPERT;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'R':   /* Remember current sub/dir */
-			user.misc^=CURSUB;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'Y':   /* Prompt for scanning message to you */
-			user.misc^=ASK_SSCAN;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-            break;
-		case 'N':   /* Prompt for new message/files scanning */
-			user.misc^=ASK_NSCAN;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'M':   /* NetMail address */
-			if(noyes(text[ForwardMailQ]))
-				user.misc&=~NETMAIL;
-			else {
-				user.misc|=NETMAIL;
-				bputs(text[EnterNetMailAddress]);
-				if(!getstr(user.netmail,LEN_NETMAIL,K_EDIT|K_AUTODEL|K_LINE))
-					break;
-				putuserrec(user.number,U_NETMAIL,LEN_NETMAIL,user.netmail); }
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'C':
-			user.misc^=CLRSCRN;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'D':
-			user.misc^=QUIET;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		case 'W':
-			if(noyes(text[NewPasswordQ]))
-				break;
-			bputs(text[CurrentPassword]);
-			console|=CON_R_ECHOX;
-			if(!(sys_misc&SM_ECHO_PW))
-				console|=CON_L_ECHOX;
-			ch=getstr(str,LEN_PASS,K_UPPER);
-			console&=~(CON_R_ECHOX|CON_L_ECHOX);
-			if(strcmp(str,user.pass)) {
-				bputs(text[WrongPassword]);
-				pause();
-                break; }
-			bputs(text[NewPassword]);
-			if(!getstr(str,LEN_PASS,K_UPPER|K_LINE))
-				break;
-			truncsp(str);
-			if(!chkpass(str,user)) {
-				CRLF;
-				pause();
-				break; }
-			bputs(text[VerifyPassword]);
-			console|=CON_R_ECHOX;
-			if(!(sys_misc&SM_ECHO_PW))
-				console|=CON_L_ECHOX;
-			getstr(tmp,LEN_PASS,K_UPPER);
-			console&=~(CON_R_ECHOX|CON_L_ECHOX);
-			if(strcmp(str,tmp)) {
-				bputs(text[WrongPassword]);
-				pause();
-				break; }
-			if(!online)
-				break;
-			putuserrec(user.number,U_PASS,LEN_PASS,str);
-			now=time(NULL);
-			putuserrec(user.number,U_PWMOD,8,ultoa(now,tmp,16));
-			bputs(text[PasswordChanged]);
-			logline(nulstr,"Changed password");
-			pause();
-			break;
-		case 'Z':
-			menu("DLPROT");
-            SYNC;
-            mnemonics(text[ProtocolOrQuit]);
-			strcpy(str,"Q");
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
-                    sprintf(tmp,"%c",prot[i]->mnemonic);
-					strcat(str,tmp); }
-			ch=getkeys(str,0);
-			if(ch=='Q' || sys_status&SS_ABORT) {
-				ch=SP;
-				putuserrec(user.number,U_PROT,1,&ch); }
-			else
-				putuserrec(user.number,U_PROT,1,&ch);
-			if(yesno(text[HangUpAfterXferQ]))
-				user.misc|=AUTOHANG;
-			else
-				user.misc&=~AUTOHANG;
-			putuserrec(user.number,U_MISC,8,ultoa(user.misc,str,16));
-			break;
-		default:
-			return; } }
-}
-
-void purgeuser(int usernumber)
-{
-	uchar str[128];
-	user_t user;
-
-user.number=usernumber;
-getuserdat(&user);
-sprintf(str,"Purged %s #%u",user.alias,usernumber);
-logentry("!*",str);
-delallmail(usernumber);
-putusername(usernumber,nulstr);
-putuserrec(usernumber,U_MISC,8,ultoa(user.misc|DELETED,str,16));
-}
diff --git a/src/sbbs2/userrec.c b/src/sbbs2/userrec.c
deleted file mode 100644
index 91fe764d726ad72b851b0b03c90e7453656e9822..0000000000000000000000000000000000000000
--- a/src/sbbs2/userrec.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#line 1 "USERREC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Fills 'str' with record for usernumber starting at start for length bytes*/
-/* Called from function ???													*/
-/****************************************************************************/
-void getuserrec(int usernumber,int start, char length, char *str)
-{
-	char c,path[256];
-	int i,file;
-
-if(!usernumber) {
-	errormsg(WHERE,ERR_CHK,"user number",0);
-	return; }
-sprintf(path,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(path,O_RDONLY|O_DENYNONE))==-1) {
-	errormsg(WHERE,ERR_OPEN,path,O_RDONLY);
-	return; }
-if(usernumber<1
-	|| filelength(file)<(long)((long)(usernumber-1L)*U_LEN)+(long)start) {
-	close(file);
-	errormsg(WHERE,ERR_CHK,"user number",usernumber);
-	return; }
-lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
-
-i=0;
-while(i<LOOP_NODEDAB
-	&& lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
-	if(i>10)
-		mswait(55);
-	i++; }
-
-if(i>=LOOP_NODEDAB) {
-	close(file);
-	errormsg(WHERE,ERR_LOCK,"USER.DAT",usernumber);
-    return; }
-
-if(read(file,str,length)!=length) {
-	unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-	close(file);
-	errormsg(WHERE,ERR_READ,"USER.DAT",length);
-	return; }
-
-unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-close(file);
-for(c=0;c<length;c++)
-	if(str[c]==ETX || str[c]==CR) break;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Places into USER.DAT at the offset for usernumber+start for length bytes */
-/* Called from various locations											*/
-/****************************************************************************/
-void putuserrec(int usernumber,int start, char length, char *str)
-{
-	char c,str2[256];
-	int file,i;
-	node_t node;
-
-if(usernumber<1) {
-	errormsg(WHERE,ERR_CHK,"user number",usernumber);
-	return; }
-sprintf(str2,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(str2,O_WRONLY|O_DENYNONE))==-1) {
-	errormsg(WHERE,ERR_OPEN,str2,O_WRONLY);
-	return; }
-strcpy(str2,str);
-if(strlen(str2)<length) {
-	for(c=strlen(str2);c<length;c++)
-		str2[c]=ETX;
-	str2[c]=0; }
-lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET);
-
-i=0;
-while(i<LOOP_NODEDAB
-	&& lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
-	if(i>10)
-		mswait(55);
-	i++; }
-
-if(i>=LOOP_NODEDAB) {
-	close(file);
-	errormsg(WHERE,ERR_LOCK,"USER.DAT",usernumber);
-    return; }
-
-write(file,str2,length);
-unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-close(file);
-for(i=1;i<=sys_nodes;i++) {	/* instant user data update */
-	if(i==node_num)
-		continue;
-	getnodedat(i,&node,0);
-	if(node.useron==usernumber && (node.status==NODE_INUSE
-		|| node.status==NODE_QUIET)) {
-		getnodedat(i,&node,1);
-		node.misc|=NODE_UDAT;
-		putnodedat(i,node);
-		break; } }
-}
-
-/****************************************************************************/
-/* Updates user 'usernumber's record (numeric string) by adding 'adj' to it */
-/* returns the new value.													*/
-/****************************************************************************/
-ulong adjustuserrec(int usernumber,int start, char length, long adj)
-{
-	char str[256],c,path[256];
-	int i,file;
-	ulong val;
-	node_t node;
-
-if(usernumber<1) {
-	errormsg(WHERE,ERR_CHK,"user number",usernumber);
-	return(0UL); }
-sprintf(path,"%sUSER\\USER.DAT",data_dir);
-if((file=nopen(path,O_RDWR|O_DENYNONE))==-1) {
-	errormsg(WHERE,ERR_OPEN,path,O_RDWR);
-	return(0UL); }
-lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
-
-i=0;
-while(i<LOOP_NODEDAB
-	&& lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
-	if(i>10)
-		mswait(55);
-	i++; }
-
-if(i>=LOOP_NODEDAB) {
-	close(file);
-	errormsg(WHERE,ERR_LOCK,"USER.DAT",usernumber);
-	return(0); }
-
-if(read(file,str,length)!=length) {
-	unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-	close(file);
-	errormsg(WHERE,ERR_READ,path,length);
-	return(0UL); }
-for(c=0;c<length;c++)
-	if(str[c]==ETX || str[c]==CR) break;
-str[c]=0;
-val=atol(str);
-if(adj<0L && val<-adj)		/* don't go negative */
-	val=0UL;
-else val+=adj;
-lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
-putrec(str,0,length,ultoa(val,tmp,10));
-if(write(file,str,length)!=length) {
-	unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-	close(file);
-	errormsg(WHERE,ERR_WRITE,path,length);
-	return(val); }
-unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
-close(file);
-for(i=1;i<=sys_nodes;i++) { /* instant user data update */
-	if(i==node_num)
-		continue;
-	getnodedat(i,&node,0);
-	if(node.useron==usernumber && (node.status==NODE_INUSE
-		|| node.status==NODE_QUIET)) {
-		getnodedat(i,&node,1);
-		node.misc|=NODE_UDAT;
-		putnodedat(i,node);
-        break; } }
-return(val);
-}
-
-/****************************************************************************/
-/* Subtract credits from the current user online, accounting for the new    */
-/* "free credits" field.                                                    */
-/****************************************************************************/
-void subtract_cdt(long amt)
-{
-    long mod;
-
-if(!amt)
-    return;
-if(useron.freecdt) {
-    if(amt>useron.freecdt) {      /* subtract both credits and */
-        mod=amt-useron.freecdt;   /* free credits */
-        putuserrec(useron.number,U_FREECDT,10,"0");
-        useron.freecdt=0;
-        useron.cdt=adjustuserrec(useron.number,U_CDT,10,-mod); }
-    else {                          /* subtract just free credits */
-        useron.freecdt-=amt;
-        putuserrec(useron.number,U_FREECDT,10
-            ,ultoa(useron.freecdt,tmp,10)); } }
-else    /* no free credits */
-    useron.cdt=adjustuserrec(useron.number,U_CDT,10,-amt);
-}
diff --git a/src/sbbs2/uti/makefile b/src/sbbs2/uti/makefile
deleted file mode 100644
index fc92d412c3a7fd6717e95f22278c27f82059b8a3..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/makefile
+++ /dev/null
@@ -1,90 +0,0 @@
-###############################
-# Makefile for Synchronet UTI #
-# For use with Turbo C++      #
-# Tabstop=8		      #
-###############################
-
-# Macros
-CC	= bcc
-LD	= tlink
-INCLUDE = \bc31\include;..;..\smb;..\rio
-LIB     = \bc31\lib
-MODEL	= l
-CFLAGS	= -d -C -m$(MODEL) -I$(INCLUDE) -w-pro
-LFLAGS  = /n /c
-OBJS	= scfgvars.obj scfglib1.obj uti.obj ars.obj
-SMB	= smblib.obj 
-LZH	= lzh.obj
-HEADERS = ..\sbbs.h ..\sbbsdefs.h ..\scfgvars.c \
-	  ..\smb\smblib.h ..\smb\smbdefs.h
-
-# Implicit C Compile Rule
-.c.obj:
-        @echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -o$*.obj -c $*.c
-
-all: utilist.exe utihigh.exe utiexprt.exe utilstrd.exe utiimprt.exe utiver.exe
-
-utilist.exe: $(OBJS) utilist.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) utilist.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-utihigh.exe: $(OBJS) $(SMB) utihigh.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) $(SMB) utihigh.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-utiexprt.exe: $(OBJS) $(SMB) $(LZH) utiexprt.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) $(SMB) $(LZH) utiexprt.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-utiimprt.exe: $(OBJS) $(SMB) $(LZH) utiimprt.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) $(SMB) $(LZH) utiimprt.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-utilstrd.exe: $(OBJS) utilstrd.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) utilstrd.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-utiver.exe: uti.h utiver.obj utiver.c
-	bcc -w-pro utiver.c
-
-# SMBLIB Functions
-smblib.obj: ..\smb\smblib.c ..\smb\smbdefs.h ..\smb\smblib.h
-	@echo Compiling ..\$*.c to $*.obj ...
-        $(CC) $(CFLAGS) -c ..\smb\$*.c
-
-# SMB LZH Functions
-lzh.obj: ..\smb\lzh.c ..\smb\lzh.h 
-	@echo Compiling ..\$*.c to $*.obj ...
-        $(CC) $(CFLAGS) -c ..\smb\$*.c
-
-# Global Variables
-scfgvars.obj: ..\scfgvars.c ..\smb\smbdefs.h 
-	@echo Compiling ..\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c ..\$*.c
-
-ars.obj: ..\ars.c ..\ars_defs.h
-        @echo Compiling ..\$&.c to $< ...
-	$(CC) $(CFLAGS) -c ..\ars.c
-
-
-# Shared Functions
-scfglib1.obj: ..\sbbs.h ..\sbbsdefs.h ..\scfglib1.c ..\scfgvars.c ..\scfglib.h
-	@echo Compiling ..\$*.c to $*.obj ...
-        $(CC) $(CFLAGS) -c ..\$*.c
-
-utiimprt.obj:	uti.h
-utiexprt.obj:	uti.h
-utilstrd.obj:	uti.h
-utihigh.obj:	uti.h
-utilist.obj:	uti.h
diff --git a/src/sbbs2/uti/uti.c b/src/sbbs2/uti/uti.c
deleted file mode 100644
index fb290e0a3313ec0656cda46b083c3de32912d501..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/uti.c
+++ /dev/null
@@ -1,298 +0,0 @@
-#line 1 "UTI.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Shared routines for most of the UTI driver programs */
-
-#include "sbbs.h"
-#include "uti.h"
-
-#define bputs	lputs
-#define bprintf lprintf
-
-int logfile;
-char scrnbuf[4000],tmp[256];
-struct text_info txtinfo;
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/* Called from everywhere                                                   */
-/****************************************************************************/
-int lprintf(char *fmat, ...) {
-	char sbuf[256];
-	int chcount;
-
-chcount=vsprintf(sbuf,fmat,_va_ptr);
-lputs(sbuf);
-return(chcount);
-}
-
-long lputs(char far *str)
-{
-	char tmp[256];
-	int i,j,k;
-
-j=strlen(str);
-for(i=k=0;i<j;i++)		/* remove CRs */
-	if(str[i]==CR && str[i+1]==LF)
-		continue;
-	else
-		tmp[k++]=str[i];
-tmp[k]=0;
-return(fputs(tmp,stdout));
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
-}
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong                       */
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char logstr[256];
-	int file,share,count=0;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-	else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(count>(LOOP_NOPEN/2))
-	lprintf("NOPEN COLLISION - File: %s Count: %d"
-		,str,count);
-if(file==-1 && errno==EACCES)
-	lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-/****************************************************************************/
-/* This function performs an nopen, but returns a file stream with a buffer */
-/* allocated.																*/
-/****************************************************************************/
-FILE *fnopen(int *file, char *str, int access)
-{
-	char mode[128];
-	FILE *stream;
-
-if(((*file)=nopen(str,access))==-1)
-	return(NULL);
-
-if(access&O_APPEND) {
-	if(access&O_RDONLY)
-		strcpy(mode,"a+");
-	else
-		strcpy(mode,"a"); }
-else {
-	if(access&O_WRONLY)
-		strcpy(mode,"r+");
-	else
-		strcpy(mode,"r"); }
-stream=fdopen((*file),mode);
-if(stream==NULL) {
-	close(*file);
-	return(NULL); }
-setvbuf(stream,NULL,_IOFBF,16*1024);
-return(stream);
-}
-
-
-/****************************************************************************/
-/* Returns the length of the file in 'filespec'                             */
-/****************************************************************************/
-long flength(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-    return(f.ff_fsize);
-return(-1L);
-}
-
-
-/****************************************************************************/
-/* Error handling routine. Prints to local and remote screens the error     */
-/* information, function, action, object and access and then attempts to    */
-/* write the error information into the file ERROR.LOG and NODE.LOG         */
-/****************************************************************************/
-void errormsg(int line, char *source, char action, char *object, ulong access)
-{
-    char str[512];
-    char actstr[256];
-
-switch(action) {
-    case ERR_OPEN:
-        strcpy(actstr,"opening");
-        break;
-    case ERR_CLOSE:
-        strcpy(actstr,"closeing");
-        break;
-    case ERR_FDOPEN:
-        strcpy(actstr,"fdopen");
-        break;
-    case ERR_READ:
-        strcpy(actstr,"reading");
-        break;
-    case ERR_WRITE:
-        strcpy(actstr,"writing");
-        break;
-    case ERR_REMOVE:
-        strcpy(actstr,"removing");
-        break;
-    case ERR_ALLOC:
-        strcpy(actstr,"allocating memory");
-        break;
-    case ERR_CHK:
-        strcpy(actstr,"checking");
-        break;
-    case ERR_LEN:
-        strcpy(actstr,"checking length");
-        break;
-    case ERR_EXEC:
-        strcpy(actstr,"executing");
-        break;
-    default:
-        strcpy(actstr,"UNKNOWN"); }
-lprintf("\7\r\nERROR -     file: %s",source);
-lprintf("\7\r\n            line: %u",line);
-lprintf("\7\r\n          action: %s",actstr);   /* tell user about error */
-lprintf("\7\r\n          object: %s",object);
-lprintf("\7\r\n          access: %lu (%lxh)",access,access);
-lputs("\r\n\r\n<Hit any key>");
-getch();
-lputs("\r\n");
-}
-
-
-void allocfail(uint size)
-{
-lprintf("\7Error allocating %u bytes of memory.\r\n",size);
-exit(1);
-}
-
-void bail(int code)
-{
-	char str[256];
-	time_t t;
-	struct time curtime;
-	struct date date;
-
-if(!code) {
-	puttext(1,1,80,25,scrnbuf); /* restore screen if no error */
-	textattr(txtinfo.attribute);
-	gotoxy(txtinfo.curx,txtinfo.cury); }
-t=time(NULL);
-unixtodos(t,&date,&curtime);
-sprintf(str,"%02u/%02u/%u %02u:%02u:%02u    Exiting (%d)\r\n\r\n"
-	,date.da_mon,date.da_day,date.da_year
-	,curtime.ti_hour,curtime.ti_min,curtime.ti_sec
-	,code);
-write(logfile,str,strlen(str));
-exit(code);
-}
-
-int getsubnum(char *code)
-{
-	int i;
-
-for(i=0;i<total_subs;i++) {
-//	  printf("%s vs %s\n",code,sub[i]->code);
-	if(!stricmp(code,sub[i]->code))
-		return(i); }
-return(-1);
-}
-
-void uti_init(char *name, int argc, char **argv)
-{
-	char str[256],*p;
-	int i;
-	read_cfg_text_t txt;
-	time_t t;
-	struct tm *tm;
-
-setvbuf(stdout,NULL,_IONBF,0);
-putenv("TZ=UTC0");
-
-txt.openerr="\7\r\nError opening %s for read.\r\n";
-txt.reading="\r\nReading %s...";
-txt.readit="\rRead %s       ";
-txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
-txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
-
-p=getenv("SBBSNODE");
-if(p==NULL) {
-	printf("\7\nSBBSNODE environment variable not set.\n");
-	exit(1); }
-strcpy(node_dir,p);
-
-strupr(node_dir);
-
-if(node_dir[strlen(node_dir)-1]!='\\')
-	strcat(node_dir,"\\");
-
-read_node_cfg(txt);
-if(ctrl_dir[0]=='.') {   /* Relative path */
-	strcpy(str,ctrl_dir);
-	sprintf(ctrl_dir,"%s%s",node_dir,str); }
-read_main_cfg(txt);
-if(data_dir[0]=='.') {   /* Relative path */
-	strcpy(str,data_dir);
-	sprintf(data_dir,"%s%s",node_dir,str); }
-read_msgs_cfg(txt);
-sprintf(str,"%sUTI.LOG",data_dir);
-if((logfile=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("\7\nCan't open %s\n",str);
-	exit(-1); }
-t=time(NULL);
-tm=gmtime(&t);
-sprintf(str,"%02u/%02u/%02u %02u:%02u:%02u    %-8s %s \""
-	,tm->tm_mon+1,tm->tm_mday,TM_YEAR(tm->tm_year)
-	,tm->tm_hour,tm->tm_min,tm->tm_sec
-	,name,VER);
-printf("\n\n");
-for(i=1;i<argc;i++) {
-	if(i>1)
-		strcat(str," ");
-	strcat(str,argv[i]);
-	printf("%s ",argv[i]); }
-strcat(str,"\"");
-write(logfile,str,strlen(str));
-write(logfile,"\r\n",2);
-printf("\n\nWorking...");
-}
diff --git a/src/sbbs2/uti/uti.h b/src/sbbs2/uti/uti.h
deleted file mode 100644
index a5e0ba278639897aa538d59b3e99fe0b3ca2acdf..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/uti.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* UTI.H */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-extern char scrnbuf[4000];
-extern struct text_info txtinfo;
-extern int logfile;
-
-#define PREPSCREEN gettext(1,1,80,25,scrnbuf); gettextinfo(&txtinfo); \
-	textattr(LIGHTGRAY); clrscr()
-
-#define VER "2.30"
-
-void uti_init(char *name,int argc, char **argv);
diff --git a/src/sbbs2/uti/utiexprt.c b/src/sbbs2/uti/utiexprt.c
deleted file mode 100644
index a5a44daf2b38c22dceac8f15cad9da31b3c8caf3..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utiexprt.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* UTIEXPRT.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "uti.h"
-#include "post.h"
-
-char *nulstr="";
-smb_t smb;
-
-ulong loadmsgs(post_t huge **post, ulong ptr)
-{
-	int i;
-	long l=0;
-	idxrec_t idx;
-
-
-if((i=smb_locksmbhdr(&smb))!=0) {				  /* Be sure noone deletes or */
-	errormsg(WHERE,ERR_LOCK,smb.file,i);		/* adds while we're reading */
-	return(0L); }
-
-fseek(smb.sid_fp,0L,SEEK_SET);
-while(!feof(smb.sid_fp)) {
-	if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
-        break;
-
-	if(idx.number<ptr || idx.attr&MSG_DELETE)
-		continue;
-
-	if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED))
-		break;
-
-	if(((*post)=(post_t huge *)REALLOC((*post),sizeof(post_t)*(l+1)))
-        ==NULL) {
-		smb_unlocksmbhdr(&smb);
-		errormsg(WHERE,ERR_ALLOC,smb.file,sizeof(post_t)*(l+1));
-		return(l); }
-	(*post)[l].offset=idx.offset;
-	(*post)[l].number=idx.number;
-	l++; }
-smb_unlocksmbhdr(&smb);
-return(l);
-}
-
-
-int main(int argc, char **argv)
-{
-	char	str[512],*buf,ch,*outbuf;
-	ushort	xlat;
-	int 	i,file,tear,cr,net=0,lzh;
-	uint	subnum;
-	long	l,m,length,buflen;
-	ulong	msgnum,posts,exported=0;
-	FILE	*stream;
-	post_t	huge *post;
-	smbmsg_t msg;
-	struct	date date;
-	struct	time curtime;
-
-PREPSCREEN;
-
-printf("Synchronet UTIEXPRT v%s\n",VER);
-
-if(argc<3)
-	exit(1);
-
-if(argc>4 && !stricmp(argv[4],"/NETWORK"))
-	net=1;
-
-uti_init("UTIEXPRT",argc,argv);
-
-if((file=nopen(argv[3],O_CREAT|O_TRUNC|O_WRONLY))==-1)
-	bail(2);
-if((stream=fdopen(file,"wb"))==NULL)
-	bail(2);
-setvbuf(stream,0,_IOFBF,4096);
-
-subnum=getsubnum(argv[1]);
-if((int)subnum==-1)
-	bail(7);
-msgnum=atol(argv[2]);
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	bail(5); }
-
-post=NULL;
-posts=loadmsgs(&post,msgnum);
-
-printf("\nExporting\n\n");
-for(l=0;l<posts;l++) {
-	printf("\rScanning: %lu of %lu  Exported: %lu",l+1,posts,exported);
-	msg.idx.offset=post[l].offset;
-	if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-		continue; }
-	i=smb_getmsghdr(&smb,&msg);
-	if(i || msg.hdr.number!=post[l].number) {
-		smb_unlockmsghdr(&smb,&msg);
-		smb_freemsgmem(&msg);
-
-		msg.hdr.number=post[l].number;
-		if((i=smb_getmsgidx(&smb,&msg))!=0) {
-			errormsg(WHERE,ERR_READ,smb.file,i);
-			continue; }
-		if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-			errormsg(WHERE,ERR_LOCK,smb.file,i);
-			continue; }
-		if((i=smb_getmsghdr(&smb,&msg))!=0) {
-			smb_unlockmsghdr(&smb,&msg);
-			errormsg(WHERE,ERR_READ,smb.file,i);
-			continue; } }
-
-	if(net										/* Network */
-		&& (!strncmpi(msg.subj,"NE:",3)         /* No Echo */
-		|| msg.from_net.type==NET_POSTLINK)) {	/* from PostLink */
-		smb_unlockmsghdr(&smb,&msg);
-		smb_freemsgmem(&msg);
-		continue; } 					/* From a Fido node, ignore it */
-
-	if(net && !(sub[subnum]->misc&SUB_GATE) && msg.from_net.type) {
-		smb_unlockmsghdr(&smb,&msg);
-		smb_freemsgmem(&msg);
-		continue; }
-
-	exported++;
-
-	fprintf(stream,"%s\r\n%s\r\n%s\r\n"
-		,msg.to,msg.from,msg.subj);
-	unixtodos(msg.hdr.when_written.time,&date,&curtime);
-	fprintf(stream,"%lu\r\n%lu\r\n%02u/%02u/%02u\r\n%02u:%02u\r\n"
-		"%s\r\n%c\r\n%c\r\nTEXT:\r\n"
-		,msg.hdr.number
-		,msg.hdr.thread_orig
-		,date.da_mon,date.da_day,TM_YEAR(date.da_year-1900)
-		,curtime.ti_hour,curtime.ti_min
-		,msg.hdr.attr&MSG_PRIVATE ? "PRIVATE" : "PUBLIC"
-		,msg.hdr.attr&MSG_READ ? 'Y':'N'
-		,strncmpi(msg.subj,"NE:",3) ? 'Y':'N');
-
-	for(i=0;i<msg.hdr.total_dfields;i++) {
-
-		if(msg.dfield[i].type!=TEXT_BODY
-			&& msg.dfield[i].type!=TEXT_TAIL)
-			continue;					/* skip non-text data fields */
-
-		if(msg.dfield[i].length<3)		/* need at least 3 bytes */
-			continue;
-
-		fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset,SEEK_SET);
-
-		lzh=0;
-		fread(&xlat,2,1,smb.sdt_fp);
-		if(xlat==XLAT_LZH) {
-			lzh=1;
-			fread(&xlat,2,1,smb.sdt_fp); }
-		if(xlat!=XLAT_NONE) 			/* no translations supported */
-			continue;
-
-		length=msg.dfield[i].length-2;
-		if(lzh)
-			length-=2;
-
-		if((buf=MALLOC(length))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,nulstr,length);
-			continue; }
-
-		fread(buf,length,1,smb.sdt_fp);
-
-		if(lzh) {
-			buflen=*(long *)buf;
-			if((outbuf=MALLOC(buflen))==NULL) {
-				errormsg(WHERE,ERR_ALLOC,"lzh",buflen);
-				FREE(buf);
-				continue; }
-			length=lzh_decode(buf,length,outbuf);
-			FREE(buf);
-			buf=outbuf; }
-
-		tear=0;
-		for(m=0,cr=1;m<length;m++) {
-			if(buf[m]==1) { /* Ctrl-A, so skip it and the next char */
-				m++;
-				continue; }
-			if(buf[m]==0)  /* Ignore line feeds */
-				continue;
-
-			if(m+3<length && cr && buf[m]=='-' && buf[m+1]=='-'
-				&& buf[m+2]=='-' && (buf[m+3]==CR || buf[m+3]==SP))
-				tear=1;
-
-			if(buf[m]==LF)
-				cr=1;
-			else
-				cr=0;
-
-			if(sub[subnum]->misc&SUB_ASCII) {
-				if(buf[m]<SP && buf[m]!=CR) /* Ctrl ascii */
-					buf[m]='.';             /* converted to '.' */
-				if((uchar)buf[m]>0x7f)		/* extended ASCII */
-					buf[m]='*'; }           /* converted to '*' */
-			fputc(buf[m],stream); }
-		fprintf(stream,"\r\n");
-		FREE(buf); }
-
-	if(!(sub[subnum]->misc&SUB_NOTAG)) {
-		if(!tear)	/* No previous tear line */
-			fprintf(stream,"---\r\n");            /* so add one */
-		if(sub[subnum]->misc&SUB_ASCII) ch='*';
-		else ch='�';
-		fprintf(stream," %c Synchronet UTI v%s\r\n",ch,VER); }
-
-	fprintf(stream,"\xff\r\n");
-	smb_unlockmsghdr(&smb,&msg);
-	smb_freemsgmem(&msg); }
-
-sprintf(str,"%20s Scanned %lu, Exported %lu\r\n"
-	,"",posts,exported);
-write(logfile,str,strlen(str));
-printf("\nDone.\n");
-smb_close(&smb);
-FREE(post);
-bail(0);
-return(0);
-}
diff --git a/src/sbbs2/uti/utihigh.c b/src/sbbs2/uti/utihigh.c
deleted file mode 100644
index 49e29ebca02622547828caf4e0127c657c11ed28..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utihigh.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* UTIHIGH.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "uti.h"
-
-smb_t smb;
-
-/****************************************************************************/
-/* Returns the total number of msgs in the sub-board and sets 'ptr' to the  */
-/* number of the last message in the sub (0) if no messages.                */
-/****************************************************************************/
-ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
-{
-    char        str[256];
-    int         i;
-    ulong       total;
-    idxrec_t    idx;
-
-if(ptr)
-    (*ptr)=0;
-if(t)
-    (*t)=0;
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-    return(0); }
-
-if(!filelength(fileno(smb.sid_fp))) {			/* Empty base */
-	smb_close(&smb);
-    return(0); }
-if((i=smb_locksmbhdr(&smb))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_LOCK,smb.file,i);
-    return(0); }
-if((i=smb_getlastidx(&smb,&idx))!=0) {
-	smb_close(&smb);
-	errormsg(WHERE,ERR_READ,smb.file,i);
-    return(0); }
-total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
-smb_unlocksmbhdr(&smb);
-smb_close(&smb);
-if(ptr)
-    (*ptr)=idx.number;
-if(t)
-    (*t)=idx.time;
-return(total);
-}
-
-
-int main(int argc, char **argv)
-{
-	char str[256];
-	int file,subnum,i;
-	ulong ptr;
-
-PREPSCREEN;
-
-printf("Synchronet UTIHIGH v%s\n",VER);
-
-
-if(argc<3)
-	exit(1);
-
-uti_init("UTIHIGH",argc,argv);
-
-subnum=getsubnum(argv[1]);
-if((int)subnum==-1)
-	bail(7);
-getlastmsg(subnum,&ptr,0);
-
-if((file=nopen(argv[2],O_CREAT|O_TRUNC|O_WRONLY))==-1)
-	bail(2);
-
-sprintf(str,"%lu",ptr);
-write(file,str,strlen(str));
-close(file);
-sprintf(str,"%20s Last message #%lu\r\n","",ptr);
-write(logfile,str,strlen(str));
-printf("\nDone.\n");
-bail(0);
-return(0);
-}
diff --git a/src/sbbs2/uti/utiimprt.c b/src/sbbs2/uti/utiimprt.c
deleted file mode 100644
index acfac0697e964cdb5202401fe9172d69a296378b..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utiimprt.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* UTIIMPRT.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "uti.h"
-#include "crc32.h"
-
-smb_t smb;
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-#define PRIVATE 0
-#define PUBLIC	1
-
-#define DEBUG 0
-
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-
-void remove_re(char *str)
-{
-while(!strnicmp(str,"RE:",3)) {
-	strcpy(str,str+3);
-	while(str[0]==SP)
-		strcpy(str,str+1); }
-}
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	struct time curtime;
-	struct date date;
-
-#if DEBUG
-printf("\rdstrtounix           ");
-#endif
-
-curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-date.da_year=((str[6]&0xf)*10)+(str[7]&0xf);
-if(date.da_year<Y2K_2DIGIT_WINDOW)
-	date.da_year+=100;
-date.da_year+=1900;
-date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-date.da_day=((str[3]&0xf)*10)+(str[4]&0xf);
-return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/* Called from upload                                                       */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* This function reads files that are potentially larger than 32k.  		*/
-/* Up to one megabyte of data can be read with each call.                   */
-/****************************************************************************/
-long lread(int file, char huge *buf,long bytes)
-{
-	long count;
-
-for(count=bytes;count>32767;count-=32767,buf+=32767)
-	if(read(file,(char *)buf,32767)!=32767)
-		return(-1L);
-if(read(file,(char *)buf,(int)count)!=count)
-	return(-1L);
-return(bytes);
-}
-
-
-int main(int argc, char **argv)
-{
-	char	str[256],to[256],from[256],title[256],*p,*buf,*outbuf;
-	ushort	xlat,net=0;
-	int 	i,j,file,lzh,storage;
-	uint	subnum,imported=0;
-	ulong	l,length,lzhlen,offset,crc;
-	FILE	*stream;
-	smbmsg_t	msg;
-	smbstatus_t status;
-
-PREPSCREEN;
-
-printf("Synchronet UTIIMPRT v%s\n",VER);
-
-if(argc<3)
-	exit(1);
-
-if((argc>3 && !stricmp(argv[3],"/NETWORK"))
-	|| (argc>4 && !stricmp(argv[4],"/NETWORK")))
-	net=NET_POSTLINK;
-
-uti_init("UTIIMPRT",argc,argv);
-
-if((file=nopen(argv[2],O_RDONLY))==-1)
-	bail(2);
-if((stream=fdopen(file,"rb"))==NULL)
-	bail(2);
-
-subnum=getsubnum(argv[1]);
-if((int)subnum==-1)
-	bail(7);
-
-sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
-smb.retry_time=30;
-if((i=smb_open(&smb))!=0) {
-	errormsg(WHERE,ERR_OPEN,smb.file,i);
-	bail(5); }
-
-if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
-	smb.status.max_crcs=sub[subnum]->maxcrcs;
-	smb.status.max_msgs=sub[subnum]->maxmsgs;
-	smb.status.max_age=sub[subnum]->maxage;
-	smb.status.attr=sub[subnum]->misc&SUB_HYPER ? SMB_HYPERALLOC : 0;
-	if((i=smb_create(&smb))!=0) {
-		errormsg(WHERE,ERR_CREATE,smb.file,i);
-		bail(5); } }
-
-printf("\r\nImporting ");
-
-while(!feof(stream) && !ferror(stream)) {
-	memset(&msg,0,sizeof(smbmsg_t));
-	memcpy(msg.hdr.id,"SHD\x1a",4);
-	msg.hdr.version=SMB_VERSION;
-	msg.hdr.when_imported.time=time(NULL);
-	msg.hdr.when_imported.zone=sys_timezone;
-	if(sub[subnum]->misc&SUB_AONLY)
-		msg.hdr.attr|=MSG_ANONYMOUS;
-
-	if(!fgets(to,250,stream))
-		break;
-	if(!fgets(from,250,stream))
-		break;
-	if(!fgets(title,250,stream))
-		break;
-	imported++;
-	printf("%-5u\b\b\b\b\b",imported);
-	truncsp(to);
-	truncsp(from);
-	truncsp(title);
-
-	smb_hfield(&msg,RECIPIENT,strlen(to),to);
-	strlwr(to);
-	msg.idx.to=crc16(to);
-
-	smb_hfield(&msg,SENDER,strlen(from),from);
-	strlwr(from);
-	msg.idx.from=crc16(from);
-
-	if(net)
-		i=smb_hfield(&msg,SENDERNETTYPE,2,&net);
-
-	i=smb_hfield(&msg,SUBJECT,strlen(title),title);
-	strlwr(title);
-	remove_re(title);
-	msg.idx.subj=crc16(title);
-
-	fgets(str,128,stream);	 /* skip msg # */
-	fgets(str,128,stream);	 /* ref # */
-	msg.hdr.thread_orig=atol(str);
-	fgets(str,128,stream);	 /* date */
-	msg.hdr.when_written.time=dstrtounix(str);
-	fgets(str,128,stream);	 /* time */
-	msg.hdr.when_written.time+=atoi(str)*60*60;  /* hours */
-	p=strchr(str,':');
-	if(p)
-		msg.hdr.when_written.time+=atoi(p+1)*60; /* mins */
-	fgets(str,128,stream);	 /* private/public */
-	if(!stricmp(str,"PRIVATE"))
-		msg.hdr.attr|=MSG_PRIVATE;
-	fgets(str,128,stream);	 /* Read? Y/N */
-	if(toupper(str[0])=='Y')
-		msg.hdr.attr|=MSG_READ;
-	fgets(str,128,stream);	 /* Net? Y/N - ignore */
-	if(toupper(str[0])=='Y')
-		msg.hdr.netattr|=MSG_TYPELOCAL;
-	while(!feof(stream) && !ferror(stream)) {
-		fgets(str,128,stream);
-		if(!strcmp(str,"TEXT:\r\n"))
-			break; }
-
-	buf=NULL;
-	length=0;
-	crc=0xffffffff;
-	while(!feof(stream) && !ferror(stream)) {
-		fgets(str,128,stream);
-		if(!strcmp(str,"\xff\r\n"))     /* end of text */
-			break;
-		j=strlen(str);
-		if((buf=REALLOC(buf,length+j+1))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,argv[1],length+j+1);
-			bail(3); }
-		if(sub[subnum]->maxcrcs) {
-			for(i=0;i<j;i++)
-				crc=ucrc32(str[i],crc); }
-		strcpy(buf+length,str);
-		length+=strlen(str); }
-	crc=~crc;
-
-	if((i=smb_locksmbhdr(&smb))!=0) {
-		errormsg(WHERE,ERR_LOCK,smb.file,i);
-		bail(11); }
-
-	if((i=smb_getstatus(&smb))!=0) {
-		errormsg(WHERE,ERR_READ,smb.file,i);
-		bail(12); }
-
-	if(sub[subnum]->maxcrcs) {
-		i=smb_addcrc(&smb,crc);
-		if(i) {
-			printf("\nDuplicate message!\n");
-			FREE(buf);
-			smb_unlocksmbhdr(&smb);
-			smb_freemsgmem(&msg);
-			continue; } }
-
-	if(length>=2 && buf[length-1]==LF && buf[length-2]==CR)
-		length-=2;
-	if(length>=2 && buf[length-1]==LF && buf[length-2]==CR)
-        length-=2;
-
-	lzh=0;
-	if(sub[subnum]->misc&SUB_LZH && length+2>=SDT_BLOCK_LEN) {
-		if((outbuf=(char *)MALLOC(length*2))==NULL) {
-			errormsg(WHERE,ERR_ALLOC,"lzh",length*2);
-			smb_unlocksmbhdr(&smb);
-			smb_freemsgmem(&msg);
-			bail(3); }
-		lzhlen=lzh_encode(buf,length,outbuf);
-		if(lzhlen>1
-			&& smb_datblocks(lzhlen+4)
-				<smb_datblocks(length+2)) { /* Compressable */
-			length=lzhlen+2;
-			FREE(buf);
-			lzh=1;
-			buf=outbuf; }
-		else				/* Uncompressable */
-			FREE(outbuf); }
-
-	length+=2;						/* for translation string */
-
-	if(status.attr&SMB_HYPERALLOC) {
-		offset=smb_hallocdat(&smb);
-		storage=SMB_HYPERALLOC; }
-	else {
-		if((i=smb_open_da(&smb))!=0) {
-			errormsg(WHERE,ERR_OPEN,smb.file,i);
-			bail(5); }
-		if(sub[subnum]->misc&SUB_FAST) {
-			offset=smb_fallocdat(&smb,length,1);
-			storage=SMB_FASTALLOC; }
-		else {
-			offset=smb_allocdat(&smb,length,1);
-			storage=SMB_SELFPACK; }
-		fclose(smb.sda_fp); }
-
-	msg.hdr.offset=offset;
-
-	smb_dfield(&msg,TEXT_BODY,length);
-
-	fseek(smb.sdt_fp,offset,SEEK_SET);
-	if(lzh) {
-		xlat=XLAT_LZH;
-		fwrite(&xlat,2,1,smb.sdt_fp); }
-	xlat=XLAT_NONE;
-	fwrite(&xlat,2,1,smb.sdt_fp);
-	j=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
-	if(lzh)
-		j-=2;
-	l=0;
-	length-=2;
-	if(lzh)
-		length-=2;
-	while(l<length) {
-		if(l+j>length)
-			j=length-l;
-		fwrite(buf+l,j,1,smb.sdt_fp);
-		l+=j;
-		j=SDT_BLOCK_LEN; }
-	fflush(smb.sdt_fp);
-	FREE(buf);
-	smb_unlocksmbhdr(&smb);
-	smb_addmsghdr(&smb,&msg,storage);
-	smb_freemsgmem(&msg); }
-
-sprintf(str,"%20s Imported %u\r\n","",imported);
-write(logfile,str,strlen(str));
-printf("\nDone.\n");
-bail(0);
-return(0);
-}
-
diff --git a/src/sbbs2/uti/utilist.c b/src/sbbs2/uti/utilist.c
deleted file mode 100644
index a880ba429be49c1b1fa77dcdf4f8e567cee0ae45..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utilist.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* UTILIST.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "uti.h"
-
-int main(int argc, char **argv)
-{
-	char str[256];
-	int i,j,file;
-
-PREPSCREEN;
-
-printf("Synchronet UTILIST v%s\n",VER);
-
-if(argc<2)
-	exit(1);
-
-uti_init("UTILIST",argc,argv);
-
-if((file=nopen(argv[1],O_CREAT|O_TRUNC|O_WRONLY))==-1)
-    exit(2);
-
-for(j=0;j<total_grps;j++)
-	for(i=0;i<total_subs;i++) {
-		if(sub[i]->grp!=j)
-			continue;
-		sprintf(str,"%s\r\n%s\r\n",sub[i]->code,sub[i]->code);
-		write(file,str,strlen(str));
-		sprintf(str,"%s\r\n",sub[i]->lname);
-		write(file,str,strlen(str)); }
-close(file);
-printf("\nDone.\n");
-bail(0);
-return(0);
-}
diff --git a/src/sbbs2/uti/utilstrd.c b/src/sbbs2/uti/utilstrd.c
deleted file mode 100644
index 1c8bf05222ef44b2beeb8adec86e773b358fd855..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utilstrd.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* UTILSTRD.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-#include "uti.h"
-
-#define READ	1
-#define WRITE	2
-
-int main(int argc, char **argv)
-{
-	char	*p,str[256],name[256],mode=0;
-	int 	i,file;
-	uint	usernumber;
-	time_t	ptr;
-	FILE	*stream;
-
-PREPSCREEN;
-
-printf("Synchronet UTILSTRD v%s\n",VER);
-
-if(argc<4)
-	exit(1);
-
-if(!stricmp(argv[1],"READ"))
-    mode=READ;
-else if(!stricmp(argv[1],"WRITE"))
-    mode=WRITE;
-if(!mode)
-    exit(1);
-
-uti_init("UTILSTRD",argc,argv);
-
-if(mode==READ) {
-	if((file=nopen(argv[2],O_CREAT|O_TRUNC|O_WRONLY))==-1)
-		exit(2); }
-else {
-	if((file=nopen(argv[2],O_RDONLY))==-1)
-		exit(2); }
-
-if((stream=fdopen(file,"wb"))==NULL)
-	exit(2);
-
-
-strcpy(name,argv[3]);		/* build the user name */
-for(i=4;i<argc;i++) {
-	strcat(name," ");
-	strcat(name,argv[i]); }
-
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if((file=nopen(str,O_RDONLY))==-1)
-	exit(8);
-
-usernumber=1;
-while(!eof(file)) {
-	read(file,str,LEN_ALIAS+2);
-	str[25]=0;
-	p=strchr(str,3);
-	if(p) *p=0;
-	if(!stricmp(str,name))
-		break;
-	usernumber++; }
-if(stricmp(str,name)) {
-	printf("Username '%s' not found.\n",name);
-	exit(9); }
-close(file);
-
-sprintf(str,"%sUSER\\PTRS\\%4.4u.IXB",data_dir,usernumber);
-if((file=nopen(str,mode==READ ? O_RDONLY : O_WRONLY|O_CREAT))==-1)
-	exit(10);
-for(i=0;i<total_subs;i++) {
-	lseek(file,((long)sub[i]->ptridx)*10L,SEEK_SET);
-	if(mode==READ) {
-		read(file,&ptr,4);
-		fprintf(stream,"%lu\r\n",ptr); }
-	else {
-		fgets(str,81,stream);
-		ptr=atol(str);
-		write(file,&ptr,4); } }
-close(file);
-printf("\nDone.\n");
-bail(0);
-return(0);
-}
-
diff --git a/src/sbbs2/uti/utiver.c b/src/sbbs2/uti/utiver.c
deleted file mode 100644
index 6f0111f25b01c53b7a22f8338eeec5e21ed1839a..0000000000000000000000000000000000000000
--- a/src/sbbs2/uti/utiver.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* UTIVER.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <stdio.h>
-#include <conio.h>
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include "uti.h"
-
-int main(int argc, char **argv)
-{
-	char str[1024];
-	int file;
-
-sprintf(str,"2\r\nSynchronet UTI Driver v%s - "
-			"Developed 1995-1997 Rob Swindell\r\n",VER);
-if(argc<2)
-	exit(1);
-if((file=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,S_IWRITE))==-1)
-	exit(2);
-write(file,str,strlen(str));
-close(file);
-return(0);
-}
diff --git a/src/sbbs2/vars.c b/src/sbbs2/vars.c
deleted file mode 100644
index 5fb3e2bc222b0c26f5d0c2309341b366c98dafef..0000000000000000000000000000000000000000
--- a/src/sbbs2/vars.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* VARS.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*************************************************************/
-/* External (Global/Public) Variables for use only with SBBS */
-/*************************************************************/
-
-#include <stdio.h>
-#include <dos.h>
-
-#ifndef GLOBAL
-#define GLOBAL
-unsigned _stklen=22000; 			/* Set stack size in code, not header */
-									/* 20k, NOT enough */
-#endif
-
-#include "sbbsdefs.h"
-#include "smbdefs.h"
-#include "text.h"
-
-GLOBAL char 	*envp[128]; 	/* Original environment */
-
-GLOBAL char 	menu_dir[128];	/* Over-ride default menu dir */
-GLOBAL char 	menu_file[128]; /* Over-ride menu file */
-
-GLOBAL user_t	useron; 		/* User currently online */
-GLOBAL node_t	thisnode;		/* Node information */
-GLOBAL smb_t	smb;			/* Currently open message base */
-
-								/* Batch download queue */
-GLOBAL char 	**batdn_name;	/* Filenames */
-GLOBAL ushort	*batdn_alt; 	/* Alternate path */
-GLOBAL uint 	*batdn_dir, 	/* Directory for each file */
-				batdn_total;	/* Total files */
-GLOBAL long 	*batdn_offset;	/* Offset for data */
-GLOBAL ulong	*batdn_size;	/* Size of file in bytes */
-GLOBAL ulong	*batdn_cdt; 	/* Credit value of file */
-
-								/* Batch upload queue */
-GLOBAL char 	**batup_desc,	/* Description for each file */
-				**batup_name,	/* Filenames */
-				*batup_misc;	/* Miscellaneous bits */
-GLOBAL ushort	*batup_alt; 	/* Alternate path */
-GLOBAL uint 	*batup_dir, 	/* Directory for each file */
-				batup_total;	/* Total files */
-
-/*********************************/
-/* Color Configuration Variables */
-/*********************************/
-GLOBAL char 	*text[TOTAL_TEXT];			/* Text from CTRL\TEXT.DAT */
-GLOBAL char 	*text_sav[TOTAL_TEXT];		/* Text from CTRL\TEXT.DAT */
-GLOBAL int		directvideo;	/* Turbo C's video flag - direct or bios */
-GLOBAL char 	qoc;			/* Quit after one caller */
-GLOBAL long 	freedosmem; 	/* Amount of free DOS memory */
-GLOBAL char 	orgcmd[129];	/* Original command to execute bbs */
-GLOBAL char 	dszlog[127];	/* DSZLOG enviornment variable */
-GLOBAL char 	debug;			/* Flag to allow debug writes */
-GLOBAL int		keybuftop,keybufbot;	/* Keyboard input buffer pointers */
-GLOBAL char 	keybuf[KEY_BUFSIZE];	/* Keyboard input buffer */
-GLOBAL char 	connection[LEN_MODEM+1];/* Connection Description */
-GLOBAL ulong	cur_rate;		/* Current Connection (DCE) Rate */
-GLOBAL ulong	cur_cps;		/* Current Average Transfer CPS */
-GLOBAL ulong	dte_rate;		/* Current COM Port (DTE) Rate */
-GLOBAL time_t 	timeout;		/* User inactivity timeout reference */
-GLOBAL char 	timeleft_warn;	/* low timeleft warning flag */
-GLOBAL char 	curatr; 		/* Current Text Attributes Always */
-GLOBAL long 	lncntr; 		/* Line Counter - for PAUSE */
-GLOBAL long 	tos;			/* Top of Screen */
-GLOBAL long 	rows;			/* Current Rows for User */
-GLOBAL long 	autoterm;		/* Autodetected terminal type */
-GLOBAL char 	slbuf[SAVE_LINES][LINE_BUFSIZE+1]; /* Saved for redisplay */
-GLOBAL char 	slatr[SAVE_LINES];	/* Starting attribute of each line */
-GLOBAL char 	slcnt;			/* Number of lines currently saved */
-GLOBAL char 	lbuf[LINE_BUFSIZE+1];/* Temp storage for each line output */
-GLOBAL int		lbuflen;		/* Number of characters in line buffer */
-GLOBAL char 	latr;			/* Starting attribute of line buffer */
-GLOBAL ulong	console;		/* Defines current Console settings */
-GLOBAL char 	tmp[256];		/* Used all over as temp string */
-GLOBAL char 	*nulstr;		/* Null string pointer */
-GLOBAL char 	*crlf;			/* CRLF string pointer */
-GLOBAL char 	wordwrap[81];	/* Word wrap buffer */
-GLOBAL time_t	now,			/* Used to store current time in Unix format */
-				answertime, 	/* Time call was answered */
-				logontime,		/* Time user logged on */
-				starttime,		/* Time stamp to use for time left calcs */
-				ns_time,		/* File new-scan time */
-				last_ns_time;	/* Most recent new-file-scan this call */
-GLOBAL uchar 	action;			/* Current action of user */
-GLOBAL char 	statline;		/* Current Status Line number */
-GLOBAL long 	online; 		/* Remote/Local or not online */
-GLOBAL long 	sys_status; 	/* System Status */
-GLOBAL char 	*sub_misc;		/* Save misc and ptrs for subs */
-GLOBAL ulong	*sub_ptr;		/* for fast pointer update */
-GLOBAL ulong	*sub_last;		/* last read message pointer */
-
-GLOBAL ulong	logon_ulb,		/* Upload Bytes This Call */
-				logon_dlb,		/* Download Bytes This Call */
-				logon_uls,		/* Uploads This Call */
-				logon_dls,		/* Downloads This Call */
-				logon_posts,	/* Posts This Call */
-				logon_emails,	/* Emails This Call */
-				logon_fbacks;	/* Feedbacks This Call */
-GLOBAL uchar	logon_ml;		/* ML of the user apon logon */
-
-GLOBAL int 		node_disk;		/* Number of Node's disk */
-GLOBAL uint 	main_cmds;		/* Number of Main Commands this call */
-GLOBAL uint 	xfer_cmds;		/* Number of Xfer Commands this call */
-GLOBAL ulong	posts_read; 	/* Number of Posts read this call */
-GLOBAL char 	temp_uler[31];  /* User who uploaded the files to temp dir */
-GLOBAL char 	temp_file[41];	/* Origin of extracted temp files */
-GLOBAL long 	temp_cdt;		/* Credit value of file that was extracted */
-GLOBAL char 	autohang;		/* Used for auto-hangup after transfer */
-GLOBAL char 	cap_fname[41];	/* Capture filename - default is CAPTURE.TXT */
-GLOBAL FILE 	*capfile;		/* File string to use for capture file */
-GLOBAL int 		inputfile;		/* File handle to use for input */
-GLOBAL int 		logfile; 		/* File handle for node.log */
-GLOBAL int 		nodefile;		/* File handle for node.dab */
-GLOBAL int		node_ext;		/* File handle for node.exb */
-GLOBAL char 	logcol; 		/* Current column of log file */
-GLOBAL uint 	criterrs; 		/* Critical error counter */
-GLOBAL struct date date;		/* Used for DOS compatible date pointer */
-GLOBAL struct time curtime; 	/* Used for DOS compatible time pointer */
-
-GLOBAL uint 	curgrp, 		/* Current group */
-				*cursub,		/* Current sub-board for each group */
-				curlib, 		/* Current library */
-				*curdir;		/* Current directory for each library */
-GLOBAL uint 	*usrgrp,		/* Real group numbers */
-				usrgrps;		/* Number groups this user has access to */
-GLOBAL uint 	*usrlib,		/* Real library numbers */
-				usrlibs;		/* Number of libs this user can access */
-GLOBAL uint 	**usrsub,		/* Real sub numbers */
-				*usrsubs;		/* Num of subs with access for each grp */
-GLOBAL uint 	**usrdir,		/* Real dir numbers */
-				*usrdirs;		/* Num of dirs with access for each lib */
-GLOBAL int		cursubnum;		/* For ARS */
-GLOBAL int		curdirnum;		/* For ARS */
-GLOBAL long 	timeleft;		/* Number of seconds user has left online */
-GLOBAL uchar	sbbsnode[81];	/* Environment var to contain node dir path */
-GLOBAL uchar	sbbsnnum[81];	/* Environment var to contain node num */
-GLOBAL char 	*comspec;		/* Pointer to environment variable COMSPEC */
-GLOBAL ushort	altul;			/* Upload to alternate path flag */
-GLOBAL uint 	inDV;			/* DESQview version, or 0 if not under DV */
-GLOBAL uchar	lastnodemsg;	/* Number of node last message was sent to */
-GLOBAL char 	color[TOTAL_COLORS];	/* Different colors for the BBS */
-GLOBAL time_t	next_event; 	/* Next event time - from front-end */
-GLOBAL char 	lastuseron[LEN_ALIAS+1];  /* Name of user last online */
-GLOBAL char 	cid[LEN_CID+1]; /* Caller ID of current caller */
-GLOBAL uint 	emshandle;		/* EMS handle for overlay swap */
-GLOBAL char 	emsver; 		/* Version of EMS installed */
-GLOBAL char 	*noaccess_str;	/* Why access was denied via ARS */
-GLOBAL long 	noaccess_val;	/* Value of parameter not met in ARS */
-GLOBAL int		errorlevel; 	/* Error level of external program */
diff --git a/src/sbbs2/ver.c b/src/sbbs2/ver.c
deleted file mode 100644
index caac3f66c7d47b8ea712c53adc6b973ae523c2c3..0000000000000000000000000000000000000000
--- a/src/sbbs2/ver.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* VER.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include <dos.h>
-#include "sbbs.h"
-#include "riolib.h"
-#include "riodefs.h"
-#include "etext.h"
-
-extern uint inDV;
-extern uint asmrev;
-extern uint emshandle;
-extern char emsver;
-
-char *compile_time=__TIME__,*compile_date=__DATE__;
-
-char *decrypt(ulong [], char *str);
-
-void ver()
-{
-	char str[128],tmp[128];
-	int i;
-
-i=rioctl(FIFOCTL);
-CRLF;
-#if defined(__OS2__)
-strcpy(str,decrypt(VersionNoticeOS2,0));
-#elif defined(__WIN32__)
-strcpy(str,decrypt(VersionNoticeW32,0));
-#else
-strcpy(str,decrypt(VersionNoticeDOS,0));
-#endif
-center(str);
-CRLF;
-
-sprintf(str,"Revision %c%s %s %.5s  "
-#ifdef __FLAT__
-	"RIOLIB %u.%02u"
-#else
-	"RCIOL %u"
-#endif
-	"  SMBLIB %s  BCC %X.%02X"
-	,REVISION,BETA,compile_date,compile_time
-#ifdef __FLAT__
-	,rioctl(GVERS)/100,rioctl(GVERS)%100
-#else
-	,rioctl(GVERS)
-#endif
-	,smb_lib_ver()
-	,__BORLANDC__>>8
-	,__BORLANDC__&0xff);
-center(str);
-CRLF;
-
-center(decrypt(CopyrightAddress,0));
-CRLF;
-
-#if defined(__OS2__)
-
-sprintf(str,"OS/2 %u.%u (%u.%u)",_osmajor/10,_osminor/10,_osmajor,_osminor);
-
-#elif defined(__WIN32__)
-
-sprintf(str,"Win32 %u.%02u",_osmajor,_osminor);
-
-#else	/* DOS */
-
-sprintf(str,"DOS %u.%02u",_osmajor,_osminor);
-if(inDV) {
-	sprintf(tmp,"   DESQview %u.%02u",inDV>>8,inDV&0xff);
-	strcat(str,tmp); }
-if(emsver) {
-	sprintf(tmp,"   EMS %u.%u",(emsver&0xf0)>>4,emsver&0xf);
-	strcat(str,tmp);
-    if(emshandle!=0xffff)
-		strcat(str," (overlay)"); }
-
-#endif
-
-if(i&0xc0) {
-	strcat(str,"   16550 UART");
-	if(i&0xc)
-		strcat(str," FIFO"); }
-#if DEBUG
-	i=open("NODE.CFG",0);
-	bprintf("   Files (%d)",i);
-	close(i);
-#endif
-center(str);
-}
diff --git a/src/sbbs2/viewfile.c b/src/sbbs2/viewfile.c
deleted file mode 100644
index 24c234f674f442cb87b9686ccdfcee683dc4d02a..0000000000000000000000000000000000000000
--- a/src/sbbs2/viewfile.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#line 1 "VIEWFILE.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-void viewfilecontents(file_t f)
-{
-	char str[128],cmd[128];
-	int i;
-
-if(f.size<=0L) {
-	bputs(text[FileNotThere]);
-	return; }
-
-sprintf(str,"%s%s",f.altpath > 0 && f.altpath<=altpaths
-	? altpath[f.altpath-1] : dir[f.dir]->path
-	,unpadfname(f.name,tmp));
-strcpy(tmp,f.name);
-truncsp(tmp);
-for(i=0;i<total_fviews;i++) {
-	if(!stricmp(tmp+9,fview[i]->ext)
-		&& chk_ar(fview[i]->ar,useron)) {
-		strcpy(cmd,fview[i]->cmd);
-		break; } }
-if(i==total_fviews)
-	bprintf(text[NonviewableFile],tmp+9);
-else
-	if((i=external(cmdstr(cmd,str,str,NULL)
-		,EX_OUTL|EX_OUTR|EX_INR|EX_CC))!=0)
-		errormsg(WHERE,ERR_EXEC,cmdstr(cmd,str,str,NULL),i);
-}
-
-/****************************************************************************/
-/* Views file with:                                                         */
-/* (B)atch download, (V)iew file (E)xtended info, (Q)uit, or [Next]:        */
-/* call with ext=1 for default to extended info, or 0 for file view         */
-/* Returns -1 for Batch, 1 for Next, or 0 for Quit                          */
-/****************************************************************************/
-int viewfile(file_t f, int ext)
-{
-	char ch,str[256];
-    int i;
-
-curdirnum=f.dir;	/* for ARS */
-while(online) {
-    if(ext)
-        fileinfo(f);
-	else
-		viewfilecontents(f);
-    ASYNC;
-    CRLF;
-    sprintf(str,text[FileInfoPrompt],unpadfname(f.name,tmp));
-    mnemonics(str);
-    ch=getkeys("BEVQ\r",0);
-    if(ch=='Q' || sys_status&SS_ABORT)
-        return(0);
-    switch(ch) {
-        case 'B':
-            addtobatdl(f);
-            CRLF;
-            return(-1);
-        case 'E':
-            ext=1;
-            continue;
-        case 'V':
-            ext=0;
-            continue;
-        case CR:
-            return(1); } }
-return(0);
-}
-
diff --git a/src/sbbs2/xfer_hi.c b/src/sbbs2/xfer_hi.c
deleted file mode 100644
index 78e8f36bc7114b5f280b4f1b09aa8343c3a108f8..0000000000000000000000000000000000000000
--- a/src/sbbs2/xfer_hi.c
+++ /dev/null
@@ -1,1516 +0,0 @@
-#line 1 "XFER_HI.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-uint temp_dirnum;
-
-/****************************************************************************/
-/* Uploads files                                                            */
-/****************************************************************************/
-void upload(uint dirnum)
-{
-    static char lastdesc[59];
-	uchar str[256],src[256]={""},descbeg[25]={""},descend[25]={""},path[256]
-        ,fname[13],keys[256],ch,*p;
-    time_t start,end;
-    int i,j,file,destuser[MAX_USERXFER],destusers=0;
-	uint k;
-    file_t f;
-    struct dfree d;
-    user_t user;
-    node_t node;
-
-if(sys_status&SS_EVENT && online==ON_REMOTE && !dir_op(dirnum))
-    bprintf(text[UploadBeforeEvent],timeleft/60);
-if(altul)
-    strcpy(path,altpath[altul-1]);
-else
-    strcpy(path,dir[dirnum]->path);
-if(path[1]==':')
-    i=path[0]-'A'+1;
-else i=0;
-getdfree(i,&d);
-if(d.df_sclus==0xffff)
-    errormsg(WHERE,ERR_CHK,path,0);
-if((ulong)d.df_bsec*(ulong)d.df_sclus
-    *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
-    bputs(text[LowDiskSpace]);
-    sprintf(str,"Diskspace is low: %s",path);
-    errorlog(str);
-	if(!dir_op(dirnum))
-        return; }
-bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
-    *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
-f.dir=curdirnum=dirnum;
-f.misc=0;
-f.altpath=altul;
-bputs(text[Filename]);
-if(!getstr(fname,12,K_UPPER) || strchr(fname,'?') || strchr(fname,'*')
-	|| !checkfname(fname) || (trashcan(fname,"FILE") && !dir_op(dirnum))) {
-	if(fname[0])
-		bputs(text[BadFilename]);
-	return; }
-if(dirnum==sysop_dir)
-    sprintf(str,text[UploadToSysopDirQ],fname);
-else if(dirnum==user_dir)
-    sprintf(str,text[UploadToUserDirQ],fname);
-else
-    sprintf(str,text[UploadToCurDirQ],fname,lib[dir[dirnum]->lib]->sname
-        ,dir[dirnum]->sname);
-if(!yesno(str)) return;
-action=NODE_ULNG;
-padfname(fname,f.name);
-sprintf(str,"%s%s",path,fname);
-if(fexist(str)) {   /* File is on disk */
-	if(!dir_op(dirnum) && online!=ON_LOCAL) {		 /* local users or sysops */
-        bprintf(text[FileAlreadyThere],fname);
-        return; }
-    if(!yesno(text[FileOnDiskAddQ]))
-        return; }
-else if(online==ON_LOCAL) {
-    bputs(text[FileNotOnDisk]);
-    bputs(text[EnterPath]);
-    if(!getstr(tmp,60,K_LINE|K_UPPER))
-        return;
-    backslash(tmp);
-    sprintf(src,"%s%s",tmp,fname); }
-strcpy(str,dir[dirnum]->exts);
-strcpy(tmp,f.name);
-truncsp(tmp);
-j=strlen(str);
-for(i=0;i<j;i+=ch+1) { /* Check extension of upload with allowable exts */
-    p=strchr(str+i,',');
-    if(p!=NULL)
-        *p=0;
-    ch=strlen(str+i);
-    if(!strcmp(tmp+9,str+i))
-        break; }
-if(j && i>=j) {
-    bputs(text[TheseFileExtsOnly]);
-    bputs(dir[dirnum]->exts);
-    CRLF;
-	if(!dir_op(dirnum)) return; }
-bputs(text[SearchingForDupes]);
-for(i=k=0;i<usrlibs;i++)
-	for(j=0;j<usrdirs[i];j++,k++) {
-		outchar('.');
-		if(k && !(k%5))
-			bputs("\b\b\b\b\b     \b\b\b\b\b");
-		if((usrdir[i][j]==dirnum || dir[usrdir[i][j]]->misc&DIR_DUPES)
-			&& findfile(usrdir[i][j],f.name)) {
-            bputs(text[SearchedForDupes]);
-			bprintf(text[FileAlreadyOnline],f.name);
-			if(!dir_op(dirnum))
-				return; 	 /* File is in database for another dir */
-			if(usrdir[i][j]==dirnum)
-				return; } } /* don't allow duplicates */
-bputs(text[SearchedForDupes]);
-if(dirnum==user_dir) {  /* User to User transfer */
-    bputs(text[EnterAfterLastDestUser]);
-	while((!dir_op(dirnum) && destusers<max_userxfer) || destusers<MAX_USERXFER) {
-        bputs(text[SendFileToUser]);
-		if(!getstr(str,LEN_ALIAS,K_UPRLWR))
-            break;
-        if((user.number=finduser(str))!=0) {
-			if(!dir_op(dirnum) && user.number==useron.number) {
-                bputs(text[CantSendYourselfFiles]);
-                continue; }
-            for(i=0;i<destusers;i++)
-                if(user.number==destuser[i])
-                    break;
-            if(i<destusers) {
-                bputs(text[DuplicateUser]);
-                continue; }
-            getuserdat(&user);
-            if((user.rest&(FLAG('T')|FLAG('D')))
-                || !chk_ar(lib[dir[user_dir]->lib]->ar,user)
-                || !chk_ar(dir[user_dir]->dl_ar,user)) {
-                bprintf(text[UserWontBeAbleToDl],user.alias); }
-            else {
-                bprintf(text[UserAddedToDestList],user.alias);
-                destuser[destusers++]=user.number; } }
-        else {
-            CRLF; } }
-    if(!destusers)
-        return; }
-if(dir[dirnum]->misc&DIR_RATE) {
-    SYNC;
-    bputs(text[RateThisFile]);
-	ch=getkey(K_ALPHA);
-	if(!isalpha(ch) || sys_status&SS_ABORT)
-		return;
-	CRLF;
-	sprintf(descbeg,text[Rated],toupper(ch)); }
-if(dir[dirnum]->misc&DIR_ULDATE) {
-    now=time(NULL);
-    if(descbeg[0])
-        strcat(descbeg," ");
-    sprintf(str,"%s  ",unixtodstr(now,tmp));
-    strcat(descbeg,str); }
-if(dir[dirnum]->misc&DIR_MULT) {
-    SYNC;
-    if(!noyes(text[MultipleDiskQ])) {
-        bputs(text[HowManyDisksTotal]);
-        if((i=getnum(99))<2)
-            return;
-        bputs(text[NumberOfFile]);
-        if((j=getnum(i))<1)
-            return;
-        if(j==1)
-            lastdesc[0]=0;
-        if(i>9)
-            sprintf(descend,text[FileOneOfTen],j,i);
-        else
-            sprintf(descend,text[FileOneOfTwo],j,i); }
-    else
-        lastdesc[0]=0; }
-else
-    lastdesc[0]=0;
-bputs(text[EnterDescNow]);
-i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
-getstr(lastdesc,i,K_LINE|K_EDIT|K_AUTODEL);
-if(sys_status&SS_ABORT)
-	return;
-if(descend[0])      /* end of desc specified, so pad desc with spaces */
-    sprintf(f.desc,"%s%-*s%s",descbeg,i,lastdesc,descend);
-else                /* no end specified, so string ends at desc end */
-    sprintf(f.desc,"%s%s",descbeg,lastdesc);
-
-if(dir[dirnum]->misc&DIR_ANON && !(dir[dirnum]->misc&DIR_AONLY)
-	&& (dir_op(dirnum) || useron.exempt&FLAG('A'))) {
-    if(!noyes(text[AnonymousQ]))
-        f.misc|=FM_ANON; }
-sprintf(str,"%s%s",path,fname);
-if(src[0]) {    /* being copied from another local dir */
-    bprintf(text[RetrievingFile],fname);
-    if(mv(src,str,1))
-        return;
-    CRLF; }
-if(fexist(str)) {   /* File is on disk */
-	if(!uploadfile(&f))
-        return; }
-else {
-    menu("ULPROT");
-    SYNC;
-    strcpy(keys,"Q");
-    if(dirnum==user_dir || !max_batup)  /* no batch user to user xfers */
-        mnemonics(text[ProtocolOrQuit]);
-    else {
-        mnemonics(text[ProtocolBatchOrQuit]);
-        strcat(keys,"B"); }
-    for(i=0;i<total_prots;i++)
-		if(prot[i]->ulcmd[0] && chk_ar(prot[i]->ar,useron)) {
-            sprintf(tmp,"%c",prot[i]->mnemonic);
-            strcat(keys,tmp); }
-    ch=getkeys(keys,0);
-	if(ch=='Q')
-		return;
-    if(ch=='B') {
-        if(batup_total>=max_batup)
-            bputs(text[BatchUlQueueIsFull]);
-        else {
-            for(i=0;i<batup_total;i++)
-                if(!strcmp(batup_name[i],f.name)) {
-					bprintf(text[FileAlreadyInQueue],f.name);
-                    return; }
-            strcpy(batup_name[batup_total],f.name);
-            strcpy(batup_desc[batup_total],f.desc);
-            batup_dir[batup_total]=dirnum;
-            batup_misc[batup_total]=f.misc;
-            batup_alt[batup_total]=altul;
-            batup_total++;
-            bprintf(text[FileAddedToUlQueue]
-                ,f.name,batup_total,max_batup); } }
-    else {
-        for(i=0;i<total_prots;i++)
-			if(prot[i]->ulcmd[0] && prot[i]->mnemonic==ch
-				&& chk_ar(prot[i]->ar,useron))
-                break;
-        if(i<total_prots) {
-            start=time(NULL);
-			protocol(cmdstr(prot[i]->ulcmd,str,nulstr,NULL),0);
-            end=time(NULL);
-			if(!(dir[dirnum]->misc&DIR_ULTIME)) /* Don't deduct upload time */
-				starttime+=end-start;
-			ch=uploadfile(&f);
-            autohangup();
-			if(!ch)  /* upload failed, don't process user to user xfer */
-				return; } } }
-if(dirnum==user_dir) {  /* Add files to XFER.IXT in INDX dir */
-	sprintf(str,"%sXFER.IXT",data_dir);
-    if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-        errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-        return; }
-    for(j=0;j<destusers;j++) {
-        for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
-            getnodedat(i,&node,0);
-            if(node.useron==destuser[j] && !(node.misc&NODE_POFF)
-                && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
-                sprintf(str,text[UserToUserXferNodeMsg],node_num,useron.alias);
-                putnmsg(i,str);
-                break; } }
-        if(i>sys_nodes) {   /* User not online */
-            sprintf(str,text[UserSentYouFile],useron.alias);
-            putsmsg(destuser[j],str); }
-        sprintf(str,"%4.4u %12.12s %4.4u\r\n"
-            ,destuser[j],f.name,useron.number);
-        write(file,str,strlen(str)); }
-    close(file); }
-}
-
-/****************************************************************************/
-/* Checks directory for 'dir' and prompts user to enter description for     */
-/* the files that aren't in the database.                                   */
-/* Returns 1 if the user aborted, 0 if not.                                 */
-/****************************************************************************/
-char bulkupload(uint dirnum)
-{
-    char done,str[256];
-    struct ffblk ff;
-    file_t f;
-
-memset(&f,0,sizeof(file_t));
-f.dir=dirnum;
-f.altpath=altul;
-bprintf(text[BulkUpload],lib[dir[dirnum]->lib]->sname,dir[dirnum]->sname);
-sprintf(str,"%s*.*",altul>0 && altul<=altpaths ? altpath[altul-1]
-    : dir[dirnum]->path);
-done=findfirst(str,&ff,0);
-action=NODE_ULNG;
-SYNC;
-while(!done && !msgabort()) {
-    if(gettotalfiles(dirnum)>dir[dirnum]->maxfiles) {
-        bputs(text[DirFull]);
-        return(0); }
-    strupr(ff.ff_name);
-    padfname(ff.ff_name,str);
-    if(findfile(f.dir,str)==0) {
-        strcpy(f.name,str);
-		f.cdt=ff.ff_fsize;
-        bprintf(text[BulkUploadDescPrompt],f.name,f.cdt);
-		getstr(f.desc,LEN_FDESC,K_LINE);
-		if(sys_status&SS_ABORT)
-			return(1);
-		uploadfile(&f); }	/* used to abort here if the file failed upload */
-    done=findnext(&ff); }
-return(0);
-}
-
-
-
-/****************************************************************************/
-/* This is the batch menu section                                           */
-/****************************************************************************/
-void batchmenu()
-{
-    char str[129],tmp2[250],done=0,ch;
-	uint i,j,xfrprot,xfrdir;
-    ulong totalcdt,totalsize,totaltime;
-    time_t start,end;
-    int file,n;
-    file_t f;
-
-if(!batdn_total && !batup_total && upload_dir==INVALID_DIR) {
-    bputs(text[NoFilesInBatchQueue]);
-    return; }
-if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT))
-    menu("BATCHXFR");
-lncntr=0;
-while(online && !done && (batdn_total || batup_total
-	|| upload_dir!=INVALID_DIR)) {
-	if(!(useron.misc&(EXPERT|RIP|WIP))) {
-        sys_status&=~SS_ABORT;
-        if(lncntr) {
-            SYNC;
-            CRLF;
-            if(lncntr)          /* CRLF or SYNC can cause pause */
-                pause(); }
-        menu("BATCHXFR"); }
-    ASYNC;
-    bputs(text[BatchMenuPrompt]);
-    ch=getkeys("BCDLQRU?\r",0);
-    if(ch>SP)
-        logch(ch,0);
-    switch(ch) {
-        case '?':
-			if(useron.misc&(EXPERT|RIP|WIP))
-                menu("BATCHXFR");
-            break;
-        case CR:
-        case 'Q':
-            lncntr=0;
-            done=1;
-            break;
-        case 'B':   /* Bi-directional transfers */
-            if(useron.rest&FLAG('D')) {
-                bputs(text[R_Download]);
-				break; }
-            if(useron.rest&FLAG('U')) {
-                bputs(text[R_Upload]);
-				break; }
-            if(!batdn_total) {
-                bputs(text[DownloadQueueIsEmpty]);
-                break; }
-			if(!batup_total && upload_dir==INVALID_DIR) {
-                bputs(text[UploadQueueIsEmpty]);
-                break; }
-            for(i=0,totalcdt=0;i<batdn_total;i++)
-                    totalcdt+=batdn_cdt[i];
-            if(!(useron.exempt&FLAG('D'))
-                && totalcdt>useron.cdt+useron.freecdt) {
-                bprintf(text[YouOnlyHaveNCredits]
-                    ,ultoac(useron.cdt+useron.freecdt,tmp));
-                break; }
-            for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
-                totalsize+=batdn_size[i];
-                if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
-                    totaltime+=batdn_size[i]/(ulong)cur_cps; }
-			if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
-                bputs(text[NotEnoughTimeToDl]);
-                break; }
-            menu("BIPROT");
-            if(!create_batchdn_lst())
-                break;
-            if(!create_batchup_lst())
-                break;
-            if(!create_bimodem_pth())
-                break;
-            SYNC;
-            mnemonics(text[ProtocolOrQuit]);
-            strcpy(tmp2,"Q");
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron)) {
-                    sprintf(tmp,"%c",prot[i]->mnemonic);
-                    strcat(tmp2,tmp); }
-			ungetkey(useron.prot);
-            ch=getkeys(tmp2,0);
-            if(ch=='Q')
-                break;
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->bicmd[0] && prot[i]->mnemonic==ch
-					&& chk_ar(prot[i]->ar,useron))
-                    break;
-            if(i<total_prots) {
-                xfrprot=i;
-                action=NODE_BXFR;
-                SYNC;
-				for(i=0;i<batdn_total;i++)
-                    if(dir[batdn_dir[i]]->seqdev) {
-                        lncntr=0;
-                        unpadfname(batdn_name[i],tmp);
-                        sprintf(tmp2,"%s%s",temp_dir,tmp);
-                        if(!fexist(tmp2)) {
-                            seqwait(dir[batdn_dir[i]]->seqdev);
-                            bprintf(text[RetrievingFile],tmp);
-                            sprintf(str,"%s%s"
-                                ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-                                ? altpath[batdn_alt[i]-1]
-                                : dir[batdn_dir[i]]->path
-                                ,tmp);
-                            mv(str,tmp2,1); /* copy the file to temp dir */
-                            getnodedat(node_num,&thisnode,1);
-							thisnode.aux=0xff;
-                            putnodedat(node_num,thisnode);
-                            CRLF; } }
-                sprintf(str,"%sBATCHDN.LST",node_dir);
-                sprintf(tmp2,"%sBATCHUP.LST",node_dir);
-                start=time(NULL);
-				protocol(cmdstr(prot[xfrprot]->bicmd,str,tmp2,NULL),0);
-                end=time(NULL);
-				for(i=0;i<batdn_total;i++)
-					if(dir[batdn_dir[i]]->seqdev) {
-						unpadfname(batdn_name[i],tmp);
-						sprintf(tmp2,"%s%s",temp_dir,tmp);
-						remove(tmp2); }
-                batch_upload();
-                batch_download(xfrprot);
-                if(batdn_total)     /* files still in queue, not xfered */
-                    notdownloaded(totalsize,start,end);
-                autohangup(); }
-            break;
-        case 'C':
-            if(batup_total) {
-                if(!noyes(text[ClearUploadQueueQ])) {
-                    batup_total=0;
-                    bputs(text[UploadQueueCleared]); } }
-            if(batdn_total) {
-                if(!noyes(text[ClearDownloadQueueQ])) {
-                    for(i=0;i<batdn_total;i++) {
-                        f.dir=batdn_dir[i];
-                        f.datoffset=batdn_offset[i];
-                        f.size=batdn_size[i];
-                        strcpy(f.name,batdn_name[i]);
-                        closefile(f); }
-                    batdn_total=0;
-                    bputs(text[DownloadQueueCleared]); } }
-            break;
-        case 'D':
-            if(useron.rest&FLAG('D')) {
-                bputs(text[R_Download]);
-				break; }
-            if(!batdn_total) {
-                bputs(text[DownloadQueueIsEmpty]);
-                break; }
-            start_batch_download();
-            break;
-        case 'L':
-            if(batup_total) {
-                bputs(text[UploadQueueLstHdr]);
-                for(i=0;i<batup_total;i++)
-                    bprintf(text[UploadQueueLstFmt],i+1,batup_name[i]
-                        ,batup_desc[i]); }
-            if(batdn_total) {
-                bputs(text[DownloadQueueLstHdr]);
-                for(i=0,totalcdt=0,totalsize=0;i<batdn_total;i++) {
-                    bprintf(text[DownloadQueueLstFmt],i+1
-                        ,batdn_name[i],ultoac(batdn_cdt[i],tmp)
-                        ,ultoac(batdn_size[i],str)
-                        ,cur_cps
-                        ? sectostr(batdn_size[i]/(ulong)cur_cps,tmp2)
-                        : "??:??:??");
-                    totalsize+=batdn_size[i];
-                    totalcdt+=batdn_cdt[i]; }
-                bprintf(text[DownloadQueueTotals]
-                    ,ultoac(totalcdt,tmp),ultoac(totalsize,str),cur_cps
-                    ? sectostr(totalsize/(ulong)cur_cps,tmp2)
-                    : "??:??:??"); }
-            break;  /* Questionable line ^^^, see note above function */
-        case 'R':
-            if(batup_total) {
-                bprintf(text[RemoveWhichFromUlQueue],batup_total);
-                n=getnum(batup_total);
-                if(n>=1) {
-                    n--;
-                    batup_total--;
-                    while(n<batup_total) {
-                        batup_dir[n]=batup_dir[n+1];
-                        batup_misc[n]=batup_misc[n+1];
-                        batup_alt[n]=batup_alt[n+1];
-                        strcpy(batup_name[n],batup_name[n+1]);
-                        strcpy(batup_desc[n],batup_desc[n+1]);
-                        n++; }
-                    if(!batup_total)
-                        bputs(text[UploadQueueCleared]); } }
-             if(batdn_total) {
-                bprintf(text[RemoveWhichFromDlQueue],batdn_total);
-                n=getnum(batdn_total);
-                if(n>=1) {
-                    n--;
-                    f.dir=batdn_dir[n];
-                    strcpy(f.name,batdn_name[n]);
-                    f.datoffset=batdn_offset[n];
-                    f.size=batdn_size[n];
-                    closefile(f);
-                    batdn_total--;
-                    while(n<batdn_total) {
-                        strcpy(batdn_name[n],batdn_name[n+1]);
-                        batdn_dir[n]=batdn_dir[n+1];
-                        batdn_cdt[n]=batdn_cdt[n+1];
-                        batdn_alt[n]=batdn_alt[n+1];
-                        batdn_size[n]=batdn_size[n+1];
-                        batdn_offset[n]=batdn_offset[n+1];
-                        n++; }
-                    if(!batdn_total)
-                        bputs(text[DownloadQueueCleared]); } }
-            break;
-       case 'U':
-			if(useron.rest&FLAG('U')) {
-                bputs(text[R_Upload]);
-				break; }
-			if(!batup_total && upload_dir==INVALID_DIR) {
-                bputs(text[UploadQueueIsEmpty]);
-                break; }
-            menu("BATUPROT");
-            if(!create_batchup_lst())
-                break;
-            if(!create_bimodem_pth())
-                break;
-            ASYNC;
-            mnemonics(text[ProtocolOrQuit]);
-            strcpy(str,"Q");
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->batulcmd[0] && chk_ar(prot[i]->ar,useron)) {
-                    sprintf(tmp,"%c",prot[i]->mnemonic);
-                    strcat(str,tmp); }
-            ch=getkeys(str,0);
-            if(ch=='Q')
-                break;
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->batulcmd[0] && prot[i]->mnemonic==ch
-					&& chk_ar(prot[i]->ar,useron))
-                    break;
-            if(i<total_prots) {
-                sprintf(str,"%sBATCHUP.LST",node_dir);
-                xfrprot=i;
-				if(batup_total)
-					xfrdir=batup_dir[0];
-				else
-					xfrdir=upload_dir;
-                action=NODE_ULNG;
-                SYNC;
-				if(online==ON_REMOTE) {
-					delfiles(temp_dir,"*.*");
-					start=time(NULL);
-					protocol(cmdstr(prot[xfrprot]->batulcmd,str,nulstr,NULL),1);
-					end=time(NULL);
-					if(!(dir[xfrdir]->misc&DIR_ULTIME))
-						starttime+=end-start; }
-                batch_upload();
-                delfiles(temp_dir,"*.*");
-                autohangup(); }
-            break; } }
-delfiles(temp_dir,"*.*");
-}
-
-/****************************************************************************/
-/* Download files from batch queue                                          */
-/****************************************************************************/
-void start_batch_download()
-{
-	char ch,str[256],tmp2[256],tmp3[128],fname[64];
-    int j;
-    uint i,xfrprot;
-    ulong totalcdt,totalsize,totaltime;
-    time_t start,end;
-    file_t f;
-
-if(useron.rest&FLAG('D')) {     /* Download restriction */
-    bputs(text[R_Download]);
-    return; }
-for(i=0,totalcdt=0;i<batdn_total;i++)
-    totalcdt+=batdn_cdt[i];
-if(!(useron.exempt&FLAG('D'))
-    && totalcdt>useron.cdt+useron.freecdt) {
-    bprintf(text[YouOnlyHaveNCredits]
-        ,ultoac(useron.cdt+useron.freecdt,tmp));
-    return; }
-
-if(online==ON_LOCAL) {          /* Local download */
-    bputs(text[EnterPath]);
-    if(!getstr(str,60,K_LINE|K_UPPER))
-        return;
-    backslash(str);
-    for(i=0;i<batdn_total;i++) {
-		curdirnum=batdn_dir[i]; 		/* for ARS */
-        lncntr=0;
-        unpadfname(batdn_name[i],tmp);
-        sprintf(tmp2,"%s%s",str,tmp);
-		seqwait(dir[batdn_dir[i]]->seqdev);
-        bprintf(text[RetrievingFile],tmp);
-        sprintf(tmp3,"%s%s"
-            ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-            ? altpath[batdn_alt[i]-1]
-            : dir[batdn_dir[i]]->path
-            ,tmp);
-        j=mv(tmp3,tmp2,1);
-        getnodedat(node_num,&thisnode,1);
-		thisnode.aux=30; /* clear the seq dev # */
-        putnodedat(node_num,thisnode);
-        CRLF;
-        if(j)   /* copy unsuccessful */
-			return;
-		for(j=0;j<total_dlevents;j++)
-			if(!stricmp(dlevent[j]->ext,batdn_name[i]+9)
-				&& chk_ar(dlevent[j]->ar,useron)) {
-				bputs(dlevent[j]->workstr);
-				external(cmdstr(dlevent[j]->cmd,tmp2,nulstr,NULL),EX_OUTL);
-				CRLF; }
-		}
-    for(i=0;i<batdn_total;i++) {
-		curdirnum=batdn_dir[i]; 		/* for ARS */
-        f.dir=batdn_dir[i];
-        strcpy(f.name,batdn_name[i]);
-        f.datoffset=batdn_offset[i];
-        f.size=batdn_size[i];
-        f.altpath=batdn_alt[i];
-        downloadfile(f);
-        closefile(f); }
-    batdn_total=0;
-    return; }
-
-for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
-    totalsize+=batdn_size[i];
-    if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
-        totaltime+=batdn_size[i]/(ulong)cur_cps; }
-if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
-    bputs(text[NotEnoughTimeToDl]);
-    return; }
-menu("BATDPROT");
-if(!create_batchdn_lst())
-    return;
-if(!create_bimodem_pth())
-    return;
-ASYNC;
-mnemonics(text[ProtocolOrQuit]);
-strcpy(tmp2,"Q");
-for(i=0;i<total_prots;i++)
-	if(prot[i]->batdlcmd[0] && chk_ar(prot[i]->ar,useron)) {
-        sprintf(tmp,"%c",prot[i]->mnemonic);
-        strcat(tmp2,tmp); }
-ungetkey(useron.prot);
-ch=getkeys(tmp2,0);
-if(ch=='Q' || sys_status&SS_ABORT)
-    return;
-for(i=0;i<total_prots;i++)
-	if(prot[i]->batdlcmd[0] && prot[i]->mnemonic==ch
-		&& chk_ar(prot[i]->ar,useron))
-        break;
-if(i<total_prots) {
-    xfrprot=i;
-    /* delfiles(temp_dir,"*.*"); fix for CD-ROM */
-	for(i=0;i<batdn_total;i++) {
-		curdirnum=batdn_dir[i]; 		/* for ARS */
-		unpadfname(batdn_name[i],fname);
-        if(dir[batdn_dir[i]]->seqdev) {
-            lncntr=0;
-			sprintf(tmp2,"%s%s",temp_dir,fname);
-            if(!fexist(tmp2)) {
-                seqwait(dir[batdn_dir[i]]->seqdev);
-				bprintf(text[RetrievingFile],fname);
-                sprintf(str,"%s%s"
-                    ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-                    ? altpath[batdn_alt[i]-1]
-                    : dir[batdn_dir[i]]->path
-					,fname);
-                mv(str,tmp2,1); /* copy the file to temp dir */
-                getnodedat(node_num,&thisnode,1);
-				thisnode.aux=40; /* clear the seq dev # */
-                putnodedat(node_num,thisnode);
-                CRLF; } }
-		else
-			sprintf(tmp2,"%s%s"
-				,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-				? altpath[batdn_alt[i]-1]
-				: dir[batdn_dir[i]]->path
-				,fname);
-		sprintf(str,"total_dlevents=%d",total_dlevents);
-//		  logline("dl",str);
-		for(j=0;j<total_dlevents;j++) {
-//			  logline("dl",dlevent[j]->ext);
-  //		  logline("dl",dlevent[j]->cmd);
-	//		  logline("dl",tmp2);
-			if(stricmp(dlevent[j]->ext,batdn_name[i]+9))
-				continue;
-//			  logline("dl","chkar");
-			if(!chk_ar(dlevent[j]->ar,useron))
-				continue;
-//			  logline("dl","bputs");
-			bputs(dlevent[j]->workstr);
-//			  logline("dl","external");
-			external(cmdstr(dlevent[j]->cmd,tmp2,nulstr,NULL),EX_OUTL);
-//			  logline("dl","crlf");
-			CRLF; }
-//		  logline("dl","after dlevents");
-		}
-
-    sprintf(str,"%sBATCHDN.LST",node_dir);
-    getnodedat(node_num,&thisnode,1);
-    action=NODE_DLNG;
-    if(cur_cps)
-        unixtodos(now+(totalsize/(ulong)cur_cps)
-            ,&date,&curtime);
-    thisnode.aux=(curtime.ti_hour*60)+curtime.ti_min;
-	thisnode.action=action;
-    putnodedat(node_num,thisnode); /* calculate ETA */
-    start=time(NULL);
-	protocol(cmdstr(prot[xfrprot]->batdlcmd,str,nulstr,NULL),0);
-    end=time(NULL);
-    batch_download(xfrprot);
-    if(batdn_total)
-        notdownloaded(totalsize,start,end);
-    /* delfiles(temp_dir,"*.*"); fix for CD-ROM */
-    autohangup(); }
-}
-
-/*****************************************************************************/
-/* Temp directory section. Files must be extracted here and both temp_uler   */
-/* and temp_uler fields should be filled before entrance.                    */
-/*****************************************************************************/
-void temp_xfer()
-{
-    char str[256],tmp2[256],done=0,ch;
-    uint i,dirnum=total_dirs,j,files;
-    ulong bytes;
-    time_t start,end;
-    struct ffblk ff;
-    struct dfree d;
-    file_t f;
-
-if(!usrlibs)
-	return;
-if(useron.rest&FLAG('D')) {
-    bputs(text[R_Download]);
-    return; }
-/*************************************/
-/* Create TEMP directory information */
-/*************************************/
-if((dir[dirnum]=(dir_t *)MALLOC(sizeof(dir_t)))==0) {
-    errormsg(WHERE,ERR_ALLOC,"temp_dir",sizeof(dir_t));
-    return; }
-memset(dir[dirnum],0,sizeof(dir_t));
-dir[dirnum]->lname="Temporary";
-dir[dirnum]->sname="Temp";
-strcpy(dir[dirnum]->code,"TEMP");
-dir[dirnum]->path=temp_dir;
-dir[dirnum]->maxfiles=MAX_FILES;
-dir[dirnum]->data_dir=dir[0]->data_dir;
-dir[dirnum]->op_ar=nulstr;
-temp_dirnum=curdirnum=usrdir[curlib][curdir[curlib]];
-total_dirs++;
-
-/****************************/
-/* Fill filedat information */
-/****************************/
-sprintf(f.name,"TEMP_%3.3d.%s",node_num,useron.tmpext);
-strcpy(f.desc,"Temp File");
-f.dir=dirnum;
-f.misc=f.timesdled=f.dateuled=f.datedled=0L;
-
-if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT))
-    menu("TEMPXFER");
-lncntr=0;
-while(online && !done) {
-	if(!(useron.misc&(EXPERT|RIP|WIP))) {
-        sys_status&=~SS_ABORT;
-        if(lncntr) {
-            SYNC;
-            CRLF;
-            if(lncntr)          /* CRLF or SYNC can cause pause */
-                pause(); }
-        menu("TEMPXFER"); }
-    ASYNC;
-    bputs(text[TempDirPrompt]);
-    strcpy(f.uler,temp_uler);
-    ch=getkeys("ADEFNILQRVX?\r",0);
-    if(ch>SP)
-        logch(ch,0);
-    switch(ch) {
-        case 'A':   /* add to temp file */
-            if(temp_dir[1]==':')
-                i=temp_dir[0]-'A'+1;
-            else i=0;
-            getdfree(i,&d);
-            if(d.df_sclus==0xffff)
-                errormsg(WHERE,ERR_CHK,temp_dir,0);
-            if((ulong)d.df_bsec*(ulong)d.df_sclus
-                *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
-                bputs(text[LowDiskSpace]);
-                sprintf(str,"Diskspace is low: %s",temp_dir);
-                errorlog(str);
-				if(!dir_op(dirnum))
-                    break; }
-            bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
-                *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
-			if(!getfilespec(str))
-                break;
-            if(!checkfname(str))
-                break;
-            sprintf(tmp2,"Added %s to %s",str,f.name);
-            logline(nulstr,tmp2);
-            sprintf(tmp2,"%s%s",temp_dir,str);
-            sprintf(str,"%s%s",temp_dir,f.name);
-			external(cmdstr(temp_cmd(),str,tmp2,NULL),EX_CC|EX_OUTL|EX_OUTR);
-            break;
-        case 'D':   /* download from temp dir */
-            sprintf(str,"%s%s",temp_dir,f.name);
-            if(!fexist(str)) {
-                bprintf(text[TempFileNotCreatedYet],f.name);
-                break; }
-            f.size=f.cdt=flength(str);
-            f.opencount=0;
-            if(temp_cdt)    /* if file was not free */
-				f.cdt=f.size;
-            else
-                f.cdt=0;
-            if(!(useron.exempt&FLAG('D'))
-                && f.cdt>useron.cdt+useron.freecdt) {
-                bprintf(text[YouOnlyHaveNCredits]
-                    ,ultoac(useron.cdt+useron.freecdt,tmp));
-                break; }    /* f.cdt must equal size here */
-			if(!(useron.exempt&FLAG('T')) && !dir_op(dirnum)
-                && !(dir[temp_dirnum]->misc&DIR_TFREE) && cur_cps
-                && f.size/(ulong)cur_cps>timeleft) {
-                bputs(text[NotEnoughTimeToDl]);
-                break; }
-            if(!chk_ar(dir[temp_dirnum]->dl_ar,useron)) {
-                bputs(text[CantDownloadFromDir]);
-                break; }
-            addfiledat(&f);
-            menu("DLPROT");
-            SYNC;
-            mnemonics(text[ProtocolOrQuit]);
-            strcpy(tmp2,"Q");
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
-                    sprintf(tmp,"%c",prot[i]->mnemonic);
-                    strcat(tmp2,tmp); }
-			ungetkey(useron.prot);
-            ch=getkeys(tmp2,0);
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->dlcmd[0] && prot[i]->mnemonic==ch
-					&& chk_ar(prot[i]->ar,useron))
-                    break;
-            if(i<total_prots) {
-                getnodedat(node_num,&thisnode,1);
-                action=NODE_DLNG;
-                if(cur_cps)
-                    unixtodos(now+(f.size/(ulong)cur_cps)
-                        ,&date,&curtime);
-                thisnode.aux=(curtime.ti_hour*60)+curtime.ti_min;
-                putnodedat(node_num,thisnode); /* calculate ETA */
-                start=time(NULL);
-				j=protocol(cmdstr(prot[i]->dlcmd,str,nulstr,NULL),0);
-                end=time(NULL);
-                if(dir[temp_dirnum]->misc&DIR_TFREE)
-                    starttime+=end-start;
-                if(prot[i]->misc&PROT_DSZLOG) {
-                    if(checkprotlog(f))
-                        downloadfile(f);
-                    else
-                        notdownloaded(f.size,start,end); }
-                else {
-                    if(!j)
-                        downloadfile(f);
-                    else {
-                        bprintf(text[FileNotSent],f.name);
-                        notdownloaded(f.size,start,end); } }
-                autohangup(); }
-            removefiledat(f);
-            break;
-        case 'E':
-			extract(usrdir[curlib][curdir[curlib]]);
-            sys_status&=~SS_ABORT;
-            break;
-        case 'F':   /* Create a file list */
-            delfiles(temp_dir,"*.*");
-            create_filelist("FILELIST.TXT",0);
-            if(!(sys_status&SS_ABORT))
-                logline(nulstr,"Created list of all files");
-            CRLF;
-            sys_status&=~SS_ABORT;
-            break;
-        case 'I':   /* information on what's here */
-            bprintf(text[TempFileInfo],f.uler,temp_file);
-            break;
-        case 'L':   /* list files in dir */
-            if(!getfilespec(str))
-                break;
-			if(!checkfname(str))
-				break;
-            bytes=files=0L;
-            CRLF;
-            sprintf(tmp2,"%s%s",temp_dir,str);
-            i=findfirst(tmp2,&ff,0);
-            while(!i && !msgabort()) {
-                bprintf("%s %10s\r\n",padfname(ff.ff_name,str)
-                    ,ultoac(ff.ff_fsize,tmp));
-                files++;
-                bytes+=ff.ff_fsize;
-                i=findnext(&ff); }
-            if(!files)
-                bputs(text[EmptyDir]);
-            else if(files>1)
-                bprintf(text[TempDirTotal],ultoac(bytes,tmp),files);
-            break;
-        case 'N':   /* Create a list of new files */
-            delfiles(temp_dir,"*.*");
-            create_filelist("NEWFILES.TXT",FL_ULTIME);
-            if(!(sys_status&SS_ABORT))
-                logline(nulstr,"Created list of new files");
-            CRLF;
-            sys_status&=~SS_ABORT;
-            break;
-        case 'R':   /* Remove files from dir */
-            if(!getfilespec(str))
-                break;
-			// padfname(str,tmp);  Removed 04/14/96
-			bprintf(text[NFilesRemoved],delfiles(temp_dir,tmp));
-            break;
-        case 'V':   /* view files in dir */
-            bputs(text[FileSpec]);
-            if(!getstr(str,12,K_UPPER) || !checkfname(str))
-                break;
-            viewfiles(dirnum,str);
-            break;
-        case CR:
-        case 'Q':   /* quit */
-            done=1;
-            break;
-        case 'X':   /* extract from archive in temp dir */
-            extract(dirnum);
-            sys_status&=~SS_ABORT;
-            break;
-        case '?':   /* menu */
-			if(useron.misc&(EXPERT|RIP|WIP))
-                menu("TEMPXFER");
-            break; }
-    if(sys_status&SS_ABORT)
-        break; }
-FREE(dir[dirnum]);
-total_dirs--;
-}
-
-
-/****************************************************************************/
-/* Re-sorts file directory 'dirnum' according to dir[dirnum]->sort type     */
-/****************************************************************************/
-void resort(uint dirnum)
-{
-	char str[25],ixbfname[128],datfname[128],exbfname[128],txbfname[128]
-		,ext[512],nulbuf[512];
-	uchar HUGE16 *ixbbuf, HUGE16 *datbuf;
-	uchar HUGE16 *ixbptr[MAX_FILES];
-	int ixbfile,datfile,exbfile,txbfile,i,j;
-	ulong ixblen,datlen,offset,newoffset,l;
-
-memset(nulbuf,0,512);
-bprintf(text[ResortLineFmt],lib[dir[dirnum]->lib]->sname,dir[dirnum]->sname);
-sprintf(ixbfname,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-sprintf(datfname,"%s%s.DAT",dir[dirnum]->data_dir,dir[dirnum]->code);
-sprintf(exbfname,"%s%s.EXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-sprintf(txbfname,"%s%s.TXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-
-if(flength(ixbfname)<1L || flength(datfname)<1L) {
-	remove(exbfname);
-	remove(txbfname);
-    remove(ixbfname);
-    remove(datfname);
-    bputs(text[ResortEmptyDir]);
-    return; }
-bputs(text[Sorting]);
-if((ixbfile=nopen(ixbfname,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_OPEN,ixbfname,O_RDONLY);
-    return; }
-if((datfile=nopen(datfname,O_RDONLY))==-1) {
-    close(ixbfile);
-    errormsg(WHERE,ERR_OPEN,datfname,O_RDONLY);
-    return; }
-ixblen=filelength(ixbfile);
-datlen=filelength(datfile);
-if((ixbbuf=MALLOC(ixblen))==NULL) {
-    close(ixbfile);
-    close(datfile);
-    errormsg(WHERE,ERR_ALLOC,ixbfname,ixblen);
-    return; }
-if((datbuf=MALLOC(datlen))==NULL) {
-    close(ixbfile);
-    close(datfile);
-    FREE((char *)ixbbuf);
-    errormsg(WHERE,ERR_ALLOC,datfname,datlen);
-    return; }
-if(lread(ixbfile,ixbbuf,ixblen)!=ixblen) {
-    close(ixbfile);
-    close(datfile);
-    FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-    errormsg(WHERE,ERR_READ,ixbfname,ixblen);
-    return; }
-if(lread(datfile,datbuf,datlen)!=datlen) {
-    close(ixbfile);
-    close(datfile);
-    FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-    errormsg(WHERE,ERR_READ,datfname,datlen);
-    return; }
-close(ixbfile);
-close(datfile);
-if((ixbfile=nopen(ixbfname,O_WRONLY|O_TRUNC))==-1) {
-    FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-    errormsg(WHERE,ERR_OPEN,ixbfname,O_WRONLY|O_TRUNC);
-    return; }
-if((datfile=nopen(datfname,O_WRONLY|O_TRUNC))==-1) {
-    close(ixbfile);
-    FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-    errormsg(WHERE,ERR_OPEN,datfname,O_WRONLY|O_TRUNC);
-    return; }
-for(l=0,i=0;l<ixblen && i<MAX_FILES;l+=F_IXBSIZE,i++)
-    ixbptr[i]=ixbbuf+l;
-switch(dir[dirnum]->sort) {
-    case SORT_NAME_A:
-        qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
-            ,(int(*)(const void*, const void*))fnamecmp_a);
-        break;
-    case SORT_NAME_D:
-        qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
-            ,(int(*)(const void*, const void*))fnamecmp_d);
-        break;
-    case SORT_DATE_A:
-        qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
-            ,(int(*)(const void*, const void*))fdatecmp_a);
-        break;
-    case SORT_DATE_D:
-        qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
-            ,(int(*)(const void*, const void*))fdatecmp_d);
-        break; }
-
-if((exbfile=nopen(exbfname,O_RDWR|O_CREAT))==-1) {
-	close(ixbfile);
-	close(datfile);
-	FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-    errormsg(WHERE,ERR_OPEN,exbfname,O_RDWR|O_CREAT);
-	return; }
-if((txbfile=nopen(txbfname,O_RDWR|O_CREAT))==-1) {
-    close(exbfile);
-	close(datfile);
-	close(exbfile);
-	FREE((char *)ixbbuf);
-    FREE((char *)datbuf);
-	errormsg(WHERE,ERR_OPEN,txbfname,O_RDWR|O_CREAT);
-	return; }
-
-for(i=0;i<ixblen/F_IXBSIZE;i++) {
-    offset=ixbptr[i][11]|((long)ixbptr[i][12]<<8)|((long)ixbptr[i][13]<<16);
-    lwrite(datfile,&datbuf[offset],F_LEN);
-
-	newoffset=(ulong)i*(ulong)F_LEN;
-
-	j=datbuf[offset+F_MISC];  /* misc bits */
-	if(j!=ETX) j-=SP;
-	if(j&FM_EXTDESC) { /* extended description */
-		lseek(exbfile,(offset/F_LEN)*512L,SEEK_SET);
-		memset(ext,0,512);
-		read(exbfile,ext,512);
-		while(filelength(txbfile)<(newoffset/F_LEN)*512L) {
-//			  lseek(txbfile,0L,SEEK_END);
-			write(txbfile,nulbuf,512); }
-		lseek(txbfile,(newoffset/F_LEN)*512L,SEEK_SET);
-		write(txbfile,ext,512); }
-
-	str[0]=newoffset&0xff;	   /* Get offset within DAT file for IXB file */
-	str[1]=(newoffset>>8)&0xff;
-	str[2]=(newoffset>>16)&0xff;
-    lwrite(ixbfile,ixbptr[i],11);       /* filename */
-    lwrite(ixbfile,str,3);              /* offset */
-    lwrite(ixbfile,ixbptr[i]+14,8); }   /* upload and download times */
-close(exbfile);
-close(txbfile);
-close(ixbfile);
-close(datfile);
-remove(exbfname);
-rename(txbfname,exbfname);
-if(!flength(exbfname))
-	remove(exbfname);
-FREE((char *)ixbbuf);
-FREE((char *)datbuf);
-if(ixblen/F_IXBSIZE==datlen/F_LEN)
-    bputs(text[Sorted]);
-else
-    bprintf(text[Compressed]
-        ,(uint)((datlen/F_LEN)-(ixblen/F_IXBSIZE))
-        ,ultoac(((datlen/F_LEN)-(ixblen/F_IXBSIZE))*F_LEN,tmp));
-}
-
-/*****************************************************************************/
-/* Handles extraction from a normal transfer file to the temp directory      */
-/*****************************************************************************/
-void extract(uint dirnum)
-{
-    char fname[13],str[256],excmd[256],path[256],done
-		,files[256],tmp[256],intmp=0;
-    int i,j;
-    struct ffblk ff;
-    file_t f;
-    struct dfree d;
-
-temp_dirnum=curdirnum=dirnum;
-if(!strcmp(dir[dirnum]->code,"TEMP"))
-    intmp=1;
-if(temp_dir[1]==':')
-    i=temp_dir[0]-'A'+1;
-else i=0;
-getdfree(i,&d);
-if(d.df_sclus==0xffff)
-    errormsg(WHERE,ERR_CHK,temp_dir,0);
-if((ulong)d.df_bsec*(ulong)d.df_sclus
-    *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
-    bputs(text[LowDiskSpace]);
-    sprintf(str,"Diskspace is low: %s",temp_dir);
-    errorlog(str);
-	if(!dir_op(dirnum))
-        return; }
-else if(!intmp) {   /* not in temp dir */
-    CRLF; }
-bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
-    *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
-if(!intmp) {    /* not extracting FROM temp directory */
-    sprintf(str,"%s*.*",temp_dir);
-    if(fexist(str)) {
-        bputs(text[RemovingTempFiles]);
-        done=findfirst(str,&ff,0);
-        while(!done) {
-            sprintf(str,"%s%s",temp_dir,ff.ff_name);
-            remove(str);
-            done=findnext(&ff); }
-        CRLF; } }
-bputs(text[ExtractFrom]);
-if(!getstr(fname,12,K_UPPER) || !checkfname(fname) || strchr(fname,'*')
-    || strchr(fname,'?'))
-    return;
-padfname(fname,f.name);
-strcpy(str,f.name);
-truncsp(str);
-for(i=0;i<total_fextrs;i++)
-	if(!strcmp(str+9,fextr[i]->ext) && chk_ar(fextr[i]->ar,useron)) {
-        strcpy(excmd,fextr[i]->cmd);
-        break; }
-if(i==total_fextrs) {
-    bputs(text[UnextractableFile]);
-    return; }
-if(!intmp && !findfile(dirnum,f.name)) {    /* not temp dir */
-    bputs(text[SearchingAllDirs]);
-    for(i=0;i<usrdirs[curlib] && !msgabort();i++) {
-        if(i==dirnum) continue;
-        if(findfile(usrdir[curlib][i],f.name))
-            break; }
-    if(i==usrdirs[curlib]) { /* not found in cur lib */
-        bputs(text[SearchingAllLibs]);
-        for(i=0;i<usrlibs;i++) {
-            if(i==curlib) continue;
-            for(j=0;j<usrdirs[i] && !msgabort();j++)
-                if(findfile(usrdir[i][j],f.name))
-                    break;
-            if(j<usrdirs[i])
-                break; }
-        if(i==usrlibs) {
-            bputs(text[FileNotFound]);  /* not in database */
-            return; }
-		dirnum=usrdir[i][j]; }
-	else
-        dirnum=usrdir[curlib][i]; }
-if(sys_status&SS_ABORT)
-    return;
-sprintf(path,"%s%s",dir[dirnum]->path,fname);
-if(!intmp) {    /* not temp dir, so get temp_file info */
-    f.datoffset=f.dateuled=f.datedled=0L;
-    f.dir=dirnum;
-    getfileixb(&f);
-    if(!f.datoffset && !f.dateuled && !f.datedled)  /* error reading ixb */
-        return;
-    f.size=0;
-    getfiledat(&f);
-    fileinfo(f);
-    if(f.altpath>0 && f.altpath<=altpaths)
-        sprintf(path,"%s%s",altpath[f.altpath-1],fname);
-    temp_dirnum=dirnum;
-    if(dir[f.dir]->misc&DIR_FREE)
-        temp_cdt=0L;
-    else
-        temp_cdt=f.cdt;
-    strcpy(temp_uler,f.uler);
-    strcpy(temp_file,f.name); }     /* padded filename */
-if(!fexist(path)) {
-    bputs(text[FileNotThere]);  /* not on disk */
-    return; }
-done=0;
-while(online && !done) {
-    mnemonics(text[ExtractFilesPrompt]);
-    switch(getkeys("EVQ",0)) {
-        case 'E':
-			if(!getfilespec(str))
-                break;
-            if(!checkfname(str))
-                break;
-			if((i=external(cmdstr(excmd,path,str,NULL)
-                ,EX_INR|EX_OUTL|EX_OUTR|EX_CC))!=0) {
-				errormsg(WHERE,ERR_EXEC,cmdstr(excmd,path,str,NULL),i);
-                return; }
-			sprintf(tmp,"Extracted %s from %s",str,path);
-			logline(nulstr,tmp);
-            CRLF;
-            break;
-        case 'V':
-            viewfiles(dirnum,fname);
-            break;
-        default:
-            done=1;
-            break; } }
-}
-
-/****************************************************************************/
-/* Creates the file BATCHDN.LST in the node directory. Returns 1 if         */
-/* everything goes okay. 0 if not.                                          */
-/****************************************************************************/
-int create_batchdn_lst()
-{
-    char str[256];
-    int i,file;
-
-sprintf(str,"%sBATCHDN.LST",node_dir);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return(0); }
-for(i=0;i<batdn_total;i++) {
-    if(batdn_dir[i]>=total_dirs || dir[batdn_dir[i]]->seqdev)
-        strcpy(str,temp_dir);
-    else
-        strcpy(str,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-            ? altpath[batdn_alt[i]-1] : dir[batdn_dir[i]]->path);
-    write(file,str,strlen(str));
-    unpadfname(batdn_name[i],str);
-    strcat(str,crlf);
-    write(file,str,strlen(str)); }
-close(file);
-return(1);
-}
-
-/****************************************************************************/
-/* Creates the file BATCHUP.LST in the node directory. Returns 1 if         */
-/* everything goes okay. 0 if not.                                          */
-/* This list is not used by any protocols to date.                          */
-/****************************************************************************/
-int create_batchup_lst()
-{
-    char str[256];
-    int i,file;
-
-sprintf(str,"%sBATCHUP.LST",node_dir);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return(0); }
-for(i=0;i<batup_total;i++) {
-    if(batup_dir[i]>=total_dirs)
-        strcpy(str,temp_dir);
-    else
-        strcpy(str,batup_alt[i]>0 && batup_alt[i]<=altpaths
-            ? altpath[batup_alt[i]-1] : dir[batup_dir[i]]->path);
-    write(file,str,strlen(str));
-    unpadfname(batup_name[i],str);
-    strcat(str,crlf);
-    write(file,str,strlen(str)); }
-close(file);
-return(1);
-}
-
-/****************************************************************************/
-/* Creates the file BIMODEM.PTH in the node directory. Returns 1 if         */
-/* everything goes okay. 0 if not.                                          */
-/****************************************************************************/
-int create_bimodem_pth()
-{
-    char str[256],tmp2[512];
-    int i,file;
-
-sprintf(str,"%sBIMODEM.PTH",node_dir);  /* Create bimodem file */
-if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-    errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-    return(0); }
-for(i=0;i<batup_total;i++) {
-    sprintf(str,"%s%s",batup_dir[i]>=total_dirs ? temp_dir
-        : batup_alt[i]>0 && batup_alt[i]<=altpaths
-        ? altpath[batup_alt[i]-1] : dir[batup_dir[i]]->path
-        ,unpadfname(batup_name[i],tmp));
-    sprintf(tmp2,"D       %-80.80s%-160.160s"
-        ,unpadfname(batup_name[i],tmp),str);
-    write(file,tmp2,248); }
-for(i=0;i<batdn_total;i++) {
-    sprintf(str,"%s%s"
-        ,(batdn_dir[i]>=total_dirs || dir[batdn_dir[i]]->seqdev)
-        ? temp_dir : batdn_alt[i]>0 && batdn_alt[i]<=altpaths
-            ? altpath[batdn_alt[i]-1] : dir[batdn_dir[i]]->path
-            ,unpadfname(batdn_name[i],tmp));
-    sprintf(tmp2,"U       %-240.240s",str);
-    write(file,tmp2,248); }
-close(file);
-return(1);
-}
-
-/****************************************************************************/
-/* Processes files that were supposed to be received in the batch queue     */
-/****************************************************************************/
-void batch_upload()
-{
-    char str1[256],str2[256];
-	int i,j,x,y;
-    file_t f;
-	struct ffblk ff;
-
-for(i=0;i<batup_total;) {
-	curdirnum=batup_dir[i]; 			/* for ARS */
-    lncntr=0;                               /* defeat pause */
-    unpadfname(batup_name[i],tmp);
-    sprintf(str1,"%s%s",temp_dir,tmp);
-    sprintf(str2,"%s%s",dir[batup_dir[i]]->path,tmp);
-    if(fexist(str1) && fexist(str2)) { /* file's in two places */
-        bprintf(text[FileAlreadyThere],batup_name[i]);
-        remove(str1);    /* this is the one received */
-        i++;
-        continue; }
-    if(fexist(str1))
-        mv(str1,str2,0);
-    strcpy(f.name,batup_name[i]);
-    strcpy(f.desc,batup_desc[i]);
-    f.dir=batup_dir[i];
-    f.misc=batup_misc[i];
-    f.altpath=batup_alt[i];
-	if(uploadfile(&f)) {
-        batup_total--;
-        for(j=i;j<batup_total;j++) {
-            batup_dir[j]=batup_dir[j+1];
-            batup_alt[j]=batup_alt[j+1];
-            batup_misc[j]=batup_misc[j+1];
-            strcpy(batup_name[j],batup_name[j+1]);
-            strcpy(batup_desc[j],batup_desc[j+1]); } }
-    else i++; }
-if(upload_dir==INVALID_DIR)
-	return;
-sprintf(str1,"%s*.*",temp_dir);
-i=findfirst(str1,&ff,0);
-while(!i) {
-	memset(&f,0,sizeof(file_t));
-	f.dir=upload_dir;
-	padfname(ff.ff_name,f.name);
-	strupr(f.name);
-	sprintf(str1,"%s%s",temp_dir,ff.ff_name);
-	for(x=0;x<usrlibs;x++) {
-		for(y=0;y<usrdirs[x];y++)
-			if(dir[usrdir[x][y]]->misc&DIR_DUPES
-				&& findfile(usrdir[x][y],f.name))
-				break;
-		if(y<usrdirs[x])
-            break; }
-	sprintf(str2,"%s%s",dir[f.dir]->path,ff.ff_name);
-	if(x<usrlibs || fexist(str2)) {
-		bprintf(text[FileAlreadyOnline],f.name);
-		remove(str1); }
-	else {
-		mv(str1,str2,0);
-		uploadfile(&f); }
-	i=findnext(&ff); }
-}
-
-/****************************************************************************/
-/* Processes files that were supposed to be sent from the batch queue       */
-/* xfrprot is -1 if downloading files from within QWK (no DSZLOG)           */
-/****************************************************************************/
-void batch_download(int xfrprot)
-{
-    int i,j;
-    file_t f;
-
-for(i=0;i<batdn_total;) {
-    lncntr=0;                               /* defeat pause */
-	f.dir=curdirnum=batdn_dir[i];
-    strcpy(f.name,batdn_name[i]);
-    f.datoffset=batdn_offset[i];
-    f.size=batdn_size[i];
-/*											   Removed 05/18/95
-	if(dir[f.dir]->misc&DIR_TFREE && cur_cps)  Looks like it gave back double
-        starttime+=f.size/(ulong)cur_cps;
-*/
-    f.altpath=batdn_alt[i];
-    if(xfrprot==-1 || (prot[xfrprot]->misc&PROT_DSZLOG && checkprotlog(f))
-        || !(prot[xfrprot]->misc&PROT_DSZLOG)) {
-        if(dir[f.dir]->misc&DIR_TFREE && cur_cps)
-            starttime+=f.size/(ulong)cur_cps;
-        downloadfile(f);
-        closefile(f);
-        batdn_total--;
-        for(j=i;j<batdn_total;j++) {
-            strcpy(batdn_name[j],batdn_name[j+1]);
-            batdn_dir[j]=batdn_dir[j+1];
-            batdn_cdt[j]=batdn_cdt[j+1];
-            batdn_alt[j]=batdn_alt[j+1];
-            batdn_size[j]=batdn_size[j+1];
-            batdn_offset[j]=batdn_offset[j+1]; } }
-    else i++; }
-}
-
-/****************************************************************************/
-/* Adds a list of files to the batch download queue 						*/
-/****************************************************************************/
-void batch_add_list(char *list)
-{
-    char str[128];
-	int file,i,j,k;
-    FILE *stream;
-	file_t	f;
-
-if((stream=fnopen(&file,list,O_RDONLY))!=NULL) {
-	bputs(text[SearchingAllLibs]);
-	while(!feof(stream)) {
-		checkline();
-		if(!online)
-			break;
-        if(!fgets(str,127,stream))
-            break;
-        truncsp(str);
-        sprintf(f.name,"%.12s",str);
-		strupr(f.name);
-		lncntr=0;
-        for(i=k=0;i<usrlibs;i++) {
-            for(j=0;j<usrdirs[i];j++,k++) {
-                outchar('.');
-                if(k && !(k%5))
-                    bputs("\b\b\b\b\b     \b\b\b\b\b");
-                if(findfile(usrdir[i][j],f.name))
-                    break; }
-            if(j<usrdirs[i])
-                break; }
-        if(i<usrlibs) {
-            f.dir=usrdir[i][j];
-            getfileixb(&f);
-            f.size=0;
-            getfiledat(&f);
-            if(f.size==-1L)
-				bprintf(text[FileIsNotOnline],f.name);
-            else
-                addtobatdl(f); } }
-    fclose(stream);
-	remove(list);
-	CRLF; }
-}
-
-/****************************************************************************/
-/* Creates a text file named NEWFILES.DAT in the temp directory that        */
-/* all new files since p-date. Returns number of files in list.             */
-/****************************************************************************/
-ulong create_filelist(char *name, char mode)
-{
-    char str[256];
-	int i,j,d,file;
-	ulong	l,k;
-
-bprintf(text[CreatingFileList],name);
-sprintf(str,"%s%s",temp_dir,name);
-if((file=nopen(str,O_CREAT|O_WRONLY|O_APPEND))==-1) {
-	errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_APPEND);
-    return(0); }
-k=0;
-if(mode&FL_ULTIME) {
-    sprintf(str,"New files since: %s\r\n",timestr(&ns_time));
-    write(file,str,strlen(str)); }
-for(i=d=0;i<usrlibs;i++) {
-	for(j=0;j<usrdirs[i];j++,d++) {
-		outchar('.');
-		if(d && !(d%5))
-			bputs("\b\b\b\b\b     \b\b\b\b\b");
-		if(mode&FL_ULTIME /* New-scan */
-			&& (lib[usrlib[i]]->offline_dir==usrdir[i][j]
-			|| dir[usrdir[i][j]]->misc&DIR_NOSCAN))
-            continue;
-        l=listfiles(usrdir[i][j],nulstr,file,mode);
-		if((long)l==-1)
-            break;
-        k+=l; }
-    if(j<usrdirs[i])
-        break; }
-if(k>1) {
-    sprintf(str,"\r\n%d Files Listed.\r\n",k);
-    write(file,str,strlen(str)); }
-close(file);
-if(k)
-    bprintf(text[CreatedFileList],name);
-else {
-    bputs(text[NoFiles]);
-    sprintf(str,"%s%s",temp_dir,name);
-    remove(str); }
-strcpy(temp_file,name);
-strcpy(temp_uler,"File List");
-return(k);
-}
-
diff --git a/src/sbbs2/xfer_lo.c b/src/sbbs2/xfer_lo.c
deleted file mode 100644
index 21fb1e7f96c68628c259060db81fbc989eec13c6..0000000000000000000000000000000000000000
--- a/src/sbbs2/xfer_lo.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#line 1 "XFER_LO.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* Prompts user for file specification. <CR> is *.* and .* is assumed.      */
-/* Returns padded file specification.                                       */
-/* Returns NULL if input was aborted.                                       */
-/****************************************************************************/
-char *getfilespec(char *str)
-{
-bputs(text[FileSpecStarDotStar]);
-if(!getstr(str,12,K_UPPER))
-    strcpy(str,"*.*");
-else if(!strchr(str,'.') && strlen(str)<=8)
-    strcat(str,".*");
-if(sys_status&SS_ABORT)
-    return(0);
-return(str);
-}
-
-/****************************************************************************/
-/* Turns FILE.EXT into FILE    .EXT                                         */
-/****************************************************************************/
-char *padfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0;c<8;c++)
-    if(filename[c]=='.' || !filename[c]) break;
-    else str[c]=filename[c];
-d=c;
-if(filename[c]=='.') c++;
-while(d<8)
-    str[d++]=SP;
-str[d++]='.';
-while(d<12)
-    if(!filename[c]) break;
-    else str[d++]=filename[c++];
-while(d<12)
-    str[d++]=SP;
-str[d]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Turns FILE    .EXT into FILE.EXT                                         */
-/****************************************************************************/
-char *unpadfname(char *filename, char *str)
-{
-    char c,d;
-
-for(c=0,d=0;c<strlen(filename);c++)
-    if(filename[c]!=SP) str[d++]=filename[c];
-str[d]=0;
-return(str);
-}
-
-/****************************************************************************/
-/* Checks to see if filename matches filespec. Returns 1 if yes, 0 if no    */
-/****************************************************************************/
-char filematch(char *filename, char *filespec)
-{
-    char c;
-
-for(c=0;c<8;c++) /* Handle Name */
-    if(filespec[c]=='*') break;
-    else if(filespec[c]=='?') continue;
-    else if(filename[c]!=filespec[c]) return(0);
-for(c=9;c<12;c++)
-    if(filespec[c]=='*') break;
-    else if(filespec[c]=='?') continue;
-    else if(filename[c]!=filespec[c]) return(0);
-return(1);
-}
-
-/****************************************************************************/
-/* Deletes all files in dir 'path' that match file spec 'spec'              */
-/****************************************************************************/
-int delfiles(char *inpath, char *spec)
-{
-	char str[256],path[128],done;
-    int files=0;
-    struct ffblk ff;
-
-strcpy(path,inpath);
-backslash(path);
-sprintf(str,"%s%s",path,spec);
-done=findfirst(str,&ff,0);
-while(!done) {
-    sprintf(str,"%s%s",path,ff.ff_name);
-	_chmod(str,1,FA_NORMAL);	// Incase it's been marked RDONLY
-    if(remove(str))
-        errormsg(WHERE,ERR_REMOVE,str,0);
-    else
-        files++;
-    done=findnext(&ff); }
-return(files);
-}
-
-/*****************************************************************************/
-/* Checks the filename 'fname' for invalid symbol or character sequences     */
-/*****************************************************************************/
-char checkfname(char *fname)
-{
-	char str[256],c=0,d;
-
-if(strcspn(fname,"\\/|<>+[]:=\";,%")!=strlen(fname)) {
-	sprintf(str,"Suspicious filename attempt: '%s'",fname);
-    errorlog(str);
-	return(0); }
-if(strstr(fname,".."))
-	return(0);
-if(strcspn(fname,".")>8)
-	return(0);
-d=strlen(fname);
-while(c<d) {
-	if(fname[c]<=SP || fname[c]&0x80)
-		return(0);
-	c++; }
-return(1);
-}
-
-/**************************************************************************/
-/* Add file 'f' to batch download queue. Return 1 if successful, 0 if not */
-/**************************************************************************/
-char addtobatdl(file_t f)
-{
-    char str[256],tmp2[256];
-    uint i;
-	ulong totalcdt, totalsize, totaltime;
-
-if(useron.rest&FLAG('D')) {
-	bputs(text[R_Download]);
-	return(0); }
-/***
-sprintf(str,"%s%s",f.altpath>0 && f.altpath<=altpaths ? altpath[f.altpath-1]
-    : dir[f.dir]->path,unpadfname(f.name,tmp));
-***/
-for(i=0;i<batdn_total;i++) {
-    if(!strcmp(batdn_name[i],f.name) && f.dir==batdn_dir[i]) {
-		bprintf(text[FileAlreadyInQueue],f.name);
-        return(0); } }
-if(f.size<=0 /* !fexist(str) */) {
-	bprintf(text[CantAddToQueue],f.name);
-    bputs(text[FileIsNotOnline]);
-    return(0); }
-if(batdn_total>=max_batdn) {
-	bprintf(text[CantAddToQueue],f.name);
-    bputs(text[BatchDlQueueIsFull]);
-    return(0); }
-for(i=0,totalcdt=0;i<batdn_total;i++)
-    totalcdt+=batdn_cdt[i];
-if(dir[f.dir]->misc&DIR_FREE) f.cdt=0L;
-totalcdt+=f.cdt;
-if(!(useron.exempt&FLAG('D')) && totalcdt>useron.cdt+useron.freecdt) {
-	bprintf(text[CantAddToQueue],f.name);
-	bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt+useron.freecdt,tmp));
-    return(0); }
-if(!chk_ar(dir[f.dir]->dl_ar,useron)) {
-	bprintf(text[CantAddToQueue],f.name);
-	bputs(text[CantDownloadFromDir]);
-	return(0); }
-for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
-    totalsize+=batdn_size[i];
-	if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
-		totaltime+=batdn_size[i]/(ulong)cur_cps; }
-totalsize+=f.size;
-if(!(dir[f.dir]->misc&DIR_TFREE) && cur_cps)
-	totaltime+=f.size/(ulong)cur_cps;
-if(!(useron.exempt&FLAG('T')) && totaltime>timeleft) {
-	bprintf(text[CantAddToQueue],f.name);
-    bputs(text[NotEnoughTimeToDl]);
-    return(0); }
-strcpy(batdn_name[batdn_total],f.name);
-batdn_dir[batdn_total]=f.dir;
-batdn_cdt[batdn_total]=f.cdt;
-batdn_offset[batdn_total]=f.datoffset;
-batdn_size[batdn_total]=f.size;
-batdn_alt[batdn_total]=f.altpath;
-batdn_total++;
-openfile(f);
-bprintf(text[FileAddedToBatDlQueue]
-    ,f.name,batdn_total,max_batdn,ultoac(totalcdt,tmp)
-    ,ultoac(totalsize,tmp2)
-    ,sectostr(totalsize/(ulong)cur_cps,str));
-return(1);
-}
-
-/****************************************************************************/
-/* This function returns the command line for the temp file extension for	*/
-/* current user online. 													*/
-/****************************************************************************/
-char *temp_cmd(void)
-{
-	int i;
-
-if(!total_fcomps) {
-	errormsg(WHERE,ERR_CHK,"compressable file types",0);
-	return(nulstr); }
-for(i=0;i<total_fcomps;i++)
-	if(!stricmp(useron.tmpext,fcomp[i]->ext)
-		&& chk_ar(fcomp[i]->ar,useron))
-		return(fcomp[i]->cmd);
-return(fcomp[0]->cmd);
-}
-
diff --git a/src/sbbs2/xfer_mid.c b/src/sbbs2/xfer_mid.c
deleted file mode 100644
index 4d1cbfe6ce5ec44eedbadb6a573f6c255d507234..0000000000000000000000000000000000000000
--- a/src/sbbs2/xfer_mid.c
+++ /dev/null
@@ -1,792 +0,0 @@
-#line 1 "XFER_MID.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-/****************************************************************************/
-/* This function is called when a file is unsuccessfully downloaded.        */
-/* It logs the tranfer time and checks for possible leech protocol use.     */
-/****************************************************************************/
-void notdownloaded(ulong size, time_t start, time_t end)
-{
-    char str[256],tmp2[256];
-
-sprintf(str,"Estimated Time: %s  Transfer Time: %s"
-    ,sectostr(cur_cps ? size/cur_cps : 0,tmp)
-    ,sectostr((uint)end-start,tmp2));
-logline(nulstr,str);
-if(leech_pct && cur_cps                 /* leech detection */
-    && end-start>=leech_sec
-    && end-start>=(double)(size/cur_cps)*(double)leech_pct/100.0) {
-    sprintf(str,"Possible use of leech protocol (leech=%u  downloads=%u)"
-        ,useron.leech+1,useron.dls);
-    errorlog(str);
-    useron.leech=adjustuserrec(useron.number,U_LEECH,2,1); }
-}
-
-/****************************************************************************/
-/* List detailed information about the files in 'filespec'. Prompts for     */
-/* action depending on 'mode.'                                              */
-/* Returns number of files matching filespec that were found                */
-/****************************************************************************/
-int listfileinfo(uint dirnum, char *filespec, char mode)
-{
-	uchar str[258],path[258],dirpath[256],done=0,ch,fname[13],ext[513];
-	uchar HUGE16 *ixbbuf,*usrxfrbuf=NULL,*p;
-    int i,j,found=0,file;
-    ulong l,m,usrcdt,usrxfrlen;
-    time_t start,end;
-    file_t f;
-
-sprintf(str,"%sXFER.IXT",data_dir);
-if(mode==FI_USERXFER && flength(str)>0L) {
-    if((file=nopen(str,O_RDONLY))==-1) {
-        errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
-        return(0); }
-    usrxfrlen=filelength(file);
-	if((usrxfrbuf=MALLOC(usrxfrlen))==NULL) {
-        close(file);
-        errormsg(WHERE,ERR_ALLOC,str,usrxfrlen);
-        return(0); }
-    if(read(file,usrxfrbuf,usrxfrlen)!=usrxfrlen) {
-        close(file);
-		FREE(usrxfrbuf);
-        errormsg(WHERE,ERR_READ,str,usrxfrlen);
-        return(0); }
-    close(file); }
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1)
-    return(0);
-l=filelength(file);
-if(!l) {
-    close(file);
-    return(0); }
-if((ixbbuf=(char *)MALLOC(l))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,l);
-    return(0); }
-if(lread(file,ixbbuf,l)!=l) {
-    close(file);
-    errormsg(WHERE,ERR_READ,str,l);
-	FREE((char *)ixbbuf);
-    if(usrxfrbuf)
-		FREE(usrxfrbuf);
-    return(0); }
-close(file);
-sprintf(str,"%s%s.DAT",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) {
-    errormsg(WHERE,ERR_READ,str,O_RDONLY);
-	FREE((char *)ixbbuf);
-    if(usrxfrbuf)
-		FREE(usrxfrbuf);
-    return(0); }
-close(file);
-m=0;
-while(online && !done && m<l) {
-	if(mode==FI_REMOVE && dir_op(dirnum))
-        action=NODE_SYSP;
-    else action=NODE_LFIL;
-    if(msgabort()) {
-        found=-1;
-        break; }
-    for(i=0;i<12 && m<l;i++)
-        if(i==8)
-            str[i]='.';
-        else
-            str[i]=ixbbuf[m++];     /* Turns FILENAMEEXT into FILENAME.EXT */
-    str[i]=0;
-    unpadfname(str,fname);
-    if(filespec[0] && !filematch(str,filespec)) {
-        m+=11;
-        continue; }
-    f.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
-    f.dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
-        |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
-    f.datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
-        |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24);
-    m+=11;
-    if(mode==FI_OLD && f.datedled>ns_time)
-        continue;
-    if((mode==FI_OLDUL || mode==FI_OLD) && f.dateuled>ns_time)
-        continue;
-	f.dir=curdirnum=dirnum;
-    strcpy(f.name,str);
-	f.size=0;
-    getfiledat(&f);
-	if(mode==FI_OFFLINE && f.size>=0)
-		continue;
-    if(f.altpath>0 && f.altpath<=altpaths)
-        strcpy(dirpath,altpath[f.altpath-1]);
-    else
-        strcpy(dirpath,dir[f.dir]->path);
-    if(mode==FI_CLOSE && !f.opencount)
-        continue;
-    if(mode==FI_USERXFER) {
-        for(p=usrxfrbuf;p<usrxfrbuf+usrxfrlen;p+=24) {
-            sprintf(str,"%17.17s",p);   /* %4.4u %12.12s */
-            if(!strcmp(str+5,f.name) && useron.number==atoi(str))
-                break; }
-        if(p>=usrxfrbuf+usrxfrlen) /* file wasn't found */
-            continue; }
-	if((mode==FI_REMOVE) && (!dir_op(dirnum) && strcmpi(f.uler
-		,useron.alias) && !(useron.exempt&FLAG('R'))))
-		continue;
-    found++;
-	if(mode==FI_INFO) {
-		if(!viewfile(f,1)) {
-			done=1;
-			found=-1; } }
-	else
-		fileinfo(f);
-    if(mode==FI_CLOSE) {
-        if(!noyes(text[CloseFileRecordQ])) {
-            f.opencount=0;
-            putfiledat(f); } }
-    else if(mode==FI_REMOVE || mode==FI_OLD || mode==FI_OLDUL
-        || mode==FI_OFFLINE) {
-        SYNC;
-        CRLF;
-        if(f.opencount) {
-            mnemonics(text[QuitOrNext]);
-            strcpy(str,"Q\r"); }
-		else if(dir_op(dirnum)) {
-            mnemonics(text[SysopRemoveFilePrompt]);
-			strcpy(str,"VEFMCQR\r"); }
-        else if(useron.exempt&FLAG('R')) {
-            mnemonics(text[RExemptRemoveFilePrompt]);
-			strcpy(str,"VEMQR\r"); }
-        else {
-            mnemonics(text[UserRemoveFilePrompt]);
-			strcpy(str,"VEQR\r"); }
-        switch(getkeys(str,0)) {
-			case 'V':
-				viewfilecontents(f);
-				CRLF;
-				ASYNC;
-				pause();
-				m-=F_IXBSIZE;
-				continue;
-            case 'E':   /* edit file information */
-				if(dir_op(dirnum)) {
-                    bputs(text[EditFilename]);
-                    strcpy(str,fname);
-					getstr(str,12,K_EDIT|K_AUTODEL|K_UPPER);
-                    if(strcmp(str,fname)) { /* rename */
-                        padfname(str,path);
-                        if(findfile(f.dir,path))
-                            bprintf(text[FileAlreadyThere],path);
-                        else {
-                            sprintf(path,"%s%s",dirpath,fname);
-                            sprintf(tmp,"%s%s",dirpath,str);
-                            if(rename(path,tmp))
-                                bprintf(text[CouldntRenameFile],path,tmp);
-                            else {
-                                bprintf(text[FileRenamed],path,tmp);
-                                strcpy(fname,str);
-                                removefiledat(f);
-                                strcpy(f.name,padfname(str,tmp));
-                                addfiledat(&f); } } } }
-                bputs(text[EditDescription]);
-				getstr(f.desc,LEN_FDESC,K_LINE|K_EDIT|K_AUTODEL);
-                if(f.misc&FM_EXTDESC) {
-					if(!noyes(text[DeleteExtDescriptionQ])) {
-                        remove(str);
-                        f.misc&=~FM_EXTDESC; } }
-				if(!dir_op(dirnum)) {
-                    putfiledat(f);
-                    break; }
-                bputs(text[EditUploader]);
-				getstr(f.uler,LEN_ALIAS,K_UPRLWR|K_EDIT|K_AUTODEL);
-                ultoa(f.cdt,str,10);
-                bputs(text[EditCreditValue]);
-				getstr(str,7,K_NUMBER|K_EDIT|K_AUTODEL);
-                f.cdt=atol(str);
-                itoa(f.timesdled,str,10);
-                bputs(text[EditTimesDownloaded]);
-				getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL);
-                f.timesdled=atoi(str);
-                if(f.opencount) {
-                    itoa(f.opencount,str,10);
-                    bputs(text[EditOpenCount]);
-					getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-                    f.opencount=atoi(str); }
-                if(altpaths || f.altpath) {
-                    itoa(f.altpath,str,10);
-                    bputs(text[EditAltPath]);
-					getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
-                    f.altpath=atoi(str);
-                    if(f.altpath>altpaths)
-                        f.altpath=0; }
-                putfiledat(f);
-				inputnstime(&f.dateuled);
-				update_uldate(f);
-                break;
-            case 'F':   /* delete file only */
-                sprintf(str,"%s%s",dirpath,fname);
-                if(!fexist(str))
-                    bputs(text[FileNotThere]);
-                else {
-                    if(!noyes(text[AreYouSureQ])) {
-                        if(remove(str))
-                            bprintf(text[CouldntRemoveFile],str);
-                        else {
-                            sprintf(tmp,"Deleted %s",str);
-                            logline(nulstr,tmp); } } }
-                break;
-            case 'R':   /* remove file from database */
-                if(noyes(text[AreYouSureQ]))
-                    break;
-                removefiledat(f);
-                sprintf(str,"Removed %s from %s %s",f.name
-                    ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-                logline("U-",str);
-                sprintf(str,"%s%s",dirpath,fname);
-                if(fexist(str)) {
-					if(dir_op(dirnum)) {
-                        if(!noyes(text[DeleteFileQ])) {
-                            if(remove(str))
-                                bprintf(text[CouldntRemoveFile],str);
-                            else {
-                                sprintf(tmp,"Deleted %s",str);
-                                logline(nulstr,tmp); } } }
-                    else if(remove(str))    /* always remove if not sysop */
-                        bprintf(text[CouldntRemoveFile],str); }
-				if(dir_op(dirnum) || useron.exempt&FLAG('R')) {
-                    i=lib[dir[f.dir]->lib]->offline_dir;
-                    if(i!=dirnum && i!=(int)INVALID_DIR
-                        && !findfile(i,f.name)) {
-                        sprintf(str,text[AddToOfflineDirQ]
-                            ,fname,lib[dir[i]->lib]->sname,dir[i]->sname);
-                        if(yesno(str)) {
-							getextdesc(f.dir,f.datoffset,ext);
-                            f.dir=i;
-							addfiledat(&f);
-							if(f.misc&FM_EXTDESC)
-								putextdesc(f.dir,f.datoffset,ext); } } }
-				if(dir_op(dirnum) || strcmpi(f.uler,useron.alias)) {
-                    if(noyes(text[RemoveCreditsQ]))
-/* Fall through */      break; }
-            case 'C':   /* remove credits only */
-                if((i=matchuser(f.uler))==0) {
-					bputs(text[UnknownUser]);
-                    break; }
-				if(dir_op(dirnum)) {
-					usrcdt=(ulong)(f.cdt*(dir[f.dir]->up_pct/100.0));
-                    if(f.timesdled)     /* all downloads */
-                        usrcdt+=(ulong)((long)f.timesdled
-							*f.cdt*(dir[f.dir]->dn_pct/100.0));
-                    ultoa(usrcdt,str,10);
-                    bputs(text[CreditsToRemove]);
-					getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL);
-                    f.cdt=atol(str); }
-                usrcdt=adjustuserrec(i,U_CDT,10,-f.cdt);
-                if(i==useron.number)
-                    useron.cdt=usrcdt;
-                sprintf(str,text[FileRemovedUserMsg]
-					,f.name,f.cdt ? ultoac(f.cdt,tmp) : text[No]);
-                putsmsg(i,str);
-                usrcdt=adjustuserrec(i,U_ULB,10,-f.size);
-                if(i==useron.number)
-                    useron.ulb=usrcdt;
-                usrcdt=adjustuserrec(i,U_ULS,5,-1);
-                if(i==useron.number)
-                    useron.uls=usrcdt;
-                break;
-            case 'M':   /* move the file to another dir */
-				CRLF;
-                for(i=0;i<usrlibs;i++)
-                    bprintf(text[MoveToLibLstFmt],i+1,lib[usrlib[i]]->lname);
-                SYNC;
-                bprintf(text[MoveToLibPrompt],dir[dirnum]->lib+1);
-				if((i=getnum(usrlibs))==-1)
-                    continue;
-                if(!i)
-                    i=dir[dirnum]->lib;
-                else
-                    i--;
-                CRLF;
-                for(j=0;j<usrdirs[i];j++)
-                    bprintf(text[MoveToDirLstFmt]
-                        ,j+1,dir[usrdir[i][j]]->lname);
-                SYNC;
-                bprintf(text[MoveToDirPrompt],usrdirs[i]);
-                if((j=getnum(usrdirs[i]))==-1)
-                    continue;
-                if(!j)
-                    j=usrdirs[i]-1;
-                else j--;
-                CRLF;
-                if(findfile(usrdir[i][j],f.name)) {
-                    bprintf(text[FileAlreadyThere],f.name);
-                    break; }
-				getextdesc(f.dir,f.datoffset,ext);
-                removefiledat(f);
-				if(f.dir==upload_dir || f.dir==sysop_dir)
-					f.dateuled=time(NULL);
-                f.dir=usrdir[i][j];
-                addfiledat(&f);
-                bprintf(text[MovedFile],f.name
-                    ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-                sprintf(str,"Moved %s to %s %s",f.name
-                    ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-                logline(nulstr,str);
-                if(!f.altpath) {    /* move actual file */
-                    sprintf(str,"%s%s",dir[dirnum]->path,fname);
-                    if(fexist(str)) {
-                        sprintf(path,"%s%s",dir[f.dir]->path,fname);
-                        mv(str,path,0); } }
-				if(f.misc&FM_EXTDESC)
-					putextdesc(f.dir,f.datoffset,ext);
-                break;
-            case 'Q':   /* quit */
-                found=-1;
-                done=1;
-                break; } }
-    else if(mode==FI_DOWNLOAD || mode==FI_USERXFER) {
-        sprintf(path,"%s%s",dirpath,fname);
-        if(f.size<1L) { /* getfiledat will set this to -1 if non-existant */
-            SYNC;       /* and 0 byte files shouldn't be d/led */
-            mnemonics(text[QuitOrNext]);
-            if(getkeys("\rQ",0)=='Q') {
-                found=-1;
-                break; }
-            continue; }
-        if(!(dir[f.dir]->misc&DIR_FREE) && !(useron.exempt&FLAG('D'))
-			&& f.cdt>(useron.cdt+useron.freecdt)) {
-            SYNC;
-			bprintf(text[YouOnlyHaveNCredits]
-				,ultoac(useron.cdt+useron.freecdt,tmp));
-            mnemonics(text[QuitOrNext]);
-            if(getkeys("\rQ",0)=='Q') {
-                found=-1;
-                break; }
-            continue; }
-		if(!chk_ar(dir[f.dir]->dl_ar,useron)) {
-			SYNC;
-			bputs(text[CantDownloadFromDir]);
-			mnemonics(text[QuitOrNext]);
-            if(getkeys("\rQ",0)=='Q') {
-                found=-1;
-                break; }
-            continue; }
-		if(!(dir[f.dir]->misc&DIR_TFREE) && f.timetodl>timeleft && !dir_op(dirnum)
-			&& !(useron.exempt&FLAG('T'))) {
-            SYNC;
-            bputs(text[NotEnoughTimeToDl]);
-            mnemonics(text[QuitOrNext]);
-            if(getkeys("\rQ",0)=='Q') {
-                found=-1;
-                break; }
-            continue; }
-        menu("DLPROT");
-        openfile(f);
-        SYNC;
-        mnemonics(text[ProtocolBatchQuitOrNext]);
-        strcpy(str,"BQ\r");
-        for(i=0;i<total_prots;i++)
-			if(prot[i]->dlcmd[0]
-				&& chk_ar(prot[i]->ar,useron)) {
-                sprintf(tmp,"%c",prot[i]->mnemonic);
-                strcat(str,tmp); }
-//		  ungetkey(useron.prot);
-		ch=getkeys(str,0);
-        if(ch=='Q') {
-            found=-1;
-            done=1; }
-        else if(ch=='B') {
-            if(!addtobatdl(f)) {
-                closefile(f);
-                break; } }
-        else if(ch!=CR) {
-            for(i=0;i<total_prots;i++)
-				if(prot[i]->dlcmd[0] && prot[i]->mnemonic==ch
-					&& chk_ar(prot[i]->ar,useron))
-                    break;
-            if(i<total_prots) {
-				if(online==ON_LOCAL) {
-					bputs(text[EnterPath]);
-					if(getstr(path,60,K_UPPER|K_LINE)) {
-						backslash(path);
-						strcat(path,fname);
-						sprintf(str,"%s%s",dirpath,fname);
-						if(!mv(str,path,1))
-							downloadfile(f);
-						for(j=0;j<total_dlevents;j++)
-							if(!stricmp(dlevent[j]->ext,f.name+9)
-								&& chk_ar(dlevent[j]->ar,useron)) {
-								bputs(dlevent[j]->workstr);
-								external(cmdstr(dlevent[j]->cmd,path,nulstr
-									,NULL)
-									,EX_OUTL);
-								CRLF; }
-							} }
-				else {
-					delfiles(temp_dir,"*.*");
-					if(dir[f.dir]->seqdev) {
-						lncntr=0;
-						seqwait(dir[f.dir]->seqdev);
-						bprintf(text[RetrievingFile],fname);
-						sprintf(str,"%s%s",dirpath,fname);
-						sprintf(path,"%s%s",temp_dir,fname);
-						mv(str,path,1); /* copy the file to temp dir */
-						getnodedat(node_num,&thisnode,1);
-						thisnode.aux=0xf0;
-						putnodedat(node_num,thisnode);
-						CRLF; }
-					for(j=0;j<total_dlevents;j++)
-						if(!stricmp(dlevent[j]->ext,f.name+9)
-							&& chk_ar(dlevent[j]->ar,useron)) {
-							bputs(dlevent[j]->workstr);
-							external(cmdstr(dlevent[j]->cmd,path,nulstr,NULL)
-								,EX_OUTL);
-							CRLF; }
-					getnodedat(node_num,&thisnode,1);
-					action=NODE_DLNG;
-					unixtodos(now+f.timetodl,&date,&curtime);
-					thisnode.aux=(curtime.ti_hour*60)+curtime.ti_min;
-					putnodedat(node_num,thisnode); /* calculate ETA */
-					start=time(NULL);
-					j=protocol(cmdstr(prot[i]->dlcmd,path,nulstr,NULL),0);
-					end=time(NULL);
-					if(dir[f.dir]->misc&DIR_TFREE)
-						starttime+=end-start;
-					if(prot[i]->misc&PROT_DSZLOG) {
-						if(checkprotlog(f))
-							downloadfile(f);
-						else
-							notdownloaded(f.size,start,end); }
-					else {
-						if(!j)
-							downloadfile(f);
-						else {
-							bprintf(text[FileNotSent],f.name);
-							notdownloaded(f.size,start,end); } }
-					delfiles(temp_dir,"*.*");
-					autohangup(); } } }
-        closefile(f); }
-    if(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?')) break; }
-FREE((char *)ixbbuf);
-if(usrxfrbuf)
-	FREE(usrxfrbuf);
-return(found);
-}
-
-
-/****************************************************************************/
-/* Checks  directory data file for 'filename' (must be padded). If found,   */
-/* it returns the 1, else returns 0.                                        */
-/* Called from upload and bulkupload                                        */
-/****************************************************************************/
-char findfile(uint dirnum, char *filename)
-{
-	char str[256],c,fname[13],HUGE16 *ixbbuf;
-    int file;
-    ulong length,l;
-
-sprintf(fname,"%.12s",filename);
-strupr(fname);
-for(c=8;c<12;c++)   /* Turn FILENAME.EXT into FILENAMEEXT */
-    fname[c]=fname[c+1];
-sprintf(str,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
-if((file=nopen(str,O_RDONLY))==-1) return(0);
-length=filelength(file);
-if(!length) {
-    close(file);
-    return(0); }
-if((ixbbuf=(char *)MALLOC(length))==NULL) {
-    close(file);
-    errormsg(WHERE,ERR_ALLOC,str,length);
-    return(0); }
-if(lread(file,ixbbuf,length)!=length) {
-    close(file);
-    errormsg(WHERE,ERR_READ,str,length);
-	FREE((char *)ixbbuf);
-    return(0); }
-close(file);
-for(l=0;l<length;l+=F_IXBSIZE) {
-    for(c=0;c<11;c++)
-        if(fname[c]!=toupper(ixbbuf[l+c])) break;
-    if(c==11) break; }
-FREE((char *)ixbbuf);
-if(l!=length)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Prints one file's information on a single line to a file 'file'          */
-/****************************************************************************/
-void listfiletofile(char *fname, char HUGE16 *buf, uint dirnum, int file)
-{
-    char str[256],exist=1;
-    uchar alt;
-    ulong cdt;
-
-strcpy(str,fname);
-if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC)
-    strcat(str,"+");
-else
-    strcat(str," ");
-write(file,str,13);
-getrec((char *)buf,F_ALTPATH,2,str);
-alt=(uchar)ahtoul(str);
-sprintf(str,"%s%s",alt>0 && alt<=altpaths ? altpath[alt-1]
-    : dir[dirnum]->path,unpadfname(fname,tmp));
-if(dir[dirnum]->misc&DIR_FCHK && !fexist(str))
-    exist=0;
-getrec((char *)buf,F_CDT,LEN_FCDT,str);
-cdt=atol(str);
-if(!cdt)
-    strcpy(str,"   FREE");
-else
-    sprintf(str,"%7lu",cdt);
-if(exist)
-    strcat(str," ");
-else
-    strcat(str,"-");
-write(file,str,8);
-getrec((char *)buf,F_DESC,LEN_FDESC,str);
-write(file,str,strlen(str));
-write(file,crlf,2);
-}
-
-
-
-/****************************************************************************/
-/* Handles start and stop routines for transfer protocols                   */
-/****************************************************************************/
-int protocol(char *cmdline, int cd)
-{
-	char tmp[128];
-    int i;
-
-sprintf(tmp,"%sPROTOCOL.LOG",node_dir);
-remove(tmp);                            /* Deletes the protocol log */
-if(useron.misc&AUTOHANG)
-	autohang=1;
-else
-	autohang=yesno(text[HangUpAfterXferQ]);
-if(sys_status&SS_ABORT) {				/* if ctrl-c */
-	autohang=0;
-	return(-1); }
-bputs(text[StartXferNow]);
-RIOSYNC(0);
-lprintf("%s\r\n",cmdline);
-if(cd) {
-	if(temp_dir[1]==':')    /* fix for DSZ */
-		setdisk(toupper(temp_dir[0])-'A');
-	strcpy(tmp,temp_dir);
-	tmp[strlen(tmp)-1]=0;	/* take off '\' */
-	if(chdir(tmp))
-		errormsg(WHERE,ERR_CHDIR,tmp,0); }
-i=external(cmdline,EX_OUTL);	/* EX_CC removed because of error level prob */
-if(online==ON_REMOTE)
-    rioctl(IOFB);
-CRLF;
-if(autohang) sys_status|=SS_PAUSEOFF;	/* Pause off after download */
-return(i);
-}
-
-/****************************************************************************/
-/* Invokes the timed auto-hangup after transfer routine                     */
-/****************************************************************************/
-void autohangup()
-{
-    char a,c,k;
-
-SYNC;
-sys_status&=~SS_PAUSEOFF;		/* turn pause back on */
-rioctl(IOFI);
-if(!autohang) return;
-lncntr=0;
-bputs(text[Disconnecting]);
-attr(GREEN);
-outchar('[');
-for(c=9,a=0;c>-1 && online && !a;c--) {
-    checkline();
-    attr(LIGHTGRAY|HIGH);
-    bputs(itoa(c,tmp,10));
-    attr(GREEN);
-    outchar(']');
-	while((k=inkey(0))!=0 && online) {
-        if(toupper(k)=='H') {
-            c=0;
-            break; }
-        if(toupper(k)=='A') {
-            a=1;
-            break; } }
-	mswait(DELAY_AUTOHG);
-	if(!a) {
-		outchar(BS);
-		outchar(BS); } }
-if(c==-1) {
-    bputs(text[Disconnected]);
-    hangup(); }
-else
-    CRLF;
-}
-
-/****************************************************************************/
-/* Checks dsz compatible log file for errors in transfer                    */
-/* Returns 1 if the file in the struct file_t was successfuly transfered    */
-/****************************************************************************/
-char checkprotlog(file_t f)
-{
-	char str[256],size[128];
-    int file;
-    FILE *stream;
-
-sprintf(str,"%sPROTOCOL.LOG",node_dir);
-if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-    bprintf(text[FileNotSent],f.name);
-    if(f.dir<total_dirs)
-		sprintf(str,"Attempted to download %s (%s) from %s %s"
-			,f.name,ultoac(f.size,size)
-            ,lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-	else if(f.dir==total_dirs)
-        strcpy(str,"Attempted to download QWK packet");
-	else if(f.dir==total_dirs+1)
-		sprintf(str,"Attempted to download attached file: %s",f.name);
-    logline("D!",str);
-    return(0); }
-unpadfname(f.name,tmp);
-if(tmp[strlen(tmp)-1]=='.')     /* DSZ log uses FILE instead of FILE. */
-    tmp[strlen(tmp)-1]=0;       /* when there isn't an extension.     */
-while(!ferror(stream)) {
-    if(!fgets(str,256,stream))
-        break;
-    if(str[strlen(str)-2]==CR)
-        str[strlen(str)-2]=0;       /* chop off CRLF */
-    strupr(str);
-    if(strstr(str,tmp)) {   /* Only check for name, Bimodem doesn't put path */
-        logline(nulstr,str);
-		if(str[0]=='E' || str[0]=='L' || (str[6]==SP && str[7]=='0'))
-            break;          /* E for Error or L for Lost Carrier */
-        fclose(stream);     /* or only sent 0 bytes! */
-        return(1); } }
-fclose(stream);
-bprintf(text[FileNotSent],f.name);
-if(f.dir<total_dirs)
-    sprintf(str,"Attempted to download %s (%s) from %s %s",f.name
-        ,ultoac(f.size,tmp),lib[dir[f.dir]->lib]->sname,dir[f.dir]->sname);
-else
-    strcpy(str,"Attempted to download QWK packet");
-logline("D!",str);
-return(0);
-}
-
-/*****************************************************************************/
-/* View viewable file types from dir 'dirnum'                                */
-/* 'fspec' must be padded                                                    */
-/*****************************************************************************/
-void viewfiles(uint dirnum, char *fspec)
-{
-    char viewcmd[256];
-    int i;
-
-curdirnum=dirnum;	/* for ARS */
-sprintf(viewcmd,"%s%s",dir[dirnum]->path,fspec);
-if(!fexist(viewcmd)) {
-    bputs(text[FileNotFound]);
-    return; }
-padfname(fspec,tmp);
-truncsp(tmp);
-for(i=0;i<total_fviews;i++)
-	if(!strcmp(tmp+9,fview[i]->ext) && chk_ar(fview[i]->ar,useron)) {
-        strcpy(viewcmd,fview[i]->cmd);
-        break; }
-if(i==total_fviews) {
-	bprintf(text[NonviewableFile],tmp+9);
-    return; }
-sprintf(tmp,"%s%s",dir[dirnum]->path,fspec);
-if((i=external(cmdstr(viewcmd,tmp,tmp,NULL),EX_OUTL|EX_OUTR|EX_INR|EX_CC))!=0)
-	errormsg(WHERE,ERR_EXEC,viewcmd,i);    /* must of EX_CC to ^C */
-}
-
-/****************************************************************************/
-/* Compares filenames for ascending name sort								*/
-/****************************************************************************/
-int fnamecmp_a(char **str1, char **str2)
-{
-return(strncmp(*str1,*str2,11));
-}
-
-/****************************************************************************/
-/* Compares filenames for descending name sort								*/
-/****************************************************************************/
-int fnamecmp_d(char **str1, char **str2)
-{
-return(strncmp(*str2,*str1,11));
-}
-
-/****************************************************************************/
-/* Compares file upload dates for ascending date sort						*/
-/****************************************************************************/
-int fdatecmp_a(uchar **buf1, uchar **buf2)
-{
-	time_t date1,date2;
-
-date1=((*buf1)[14]|((long)(*buf1)[15]<<8)|((long)(*buf1)[16]<<16)
-	|((long)(*buf1)[17]<<24));
-date2=((*buf2)[14]|((long)(*buf2)[15]<<8)|((long)(*buf2)[16]<<16)
-	|((long)(*buf2)[17]<<24));
-if(date1>date2)	return(1);
-if(date1<date2)	return(-1);
-return(0);
-}
-
-/****************************************************************************/
-/* Compares file upload dates for descending date sort						*/
-/****************************************************************************/
-int fdatecmp_d(uchar **buf1, uchar **buf2)
-{
-	time_t date1,date2;
-
-date1=((*buf1)[14]|((long)(*buf1)[15]<<8)|((long)(*buf1)[16]<<16)
-	|((long)(*buf1)[17]<<24));
-date2=((*buf2)[14]|((long)(*buf2)[15]<<8)|((long)(*buf2)[16]<<16)
-	|((long)(*buf2)[17]<<24));
-if(date1>date2)	return(-1);
-if(date1<date2)	return(1);
-return(0);
-}
-
-/************************************************************************/
-/* Wait (for a limited period of time) for sequential dev to become 	*/
-/* available for file retrieval 										*/
-/************************************************************************/
-void seqwait(uint devnum)
-{
-	char loop=0;
-	int i;
-	time_t start;
-	node_t node;
-
-
-if(!devnum)
-	return;
-for(start=now=time(NULL);online && now-start<90;now=time(NULL)) {
-	if(msgabort())				/* max wait ^^^^ sec */
-		break;
-	getnodedat(node_num,&thisnode,1);	/* open and lock this record */
-	for(i=1;i<=sys_nodes;i++) {
-		if(i==node_num) continue;
-		getnodedat(i,&node,1);
-		if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-			&& node.action==NODE_RFSD && node.aux==devnum) {
-			putnodedat(i,node);
-			break; }
-		putnodedat(i,node); }
-	if(i>sys_nodes) {
-		thisnode.action=NODE_RFSD;
-		thisnode.aux=devnum;
-		putnodedat(node_num,thisnode);	/* write devnum, unlock, and ret */
-		return; }
-	putnodedat(node_num,thisnode);
-	if(!loop)
-		bprintf(text[WaitingForDeviceN],devnum);
-	loop=1;
-	mswait(100); }
-
-}
diff --git a/src/sbbs2/xfer_sec.c b/src/sbbs2/xfer_sec.c
deleted file mode 100644
index 4b3ec2afec904aa763ec79c1bcf593e146f6e21f..0000000000000000000000000000000000000000
--- a/src/sbbs2/xfer_sec.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#line 1 "XFER_SEC.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/*****************************************************/
-/* This file contains the single function xfer_sec() */
-/*****************************************************/
-
-#include "sbbs.h"
-
-void xfer_cfg_cmd();
-void xfer_ext_cmd(char ch);
-void xfer_str_cmd(char *str);
-
-void scandirs(char mode);
-
-extern char no_rip_menu;
-
-/****************************************************************************/
-/* Used to scan single or multiple directories. 'mode' is the scan type.    */
-/****************************************************************************/
-void scandirs(char mode)
-{
-	char ch,str[256];
-	int s;
-	uint i,k;
-
-if(!usrlibs) return;
-mnemonics(text[DirLibOrAll]);
-ch=getkeys("DLA\r",0);
-if(sys_status&SS_ABORT || ch==CR) {
-	lncntr=0;
-	return; }
-if(ch!='A') {
-	if(mode&FL_ULTIME) {			/* New file scan */
-		bprintf(text[NScanHdr],timestr(&ns_time));
-		str[0]=0; }
-	else if(mode==FL_NO_HDR) {		/* Search for a string */
-		if(!getfilespec(tmp))
-			return;
-		padfname(tmp,str); }
-	else if(mode==FL_FINDDESC) {	/* Find text in description */
-		if(!noyes(text[SearchExtendedQ]))
-			mode=FL_EXFIND;
-		if(sys_status&SS_ABORT) {
-			lncntr=0;
-			return; }
-		bputs(text[SearchStringPrompt]);
-		if(!getstr(str,40,K_LINE|K_UPPER)) {
-			lncntr=0;
-			return; } } }
-if(ch=='D') {
-	if((s=listfiles(usrdir[curlib][curdir[curlib]],str,0,mode))==-1)
-		return;
-	bputs("\r\1>");
-	if(s>1)
-		bprintf(text[NFilesListed],s);
-	else if(!s && !(mode&FL_ULTIME))
-		bputs(text[FileNotFound]);
-	return; }
-if(ch=='L') {
-	k=0;
-	for(i=0;i<usrdirs[curlib] && !msgabort();i++) {
-		attr(LIGHTGRAY);
-		outchar('.');
-		if(i && !(i%5))
-			bputs("\b\b\b\b\b     \b\b\b\b\b");
-		if(mode&FL_ULTIME	/* New-scan */
-			&& (lib[usrlib[curlib]]->offline_dir==usrdir[curlib][i]
-			|| dir[usrdir[curlib][i]]->misc&DIR_NOSCAN))
-			continue;
-		else if((s=listfiles(usrdir[curlib][i],str,0,mode))==-1)
-			return;
-		else k+=s; }
-	bputs("\r\1>");
-	if(k>1)
-		bprintf(text[NFilesListed],k);
-	else if(!k && !(mode&FL_ULTIME))
-		bputs(text[FileNotFound]);
-	return; }
-
-scanalldirs(mode);
-}
-
-/****************************************************************************/
-/* Scan all directories in all libraries for files							*/
-/****************************************************************************/
-void scanalldirs(char mode)
-{
-	char str[256];
-	int s;
-	uint i,j,k,d;
-
-if(!usrlibs) return;
-k=0;
-if(mode&FL_ULTIME) {			/* New file scan */
-	bprintf(text[NScanHdr],timestr(&ns_time));
-	str[0]=0; }
-else if(mode==FL_NO_HDR) {		/* Search for a string */
-	if(!getfilespec(tmp))
-		return;
-	padfname(tmp,str); }
-else if(mode==FL_FINDDESC) {	/* Find text in description */
-	if(!noyes(text[SearchExtendedQ]))
-		mode=FL_EXFIND;
-	if(sys_status&SS_ABORT) {
-		lncntr=0;
-		return; }
-	bputs(text[SearchStringPrompt]);
-	if(!getstr(str,40,K_LINE|K_UPPER)) {
-		lncntr=0;
-		return; } }
-for(i=d=0;i<usrlibs;i++) {
-	for(j=0;j<usrdirs[i] && !msgabort();j++,d++) {
-		attr(LIGHTGRAY);
-		outchar('.');
-		if(d && !(d%5))
-			bputs("\b\b\b\b\b     \b\b\b\b\b");
-		if(mode&FL_ULTIME /* New-scan */
-			&& (lib[usrlib[i]]->offline_dir==usrdir[i][j]
-			|| dir[usrdir[i][j]]->misc&DIR_NOSCAN))
-			continue;
-		else if((s=listfiles(usrdir[i][j],str,0,mode))==-1)
-			return;
-		else k+=s; }
-	if(j<usrdirs[i])   /* aborted */
-		break; }
-bputs("\r\1>");
-if(k>1)
-	bprintf(text[NFilesListed],k);
-else if(!k && !(mode&FL_ULTIME))
-	bputs(text[FileNotFound]);
-}
-
diff --git a/src/sbbs2/xtrn.c b/src/sbbs2/xtrn.c
deleted file mode 100644
index d7a1d14c93b6a3031db226cdaa8ff1bd56ac85df..0000000000000000000000000000000000000000
--- a/src/sbbs2/xtrn.c
+++ /dev/null
@@ -1,500 +0,0 @@
-#line 1 "XTRN.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/***************************************************************************/
-/* Functions that pertain to external programs (other EXE or COM programs) */
-/***************************************************************************/
-
-#include "sbbs.h"
-#include "cmdshell.h"
-
-#ifndef __FLAT__
-
-#include "spawno.h"
-
-void interrupt (*oldfunc)(void);
-
-/*****************************************************************************/
-/* Interrupt routine to expand WWIV Ctrl-C# codes into ANSI escape sequences */
-/*****************************************************************************/
-void interrupt wwiv_expand()
-{
-	char str[256],al;
-	static int ctrl_c;
-	int i,j;
-
-al=_AL;
-if(al!=3 && !ctrl_c)
-	oldfunc();
-else if(al!=3 && ctrl_c) {
-	ctrl_c=0;
-	if(useron.misc&ANSI) {
-		switch(al) {
-			default:
-				strcpy(str,"\x1b[0m");          /* low grey */
-				break;
-			case '1':
-				strcpy(str,"\x1b[0;1;36m");     /* high cyan */
-				break;
-			case '2':
-				strcpy(str,"\x1b[0;1;33m");     /* high yellow */
-				break;
-			case '3':
-				strcpy(str,"\x1b[0;35m");       /* low magenta */
-				break;
-			case '4':
-				strcpy(str,"\x1b[0;1;44m");     /* white on blue */
-				break;
-			case '5':
-				strcpy(str,"\x1b[0;32m");       /* low green */
-				break;
-			case '6':
-				strcpy(str,"\x1b[0;1;5;31m");   /* high blinking red */
-				break;
-			case '7':
-				strcpy(str,"\x1b[0;1;34m");     /* high blue */
-				break;
-			case '8':
-				strcpy(str,"\x1b[0;34m");       /* low blue */
-				break;
-			case '9':
-				strcpy(str,"\x1b[0;36m");       /* low cyan */
-				break; }
-		j=strlen(str);
-		for(i=0;i<j;i++) {
-			_AL=str[i];
-			oldfunc(); } } }
-else
-	ctrl_c=1;
-}
-#endif
-
-/****************************************************************************/
-/* Runs an external program directly using spawnvp							*/
-/****************************************************************************/
-int external(char *cmdline,char mode)
-{
-	char c,d,cmdlen,*arg[30],str[256],str2[256],fname[128],*p,x,y;
-	int i,file,rmode=0;
-	long l;
-	FILE *fp;
-#ifdef __OS2__
-	RESULTCODES rc;
-#endif
-
-if(cmdline[0]=='*') {   /* Baja module */
-	strcpy(str,cmdline+1);
-	p=strchr(str,SP);
-	if(p) {
-		strcpy(main_csi.str,p+1);
-		*p=0; }
-	return(exec_bin(str,&main_csi)); }
-
-#ifdef __MSDOS__
-nosound();						/* if page is on, turn off sound */
-#endif
-attr(LIGHTGRAY);                /* set attributes to normal text */
-
-strcpy(str,cmdline);		/* Set str to program name only */
-p=strchr(str,SP);
-if(p) *p=0;
-strcpy(fname,str);
-
-
-if(!(mode&EX_CC)) {
-	if(strcspn(cmdline,"<>|")!=strlen(cmdline))
-		mode|=EX_CC;	/* DOS I/O redirection; so, use command.com */
-	else {
-		i=strlen(str);
-		if(i>4 && !stricmp(str+(i-4),".BAT"))   /* specified .BAT file */
-			mode|=EX_CC;
-		else {
-			strcat(str,".BAT");
-			if(fexist(str)) 					/* and it's a .BAT file */
-				mode|=EX_CC; } } }
-
-p=strrchr(fname,'\\');
-if(!p) p=strchr(fname,':');
-if(!p) p=fname;
-else   p++;
-
-#ifndef __FLAT__
-
-for(i=0;i<total_swaps;i++)
-	if(!stricmp(p,swap[i]->cmd))
-		break;
-if(i<total_swaps)
-	mode|=EX_SWAP;
-
-#else
-
-for(i=0;i<total_os2pgms;i++)
-	if(!stricmp(p,os2pgm[i]->name))
-		break;
-if(i<total_os2pgms) {
-	mode|=EX_OS2;
-	if(os2pgm[i]->misc&OS2_POPEN)
-		mode|=EX_POPEN; }
-
-#endif
-
-#ifndef __FLAT__
-
-if(node_swap&SWAP_NONE || mode&EX_WWIV)
-	mode&=~EX_SWAP;
-
-if(mode&EX_SWAP) {
-	if(lclwy()>1 || lclwx()>1)
-        lputs(crlf);
-	lputs("Swapping...\r\n"); }
-
-#endif
-
-
-if(!(mode&EX_OS2) && mode&EX_CC)
-	sprintf(str,"%s /C %s",
-#ifdef __OS2__
-	node_comspec	 // Only used node_comspec for OS/2 ver
-#else
-	comspec
-#endif
-	,cmdline);
-
-else strcpy(str,cmdline);
-if(!(mode&EX_OS2) && strlen(str)>126) {
-	errormsg(WHERE,ERR_LEN,str,strlen(str));
-	errorlevel=-1;
-	return(-1); }
-
-#ifndef __FLAT__
-
-arg[0]=str;	/* point to the beginning of the string */
-cmdlen=strlen(str);
-for(c=0,d=1;c<cmdlen;c++)	/* Break up command line */
-	if(str[c]==SP) {
-		str[c]=0;			/* insert nulls */
-		arg[d++]=str+c+1; } /* point to the beginning of the next arg */
-arg[d]=0;
-
-#endif
-
-if(mode&EX_OUTR && (console&CON_R_ECHO))
-	rmode|=INT29R;
-if(mode&EX_OUTL)
-	rmode|=INT29L;
-if(mode&EX_INR && (console&CON_R_INPUT))
-	rmode|=INT16;
-
-#ifndef __FLAT__
-
-if(rmode)
-	ivhctl(rmode);	/* set DOS output interception vectors */
-
-if(mode&EX_WWIV) {	/* WWIV code expansion */
-	rioctl(CPTOFF); /* turn off ctrl-p translation */
-	oldfunc=getvect(0x29);
-	setvect(0x29,wwiv_expand); }
-
-if(com_port && sys_status&SS_COMISR && !(mode&(EX_OUTR|EX_INR))) {
-	riosync(0);
-	rioini(0,0);
-	sys_status&=~SS_COMISR; }
-
-if(!rmode) {					/* clear the status line */
-    lclini(node_scrnlen);
-    x=lclwx();
-    y=lclwy();
-	STATUSLINE;
-    lclxy(1,node_scrnlen);
-	lputc(CLREOL);
-	TEXTWINDOW;
-	lclxy(x,y); }
-
-if(mode&EX_SWAP) {				/* set the resident size */
-	if(rmode)
-		__spawn_resident=7000;	/* was 6000 */
-	else
-		__spawn_resident=0;
-	i=spawnvpeo(node_swapdir,arg[0],(const char **)arg
-		,(const char **)environ); }
-else
-	i=spawnvpe(P_WAIT,arg[0],arg,environ);
-
-#else //lif defined(__OS2__)
-
-if(com_port && !(mode&EX_POPEN)
-	&& sys_status&SS_COMISR) {	/* Uninstall COM routines */
-	riosync(0);
-	rioini(0,0);
-	sys_status&=~SS_COMISR; }
-
-textattr(LIGHTGRAY);	// Redundant
-if(!(mode&EX_OS2)) {	/* DOS pgm */
-	if(lclwy()>1 || lclwx()>1)
-        lputs(crlf);
-	lprintf("Executing DOS program: %s\r\n",str);
-	sprintf(str2,"%sEXECDOS.DAT",node_dir);
-	if((file=nopen(str2,O_WRONLY|O_TRUNC|O_CREAT))!=-1) {
-		sprintf(str2,"V1.00\r\n%X\r\n%lu\r\n%u\r\n%X\r\n%X\r\n%lX\r\n%u\r\n"
-			"%s\r\n"
-			,online==ON_REMOTE ? com_base:0
-			,com_irq,dte_rate,rmode,mode,useron.misc,node_num,str);
-		write(file,str2,strlen(str2));
-		sprintf(str2,"%u\r\nDSZLOG=%s\r\n"
-			,1	/* Total env vars to setup */
-			,getenv("DSZLOG"));
-		write(file,str2,strlen(str2));
-		if(online) {
-			sprintf(str2,"%s\r\n%s\r\n%u\r\n%u\r\n%c\r\n%s\r\n%s\r\n"
-				,useron.alias
-				,useron.name
-				,useron.level
-				,getage(useron.birth)
-				,useron.sex
-				,useron.phone
-				,useron.location);
-			write(file,str2,strlen(str2)); }
-		close(file); }
-
-	sprintf(str,"%sEXECDOS.EXE %s",exec_dir,node_dir);
-
-	x=wherex();
-	y=wherey();
-	i=system(str);
-	gotoxy(x,y); }
-else {	 /* OS/2 pgm */
-	window(1,1,80,node_scrnlen);
-	x=lclwx();
-    y=lclwy();
-    lclxy(1,node_scrnlen);
-	lputc(CLREOL);
-    lclxy(x,y);
-	i=system(cmdline);
-	lputs(crlf);
-	lputs(crlf);
-	lclxy(1,node_scrnlen-1);
-	}
-
-#ifdef __OS2__
-fixkbdmode();
-#endif
-textattr(LIGHTGRAY);
-
-#endif
-
-#ifndef __WIN32__
-while(lkbrd(0)) 	/* suck up any chars in the keyboard buffer */
-	;
-#endif
-
-#ifdef __MSDOS__
-setcbrk(0);
-
-lclatr(LIGHTGRAY);
-c=wherey();
-if(c>=node_scrnlen)
-	c=node_scrnlen-1;
-lclxy(wherex(),c);			/* put the cursor where BIOS thinks it is */
-
-#endif
-
-if(com_port && !(mode&EX_POPEN)
-#ifndef __OS2__
-	&& !(mode&(EX_OUTR|EX_INR))
-#endif
-	) {
-	comini();
-	setrate();
-	rioctl(IOSM|PAUSE|ABORT); }
-
-rioctl(CPTON);	/* turn on ctrl-p translation */
-
-#ifndef __FLAT__
-if(mode&EX_WWIV)
-	setvect(0x29,oldfunc);
-
-if(rmode)
-	ivhctl(0);		/* replace DOS output interrupt vectors */
-#endif
-
-setdisk(node_disk);
-strcpy(str,node_dir);
-str[strlen(str)-1]=0;
-if(chdir(str))
-	errormsg(WHERE,ERR_CHDIR,str,0);
-
-#ifndef __FLAT__
-lclini(node_scrnlen-1);
-#endif
-
-lncntr=0;
-if(online)
-	statusline();  /*  Replace status line after calling external program */
-errorlevel=i;
-return(i);
-}
-
-#ifndef __FLAT__
-extern uint riobp;
-extern mswtyp;
-#endif
-
-uint fakeriobp=0xffff;
-
-/*****************************************************************************/
-/* Returns command line generated from instr with %c replacments             */
-/*****************************************************************************/
-char *cmdstr(char *instr, char *fpath, char *fspec, char *outstr)
-{
-	static char static_cmd[128];
-	char str[256],str2[128],*cmd;
-    int i,j,len;
-
-if(outstr==NULL)
-	cmd=static_cmd;
-else
-	cmd=outstr;
-len=strlen(instr);
-for(i=j=0;i<len && j<128;i++) {
-    if(instr[i]=='%') {
-        i++;
-        cmd[j]=0;
-        switch(toupper(instr[i])) {
-            case 'A':   /* User alias */
-                strcat(cmd,useron.alias);
-                break;
-            case 'B':   /* Baud (DTE) Rate */
-                strcat(cmd,ultoa(dte_rate,str,10));
-                break;
-            case 'C':   /* Connect Description */
-                strcat(cmd,connection);
-                break;
-            case 'D':   /* Connect (DCE) Rate */
-                strcat(cmd,ultoa((ulong)cur_rate,str,10));
-                break;
-            case 'E':   /* Estimated Rate */
-                strcat(cmd,ultoa((ulong)cur_cps*10,str,10));
-                break;
-            case 'F':   /* File path */
-                strcat(cmd,fpath);
-                break;
-            case 'G':   /* Temp directory */
-				strcat(cmd,temp_dir);
-                break;
-			case 'H':   /* Port Handle or Hardware Flow Control */
-#ifdef __OS2__
-				strcat(cmd,itoa(rio_handle,str,10));
-#else
-                if(mdm_misc&MDM_CTS)
-                    strcat(cmd,"Y");
-                else
-                    strcat(cmd,"N");
-#endif
-                break;
-            case 'I':   /* UART IRQ Line */
-                strcat(cmd,itoa(com_irq,str,10));
-                break;
-            case 'J':
-				strcat(cmd,data_dir);
-                break;
-            case 'K':
-				strcat(cmd,ctrl_dir);
-                break;
-            case 'L':   /* Lines per message */
-                strcat(cmd,itoa(level_linespermsg[useron.level],str,10));
-                break;
-            case 'M':   /* Minutes (credits) for user */
-                strcat(cmd,ultoa(useron.min,str,10));
-                break;
-            case 'N':   /* Node Directory (same as SBBSNODE environment var) */
-                strcat(cmd,node_dir);
-                break;
-            case 'O':   /* SysOp */
-                strcat(cmd,sys_op);
-                break;
-            case 'P':   /* COM Port */
-                strcat(cmd,itoa(online==ON_LOCAL ? 0:com_port,str,10));
-                break;
-            case 'Q':   /* QWK ID */
-                strcat(cmd,sys_id);
-                break;
-            case 'R':   /* Rows */
-                strcat(cmd,itoa(rows,str,10));
-                break;
-            case 'S':   /* File Spec */
-                strcat(cmd,fspec);
-                break;
-            case 'T':   /* Time left in seconds */
-                gettimeleft();
-                strcat(cmd,itoa(timeleft,str,10));
-                break;
-            case 'U':   /* UART I/O Address (in hex) */
-                strcat(cmd,itoa(com_base,str,16));
-                break;
-            case 'V':   /* Synchronet Version */
-                sprintf(str,"%s%c",VERSION,REVISION);
-                break;
-            case 'W':   /* Time-slice API type (mswtype) */
-#ifndef __FLAT__
-                strcat(cmd,itoa(mswtyp,str,10));
-#endif
-                break;
-            case 'X':
-                strcat(cmd,shell[useron.shell]->code);
-                break;
-            case '&':   /* Address of msr */
-#ifndef __FLAT__
-                sprintf(str,"%lu",sys_status&SS_DCDHIGH ? &fakeriobp
-                    : online==ON_REMOTE ? &riobp-1 : 0);
-                strcat(cmd,str);
-#else
-				strcat(cmd,"%&");
-#endif
-                break;
-			case 'Y':
-				strcat(cmd,
-#ifdef __OS2__
-				node_comspec
-#else
-				comspec
-#endif
-				);
-				break;
-			case 'Z':
-				strcat(cmd,text_dir);
-                break;
-            case '!':   /* EXEC Directory */
-				strcat(cmd,exec_dir);
-                break;
-            case '#':   /* Node number (same as SBBSNNUM environment var) */
-                sprintf(str,"%d",node_num);
-                strcat(cmd,str);
-                break;
-            case '*':
-                sprintf(str,"%03d",node_num);
-                strcat(cmd,str);
-                break;
-            case '$':   /* Credits */
-                strcat(cmd,ultoa(useron.cdt+useron.freecdt,str,10));
-                break;
-            case '%':   /* %% for percent sign */
-                strcat(cmd,"%");
-                break;
-            default:    /* unknown specification */
-                if(isdigit(instr[i])) {
-                    sprintf(str,"%0*d",instr[i]&0xf,useron.number);
-                    strcat(cmd,str); }
-/*
-                else
-                    errormsg(WHERE,ERR_CHK,instr,i);
-*/
-                break; }
-        j=strlen(cmd); }
-    else
-        cmd[j++]=instr[i]; }
-cmd[j]=0;
-
-return(cmd);
-}
-
diff --git a/src/sbbs2/xtrn_ovl.c b/src/sbbs2/xtrn_ovl.c
deleted file mode 100644
index 3066305eb9778d1bb7a4bdfbbd4cba62889715ce..0000000000000000000000000000000000000000
--- a/src/sbbs2/xtrn_ovl.c
+++ /dev/null
@@ -1,1459 +0,0 @@
-#line 1 "XTRN_OVL.C"
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-#include "sbbs.h"
-
-char *hungupstr="\1n\1h%s\1n hung up on \1h%s\1n %s\r\n";
-
-#ifndef __FLAT__
-extern uint riobp;
-#endif
-
-extern mswtyp;
-extern uint fakeriobp;
-
-/****************************************************************************/
-/* Convert C string to pascal string										*/
-/****************************************************************************/
-void str2pas(char *instr, char *outstr)
-{
-	int i;
-
-outstr[0]=strlen(instr);
-for(i=0;i<outstr[0];i++)
-	outstr[i+1]=instr[i];
-}
-
-/****************************************************************************/
-/* Convert from unix time (seconds since 1/70) to julian (days since 1900)	*/
-/****************************************************************************/
-int unixtojulian(time_t unix)
-{
-	int days[12]={0,31,59,90,120,151,181,212,243,273,304,334};
-	long j;
-	struct date d;
-	struct time t;
-
-unixtodos(unix,&d,&t);
-j=36525L*d.da_year;
-if(!(j%100) && d.da_mon<3)
-	j--;
-j=(j-(1900*36525))/100;
-j+=d.da_day+days[d.da_mon-1];
-return(j);
-}
-
-/****************************************************************************/
-/* Convert julian date into unix format 									*/
-/****************************************************************************/
-time_t juliantounix(ulong j)
-{
-    int days[2][12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
-                       0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
-    long temp;
-	int leap,counter;
-
-	if(!j) return(0L);
-
-	date.da_year=(100L*j)/36525L;
-	temp=(long)date.da_year*36525L;
-	date.da_year+=1900;
-	j-=temp/100L;
-
-	if (!(temp%100)) {
-		j++;
-		leap=1; }
-	else leap=0;
-
-	for(date.da_mon=counter=0;counter<12;counter++)
-		if(days[leap][counter]<j)
-			date.da_mon=counter;
-
-	date.da_day=j-days[leap][date.da_mon];
-	date.da_mon++;	/* go from 0 to 1 based */
-
-	curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
-	return(dostounix(&date,&curtime));
-}
-
-/****************************************************************************/
-/* Creates various types of xtrn (Doors, Chains, etc.) data files.		 */
-/****************************************************************************/
-void xtrndat(char *name, char *dropdir, uchar type, ulong tleft)
-{
-	char	str[1024],tmp2[128],c,*p;
-	int		i,file;
-	long	l;
-	ushort	w;
-	FILE *	stream;
-	struct	time lastcall;
-	stats_t stats;
-
-if(type==XTRN_SBBS) {	/* SBBS XTRN.DAT file */
-	sprintf(str,"%sXTRN.DAT",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	sprintf(str,"%s\r\n%s\r\n%s\r\n%s\r\n"
-		,name								/* User name */
-		,sys_name							/* System name */
-		,sys_op 							/* Sysop name */
-		,sys_guru); 						/* Guru name */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%s\r\n%s\r\n%u\r\n%u\r\n%lu\r\n%s\r\n%lu\r\n%lu\r\n"
-		,ctrl_dir							/* Ctrl dir */
-		,data_dir							/* Data dir */
-		,sys_nodes							/* Total system nodes */
-		,node_num							/* Current node */
-		,tleft								/* User Timeleft in seconds */
-		,useron.misc&ANSI					/* User ANSI ? (Yes/Mono/No) */
-			? useron.misc&COLOR
-			? "Yes":"Mono":"No"
-		,rows								/* User Screen lines */
-		,useron.cdt+useron.freecdt);		/* User Credits */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%u\r\n%s\r\n%c\r\n%u\r\n%s\r\n"
-		,useron.level						/* User main level */
-		,useron.level						/* User transfer level */
-		,useron.birth						/* User birthday */
-		,useron.sex 						/* User sex (M/F) */
-		,useron.number						/* User number */
-		,useron.phone); 					/* User phone number */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%u\r\n%x\r\n%lu\r\n%s\r\n%s\r\n"
-		"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%lu\r\n"
-		,online==ON_LOCAL ? 0:com_port		/* Com port or 0 if local */
-		,com_irq							/* Com IRQ */
-		,com_base							/* Com base in hex */
-		,dte_rate							/* Com rate */
-		,mdm_misc&MDM_CTS	   ? "Yes":"No" /* Hardware flow ctrl Y/N */
-		,mdm_misc&MDM_STAYHIGH ? "Yes":"No" /* Locked DTE rate Y/N */
-		,mdm_init							/* Modem initialization string */
-		,mdm_spec							/* Modem special init string */
-		,mdm_term							/* Modem terminal mode init str */
-		,mdm_dial							/* Modem dial string */
-		,mdm_offh							/* Modem off-hook string */
-		,mdm_answ							/* Modem answer string */
-#ifndef __FLAT__
-		,sys_status&SS_DCDHIGH ? &fakeriobp : &riobp-1							 /* Modem status register */
-#else
-		,0
-#endif
-		);
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n",total_xtrns);
-	write(file,str,strlen(str));			/* Total external programs */
-
-	for(i=0;i<total_xtrns;i++) {			/* Each program's name */
-		if(SYSOP || chk_ar(xtrn[i]->ar,useron))
-			strcpy(str,xtrn[i]->name);
-		else
-			str[0]=0;						/* Blank if no access */
-		strcat(str,crlf);
-		write(file,str,strlen(str)); }
-
-	sprintf(str,"%s\r\n%s\r\n"
-		,ltoaf(useron.flags1,tmp)			 /* Main flags */
-		,ltoaf(useron.flags2,tmp2)			 /* Transfer flags */
-		);
-	write(file,str,strlen(str));
-
-	sprintf(str,"%s\r\n%s\r\n%lx\r\n%s\r\n%s\r\n%s\r\n"
-		,ltoaf(useron.exempt,tmp)			/* Exemptions */
-		,ltoaf(useron.rest,tmp2)			/* Restrictions */
-		,useron.expire						/* Expiration date in unix form */
-		,useron.address 					/* Address */
-		,useron.location					/* City/State */
-		,useron.zipcode 					/* Zip/Postal code */
-		);
-	write(file,str,strlen(str));
-
-	sprintf(str,"%s\r\n%s\r\n%d\r\n%s\r\n%lu\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-		"%lx\r\n%d\r\n"
-		,ltoaf(useron.flags3,tmp)			/* Flag set #3 */
-		,ltoaf(useron.flags4,tmp2)			/* Flag set #4 */
-		,mswtyp 							/* Time-slice type */
-		,useron.name						/* Real name/company */
-		,cur_rate							/* DCE rate */
-		,exec_dir
-		,text_dir
-		,temp_dir
-		,sys_id
-		,node_misc
-#ifdef __FLAT__
-		,rio_handle
-#else
-		,-1
-#endif
-		);
-    write(file,str,strlen(str));
-
-	close(file); }
-
-else if(type==XTRN_WWIV) {	/*	WWIV CHAIN.TXT File */
-	sprintf(str,"%sCHAIN.TXT",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	sprintf(str,"%u\r\n%s\r\n%s\r\n%s\r\n%u\r\n%c\r\n"
-		,useron.number						/* User number */
-		,name								/* User name */
-		,useron.name						/* User real name */
-		,nulstr 							/* User call sign */
-		,getage(useron.birth)				/* User age */
-		,useron.sex);						/* User sex (M/F) */
-	strupr(str);
-	write(file,str,strlen(str));
-
-	sprintf(str,"%lu\r\n%s\r\n%u\r\n%lu\r\n%u\r\n%u\r\n%u\r\n%u\r\n%u\r\n"
-		,useron.cdt+useron.freecdt			/* Gold */
-		,unixtodstr(useron.laston,tmp)		/* User last on date */
-		,80 								/* User screen width */
-		,rows								/* User screen length */
-		,useron.level						/* User SL */
-		,0									/* Cosysop? */
-		,SYSOP								/* Sysop? (1/0) */
-		,(useron.misc&ANSI) ? 1:0			/* ANSI ? (1/0) */
-		,online==ON_REMOTE);				/* Remote (1/0) */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%lu\r\n%s\r\n%s\r\n%s\r\n%lu\r\n%d\r\n%s\r\n%s\r\n"
-		"%u\r\n%u\r\n%lu\r\n%u\r\n%lu\r\n%u\r\n%s\r\n"
-		,tleft								/* Time left in seconds */
-		,node_dir							/* Gfiles dir (log dir) */
-		,data_dir							/* Data dir */
-		,"NODE.LOG"                         /* Name of log file */
-		,dte_rate							/* DTE rate */
-		,com_port							/* COM port number */
-		,sys_name							/* System name */
-		,sys_op 							/* Sysop name */
-		,0									/* Logon time (sec past 12am) */
-		,0									/* Current time (sec past 12am) */
-		,useron.ulb/1024UL					/* User uploaded kbytes */
-		,useron.uls 						/* User uploaded files */
-		,useron.dlb/1024UL					/* User downloaded kbytes */
-		,useron.dls 						/* User downloaded files */
-		,"8N1");                            /* Data, parity, stop bits */
-	write(file,str,strlen(str));
-
-	close(file); }
-
-else if(type==XTRN_GAP) {	/* Gap DOOR.SYS File */
-	sprintf(str,"%sDOOR.SYS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	sprintf(str,"COM%d:\r\n%lu\r\n%u\r\n%u\r\n%lu\r\n%c\r\n%c\r\n%c\r\n%c\r\n"
-		,online==ON_REMOTE ? com_port:0 	/* 01: COM port - 0 if Local */
-		,cur_rate							/* 02: DCE rate */
-		,8									/* 03: Data bits */
-		,node_num							/* 04: Node number */
-		,dte_rate							/* 05: DTE rate */
-		,console&CON_L_ECHO ? 'Y':'N'       /* 06: Screen display */
-		,'Y'                                /* 07: Printer toggle */
-		,'Y'                                /* 08: Page bell */
-		,'Y');                              /* 09: Caller alarm */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
-		,name								/* 10: User name */
-		,useron.location					/* 11: User location */
-		,useron.phone						/* 12: User home phone */
-		,useron.phone						/* 13: User work/data phone */
-		,useron.pass);						/* 14: User password */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%u\r\n%s\r\n%lu\r\n%lu\r\n%s\r\n"
-		,useron.level						/* 15: User security level */
-		,useron.logons						/* 16: User total logons */
-		,unixtodstr(useron.laston,tmp)		/* 17: User last on date */
-		,tleft								/* 18: User time left in sec */
-		,tleft/60							/* 19: User time left in min */
-		,useron.misc&NO_EXASCII 			/* 20: GR if COLOR ANSI */
-			? "7E" : (useron.misc&(ANSI|COLOR))==(ANSI|COLOR) ? "GR" : "NG");
-	write(file,str,strlen(str));
-
-	sprintf(str,"%lu\r\n%c\r\n%s\r\n%u\r\n%s\r\n%u\r\n%c\r\n%u\r\n%u\r\n"
-		,rows								/* 21: User screen length */
-		,useron.misc&EXPERT ? 'Y':'N'       /* 22: Expert? (Y/N) */
-		,ltoaf(useron.flags1,tmp2)			/* 23: Registered conferences */
-		,0									/* 24: Conference came from */
-		,unixtodstr(useron.expire,tmp)		/* 25: User expiration date */
-		,useron.number						/* 26: User number */
-		,'Y'                                /* 27: Default protocol */
-		,useron.uls 						/* 28: User total uploads */
-		,useron.dls);						/* 29: User total downloads */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%lu\r\n%s\r\n%s\r\n%s\r\n%s"
-		"\r\n%s\r\n%02d:%02d\r\n%c\r\n"
-		,0									/* 30: Kbytes downloaded today */
-		,(useron.cdt+useron.freecdt)/1024UL /* 31: Max Kbytes to download today */
-		,useron.birth						/* 32: User birthday */
-		,node_dir							/* 33: Path to MAIN directory */
-		,data_dir							/* 34: Path to GEN directory */
-		,sys_op 							/* 35: Sysop name */
-		,nulstr 							/* 36: Alias name */
-		,0 // sys_eventtime/60				/* 37: Event time HH:MM */
-		,0 // sys_eventtime%60
-		,'Y');                              /* 38: Error correcting connection */
-	write(file,str,strlen(str));
-
-	unixtodos(ns_time,&date,&curtime);
-	sprintf(str,"%c\r\n%c\r\n%u\r\n%lu\r\n%02d/%02d/%02d\r\n"
-		,(useron.misc&(NO_EXASCII|ANSI|COLOR))==ANSI
-			? 'Y':'N'                       /* 39: ANSI supported but NG mode */
-		,'Y'                                /* 40: Use record locking */
-		,14 								/* 41: BBS default color */
-		,useron.min 						/* 42: Time credits in minutes */
-		,date.da_mon						/* 43: File new-scan date */
-		,date.da_day
-		,TM_YEAR(date.da_year-1900));
-	write(file,str,strlen(str));
-
-	unixtodos(logontime,&date,&curtime);
-	unixtodos(useron.laston,&date,&lastcall);
-	sprintf(str,"%02d:%02d\r\n%02d:%02d\r\n%u\r\n%u\r\n%lu\r\n"
-		"%lu\r\n%s\r\n%u\r\n%u\r\n"
-		,curtime.ti_hour					/* 44: Time of this call */
-		,curtime.ti_min
-		,lastcall.ti_hour					/* 45: Time of last call */
-		,lastcall.ti_min
-		,999								/* 46: Max daily files available */
-		,0									/* 47: Files downloaded so far today */
-		,useron.ulb/1024UL					/* 48: Total Kbytes uploaded */
-		,useron.dlb/1024UL					/* 49: Total Kbytes downloaded */
-		,useron.comment 					/* 50: User comment */
-		,0									/* 51: Total doors opened */
-		,useron.posts); 					/* 52: User message left */
-	write(file,str,strlen(str));
-
-	close(file); }
-
-else if(type==XTRN_RBBS || type==XTRN_RBBS1) {
-	if(type==XTRN_RBBS)
-		sprintf(str,"%sDORINFO%X.DEF",dropdir,node_num);   /* support 1-F */
-	else
-		sprintf(str,"%sDORINFO1.DEF",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-
-	strcpy(tmp,sys_op);
-	p=strchr(tmp,SP);
-	if(p)
-		*(p++)=0;
-	else
-        p=nulstr;
-
-	sprintf(str,"%s\r\n%s\r\n%s\r\nCOM%d\r\n%lu BAUD,N,8,1\r\n%u\r\n"
-		,sys_name							/* Name of BBS */
-		,tmp								/* Sysop's firstname */
-		,p									/* Sysop's lastname */
-		,online==ON_REMOTE ? com_port:0 	/* COM port number, 0 if local */
-		,dte_rate							/* DTE rate */
-		,0);								/* Network type */
-	strupr(str);
-	write(file,str,strlen(str));
-
-	strcpy(tmp,name);
-	p=strchr(tmp,SP);
-	if(p)
-		*(p++)=0;
-	else
-		p=nulstr;
-	sprintf(str,"%s\r\n%s\r\n%s\r\n%u\r\n%u\r\n%lu\r\n"
-		,tmp								/* User's firstname */
-		,p									/* User's lastname */
-		,useron.location					/* User's city */
-		,(useron.misc&ANSI)==ANSI			/* 1=ANSI 0=ASCII */
-		,useron.level						/* Security level */
-		,tleft/60); 						/* Time left in minutes */
-	strupr(str);
-	write(file,str,strlen(str));
-
-	close(file);
-
-	sprintf(str,"%sEXITINFO.BBS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-	w=dte_rate;
-	write(file,&w,sizeof(short));	  /* BaudRate */
-	/* SysInfo */
-	getstats(0,&stats);
-	write(file,&stats.logons,sizeof(long)); /* CallCount */
-	write(file,nulstr,36);					/* LastCallerName */
-	write(file,nulstr,36);					/* LastCallerAlias */
-	write(file,nulstr,92);					/* ExtraSpace */
-	/* TimeLogInfo */
-	write(file,nulstr,9);					/* StartDate */
-	write(file,nulstr,24*sizeof(short));		/* BusyPerHour */
-	write(file,nulstr,7*sizeof(short));		/* BusyPerDay */
-	/* UserInfo */
-	str2pas(name,str);				/* Name */
-	write(file,str,36);
-	str2pas(useron.location,str);
-	write(file,str,26); 					/* City */
-	str2pas(useron.pass,str);
-	write(file,str,16); 					/* Pwd */
-	str2pas(useron.phone,str);
-	write(file,str,13); 					/* DataPhone */
-	write(file,str,13); 					/* HomePhone */
-	unixtodos(useron.laston,&date,&lastcall);
-	sprintf(tmp,"%02d:%02d",lastcall.ti_hour,lastcall.ti_min);
-	str2pas(tmp,str);
-	write(file,str,6);						/* LastTime */
-	unixtodstr(useron.laston,tmp);
-	str2pas(tmp,str);
-	write(file,str,9);						/* LastDate */
-	c=0;
-	if(useron.misc&DELETED) c|=(1<<0);
-	if(useron.misc&CLRSCRN) c|=(1<<1);
-	if(useron.misc&UPAUSE)	 c|=(1<<2);
-	if(useron.misc&ANSI)	c|=(1<<3);
-	if(useron.sex=='F')     c|=(1<<7);
-	write(file,&c,1);						/* Attrib */
-	write(file,&useron.flags1,4);			/* Flags */
-	i=0;
-	w=0;
-	write(file,&w,sizeof(short)); 			/* Credit */
-	write(file,&w,sizeof(short)); 			/* Pending */
-	write(file,&useron.posts,sizeof(short));	/* TimesPosted */
-	write(file,&w,sizeof(short)); 			/* HighMsgRead */
-	w=useron.level;
-	write(file,&w,sizeof(short)); 			/* SecLvl */
-	w=0;
-	write(file,&w,sizeof(short)); 			/* Times */
-	write(file,&useron.uls,sizeof(short));	/* Ups */
-	write(file,&useron.dls,sizeof(short));	/* Downs */
-	w=useron.ulb/1024UL;
-	write(file,&w,sizeof(short)); 			/* UpK */
-	w=useron.dlb/1024UL;
-	write(file,&w,sizeof(short)); 			/* DownK */
-	w=logon_dlb/1024UL;
-	write(file,&w,sizeof(short)); 			/* TodayK */
-	w=0;
-	write(file,&w,sizeof(short)); 			/* Elapsed */
-	write(file,&w,sizeof(short)); 			/* Len */
-	write(file,&w,sizeof(short)); 			/* CombinedPtr */
-	write(file,&w,sizeof(short)); 			/* AliasPtr */
-	l=0;
-	write(file,&l,sizeof(long));			/* Birthday (as a long?) */
-	/* EventInfo */
-	c=0;
-	write(file,&c,sizeof(char));			/* Status */
-	write(file,&l /* sys_eventtime */,sizeof(long));	/* RunTime */
-	write(file,&c,sizeof(char));			/* ErrorLevel */
-	c=0xff;
-	write(file,&c,sizeof(char));			/* Days */
-	// c=sys_eventnode==node_num || sys_misc&SM_TIMED_EX ? 1 : 0;
-	c=0;
-	write(file,&c,sizeof(char));			/* Forced */
-	if(!total_events)
-		l=0;
-	else
-		l=event[0]->last;
-	write(file,&l,sizeof(long));			/* LastTimeRun */
-	memset(str,0,40);
-	write(file,str,7);						/* Spare */
-
-	c=0;
-	write(file,&c,1);						/* NetMailEntered */
-	write(file,&c,1);						/* EchoMailEntered */
-
-	unixtodos(logontime,&date,&curtime);
-	sprintf(tmp,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
-	str2pas(tmp,str);
-	write(file,str,6);						/* LoginTime */
-	unixtodstr(logontime,tmp);
-	str2pas(tmp,str);
-	write(file,str,9);						/* LoginDate */
-	write(file,&level_timepercall[useron.level],sizeof(short));  /* TmLimit */
-	write(file,&logontime,sizeof(long));	/* LoginSec */
-	write(file,&useron.cdt,sizeof(long));	/* Credit */
-	write(file,&useron.number,sizeof(short)); /* UserRecNum */
-	write(file,&i,2);						/* ReadThru */
-	write(file,&i,2);						/* PageTimes */
-	write(file,&i,2);						/* DownLimit */
-	c=sys_status&SS_SYSPAGE ? 1:0;
-	write(file,&c,1);						/* WantChat */
-	c=0;
-	write(file,&c,1);						/* GosubLevel */
-
-	memset(str,0,255);
-	for(i=1;i<20;i++)
-		write(file,str,9);					/* GosubData */
-	write(file,str,9);						/* Menu */
-	c=useron.misc&CLRSCRN ? 1:0;
-	write(file,&c,1);						/* ScreenClear */
-	c=useron.misc&UPAUSE ? 1:0;
-	write(file,&c,1);						/* MorePrompts */
-	c=useron.misc&NO_EXASCII ? 0:1;
-	write(file,&c,1);						/* GraphicsMode */
-	c=useron.xedit ? 1:0;
-	write(file,&c,1);						/* ExternEdit */
-	i=rows;
-	write(file,&i,2);						/* ScreenLength */
-	c=1;
-	write(file,&c,1);						/* MNP_Connect */
-	write(file,str,49); 					/* ChatReason */
-	c=0;
-	write(file,&c,1);						/* ExternLogoff */
-	c=useron.misc&ANSI ? 1:0;
-	write(file,&c,1);						/* ANSI_Capable */
-	close(file);
-	}
-
-else if(type==XTRN_WILDCAT) { /* WildCat CALLINFO.BBS File */
-	sprintf(str,"%sCALLINFO.BBS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-
-	if(online==ON_LOCAL) i=5;
-	else
-		switch(dte_rate) {
-			case 300:
-				i=1;
-				break;
-			case 1200:
-				i=2;
-				break;
-			case 2400:
-				i=0;
-				break;
-			case 9600:
-				i=3;
-				break;
-			case 19200:
-				i=4;
-				break;
-			case 38400:
-				i=6;
-				break;
-			default:
-				i=7;
-				break; }
-	sprintf(str,"%s\r\n%u\r\n%s\r\n%u\r\n%lu\r\n%s\r\n%s\r\n%u\r\n"
-		,name								/* User name */
-		,i									/* DTE rate */
-		,useron.location					/* User location */
-		,useron.level						/* Security level */
-		,tleft/60							/* Time left in min */
-		,useron.misc&ANSI ? "COLOR":"MONO"  /* ANSI ??? */
-		,useron.pass						/* Password */
-		,useron.number);					/* User number */
-	write(file,str,strlen(str));
-
-	unixtodos(now,&date,&curtime);
-	sprintf(str,"%lu\r\n%02d:%02d\r\n%02d:%02d %02d/%02d/%02d\r\n%s\r\n"
-		,tleft								/* Time left in seconds */
-		,curtime.ti_hour,curtime.ti_min 	/* Current time HH:MM */
-		,curtime.ti_hour,curtime.ti_min 	/* Current time and date HH:MM */
-		,date.da_mon,date.da_day			/* MM/DD/YY */
-		,TM_YEAR(date.da_year-1900)
-		,nulstr);							/* Conferences with access */
-	write(file,str,strlen(str));
-
-	unixtodos(useron.laston,&date,&lastcall);
-	sprintf(str,"%u\r\n%u\r\n%u\r\n%u\r\n%s\r\n%s %02u:%02u\r\n"
-		,0									/* Daily download total */
-		,0									/* Max download files */
-		,0									/* Daily download k total */
-		,0									/* Max download k total */
-		,useron.phone						/* User phone number */
-		,unixtodstr(useron.laston,tmp)		/* Last on date and time */
-		,lastcall.ti_hour					/* MM/DD/YY  HH:MM */
-		,lastcall.ti_min);
-	write(file,str,strlen(str));
-
-	unixtodos(ns_time,&date,&curtime);
-	sprintf(str,"%s\r\n%s\r\n%02d/%02d/%02d\r\n%u\r\n%lu\r\n%u"
-		"\r\n%u\r\n%u\r\n"
-		,useron.misc&EXPERT 				/* Expert or Novice mode */
-			? "EXPERT":"NOVICE"
-		,"All"                              /* Transfer Protocol */
-		,date.da_mon,date.da_day			/* File new-scan date */
-		,TM_YEAR(date.da_year-1900)			/* in MM/DD/YY */
-		,useron.logons						/* Total logons */
-		,rows								/* Screen length */
-		,0									/* Highest message read */
-		,useron.uls 						/* Total files uploaded */
-		,useron.dls);						/* Total files downloaded */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%s\r\nCOM%u\r\n%s\r\n%lu\r\n%s\r\n%s\r\n"
-		,8									/* Data bits */
-		,online==ON_LOCAL?"LOCAL":"REMOTE"  /* Online local or remote */
-		,com_port							/* COMx port */
-		,useron.birth						/* User birthday */
-		,dte_rate							/* DTE rate */
-		,"FALSE"                            /* Already connected? */
-		,"Normal Connection");              /* Normal or ARQ connect */
-	write(file,str,strlen(str));
-
-	sprintf(str,"%02d/%02d/%02d %02d:%02d\r\n%u\r\n%u\r\n"
-		,date.da_mon,date.da_day			/* Current date MM/DD/YY */
-		,TM_YEAR(date.da_year-1900)
-		,curtime.ti_hour,curtime.ti_min 	/* Current time HH:MM */
-		,node_num							/* Node number */
-		,0);								/* Door number */
-	write(file,str,strlen(str));
-
-	close(file); }
-
-else if(type==XTRN_PCBOARD) { /* PCBoard Files */
-	sprintf(str,"%sPCBOARD.SYS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-
-	sprintf(str,"%2d%2d%2d%2d%c%2d%c%c%5u%-5.5s"
-		,-1 								/* Display on/off */
-		,0									/* Printer on/off */
-		,sys_status&SS_SYSPAGE ? -1:0		/* Page Bell on/off */
-		,node_misc&NM_ANSALARM ? -1:0		/* Caller Alarm on/off */
-		,SP 								/* Sysop next flag */
-		,0									/* Error corrected */
-		,useron.misc&NO_EXASCII ? '7'       /* Graphics mode */
-			: (useron.misc&(COLOR|ANSI))==(COLOR|ANSI) ? 'Y':'N'
-		,'A'                                /* Node chat status */
-		,(uint)dte_rate 					/* DTE Port Speed */
-		,connection 						/* Connection description */
-		);
-	write(file,str,23);
-
-	write(file,&useron.number,2);			/* User record number */
-
-	strcpy(tmp,name);
-	p=strchr(tmp,SP);
-	if(p) *p=0;
-	sprintf(str,"%-15.15s%-12s"
-		,tmp								/* User's first name */
-		,useron.pass);						/* User's password */
-	write(file,str,27);
-
-	unixtodos(logontime,&date,&curtime);
-	i=(curtime.ti_hour*60)+curtime.ti_min;
-	write(file,&i,2);						/* Logon time in min since mid */
-
-	now=time(NULL);
-	i=-(((now-starttime)/60)+useron.ttoday); /* Negative minutes used */
-	write(file,&i,2);
-
-	sprintf(str,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
-	write(file,str,5);
-
-	i=level_timepercall[useron.level];		/* Time allowed on */
-	write(file,&i,2);
-
-	i=0;									/* Allowed K-bytes for D/L */
-	write(file,&i,2);
-	write(file,&i,1);						/* Conference user was in */
-	write(file,&i,2);						/* Conferences joined */
-	write(file,&i,2);						/* "" */
-	write(file,&i,2);						/* "" */
-	write(file,&i,2);						/* Conferences scanned */
-	write(file,&i,2);						/* "" */
-	write(file,&i,2);						/* Conference add time */
-	write(file,&i,2);						/* Upload/Sysop Chat time min */
-
-	strcpy(str,"    ");
-	write(file,str,4);						/* Language extension */
-
-	sprintf(str,"%-25.25s",name);           /* User's full name */
-	write(file,str,25);
-
-	i=(tleft/60);
-	write(file,&i,2);						/* Minutes remaining */
-
-	write(file,&node_num,1);				/* Node number */
-
-	sprintf(str,"%02d:%02d%2d%2d"           /* Scheduled Event time */
-		,0 // sys_eventtime/60
-		,0 // sys_eventtime%60
-		,0 // sys_timed[0] ? -1:0				 /* Event active ? */
-		,0									/* Slide event ? */
-		);
-	write(file,str,9);
-
-	l=0L;
-	write(file,&l,4);						/* Memorized message number */
-
-	sprintf(str,"%d%c%c%d%s%c%c%d%d%d%c%c"
-		,com_port							/* COM Port number */
-		,SP 								/* Reserved */
-		,SP 								/* "" */
-		,(useron.misc&ANSI)==ANSI			/* 1=ANSI 0=NO ANSI */
-		,"01-01-80"                         /* last event date */
-		,0,0								/* last event minute */
-		,0									/* caller exited to dos */
-		,sys_status&SS_EVENT ? 1:0			/* event up coming */
-		,0									/* stop uploads */
-		,0,0								/* conference user was in */
-		);
-	write(file,str,19);
-
-	close(file);			/* End of PCBOARD.SYS creation */
-
-	sprintf(str,"%sUSERS.SYS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-
-	/* Write goof-ball header */
-
-	i=145;
-	write(file,&i,2);		/* PCBoard version number (i.e. 145) */
-	l=useron.number;
-	write(file,&l,4);		/* Record number for USER's file */
-	i=218;
-	write(file,&i,2);		/* Size of "fixed" user record */
-	i=1;
-	write(file,&i,2);		/* Number of conference areas */
-	i=7;
-	write(file,&i,2);		/* Number of bit map fields for conferences */
-	i=5;
-	write(file,&i,2);		/* Size of each bit map field */
-	memset(str,0,15);
-	write(file,str,15); 	/* Name of Third Party Application (if any) */
-	i=0;
-	write(file,&i,2);		/* Version number for application (if any) */
-	write(file,&i,2);		/* Size of a "fixed length" record (if any) */
-	write(file,&i,2);		/* Size of conference record (if any) */
-	l=0;
-	write(file,&l,4);		/* Offset of AppRec into USERS.INF (if any) */
-	i=0;
-	write(file,&i,1);		/* 1, if USERS.SYS file has been updated */
-
-	/* Write fixed record portion */
-
-	write(file,name,26);			/* Name */
-	sprintf(str,"%.24s",useron.location);
-	write(file,str,25); 			/* Location */
-	write(file,useron.pass,13); 	/* Password */
-	write(file,useron.phone,14);	/* Business or Data Phone */
-	write(file,useron.phone,14);	/* Home or Voice Phone */
-	i=unixtojulian(useron.laston);
-	write(file,&i,2);				/* Date last on */
-	unixtodos(useron.laston,&date,&curtime);
-	sprintf(str,"%02d:%02d",curtime.ti_hour,curtime.ti_min);
-	write(file,str,6);				/* Last time on */
-	if(useron.misc&EXPERT)
-		i=1;
-	else
-		i=0;
-	write(file,&i,1);				/* Expert mode */
-	i='Z';
-	write(file,&i,1);				/* Protocol (A-Z) */
-	if(useron.misc&CLRSCRN)
-		i=2;
-	else
-		i=0;
-	write(file,&i,1);				/* bit packed flags */
-	i=0;
-	write(file,&i,2);				/* DOS date for last DIR Scan */
-	i=useron.level;
-	write(file,&i,2);				/* Security level */
-	write(file,&useron.logons,2);	/* Number of times caller has connected */
-	c=rows;
-	write(file,&c,1);				/* Page length */
-	write(file,&useron.uls,2);		/* Number of uploads */
-	write(file,&useron.dls,2);		/* Number of downloads */
-	l=0;
-	write(file,&l,4);				/* Number of download bytes today */
-	write(file,&useron.note,31);	/* Comment #1 */
-	write(file,&useron.comp,31);	/* Comment #2 */
-	i=(now-starttime)/60;
-	write(file,&i,2);				/* Minutes online (this logon?) */
-	i=unixtojulian(useron.expire);
-	write(file,&i,2);				/* Expiration date */
-	i=expired_level;
-	write(file,&i,2);				/* Expired security level */
-	i=1;
-	write(file,&i,2);				/* Current conference */
-	write(file,&useron.dlb,4);		/* Bytes downloaded */
-	write(file,&useron.ulb,4);		/* Bytes uploaded */
-	if(useron.misc&DELETED)
-		i=1;
-	else
-		i=0;
-	write(file,&i,1);				/* Deleted? */
-	l=useron.number;
-	write(file,&l,4);				/* Record number in USERS.INF file */
-	l=0;
-	memset(str,0,9);
-	write(file,str,9);				/* Reserved */
-	write(file,&l,4);				/* Number of messages read */
-	l=useron.posts+useron.emails+useron.fbacks;
-	write(file,&l,4);				/* Number of messages left */
-	close(file);
-
-	/* End of USERS.SYS creation */
-
-	}
-
-else if(type==XTRN_SPITFIRE) {	 /* SpitFire SFDOORS.DAT File */
-	sprintf(str,"%sSFDOORS.DAT",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	now=time(NULL);
-	unixtodos(now,&date,&curtime);
-	l=((((long)curtime.ti_hour*60L)+(long)curtime.ti_min)*60L)
-		+(long)curtime.ti_sec;
-
-	strcpy(tmp,name);
-	if((p=strchr(tmp,SP))!=NULL)
-		*p=0;
-
-	sprintf(str,"%u\r\n%s\r\n%s\r\n%s\r\n%lu\r\n%u\r\n%lu\r\n%lu\r\n"
-		,useron.number						/* User number */
-		,name								/* User name */
-		,useron.pass						/* Password */
-		,tmp								/* User's first name */
-		,dte_rate							/* DTE Rate */
-		,com_port							/* COM Port */
-		,tleft/60							/* Time left in minutes */
-		,l									/* Seconds since midnight (now) */
-		);
-	write(file,str,strlen(str));
-
-	unixtodos(logontime,&date,&curtime);
-	l=((((long)curtime.ti_hour*60L)+(long)curtime.ti_min)*60L)
-		+(long)curtime.ti_sec;
-
-	sprintf(str,"%s\r\n%s\r\n%u\r\n%u\r\n%u\r\n%u\r\n%lu\r\n%lu\r\n%s\r\n"
-		"%s\r\n%s\r\n%lu\r\n%s\r\n%u\r\n%u\r\n%u\r\n%u\r\n%u\r\n%lu\r\n%u\r\n"
-		"%lu\r\n%lu\r\n%s\r\n%s\r\n"
-		,dropdir
-		,useron.misc&ANSI ? "TRUE":"FALSE"  /* ANSI ? True or False */
-		,useron.level						/* Security level */
-		,useron.uls 						/* Total uploads */
-		,useron.dls 						/* Total downloads */
-		,level_timepercall[useron.level]	/* Minutes allowed this call */
-		,l									/* Secs since midnight (logon) */
-		,starttime-logontime				/* Extra time in seconds */
-		,"FALSE"                            /* Sysop next? */
-		,"FALSE"                            /* From Front-end? */
-		,"FALSE"                            /* Software Flow Control? */
-		,dte_rate							/* DTE Rate */
-		,"FALSE"                            /* Error correcting connection? */
-		,0									/* Current conference */
-		,0									/* Current file dir */
-		,node_num							/* Node number */
-		,15 								/* Downloads allowed per day */
-		,0									/* Downloads already this day */
-		,100000 							/* Download bytes allowed/day */
-		,0									/* Downloaded bytes already today */
-		,useron.ulb/1024L					/* Kbytes uploaded */
-		,useron.dlb/1024L					/* Kbytes downloaded */
-		,useron.phone						/* Phone Number */
-		,useron.location					/* City, State */
-		);
-	write(file,str,strlen(str));
-
-    close(file); }
-
-else if(type==XTRN_UTI) { /* UTI v2.1 - UTIDOOR.TXT */
-	sprintf(str,"%sUTIDOOR.TXT",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-        return; }
-
-	strcpy(tmp,name);
-	strupr(tmp);
-	sprintf(str,"%s\r\n%lu\r\n%u\r\n%lu\r\n%lu\r\n"
-		,tmp								/* User name */
-		,cur_rate							/* Actual BPS rate */
-		,online==ON_LOCAL ? 0: com_port 	/* COM Port */
-		,dte_rate							/* DTE rate */
-		,tleft);							/* Time left in sec */
-    write(file,str,strlen(str));
-
-	close(file); }
-
-else if(type==XTRN_SR) { /* Solar Realms DOORFILE.SR */
-	sprintf(str,"%sDOORFILE.SR",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	sprintf(str,"%s\r\n%d\r\n%d\r\n%lu\r\n%lu\r\n%u\r\n%lu\r\n"
-		,name								/* Complete name of user */
-		,useron.misc&ANSI ? 1:0 			/* ANSI ? */
-		,useron.misc&NO_EXASCII ? 0:1		/* IBM characters ? */
-		,rows								/* Page length */
-		,dte_rate							/* Baud rate */
-		,online==ON_LOCAL ? 0:com_port		/* COM port */
-		,tleft/60							/* Time left (in minutes) */
-		);
-	write(file,str,strlen(str));
-	close(file); }
-
-else if(type==XTRN_TRIBBS) { /* TRIBBS.SYS */
-	sprintf(str,"%sTRIBBS.SYS",dropdir);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
-		return; }
-
-	sprintf(str,"%u\r\n%s\r\n%s\r\n%u\r\n%c\r\n%c\r\n%lu\r\n%s\r\n%s\r\n%s\r\n"
-		,useron.number						/* User's record number */
-		,name								/* User's name */
-		,useron.pass						/* User's password */
-		,useron.level						/* User's level */
-		,useron.misc&EXPERT ? 'Y':'N'       /* Expert? */
-		,useron.misc&ANSI ? 'Y':'N'         /* ANSI? */
-		,tleft/60							/* Minutes left */
-		,useron.phone						/* User's phone number */
-		,useron.location					/* User's city and state */
-		,useron.birth						/* User's birth date */
-		);
-	write(file,str,strlen(str));
-
-	sprintf(str,"%u\r\n%u\r\n%lu\r\n%lu\r\n%c\r\n%c\r\n%s\r\n%s\r\n%s\r\n"
-		,node_num							/* Node number */
-		,com_port							/* Serial port */
-		,online==ON_LOCAL ? 0L:cur_rate 	/* Baud rate */
-		,dte_rate							/* Locked rate */
-		,mdm_misc&(MDM_RTS|MDM_CTS) ? 'Y':'N'
-		,'Y'                                /* Error correcting connection */
-		,sys_name							/* Board's name */
-		,sys_op 							/* Sysop's name */
-		,useron.handle						/* User's alias */
-		);
-	write(file,str,strlen(str));
-	close(file); }
-
-else if(type)
-	errormsg(WHERE,ERR_CHK,"Drop file type",type);
-
-}
-
-/****************************************************************************/
-/* Reads in MODUSER.DAT, EXITINFO.BBS, or DOOR.SYS and modify the current	*/
-/* user's values.                                                           */
-/****************************************************************************/
-void moduserdat(uint xtrnnum)
-{
-	char str[256],path[256],c,startup[128];
-	uint i;
-	long mod;
-    int file;
-    FILE *stream;
-
-sprintf(startup,"%s\\",xtrn[xtrnnum]->path);
-if(xtrn[xtrnnum]->type==XTRN_RBBS) {
-	sprintf(path,"%sEXITINFO.BBS"
-		,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
-	if((file=nopen(path,O_RDONLY))!=-1) {
-		lseek(file,361,SEEK_SET);
-		read(file,&useron.flags1,4); /* Flags */
-		putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16));
-		lseek(file,373,SEEK_SET);
-		read(file,&i,2);			/* SecLvl */
-		if(i<90) {
-			useron.level=i;
-			putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); }
-		close(file);
-		remove(path); }
-	return; }
-else if(xtrn[xtrnnum]->type==XTRN_GAP) {
-	sprintf(path,"%sDOOR.SYS"
-		,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
-	if((stream=fopen(path,"rb"))!=NULL) {
-		for(i=0;i<15;i++)			/* skip first 14 lines */
-			if(!fgets(str,128,stream))
-				break;
-		if(i==15 && isdigit(str[0])) {
-			mod=atoi(str);
-			if(mod<90) {
-				useron.level=mod;
-				putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); } }
-
-		for(;i<23;i++)
-			if(!fgets(str,128,stream))
-				break;
-		if(i==23) { 					/* set main flags */
-			useron.flags1=aftol(str);
-			putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
-
-		for(;i<25;i++)
-			if(!fgets(str,128,stream))
-				break;
-		if(i==25 && isdigit(str[0]) && isdigit(str[1])
-			&& (str[2]=='/' || str[2]=='-') /* xx/xx/xx or xx-xx-xx */
-			&& isdigit(str[3]) && isdigit(str[4])
-			&& (str[5]=='/' || str[5]=='-')
-			&& isdigit(str[6]) && isdigit(str[7])) { /* valid expire date */
-			useron.expire=dstrtounix(str);
-			putuserrec(useron.number,U_EXPIRE,8,ultoa(useron.expire,tmp,16)); }
-
-		for(;i<29;i++)					/* line 29, total downloaded files */
-			if(!fgets(str,128,stream))
-				break;
-		if(i==29) {
-			truncsp(str);
-			useron.dls=atoi(str);
-			putuserrec(useron.number,U_DLS,5,str); }
-
-		if(fgets(str,128,stream)) { 	/* line 30, Kbytes downloaded today */
-            i++;
-			truncsp(str);
-			mod=atol(str)*1024L;
-			if(mod) {
-				useron.dlb=adjustuserrec(useron.number,U_DLB,10,mod);
-				subtract_cdt(mod); } }
-
-		for(;i<42;i++)
-			if(!fgets(str,128,stream))
-				break;
-		if(i==42 && isdigit(str[0])) {	/* Time Credits in Minutes */
-			useron.min=atol(str);
-			putuserrec(useron.number,U_MIN,10,ultoa(useron.min,tmp,10)); }
-
-		fclose(stream); }
-	return; }
-
-else if(xtrn[xtrnnum]->type==XTRN_PCBOARD) {
-	sprintf(path,"%sUSERS.SYS"
-		,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
-	if((file=nopen(path,O_RDONLY))!=-1) {
-		lseek(file,39,SEEK_SET);
-		read(file,&c,1);
-		if(c==1) {	 /* file has been updated */
-			lseek(file,105,SEEK_CUR);	/* read security level */
-			read(file,&i,2);
-			if(i<90) {
-				useron.level=i;
-				putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); }
-			lseek(file,75,SEEK_CUR);	/* read in expiration date */
-			read(file,&i,2);	/* convert from julian to unix */
-			useron.expire=juliantounix(i);
-			putuserrec(useron.number,U_EXPIRE,8,ltoa(useron.expire,tmp,16)); }
-		close(file); }
-	return; }
-
-sprintf(path,"%sMODUSER.DAT"
-		,xtrn[xtrnnum]->misc&STARTUPDIR ? startup : node_dir);
-if((stream=fopen(path,"rb"))!=NULL) {        /* File exists */
-	if(fgets(str,81,stream) && (mod=atol(str))!=0) {
-		ultoac(mod>0L ? mod : -mod,tmp);		/* put commas in the # */
-		strcpy(str,"Credit Adjustment: ");
-		if(mod<0L)
-			strcat(str,"-");                    /* negative, put '-' */
-		strcat(str,tmp);
-		if(mod>0L)
-			strcpy(tmp,"$+");
-		else
-			strcpy(tmp,"$-");
-		logline(tmp,str);
-		if(mod>0L)			/* always add to real cdt */
-			useron.cdt=adjustuserrec(useron.number,U_CDT,10,mod);
-		else
-			subtract_cdt(-mod); }	/* subtract from free cdt first */
-	if(fgets(str,81,stream)) {		/* main level */
-		mod=atoi(str);
-		if(isdigit(str[0]) && mod<90) {
-			useron.level=mod;
-			putuserrec(useron.number,U_LEVEL,2,itoa(useron.level,tmp,10)); } }
-	fgets(str,81,stream);		 /* was transfer level, now ignored */
-	if(fgets(str,81,stream)) {		/* flags #1 */
-		if(strchr(str,'-'))         /* remove flags */
-			useron.flags1&=~aftol(str);
-		else						/* add flags */
-			useron.flags1|=aftol(str);
-		putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
-
-	if(fgets(str,81,stream)) {		/* flags #2 */
-		if(strchr(str,'-'))         /* remove flags */
-			useron.flags2&=~aftol(str);
-		else						/* add flags */
-			useron.flags2|=aftol(str);
-		putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,tmp,16)); }
-
-	if(fgets(str,81,stream)) {		/* exemptions */
-		if(strchr(str,'-'))
-			useron.exempt&=~aftol(str);
-		else
-			useron.exempt|=aftol(str);
-		putuserrec(useron.number,U_EXEMPT,8,ultoa(useron.exempt,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* restrictions */
-		if(strchr(str,'-'))
-			useron.rest&=~aftol(str);
-		else
-			useron.rest|=aftol(str);
-		putuserrec(useron.number,U_REST,8,ultoa(useron.rest,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* Expiration date */
-		if(isxdigit(str[0]))
-			putuserrec(useron.number,U_EXPIRE,8,str); }
-	if(fgets(str,81,stream)) {		/* additional minutes */
-		mod=atol(str);
-		if(mod) {
-			sprintf(str,"Minute Adjustment: %s",ultoac(mod,tmp));
-			logline("*+",str);
-			useron.min=adjustuserrec(useron.number,U_MIN,10,mod); } }
-
-	if(fgets(str,81,stream)) {		/* flags #3 */
-		if(strchr(str,'-'))         /* remove flags */
-			useron.flags3&=~aftol(str);
-		else						/* add flags */
-			useron.flags3|=aftol(str);
-		putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,tmp,16)); }
-
-	if(fgets(str,81,stream)) {		/* flags #4 */
-		if(strchr(str,'-'))         /* remove flags */
-			useron.flags4&=~aftol(str);
-		else						/* add flags */
-			useron.flags4|=aftol(str);
-		putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,tmp,16)); }
-
-	if(fgets(str,81,stream)) {		/* flags #1 to REMOVE only */
-		useron.flags1&=~aftol(str);
-		putuserrec(useron.number,U_FLAGS1,8,ultoa(useron.flags1,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* flags #2 to REMOVE only */
-		useron.flags2&=~aftol(str);
-		putuserrec(useron.number,U_FLAGS2,8,ultoa(useron.flags2,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* flags #3 to REMOVE only */
-		useron.flags3&=~aftol(str);
-		putuserrec(useron.number,U_FLAGS3,8,ultoa(useron.flags3,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* flags #4 to REMOVE only */
-		useron.flags4&=~aftol(str);
-		putuserrec(useron.number,U_FLAGS4,8,ultoa(useron.flags4,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* exemptions to remove */
-		useron.exempt&=~aftol(str);
-		putuserrec(useron.number,U_EXEMPT,8,ultoa(useron.exempt,tmp,16)); }
-	if(fgets(str,81,stream)) {		/* restrictions to remove */
-		useron.rest&=~aftol(str);
-		putuserrec(useron.number,U_REST,8,ultoa(useron.rest,tmp,16)); }
-
-	fclose(stream);
-	remove(path); }
-}
-
-/****************************************************************************/
-/* This is the external programs (doors) section of the bbs                 */
-/* Return 1 if no externals available, 0 otherwise. 						*/
-/****************************************************************************/
-char xtrn_sec()
-{
-	char str[256];
-	int file,j,k,xsec,*usrxtrn,usrxtrns,*usrxsec,usrxsecs;
-	uint i;
-
-if(!total_xtrns || !total_xtrnsecs) {
-	bputs(text[NoXtrnPrograms]);
-	return(1); }
-
-if((usrxtrn=(int *)MALLOC(total_xtrns*sizeof(int)))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrns);
-	return(1); }
-if((usrxsec=(int *)MALLOC(total_xtrnsecs*sizeof(int)))==NULL) {
-	errormsg(WHERE,ERR_ALLOC,nulstr,total_xtrnsecs);
-	FREE(usrxtrn);
-    return(1); }
-
-while(online) {
-	for(i=0,usrxsecs=0;i<total_xtrnsecs;i++)
-		if(chk_ar(xtrnsec[i]->ar,useron))
-			usrxsec[usrxsecs++]=i;
-	if(!usrxsecs) {
-		bputs(text[NoXtrnPrograms]);
-		FREE(usrxtrn);
-		FREE(usrxsec);
-		return(1); }
-	if(usrxsecs>1) {
-		sprintf(str,"%sMENU\\XTRN_SEC.*",text_dir);
-		if(fexist(str)) {
-			menu("XTRN_SEC");
-			xsec=getnum(usrxsecs);
-			if(xsec<=0)
-				break;
-			xsec--;
-			xsec=usrxsec[xsec]; }
-		else {
-			for(i=0;i<total_xtrnsecs;i++)
-				uselect(1,i,"External Program Section"
-					,xtrnsec[i]->name,xtrnsec[i]->ar);
-			xsec=uselect(0,0,0,0,0); }
-		if(xsec==-1)
-			break; }
-	else
-		xsec=0;
-
-	while(!chk_ar(xtrnsec[xsec]->ar,useron))
-		xsec++;
-
-	if(xsec>=total_xtrnsecs) {
-		bputs(text[NoXtrnPrograms]);
-		FREE(usrxtrn);
-		FREE(usrxsec);
-        return(1); }
-
-	while(online) {
-		for(i=0,usrxtrns=0;i<total_xtrns; i++) {
-			if(xtrn[i]->sec!=xsec)
-				continue;
-			if(xtrn[i]->misc&EVENTONLY)
-				continue;
-			if(!chk_ar(xtrn[i]->ar,useron))
-				continue;
-			usrxtrn[usrxtrns++]=i; }
-		if(!usrxtrns) {
-			bputs(text[NoXtrnPrograms]);
-			pause();
-			break; }
-		sprintf(str,"%sMENU\\XTRN%u.*",text_dir,xsec+1);
-		if(fexist(str)) {
-			sprintf(str,"XTRN%u",xsec+1);
-			menu(str); }
-		else {
-			bprintf(text[XtrnProgLstHdr],xtrnsec[xsec]->name);
-			bputs(text[XtrnProgLstTitles]);
-			if(usrxtrns>=10) {
-				bputs("     ");
-				bputs(text[XtrnProgLstTitles]); }
-			CRLF;
-			bputs(text[XtrnProgLstUnderline]);
-			if(usrxtrns>=10) {
-				bputs("     ");
-				bputs(text[XtrnProgLstUnderline]); }
-			CRLF;
-			if(usrxtrns>=10)
-				j=(usrxtrns/2)+(usrxtrns&1);
-			else
-				j=usrxtrns;
-			for(i=0;i<j && !msgabort();i++) {
-				bprintf(text[XtrnProgLstFmt],i+1
-					,xtrn[usrxtrn[i]]->name,xtrn[usrxtrn[i]]->cost);
-				if(usrxtrns>=10) {
-					k=(usrxtrns/2)+i+(usrxtrns&1);
-					if(k<usrxtrns) {
-						bputs("     ");
-						bprintf(text[XtrnProgLstFmt],k+1
-							,xtrn[usrxtrn[k]]->name
-							,xtrn[usrxtrn[k]]->cost); } }
-				CRLF; }
-			ASYNC;
-			mnemonics(text[WhichXtrnProg]); }
-		getnodedat(node_num,&thisnode,1);
-		thisnode.aux=0; /* aux is 0, only if at menu */
-		putnodedat(node_num,thisnode);
-		action=NODE_XTRN;
-		SYNC;
-		if((j=getnum(usrxtrns))<1)
-			break;
-		exec_xtrn(usrxtrn[j-1]); }
-	if(usrxsecs<2)
-		break; }
-FREE(usrxtrn);
-FREE(usrxsec);
-return(0);
-}
-
-/****************************************************************************/
-/* This function handles configured external program execution. 			*/
-/****************************************************************************/
-void exec_xtrn(uint xtrnnum)
-{
-	char str[256],str2[256],path[256],dropdir[128],name[32],c,e,mode;
-    int file;
-	uint i;
-	long mod;
-	ulong tleft;
-    FILE *stream;
-    node_t node;
-	time_t start,end;
-
-
-if(!chk_ar(xtrn[xtrnnum]->run_ar,useron)
-	|| !chk_ar(xtrnsec[xtrn[xtrnnum]->sec]->ar,useron)) {
-	bputs(text[CantRunThatProgram]);
-	return; }
-
-if(xtrn[xtrnnum]->cost && !(useron.exempt&FLAG('X'))) {    /* costs */
-	if(xtrn[xtrnnum]->cost>useron.cdt+useron.freecdt) {
-		bputs(text[NotEnoughCredits]);
-		pause();
-		return; }
-	subtract_cdt(xtrn[xtrnnum]->cost); }
-
-if(!(xtrn[xtrnnum]->misc&MULTIUSER)) {
-	for(i=1;i<=sys_nodes;i++) {
-		getnodedat(i,&node,0);
-		c=i;
-		if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-			&& node.action==NODE_XTRN && node.aux==(xtrnnum+1)) {
-			if(node.status==NODE_QUIET) {
-				strcpy(str,sys_guru);
-				c=sys_nodes+1; }
-			else if(node.misc&NODE_ANON)
-				strcpy(str,"UNKNOWN USER");
-			else
-				username(node.useron,str);
-			bprintf(text[UserRunningXtrn],str
-				,xtrn[xtrnnum]->name,c);
-			pause();
-			break; } }
-	if(i<=sys_nodes)
-		return; }
-
-sprintf(str,"%s\\",xtrn[xtrnnum]->path);
-strcpy(path,xtrn[xtrnnum]->misc&STARTUPDIR ? str : node_dir);
-strcpy(dropdir,xtrn[xtrnnum]->misc&STARTUPDIR ? str : node_dir);
-
-switch(xtrn[xtrnnum]->type) {
-	case XTRN_WWIV:
-		strcat(path,"CHAIN.TXT");
-		break;
-	case XTRN_GAP:
-		strcat(path,"DOOR.SYS");
-		break;
-	case XTRN_RBBS:
-		sprintf(str,"DORINFO%X.DEF",node_num);
-		strcat(path,str);
-		break;
-	case XTRN_RBBS1:
-		strcat(path,"DORINFO1.DEF");
-		break;
-	case XTRN_WILDCAT:
-		strcat(path,"CALLINFO.BBS");
-		break;
-	case XTRN_PCBOARD:
-		strcat(path,"PCBOARD.SYS");
-		break;
-	case XTRN_UTI:
-		strcat(path,"UTIDOOR.TXT");
-		break;
-	case XTRN_SR:
-		strcat(path,"DOORFILE.SR");
-		break;
-	default:
-		strcat(path,"XTRN.DAT");
-		break; }
-getnodedat(node_num,&thisnode,1);
-thisnode.aux=xtrnnum+1;
-thisnode.action=NODE_XTRN;
-putnodedat(node_num,thisnode);
-
-if(xtrn[xtrnnum]->misc&REALNAME)
-    strcpy(name,useron.name);
-else
-    strcpy(name,useron.alias);
-
-gettimeleft();
-tleft=timeleft+(xtrn[xtrnnum]->textra*60);
-if(xtrn[xtrnnum]->maxtime && tleft>xtrn[xtrnnum]->maxtime)
-	tleft=(xtrn[xtrnnum]->maxtime*60);
-xtrndat(name,dropdir,xtrn[xtrnnum]->type,tleft);
-if(!online)
-	return;
-sprintf(str,"Ran external: %s",xtrn[xtrnnum]->name);
-logline("X-",str);
-if(xtrn[xtrnnum]->cmd[0]!='*' && sys_status&SS_LOGOPEN) {
-	close(logfile);
-	sys_status&=~SS_LOGOPEN; }
-
-sprintf(str,"%sINTRSBBS.DAT"
-		,xtrn[xtrnnum]->path[0] ? xtrn[xtrnnum]->path : node_dir);
-remove(str);
-sprintf(str,"%sHANGUP.NOW",node_dir);
-remove(str);
-sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
-remove(str);
-
-mode=0; 	/* EX_CC */
-if(xtrn[xtrnnum]->misc&IO_INTS)
-	mode|=(EX_OUTR|EX_INR|EX_OUTL);
-if(xtrn[xtrnnum]->misc&WWIVCOLOR)
-	mode|=EX_WWIV;
-if(xtrn[xtrnnum]->misc&SWAP)
-	mode|=EX_SWAP;
-if(xtrn[xtrnnum]->misc&MODUSERDAT) {	 /* Delete MODUSER.DAT */
-	sprintf(str,"%sMODUSER.DAT",dropdir);       /* if for some weird  */
-	remove(str); }								/* reason it's there  */
-
-if(xtrn[xtrnnum]->path[0]) {
-	if(xtrn[xtrnnum]->path[1]==':')                /* drive letter specified */
-		setdisk(toupper(xtrn[xtrnnum]->path[0])-'A');
-	if(chdir(xtrn[xtrnnum]->path))
-		errormsg(WHERE,ERR_CHDIR,xtrn[xtrnnum]->path,0); }
-
-start=time(NULL);
-external(cmdstr(xtrn[xtrnnum]->cmd,path,dropdir,NULL),mode);
-end=time(NULL);
-if(xtrn[xtrnnum]->misc&FREETIME)
-	starttime+=end-start;
-if(xtrn[xtrnnum]->clean[0]) {
-	if(xtrn[xtrnnum]->path[0]) {
-		if(xtrn[xtrnnum]->path[1]==':')             /* drive letter specified */
-			setdisk(toupper(xtrn[xtrnnum]->path[0])-'A');
-		if(chdir(xtrn[xtrnnum]->path))
-			errormsg(WHERE,ERR_CHDIR,xtrn[xtrnnum]->path,0); }
-	external(cmdstr(xtrn[xtrnnum]->clean,path,nulstr,NULL)
-		,mode&~EX_INR); }
-/* Re-open the logfile */
-if(!(sys_status&SS_LOGOPEN)) {
-	sprintf(str,"%sNODE.LOG",node_dir);
-	if((logfile=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1)
-		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-	else
-		sys_status|=SS_LOGOPEN; }
-
-sprintf(str,"%sFILE\\%04u.DWN",data_dir,useron.number);
-batch_add_list(str);
-
-sprintf(str,"%sHANGUP.NOW",node_dir);
-if(fexist(str)) {
-	remove(str);
-	hangup(); }
-if(online==ON_REMOTE) {
-	checkline();
-	if(!online) {
-		sprintf(str,"%sHUNGUP.LOG",data_dir);
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
-			return; }
-		getnodedat(node_num,&thisnode,0);
-		now=time(NULL);
-		sprintf(str,hungupstr,useron.alias,xtrn[thisnode.aux-1]->name
-			,timestr(&now));
-		write(file,str,strlen(str));
-		close(file); } }
-if(xtrn[xtrnnum]->misc&MODUSERDAT) {	/* Modify user data */
-	moduserdat(xtrnnum);
-	statusline(); }
-
-getnodedat(node_num,&thisnode,1);
-thisnode.aux=0; /* aux is 0, only if at menu */
-putnodedat(node_num,thisnode);
-}
-
-/****************************************************************************/
-/* This function will execute an external program if it is configured to    */
-/* run during the event specified.                                          */
-/****************************************************************************/
-void user_event(char event)
-{
-    uint i;
-
-for(i=0;i<total_xtrns;i++) {
-	if(xtrn[i]->event!=event)
-        continue;
-	if(!chk_ar(xtrn[i]->ar,useron)
-		|| !chk_ar(xtrnsec[xtrn[i]->sec]->ar,useron))
-        continue;
-    exec_xtrn(i); }
-}
-
-
diff --git a/src/sbbs3/Makefile.bor b/src/sbbs3/Makefile.bor
deleted file mode 100644
index 9499b4e4568c490c5185fe5d7e450987b356e458..0000000000000000000000000000000000000000
--- a/src/sbbs3/Makefile.bor
+++ /dev/null
@@ -1,130 +0,0 @@
-# Makefile.bor
-
-#########################################################################
-# Makefile for Synchronet BBS 											#
-# For use with Borland C++ Builder 5 or Borland C++ 5.5 for Win32       #
-# @format.tab-size 4													#
-#																		#
-# usage: make -f makefile.bor											#
-#																		#
-# Optional build targets: dlls, utils, mono, all (default)				#
-#########################################################################
-
-# $Id$
-
-# Macros
-DEBUG	=	1				# Comment out for release (non-debug) version
-JS		=	1				# Comment out for non-JavaScript (v3.00) build
-CC		=	bcc32
-LD		=	ilink32
-SLASH	=	\\
-OFILE	=	obj
-LIBFILE	=	.dll
-EXEFILE	=	.exe
-LIBODIR	=	bcc.win32.dll	# Library output directory
-EXEODIR =	bcc.win32.exe	# Executable output directory
-CFLAGS	=	-M -g1 
-LFLAGS  =	-m -s -c -Tpd -Gi -I$(LIBODIR)
-DELETE	=	echo y | del 
-
-# Optional compile flags (disable banner, warnings and such)
-CFLAGS	=	$(CFLAGS) -q -d -H -X- -w-csu -w-pch -w-ccc -w-rch -w-par
-
-# Debug or release build?
-!ifdef DEBUG
-CFLAGS	=	$(CFLAGS) -v -Od -D_DEBUG 
-LFLAGS	=	$(LFLAGS) -v
-LIBODIR	=	$(LIBODIR).debug
-EXEODIR	=	$(EXEODIR).debug
-!else
-LIBODIR	=	$(LIBODIR).release
-EXEODIR	=	$(EXEODIR).release
-!endif
-
-# JavaScript Support
-!ifdef JS
-CFLAGS	= 	$(CFLAGS) -DJAVASCRIPT -I../mozilla/js/src
-LIBS	=	..\mozilla\js\src\Release\js32omf.lib
-!endif
-
-# Cross platform/compiler definitions
-!include targets.mak	# defines all targets
-!include objects.mak	# defines $(OBJS)
-!include headers.mak	# defines $(HEADERS)
-!include sbbsdefs.mak	# defines $(SBBSDEFS)
-
-SBBSLIB	=	$(LIBODIR)\sbbs.lib
-
-# Implicit C Compile Rule for SBBS.DLL
-{.}.c.$(OFILE):
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -WD -WM -n$(LIBODIR) -c $(SBBSDEFS) $<
-
-# Implicit C++ Compile Rule for SBBS.DLL
-{.}.cpp.$(OFILE):
-	@echo Compiling (I) $< to $@ ...
-	$(CC) $(CFLAGS) -WD -WM -n$(LIBODIR) -c $(SBBSDEFS) $<
-
-# Create output directories if they don't exist
-$(LIBODIR):
-	@if not exist $(LIBODIR) mkdir $(LIBODIR)
-$(EXEODIR):
-	@if not exist $(EXEODIR) mkdir $(EXEODIR)
-
-# Monolithic Synchronet executable Build Rule
-$(SBBSMONO): sbbscon.c $(OBJS) $(LIBODIR)\ver.$(OFILE) $(LIBODIR)\ftpsrvr.$(OFILE) \
-	$(LIBODIR)\mailsrvr.$(OFILE) $(LIBODIR)\mxlookup.$(OFILE) $(LIBODIR)\mime.$(OFILE) \
-	$(LIBODIR)\services.$(OFILE)
-	$(CC) $(CFLAGS) -WM -e$(SBBSMONO) $** $(LIBS)
-
-# SBBS DLL Link Rule
-$(SBBS): $(OBJS) $(LIBODIR)\ver.$(OFILE)
-    @echo Linking $< ...
-	$(LD) $(LFLAGS) c0d32.obj $(LIBS) $(OBJS) $(LIBODIR)\ver.$(OFILE), $*, $*, \
-		import32.lib cw32mt.lib ws2_32.lib
-
-# Mail Server DLL Link Rule
-$(MAILSRVR): mailsrvr.c mxlookup.c mime.c crc32.c $(SBBSLIB)
-    @echo Compiling $** ...
-	$(CC) $(CFLAGS) -WD -WM -lGi -n$(LIBODIR) -DMAILSRVR_EXPORTS -DSMBDLL $** $(LIBS)
-
-# FTP Server DLL Link Rule
-$(FTPSRVR): ftpsrvr.c $(SBBSLIB)
-    @echo Compiling $** ...
-	$(CC) $(CFLAGS) -WD -WM -lGi -n$(LIBODIR) -DFTPSRVR_EXPORTS $** $(LIBS)
-
-# Services DLL Link Rule
-$(SERVICES): services.c $(SBBSLIB)
-    @echo Compiling $** ...
-	$(CC) $(CFLAGS) -WD -WM -lGi -n$(LIBODIR) -DSERVICES_EXPORTS $** $(LIBS)
-
-# Synchronet Console Build Rule
-$(SBBSCON): sbbscon.c $(SBBSLIB)
-	$(CC) $(CFLAGS) -n$(EXEODIR) $**
-
-# Baja Utility
-$(BAJA): baja.c ars.c crc32.c
-	@echo Compiling $** ...
-	$(CC) $(CFLAGS) -n$(EXEODIR) $** 
-
-# Node Utility
-$(NODE): node.c 
-	@echo Compiling $** ...
-	$(CC) $(CFLAGS) -n$(EXEODIR) $** 
-
-# FIXSMB Utility
-$(FIXSMB): fixsmb.c smblib.c smbwrap.c
-	@echo Compiling $** ...
-	$(CC) $(CFLAGS) -n$(EXEODIR) $** 
-
-# CHKSMB Utility
-$(CHKSMB): chksmb.c smblib.c smbwrap.c
-	@echo Compiling $** ...
-	$(CC) $(CFLAGS) -n$(EXEODIR) $** 
-
-# SMB Utility
-$(SMBUTIL): smbutil.c smblib.c smbwrap.c smbtxt.c crc32.c lzh.c
-	@echo Compiling $** ...
-	$(CC) $(CFLAGS) -n$(EXEODIR) $** 
-
-!include depends.mak	# defines dependencies
\ No newline at end of file
diff --git a/src/sbbs3/Makefile.gnu b/src/sbbs3/Makefile.gnu
deleted file mode 100644
index a27e4aed939c24be6676e14e5aef396e8472ee71..0000000000000000000000000000000000000000
--- a/src/sbbs3/Makefile.gnu
+++ /dev/null
@@ -1,171 +0,0 @@
-# Makefile.gnu
-
-#########################################################################
-# Makefile for Synchronet BBS 											#
-# For use with GNU make and GNU C Compiler								#
-# @format.tab-size 4, @format.use-tabs true								#
-#																		#
-# Linux: make -f Makefile.gnu											#
-# Win32: make -f Makefile.gnu os=win32									#
-# FreeBSD: make -f Makefile.gnu os=freebsd								#
-#																		#
-# Optional build targets: dlls, utils, mono, all (default)				#
-#########################################################################
-
-# $Id$
-
-# Macros
-DEBUG	=	1		# Comment out for release (non-debug) version
-CC		=	gcc
-SLASH	=	/
-OFILE	=	o
-
-ifeq ($(os),win32)	# Windows
-
-LD		=	dllwrap
-LIBFILE	=	.dll
-EXEFILE	=	.exe
-LIBODIR	:=	gcc.win32.dll
-EXEODIR	:=	gcc.win32.exe
-LIBDIR	:=	/gcc/i386-mingw32/lib
-CFLAGS	:=	-mno-cygwin
-LFLAGS  :=	--target=i386-mingw32 -mno-cygwin
-DELETE	=	echo y | del 
-OUTLIB	=	--output-lib
-LIBS	=	$(LIBDIR)/libwsock32.a $(LIBDIR)/libwinmm.a
-
-else	# Unix (begin)
-
-LD		=	ld
-LIBFILE	=	.a
-EXEFILE	=	
-
-ifeq ($(os),freebsd)	# FreeBSD
-LIBODIR	:=	gcc.freebsd.lib
-EXEODIR	:=	gcc.freebsd.exe
-else                    # Linux
-LIBODIR	:=	gcc.linux.lib
-EXEODIR	:=	gcc.linux.exe
-endif
-
-LIBDIR	:=	/usr/lib
-LFLAGS  :=	
-DELETE	=	rm -f -v
-OUTLIB	=	-o
-
-CFLAGS	:=	-DJAVASCRIPT -I../mozilla/js/src
-
-ifeq ($(os),freebsd)	# FreeBSD
-CFLAGS	:=	$(CFLAGS) -pthread -D_THREAD_SAFE
-LIBS	:=	-pthread
-else			# Linux / Other UNIX
-LIBS	:=	$(LIBDIR)/libpthread.a 
-endif
-
-endif   # Unix (end)
-
-# Math library needed
-LIBS	:=	$(LIBS) -lm
-
-ifdef DEBUG
-CFLAGS	:=	$(CFLAGS) -g -O0 -D_DEBUG 
-LIBODIR	:=	$(LIBODIR).debug
-EXEODIR	:=	$(EXEODIR).debug
-ifeq ($(os),freebsd)	# FreeBSD
-LIBS	:=	$(LIBS) ../mozilla/js/src/FreeBSD4.3-RELEASE_DBG.OBJ/libjs.a
-else			# Linux
-LIBS	:=	$(LIBS) ../mozilla/js/src/Linux_All_DBG.OBJ/libjs.a
-endif
-else # RELEASE
-LFLAGS	:=	$(LFLAGS) -S
-LIBODIR	:=	$(LIBODIR).release
-EXEODIR	:=	$(EXEODIR).release
-ifeq ($(os),freebsd)	# FreeBSD
-LIBS	:=	$(LIBS) ../mozilla/js/src/FreeBSD4.3-RELEASE_OPT.OBJ/libjs.a
-else
-LIBS	:=	$(LIBS) ../mozilla/js/src/Linux_All_OPT.OBJ/libjs.a
-endif
-endif
-
-include targets.mak		# defines all targets
-include objects.mak		# defines $(OBJS)
-include headers.mak		# defines $(HEADERS)
-include sbbsdefs.mak	# defines $(SBBSDEFS)
-
-SBBSLIB	=	$(LIBODIR)/sbbs.a
-	
-
-# Implicit C Compile Rule for SBBS
-$(LIBODIR)/%.o : %.c
-	$(CC) $(CFLAGS) -c $(SBBSDEFS) $< -o $@
-
-# Implicit C++ Compile Rule for SBBS
-$(LIBODIR)/%.o : %.cpp
-	$(CC) $(CFLAGS) -c $(SBBSDEFS) $< -o $@
-
-# Create output directories
-$(LIBODIR):
-	mkdir $(LIBODIR)
-
-$(EXEODIR):
-	mkdir $(EXEODIR)
-
-# Monolithic Synchronet executable Build Rule
-$(SBBSMONO): sbbscon.c conwrap.c $(OBJS) $(LIBODIR)/ver.o $(LIBODIR)/ftpsrvr.o $(LIBODIR)/mailsrvr.o $(LIBODIR)/mxlookup.o $(LIBODIR)/mime.o $(LIBODIR)/services.o
-#	$(CC) $(CFLAGS) -o $(SBBSMONO) $^ $(LIBS)
-	$(CC) -o $(SBBSMONO) $^ $(LIBS)
-
-# Synchronet BBS library Link Rule
-$(SBBS): $(OBJS) $(LIBODIR)/ver.o
-	$(LD) $(LFLAGS) -o $(SBBS) $^ $(LIBS) $(OUTLIB) $(SBBSLIB)
-
-# FTP Server Link Rule
-$(FTPSRVR): $(LIBODIR)/ftpsrvr.o $(SBBSLIB)
-	$(LD) $(LFLAGS) -o $@ $^ $(LIBS) $(OUTLIB) $(LIBODIR)/ftpsrvr.a
-
-# Mail Server Link Rule
-$(MAILSRVR): $(LIBODIR)/mailsrvr.o $(LIBODIR)/mxlookup.o $(LIBODIR)/mime.o $(SBBSLIB)
-	$(LD) $(LFLAGS) -o $@ $^ $(LIBS) $(OUTLIB) $(LIBODIR)/mailsrvr.a
-
-# Synchronet Console Build Rule
-$(SBBSCON): sbbscon.c $(SBBSLIB)
-	$(CC) $(CFLAGS) -o $@ $^
-
-# Specifc Compile Rules
-$(LIBODIR)/ftpsrvr.o: ftpsrvr.c ftpsrvr.h
-	$(CC) $(CFLAGS) -c -DFTPSRVR_EXPORTS $< -o $@
-
-$(LIBODIR)/mailsrvr.o: mailsrvr.c mailsrvr.h
-	$(CC) $(CFLAGS) -c -DMAILSRVR_EXPORTS $< -o $@
-
-$(LIBODIR)/mxlookup.o: mxlookup.c
-	$(CC) $(CFLAGS) -c -DMAILSRVR_EXPORTS $< -o $@		
-
-$(LIBODIR)/mime.o: mime.c
-	$(CC) $(CFLAGS) -c -DMAILSRVR_EXPORTS $< -o $@		
-
-$(LIBODIR)/services.o: services.c services.h
-	$(CC) $(CFLAGS) -c -DSERVICES_EXPORTS $< -o $@
-
-# Baja Utility
-$(BAJA): baja.c ars.c smbwrap.c crc32.c
-	$(CC) $(CFLAGS) -o $@ $^
-
-# Node Utility
-$(NODE): node.c smbwrap.c
-	$(CC) $(CFLAGS) -o $@ $^
-
-# FIXSMB Utility
-$(FIXSMB): fixsmb.c smblib.c smbwrap.c
-	$(CC) $(CFLAGS) -o $@ $^
-
-# CHKSMB Utility
-$(CHKSMB): chksmb.c smblib.c smbwrap.c conwrap.c
-	$(CC) $(CFLAGS) -o $@ $^
-
-# SMB Utility
-$(SMBUTIL): smbutil.c smblib.c smbwrap.c conwrap.c smbtxt.c crc32.c lzh.c 
-	$(CC) $(CFLAGS) -o $@ $^
-
-
-include depends.mak
diff --git a/src/sbbs3/depends.mak b/src/sbbs3/depends.mak
deleted file mode 100644
index 0a976ddea5ec85d08458fe32da5a6d023b6a87a9..0000000000000000000000000000000000000000
--- a/src/sbbs3/depends.mak
+++ /dev/null
@@ -1,90 +0,0 @@
-# depends.mak
-
-# Make 'include file' defining dependencies for Synchronet SBBS.DLL
-
-# $Id$
-
-# LIBODIR, EXEODIR, SLASH, and OFILE must be pre-defined
-
-$(LIBODIR)$(SLASH)answer.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)ars.$(OFILE):			$(HEADERS) ars_defs.h
-$(LIBODIR)$(SLASH)bat_xfer.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)bulkmail.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)chk_ar.$(OFILE):		$(HEADERS) ars_defs.h
-$(LIBODIR)$(SLASH)atcodes.$(OFILE):		$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)chat.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)comio.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)con_hi.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)con_out.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)data.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)data_ovl.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)date_str.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)download.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)email.$(OFILE):		$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)exec.$(OFILE):		$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)execfile.$(OFILE):	$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)execfunc.$(OFILE):	$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)execmisc.$(OFILE):	$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)execnet.$(OFILE):	$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)execmsg.$(OFILE):		$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)fido.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)file.$(OFILE):      	$(HEADERS)
-$(LIBODIR)$(SLASH)filedat.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)getkey.$(OFILE):    	$(HEADERS)
-$(LIBODIR)$(SLASH)getmsg.$(OFILE):    	$(HEADERS)
-$(LIBODIR)$(SLASH)getnode.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)getstr.$(OFILE):    	$(HEADERS)
-$(LIBODIR)$(SLASH)ident.$(OFILE):    	$(HEADERS) ident.h
-$(LIBODIR)$(SLASH)inkey.$(OFILE):    	$(HEADERS)
-$(LIBODIR)$(SLASH)listfile.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)load_cfg.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)logfile.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)login.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)logon.$(OFILE):    	$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)logout.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)lzh.$(OFILE):			$(HEADERS)
-$(LIBODIR)$(SLASH)mail.$(OFILE):	    $(HEADERS)
-$(LIBODIR)$(SLASH)main.$(OFILE):		$(HEADERS) cmdshell.h ident.h
-$(LIBODIR)$(SLASH)misc.$(OFILE):		$(HEADERS) ars_defs.h crc32.h
-$(LIBODIR)$(SLASH)msgtoqwk.$(OFILE):	$(HEADERS) qwk.h
-$(LIBODIR)$(SLASH)netmail.$(OFILE):		$(HEADERS) qwk.h
-$(LIBODIR)$(SLASH)newuser.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)pack_qwk.$(OFILE):	$(HEADERS) qwk.h post.h
-$(LIBODIR)$(SLASH)pack_rep.$(OFILE):	$(HEADERS) qwk.h post.h
-$(LIBODIR)$(SLASH)postmsg.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)prntfile.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)putmsg.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)putnode.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)qwk.$(OFILE):			$(HEADERS) qwk.h post.h
-$(LIBODIR)$(SLASH)qwktomsg.$(OFILE):	$(HEADERS) qwk.h
-$(LIBODIR)$(SLASH)readmail.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)readmsgs.$(OFILE):	$(HEADERS) post.h
-$(LIBODIR)$(SLASH)ringbuf.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)scandirs.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)scansubs.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)scfglib1.$(OFILE):	$(HEADERS) scfglib.h
-$(LIBODIR)$(SLASH)scfglib2.$(OFILE):	$(HEADERS) scfglib.h
-$(LIBODIR)$(SLASH)smblib.$(OFILE):    	smblib.h smbdefs.h
-$(EXEODIR)$(SLASH)smblib.$(OFILE):    	smblib.h smbdefs.h
-$(LIBODIR)$(SLASH)smbtxt.$(OFILE):   	smblib.h lzh.h
-$(EXEODIR)$(SLASH)smbtxt.$(OFILE):   	smblib.h lzh.h
-$(LIBODIR)$(SLASH)smbwrap.$(OFILE):   	smbwrap.h
-$(EXEODIR)$(SLASH)smbwrap.$(OFILE):   	smbwrap.h
-$(LIBODIR)$(SLASH)sortdir.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)str.$(OFILE):			$(HEADERS)
-$(LIBODIR)$(SLASH)telgate.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)telmet.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)text_sec.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)tmp_xfer.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)un_qwk.$(OFILE):		$(HEADERS) qwk.h
-$(LIBODIR)$(SLASH)un_rep.$(OFILE):		$(HEADERS) qwk.h
-$(LIBODIR)$(SLASH)upload.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)userdat.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)useredit.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)getuser.$(OFILE):		$(HEADERS)
-$(LIBODIR)$(SLASH)ver.$(OFILE):			$(HEADERS) $(OBJS)
-$(LIBODIR)$(SLASH)viewfile.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)wrappers.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)writemsg.$(OFILE):	$(HEADERS)
-$(LIBODIR)$(SLASH)xtrn.$(OFILE):		$(HEADERS) cmdshell.h
-$(LIBODIR)$(SLASH)xtrn_sec.$(OFILE):	$(HEADERS)
diff --git a/src/sbbs3/headers.mak b/src/sbbs3/headers.mak
deleted file mode 100644
index 0081fd3ff322eec1562f9fbce4b0423049367bb0..0000000000000000000000000000000000000000
--- a/src/sbbs3/headers.mak
+++ /dev/null
@@ -1,9 +0,0 @@
-# headers.mak
-
-# Make 'include file' for building Synchronet DLLs 
-# Used with GNU and Borland compilers
-
-# $Id$
-
-HEADERS =	sbbs.h sbbsdefs.h sbbswrap.h sbbsinet.h scfgdefs.h gen_defs.h \
-			nodedefs.h smblib.h smbdefs.h text.h
diff --git a/src/sbbs3/objects.mak b/src/sbbs3/objects.mak
deleted file mode 100644
index 1d964eec26998ec849d36f07de044943a17c54fa..0000000000000000000000000000000000000000
--- a/src/sbbs3/objects.mak
+++ /dev/null
@@ -1,98 +0,0 @@
-# objects.mak
-
-# Make 'include file' listing object files for SBBS.DLL
-
-# $Id$
-
-# LIBODIR, SLASH, and OFILE must be pre-defined
-
-OBJS	=	$(LIBODIR)$(SLASH)ansiterm.$(OFILE)\
-			$(LIBODIR)$(SLASH)answer.$(OFILE)\
-			$(LIBODIR)$(SLASH)ars.$(OFILE)\
-			$(LIBODIR)$(SLASH)atcodes.$(OFILE)\
-			$(LIBODIR)$(SLASH)bat_xfer.$(OFILE)\
-			$(LIBODIR)$(SLASH)bulkmail.$(OFILE)\
-			$(LIBODIR)$(SLASH)chat.$(OFILE)\
-			$(LIBODIR)$(SLASH)chk_ar.$(OFILE)\
-			$(LIBODIR)$(SLASH)con_hi.$(OFILE)\
-			$(LIBODIR)$(SLASH)con_out.$(OFILE)\
-			$(LIBODIR)$(SLASH)crc32.$(OFILE)\
-			$(LIBODIR)$(SLASH)data.$(OFILE)\
-			$(LIBODIR)$(SLASH)data_ovl.$(OFILE)\
-			$(LIBODIR)$(SLASH)date_str.$(OFILE)\
-			$(LIBODIR)$(SLASH)download.$(OFILE)\
-			$(LIBODIR)$(SLASH)email.$(OFILE)\
-			$(LIBODIR)$(SLASH)exec.$(OFILE)\
-			$(LIBODIR)$(SLASH)execfile.$(OFILE)\
-			$(LIBODIR)$(SLASH)execfunc.$(OFILE)\
-			$(LIBODIR)$(SLASH)execmisc.$(OFILE)\
-			$(LIBODIR)$(SLASH)execmsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)execnet.$(OFILE)\
-			$(LIBODIR)$(SLASH)fido.$(OFILE)\
-			$(LIBODIR)$(SLASH)file.$(OFILE)\
-			$(LIBODIR)$(SLASH)filedat.$(OFILE)\
-			$(LIBODIR)$(SLASH)getkey.$(OFILE)\
-			$(LIBODIR)$(SLASH)getmsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)getnode.$(OFILE)\
-			$(LIBODIR)$(SLASH)getstr.$(OFILE)\
-			$(LIBODIR)$(SLASH)inkey.$(OFILE)\
-			$(LIBODIR)$(SLASH)ident.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_bbs.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_client.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_console.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_file.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_file_area.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_global.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_msg_area.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_msgbase.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_socket.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_system.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_user.$(OFILE)\
-			$(LIBODIR)$(SLASH)listfile.$(OFILE)\
-			$(LIBODIR)$(SLASH)load_cfg.$(OFILE)\
-			$(LIBODIR)$(SLASH)logfile.$(OFILE)\
-			$(LIBODIR)$(SLASH)login.$(OFILE)\
-			$(LIBODIR)$(SLASH)logon.$(OFILE)\
-			$(LIBODIR)$(SLASH)logout.$(OFILE)\
-			$(LIBODIR)$(SLASH)lzh.$(OFILE)\
-			$(LIBODIR)$(SLASH)mail.$(OFILE)\
-			$(LIBODIR)$(SLASH)main.$(OFILE)\
-			$(LIBODIR)$(SLASH)misc.$(OFILE)\
-			$(LIBODIR)$(SLASH)msgtoqwk.$(OFILE)\
-			$(LIBODIR)$(SLASH)netmail.$(OFILE)\
-			$(LIBODIR)$(SLASH)newuser.$(OFILE)\
-			$(LIBODIR)$(SLASH)pack_qwk.$(OFILE)\
-			$(LIBODIR)$(SLASH)pack_rep.$(OFILE)\
-			$(LIBODIR)$(SLASH)postmsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)prntfile.$(OFILE)\
-			$(LIBODIR)$(SLASH)putmsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)putnode.$(OFILE)\
-			$(LIBODIR)$(SLASH)qwk.$(OFILE)\
-			$(LIBODIR)$(SLASH)qwktomsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)readmail.$(OFILE)\
-			$(LIBODIR)$(SLASH)readmsgs.$(OFILE)\
-			$(LIBODIR)$(SLASH)ringbuf.$(OFILE)\
-			$(LIBODIR)$(SLASH)scandirs.$(OFILE)\
-			$(LIBODIR)$(SLASH)scansubs.$(OFILE)\
-			$(LIBODIR)$(SLASH)scfglib1.$(OFILE)\
-			$(LIBODIR)$(SLASH)scfglib2.$(OFILE)\
-			$(LIBODIR)$(SLASH)scfgsave.$(OFILE)\
-			$(LIBODIR)$(SLASH)smblib.$(OFILE)\
-			$(LIBODIR)$(SLASH)smbtxt.$(OFILE)\
-			$(LIBODIR)$(SLASH)smbwrap.$(OFILE)\
-			$(LIBODIR)$(SLASH)sortdir.$(OFILE)\
-			$(LIBODIR)$(SLASH)str.$(OFILE)\
-			$(LIBODIR)$(SLASH)telgate.$(OFILE)\
-			$(LIBODIR)$(SLASH)telnet.$(OFILE)\
-			$(LIBODIR)$(SLASH)text_sec.$(OFILE)\
-			$(LIBODIR)$(SLASH)tmp_xfer.$(OFILE)\
-			$(LIBODIR)$(SLASH)un_qwk.$(OFILE)\
-			$(LIBODIR)$(SLASH)un_rep.$(OFILE)\
-			$(LIBODIR)$(SLASH)upload.$(OFILE)\
-			$(LIBODIR)$(SLASH)userdat.$(OFILE)\
-			$(LIBODIR)$(SLASH)useredit.$(OFILE)\
-			$(LIBODIR)$(SLASH)viewfile.$(OFILE)\
-			$(LIBODIR)$(SLASH)wrappers.$(OFILE)\
-			$(LIBODIR)$(SLASH)writemsg.$(OFILE)\
-			$(LIBODIR)$(SLASH)xtrn.$(OFILE)\
-			$(LIBODIR)$(SLASH)xtrn_sec.$(OFILE) 
diff --git a/src/sbbs3/sbbsdefs.mak b/src/sbbs3/sbbsdefs.mak
deleted file mode 100644
index b42554f5688c51648b022ec9ceb73e5a9147509c..0000000000000000000000000000000000000000
--- a/src/sbbs3/sbbsdefs.mak
+++ /dev/null
@@ -1,7 +0,0 @@
-# sbbsdefs.mak
-
-# C/C++ compiler preprocessor definitions for building SBBS.DLL
-
-# $Id$
-
-SBBSDEFS=	-DSBBS -DSBBS_EXPORTS -DSMBDLL -DSMB_EXPORTS -DWRAPPER_DLL
diff --git a/src/sbbs3/targets.mak b/src/sbbs3/targets.mak
deleted file mode 100644
index 06fb1379820e259a7c43691501431131345e6faf..0000000000000000000000000000000000000000
--- a/src/sbbs3/targets.mak
+++ /dev/null
@@ -1,34 +0,0 @@
-# targets.mak
-
-# Make 'include file' defining targets for Synchronet project
-
-# $Id$
-
-# LIBODIR, EXEODIR, SLASH, LIBFILE, EXEFILE, and DELETE must be pre-defined
-
-SBBS	=	$(LIBODIR)$(SLASH)sbbs$(LIBFILE) 
-FTPSRVR	=	$(LIBODIR)$(SLASH)ftpsrvr$(LIBFILE)
-MAILSRVR=	$(LIBODIR)$(SLASH)mailsrvr$(LIBFILE)
-SERVICES=	$(LIBODIR)$(SLASH)services$(LIBFILE)
-SBBSCON	=	$(EXEODIR)$(SLASH)sbbscon$(EXEFILE)
-SBBSMONO=	$(EXEODIR)$(SLASH)sbbs$(EXEFILE)
-NODE	=	$(EXEODIR)$(SLASH)node$(EXEFILE)
-BAJA	=	$(EXEODIR)$(SLASH)baja$(EXEFILE)
-FIXSMB	=	$(EXEODIR)$(SLASH)fixsmb$(EXEFILE)
-CHKSMB	=	$(EXEODIR)$(SLASH)chksmb$(EXEFILE)
-SMBUTIL	=	$(EXEODIR)$(SLASH)smbutil$(EXEFILE)
-
-all:	$(LIBODIR) $(EXEODIR) $(SBBSMONO) \
-		$(FIXSMB) $(CHKSMB) $(SMBUTIL) $(BAJA) $(NODE)
-
-utils:	$(EXEODIR) \
-		$(FIXSMB) $(CHKSMB) $(SMBUTIL) $(BAJA) $(NODE)
-
-dlls:	$(LIBODIR) \
-		$(SBBS) $(FTPSRVR) $(MAILSRVR) $(SERVICES)
-
-mono:	$(LIBODIR) $(EXEODIR) $(SBBSMONO)
-
-clean:
-	@$(DELETE) $(LIBODIR)$(SLASH)*
-	@$(DELETE) $(EXEODIR)$(SLASH)*
\ No newline at end of file
diff --git a/src/sbbs3/useredit/MainFormUnit.pas b/src/sbbs3/useredit/MainFormUnit.pas
index 7415143f18c520898619ad30722eb331c98e43d5..b3752563f7edd4bf52d25bbaad85923add25c086 100644
--- a/src/sbbs3/useredit/MainFormUnit.pas
+++ b/src/sbbs3/useredit/MainFormUnit.pas
@@ -406,7 +406,7 @@ function TForm1.LastUser: Integer;
 var Str: AnsiString;
     f: TFileStream;
 begin
-    Str:=data_dir+'USER/USER.DAT';
+    Str:=data_dir+'user/user.dat';
     try
         f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
         Result := f.Size div U_LEN;
@@ -530,7 +530,7 @@ var Str: AnsiString;
     buf: array[0..U_LEN] of Char;
 begin
     { Open file and read user record }
-    Str:=data_dir+'USER/USER.DAT';
+    Str:=data_dir+'user/user.dat';
     try
         f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
     except
@@ -627,12 +627,18 @@ begin
     ChatCheckListBox.Tag:=0;
 
     { Initialize controls based on bits set/unset }
-    if user_misc AND DELETED <> 0 then
-        Status.Text := 'Deleted User'
-    else if user_misc AND INACTIVE <> 0 then
-        Status.Text := 'Inactive User'
-    else
+    if user_misc AND DELETED <> 0 then begin
+        Status.Text := 'Deleted User';
+        Status.Color := clRed;
+        end
+    else if user_misc AND INACTIVE <> 0 then begin
+        Status.Text := 'Inactive User';
+        Status.Color := clYellow;
+        end
+    else begin
         Status.Text := 'Active User';
+        Status.Color := clMenu;
+        end;
 
     { Security }
     GetUserText(LevelEdit,buf+U_LEVEL,2);
@@ -830,7 +836,7 @@ begin
     for i:=0 to U_LEN-1 do buf[i]:=ETX;
 
     { Open file and read current user record }
-    Str:=data_dir+'USER/USER.DAT';
+    Str:=data_dir+'user/user.dat';
     if FileExists(Str) then
         f:=TFileStream.Create(Str,fmOpenReadWrite or fmShareExclusive)
     else
@@ -847,6 +853,7 @@ begin
     PutUserText(NetMailEdit,buf+U_NETMAIL,LEN_NETMAIL);
     PutUserText(AddressEdit,buf+U_ADDRESS,LEN_ADDRESS);
     PutUserText(LocationEdit,buf+U_LOCATION,LEN_LOCATION);
+	PutUserText(NoteEdit,buf+U_NOTE,LEN_NOTE);
     PutUserText(ZipCodeEdit,buf+U_ZIPCODE,LEN_ZIPCODE);
     PutUserText(PasswordEdit,buf+U_PASS,LEN_PASS);
     PutUserText(PhoneEdit,buf+U_PHONE,LEN_PHONE);
@@ -1148,7 +1155,7 @@ begin
     SearchStr:=AnsiUpperCase(FindEdit.Text);
     usernumber:=0;
     { Open USER.DAT to search for string }
-    Str:=data_dir+'USER/USER.DAT';
+    Str:=data_dir+'user/user.dat';
     if not FileExists(Str) then Exit;
     f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
     if Sender = FindNextButton then
diff --git a/src/stp/make.bat b/src/stp/make.bat
deleted file mode 100755
index 3d8cfa45b06a6f6fe1e8ee7ebeee0720b100cc43..0000000000000000000000000000000000000000
--- a/src/stp/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -P-c -N -C -ms -w-pro stp rciols.obj ..\mswait\dos\mswaits.obj
diff --git a/src/stp/rciols.obj b/src/stp/rciols.obj
deleted file mode 100644
index 1103dcd172d4b32820e0783ff1b1fccc9d3ee1ca..0000000000000000000000000000000000000000
Binary files a/src/stp/rciols.obj and /dev/null differ
diff --git a/src/stp/stp.c b/src/stp/stp.c
deleted file mode 100644
index 6ed9f706ce9f14deba90483be274bc7b6658d7bd..0000000000000000000000000000000000000000
--- a/src/stp/stp.c
+++ /dev/null
@@ -1,2017 +0,0 @@
-/* STP.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Synchronet Transfer Protocols */
-
-#include <io.h>
-#include <dos.h>
-#include <dir.h>
-#include <time.h>
-#include <alloc.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/stat.h>
-
-#define STP 1
-
-#include "zmodem.h"
-
-#define MAXERRORS	10
-
-#define ERROR -1
-							/* Various Character/Ctrl-Code Definitions	*/
-#define SP			32		/* Space bar								*/
-#define ESC			27		/* ESC Char 								*/
-#define	CR			13		/* Carriage Return							*/
-#define FF          12      /* Form Feed								*/
-#define	LF			10		/* Line Feed								*/
-#define TAB			9		/* Horizontal Tabulation					*/
-#define BS			8		/* Back Space								*/
-#define SOH 		1		/* Start of header							*/
-#define STX         2		/* Start of text                            */
-#define ETX         3       /* End of text                              */
-#define EOT 		4		/* End of transmission						*/
-#define ACK 		6		/* Acknowledge								*/
-#define DLE 		16		/* Data link escape 						*/
-#define XON 		17		/* Ctrl-Q - resume transmission 			*/
-#define XOFF		19		/* Ctrl-S - pause transmission				*/
-#define NAK 		21		/* Negative Acknowledge 					*/
-#define CAN 		24		/* Cancel									*/
-#define CPMEOF		26		/* CP/M End of file (^Z)					*/
-#define LOC_ABORT	0x2e03	/* Local abort key	(^C)					*/
-
-#define uchar	unsigned char
-#define uint	unsigned int
-#define ulong   unsigned long
-
-#define SEND		(1<<0)	/* Sending file(s)							*/
-#define RECV		(1<<1)	/* Receiving file(s)						*/
-#define XMODEM		(1<<2)	/* Use Xmodem								*/
-#define YMODEM		(1<<3)	/* Use Ymodem								*/
-#define ZMODEM		(1<<4)	/* Use Zmodem								*/
-#define CRC 		(1<<5)	/* Use CRC error correction 				*/
-#define GMODE		(1<<6)	/* For Qmodem-G and Ymodem-G				*/
-#define DIR 		(1<<7)	/* Directory specified to download to		*/
-#define DEBUG		(1<<8)	/* Debug output 							*/
-#define OVERWRITE	(1<<9)	/* Overwrite receiving files				*/
-#define IGNORE_DCD	(1<<10) /* Ignore DCD								*/
-#define ALARM		(1<<11) /* Alarm when starting and stopping xfer	*/
-#define NO_LOCAL	(1<<12) /* Don't check local keyboard               */
-
-							/* Zmodem mode bits 						*/
-#define CTRL_ESC	(1<<0)	/* Escape all control chars 				*/
-#define VAR_HDRS	(1<<1)	/* Use variable headers 					*/
-
-#define LOOP_NOPEN	50
-
-#define MAX_FNAMES	100 	/* Up to 100 filenames						*/
-
-/************************/
-/* Remote I/O Constants */
-/************************/
-
-							/* i/o mode and state flags */
-#define CTSCK 0x1000     	/* check cts (mode only) */
-#define RTSCK 0x2000		/* check rts (mode only) */
-#define TXBOF 0x0800		/* transmit buffer overflow (outcom only) */
-#define ABORT 0x0400     	/* check for ^C (mode), aborting (state) */
-#define PAUSE 0x0200     	/* check for ^S (mode), pausing (state) */
-#define NOINP 0x0100     	/* input buffer empty (incom only) */
-
-							/* status flags */
-#define DCD 	0x80       	/* DCD on */
-#define RI		0x40		/* Ring indicate */
-#define DSR 	0x20		/* Dataset ready */
-#define CTS 	0x10       	/* CTS on */
-#define FERR 	0x08		/* Frameing error */
-#define PERR 	0x04		/* Parity error */
-#define OVRR 	0x02		/* Overrun */
-#define RXLOST 	0x01       	/* Receive buffer overflow */
-
-/* rioctl() arguments */
-/* returns mode or state flags in high 8 bits, status flags in low 8 bits */
-
-							/* the following return mode in high 8 bits */
-#define IOMODE 0        	/* no operation */
-#define IOSM 1          	/* i/o set mode flags */
-#define IOCM 2          	/* i/o clear mode flags */
-
-#define GVERS 0x007 		/* get version */
-#define GUART 0x107 		/* get uart */
-#define GIRQN 0x207 		/* get IRQ number */
-#define GBAUD 0x307 		/* get baud */
-
-							/* the following return state in high 8 bits */
-#define IOSTATE 4       	/* no operation */
-#define IOSS 5          	/* i/o set state flags */
-#define IOCS 6          	/* i/o clear state flags */
-#define IOFB 0x308      	/* i/o buffer flush */
-#define IOFI 0x208      	/* input buffer flush */
-#define IOFO 0x108      	/* output buffer flush */
-#define IOCE 9          	/* i/o clear error flags */
-
-#define TS_INT28	 1
-#define TS_WINOS2	 2
-#define TS_NODV 	 4
-
-							/* return count (16bit)	*/
-#define RXBC	0x000a		/* get receive buffer count */
-#define RXBS	0x010a		/* get receive buffer size */
-#define TXBC	0x000b		/* get transmit buffer count */
-#define TXBS	0x010b		/* get transmit buffer size */
-#define TXBF	0x020b		/* get transmit buffer free space */
-#define TXSYNC	0x000c		/* sync transmition (seconds<<8|0x0c) */
-#define IDLE	0x000d		/* suspend communication routines */
-#define RESUME	0x010d		/* return from suspended state */
-#define RLERC	0x000e		/* read line error count and clear */
-#define CPTON	0x0110		/* set input translation flag for ctrl-p on */
-#define CPTOFF	0x0010		/* set input translation flag for ctrl-p off */
-#define GETCPT	0x8010		/* return the status of ctrl-p translation */
-#define MSR 	0x0011		/* read modem status register */
-#define FIFOCTL 0x0012		/* FIFO UART control */
-#define TSTYPE	0x0013		/* Time-slice API type */
-#define GETTST	0x8013		/* Get Time-slice API type */
-
-							/* ivhctl() arguments */
-#define INT29R 1         	/* copy int 29h output to remote */
-#define INT29L 2			/* Use _putlc for int 29h */
-#define INT16  0x10      	/* return remote chars to int 16h calls */
-#define INTCLR 0            /* release int 16h, int 29h */
-
-#define DCDHIGH (rioctl(IOSTATE)&DCD || mode&IGNORE_DCD)
-
-/**************/
-/* Prototypes */
-/**************/
-
-/* LCLOLL.ASM */
-int	 lclini(int);
-void lclxy(int,int);
-int  lclwx(void);
-int  lclwy(void);
-int  lclatr(int);
-int  lclaes(void);
-void lputc(int);
-long lputs(char far *);
-uint lkbrd(int);
-
-/* RCIOLL.ASM */
-
-int  rioini(int com,int irq);          /* initialize com,irq */
-int  setbaud(int rate);                /* set baud rate */
-int  rioctl(int action);               /* remote i/o control */
-int  dtr(char onoff);                  /* set/reset dtr */
-int  incom(void);                      /* receive character */
-int  ivhctl(int intcode);              /* local i/o redirection */
-
-void riosync();
-void cancel();
-
-extern	mswtyp;
-extern uint riobp;
-
-uint	asmrev;
-
-/***************/
-/* Global Vars */
-/***************/
-long	mode=0L;						/* Program mode 					*/
-long	zmode=0L;						/* Zmodem mode						*/
-uchar	hdr_block_num;					/* Block number received in header	*/
-uchar	block[1024];					/* Block buffer 					*/
-uint	block_size; 					/* Block size (128 or 1024) 		*/
-ulong	block_num;						/* Block number 					*/
-ulong	last_block_num; 				/* Last block number sent			*/
-uint	flows=0;						/* Number of flow controls			*/
-
-/**************************************/
-/* Zmodem specific, from Chuck's RZSZ */
-/**************************************/
-char	Txhdr[ZMAXHLEN];				/* Zmodem transmit header			*/
-char	Rxhdr[ZMAXHLEN];				/* Zmodem receive header			*/
-char	attn[ZATTNLEN]; 				/* Attention string for sender		*/
-char	zconv;
-char	zmanag;
-char	ztrans;
-int 	tryzhdrtype;
-int 	Rxtimeout = 100;		/* Tenths of seconds to wait for something */
-int 	Rxframeind; 			/* ZBIN ZBIN32, or ZHEX type of frame */
-int 	Rxtype; 				/* Type of header received */
-int 	Rxhlen; 				/* Length of header received */
-int 	Rxcount;				/* Count of data bytes received */
-
-/********/
-/* Code */
-/********/
-
-int cbreakh()
-{
-return(1);
-}
-
-/****************************************************************************/
-/* Performs printf() through local assembly routines                        */
-/****************************************************************************/
-int lprintf(char *fmat, ...)
-{
-	va_list argptr;
-	char sbuf[2048];
-	int chcount;
-
-va_start(argptr,fmat);
-chcount=vsprintf(sbuf,fmat,argptr);
-va_end(argptr);
-lputs(sbuf);
-return(chcount);
-}
-
-void newline()
-{
-if(lclwx()>1)
-	lputs("\r\n");
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char count=0,logstr[256];
-	int file,share;
-
-if(access==O_RDONLY) share=O_DENYWRITE;
-	else share=O_DENYALL;
-while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN);
-if(file==-1 && errno==EACCES)
-	lprintf("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
-}
-
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into an ulong								*/
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
-}
-
-/****************************************************************************/
-/* Checks the disk drive for the existence of a file. Returns 1 if it       */
-/* exists, 0 if it doesn't.                                                 */
-/****************************************************************************/
-char fexist(char *filespec)
-{
-    struct ffblk f;
-
-if(findfirst(filespec,&f,0)==NULL)
-    return(1);
-return(0);
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/**************/
-/* Exit Point */
-/**************/
-void bail(int code)
-{
-
-if(mode&ALARM) {
-	sound(2000);
-	mswait(500);
-	sound(1000);
-	mswait(500);
-	nosound(); }
-riosync();
-rioini(0,0);	/* uninstall com routines */
-newline();
-lprintf("Exiting - Error level: %d  Flow restraint count: %u\r\n",code,flows);
-fcloseall();
-exit(code);
-}
-
-/************************************************************/
-/* Get a character from com port, time out after 10 seconds */
-/************************************************************/
-int getcom(char timeout)
-{
-	uint	i,ch;
-	time_t	start;
-
-if((ch=incom())!=NOINP)
-	return(ch);
-for(i=0;i<10000;i++)			   /* ten consecutive re-tries */
-	if((ch=incom())!=NOINP)
-		return(ch);
-flows++;
-start=time(NULL);
-while(time(NULL)-start<(long)timeout) {   /* wait up to ten seconds */
-	if((ch=incom())!=NOINP)
-		return(ch);
-	if(!DCDHIGH) {
-		newline();
-		lprintf("No carrier\r\n");
-		bail(1); }
-	mswait(0);
-	if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
-		newline();
-		lprintf("Local abort\r\n");
-		cancel();
-		bail(1); } }
-newline();
-lprintf("Input timeout\r\n");
-return(NOINP);
-}
-
-/**********************************/
-/* Output a character to COM port */
-/**********************************/
-void putcom(uchar ch)
-{
-	int i=0;
-
-while(outcom(ch)&TXBOF && i<180) { /* 10 sec delay */
-	if(!i) lputc('F');
-	if(!DCDHIGH) {
-		newline();
-		lprintf("No carrier\r\n");
-		bail(1); }
-	i++;
-	mswait(1);
-	if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
-		newline();
-		lprintf("Local abort\r\n");
-		bail(1); } }
-if(i) {
-	lprintf("\b \b");
-	flows++;
-	if(i==180) {
-		newline();
-		lprintf("Output timeout\r\n");
-		bail(1); } }
-}
-
-void put_nak()
-{
-while(getcom(1)!=NOINP && (mode&NO_LOCAL || lkbrd(0)!=LOC_ABORT))
-	;				/* wait for any trailing data */
-putcom(NAK);
-}
-
-void cancel()
-{
-	int i;
-
-for(i=0;i<10;i++)
-	putcom(CAN);
-for(i=0;i<10;i++)
-	putcom(BS);
-}
-
-/********************************/
-/* Update the CRC bytes 		*/
-/********************************/
-/****
-void update_crc(uchar c, uchar *crc1, uchar *crc2)
-{
-	int i, temp;
-	uchar carry, c_crc1, c_crc2;
-
-for (i=0; i < 8; i++) {
-	temp = c * 2;
-	c = temp;			/* rotate left */
-	carry = ((temp > 255) ? 1 : 0);
-	temp = (*crc2) * 2;
-	(*crc2) = temp;
-	(*crc2) |= carry;		   /* rotate with carry */
-	c_crc2 = ((temp > 255) ? 1 : 0);
-	temp = (*crc1) * 2;
-	(*crc1) = temp;
-	(*crc1) |= c_crc2;
-	c_crc1 = ((temp > 255) ? 1 : 0);
-	if (c_crc1) {
-		(*crc2) ^= 0x21;
-		(*crc1) ^= 0x10; } }
-}
-****/
-
-void ucrc16(uchar ch, uint *rcrc) {
-    uint i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-
-char *chr(uchar ch)
-{
-	static char str[25];
-
-switch(ch) {
-	case SOH:
-		return("SOH");
-	case STX:
-		return("STX");
-	case ETX:
-		return("ETX");
-	case EOT:
-		return("EOT");
-	case ACK:
-		return("ACK");
-	case NAK:
-		return("NAK");
-	case CAN:
-		return("CAN");
-	default:
-		sprintf(str,"%02Xh",ch);
-		return(str); }
-}
-
-/****************************************************************/
-/* Gets the filename from the filename and optional path in buf */
-/****************************************************************/
-char *justfname(char *buf, char *out)
-{
-	char *p1,*p2;
-
-if(mode&DEBUG)
-	lprintf("justfname:  in: '%s'\r\n",buf);
-p1=buf;
-while(*p1) {
-	if((p2=strchr(p1,':'))!=NULL) {      /* Remove path */
-		p1=p2+1;
-		continue; }
-	if((p2=strchr(p1,'/'))!=NULL) {
-		p1=p2+1;
-		continue; }
-	if((p2=strchr(p1,'\\'))!=NULL) {
-		p1=p2+1;
-		continue; }
-	break; }
-if(!*p1) {
-	lprintf("Invalid filename\r\n");
-	strcpy(out,""); }
-else
-	strcpy(out,p1); 					   /* Use just the filename */
-if(mode&DEBUG)
-	lprintf("justfname: out: '%s'\r\n",out);
-return(out);
-}
-
-/****************************************************************************/
-/* Receive a X/Y/Zmodem block (sector) from COM port						*/
-/* hdrblock is 1 if attempting to get Ymodem header block, 0 if data block	*/
-/* Returns 0 if all went well, -1 on error or CAN, and EOT if EOT			*/
-/****************************************************************************/
-int get_block(int hdrblock)
-{
-	uchar chksum,calc_chksum;
-	int i,b,errors,eot=0,can=0;
-	uint crc,calc_crc;
-
-for(errors=0;errors<MAXERRORS;errors++) {
-	i=getcom(10);
-	if(eot && i!=EOT)
-		eot=0;
-	if(can && i!=CAN)
-		can=0;
-	switch(i) {
-		case SOH: /* 128 byte blocks */
-			block_size=128;
-			break;
-		case STX: /* 1024 byte blocks */
-			block_size=1024;
-			break;
-		case EOT:
-			if((mode&(YMODEM|GMODE))==YMODEM && !eot) {
-				eot=1;
-				put_nak();		/* chuck's double EOT trick */
-				continue; }
-			return(EOT);
-		case CAN:
-			newline();
-			if(!can) {			/* must get two CANs in a row */
-				can=1;
-				lprintf("Received CAN  Expected SOH, STX, or EOT\r\n");
-				continue; }
-			lprintf("Cancelled remotely\r\n");
-			return(-1);
-		case NOINP: 	/* Nothing came in */
-			continue;
-		default:
-			newline();
-			lprintf("Received %s  Expected SOH, STX, or EOT\r\n",chr(i));
-			if(hdrblock)  /* Trying to get Ymodem header block */
-				return(-1);
-			put_nak();
-			continue; }
-	i=getcom(1);
-	if(i==NOINP) {
-		put_nak();
-		continue; }
-	hdr_block_num=i;
-	i=getcom(1);
-	if(i==NOINP) {
-		put_nak();
-		continue; }
-	if(hdr_block_num!=(uchar)~i) {
-		newline();
-		lprintf("Block number error\r\n");
-		put_nak();
-		continue; }
-	calc_crc=calc_chksum=0;
-	for(b=0;b<block_size;b++) {
-		i=getcom(1);
-		if(i==NOINP)
-			break;
-		block[b]=i;
-		if(mode&CRC)
-			ucrc16(block[b],&calc_crc);
-		else
-			calc_chksum+=block[b]; }
-
-	if(b<block_size) {
-		put_nak();
-		continue; }
-
-	if(mode&CRC) {
-		crc=getcom(1)<<8;
-		crc|=getcom(1); }
-	else
-		chksum=getcom(1);
-
-	if(mode&CRC) {
-		ucrc16(0,&calc_crc);
-		ucrc16(0,&calc_crc);
-		if(crc==calc_crc)
-			break;
-		newline();
-		lprintf("CRC error\r\n"); }
-
-	else {	/* CHKSUM */
-		if(chksum==calc_chksum)
-			break;
-		newline();
-		lprintf("Checksum error\r\n"); }
-
-	if(mode&GMODE) {	/* Don't bother sending a NAK. He's not listening */
-		cancel();
-		bail(1); }
-	put_nak(); }
-
-if(errors>=MAXERRORS) {
-	newline();
-	lprintf("Too many errors\r\n");
-	return(-1); }
-return(0);
-}
-
-/*****************/
-/* Sends a block */
-/*****************/
-void put_block()
-{
-	uchar ch,chksum;
-    int i;
-	uint crc;
-
-if(block_size==128)
-	putcom(SOH);
-else			/* 1024 */
-	putcom(STX);
-ch=(block_num&0xff);
-putcom(ch);
-putcom(~ch);
-chksum=crc=0;
-for(i=0;i<block_size;i++) {
-	putcom(block[i]);
-	if(mode&CRC)
-		ucrc16(block[i],&crc);
-	else
-		chksum+=block[i]; }
-
-if(mode&CRC) {
-	ucrc16(0,&crc);
-	ucrc16(0,&crc);
-	putcom(crc>>8);
-	putcom(crc&0xff); }
-else
-	putcom(chksum);
-}
-
-/************************************************************/
-/* Gets an acknowledgement - usually after sending a block	*/
-/* Returns 1 if ack received, 0 otherwise.					*/
-/************************************************************/
-int get_ack()
-{
-	int i,errors,can=0;
-
-for(errors=0;errors<MAXERRORS;errors++) {
-
-	if(mode&GMODE) {		/* Don't wait for ACK on Ymodem-G */
-		if(incom()==CAN) {
-			newline();
-			lprintf("Cancelled remotely\r\n");
-			cancel();
-			bail(1); }
-		return(1); }
-
-	i=getcom(10);
-	if(can && i!=CAN)
-		can=0;
-	if(i==ACK)
-		return(1);
-	if(i==CAN) {
-		if(can) {
-			newline();
-			lprintf("Cancelled remotely\r\n");
-			cancel();
-			bail(1); }
-		can=1; }
-	if(i!=NOINP) {
-		newline();
-		lprintf("Received %s  Expected ACK\r\n",chr(i));
-		if(i!=CAN)
-			return(0); } }
-
-return(0);
-}
-
-/****************************************************************************/
-/* Syncronizes the remote and local machines								*/
-/****************************************************************************/
-void riosync()
-{
-	int 	i=0;
-
-while(rioctl(TXBC) && i<180) { /* 10 sec */
-	if(!(mode&NO_LOCAL) && lkbrd(0)==LOC_ABORT) {
-		newline();
-		lprintf("Local abort\r\n");
-		cancel();
-		break; }
-	if(!DCDHIGH)
-		break;
-	mswait(1);
-	i++; }
-}
-
-/*********************************************************/
-/* Returns the number of blocks required to send n bytes */
-/*********************************************************/
-long blocks(long n)
-{
-	long l;
-
-l=n/(long)block_size;
-if(l*(long)block_size<n)
-	l++;
-return(l);
-}
-
-/****************************************/
-/* Zmodem specific functions start here */
-/****************************************/
-
-/**********************************************/
-/* Output single byte as two hex ASCII digits */
-/**********************************************/
-void putzhex(uchar val)
-{
-	char *digits="0123456789abcdef";
-
-putcom(digits[(val&0xF0)>>4]);
-putcom(digits[val&0xF]);
-}
-
-/***********************/
-/* Output a hex header */
-/***********************/
-void putzhhdr(char type)
-{
-	uint i,crc=0;
-
-putcom(ZPAD);
-putcom(ZPAD);
-putcom(ZDLE);
-if(zmode&VAR_HDRS) {
-	putcom(ZVHEX);
-	putzhex(4); }
-else
-	putcom(ZHEX);
-putzhex(type);
-ucrc16(type,&crc);
-for(i=0;i<4;i++) {
-	putzhex(Txhdr[i]);
-	ucrc16(Txhdr[i],&crc); }
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-putzhex(crc>>8);
-putzhex(crc&0xff);
-putcom(CR);
-putcom(LF); 	/* Chuck's RZ.C sends LF|0x80 for some unknown reason */
-if(type!=ZFIN && type!=ZACK)
-	putcom(XON);
-}
-
-/****************************************************************************/
-/* Stores a long in the Zmodem transmit header (usually position offset)	*/
-/****************************************************************************/
-void ltohdr(long l)
-{
-
-Txhdr[ZP0] = l;
-Txhdr[ZP1] = l>>8;
-Txhdr[ZP2] = l>>16;
-Txhdr[ZP3] = l>>24;
-}
-
-/****************************************************************************/
-/* Outputs single Zmodem character, escaping with ZDLE when appropriate     */
-/****************************************************************************/
-void putzcom(uchar ch)
-{
-    static lastsent;
-
-if(ch&0x60) /* not a control char */
-    putcom(lastsent=ch);
-else
-    switch(ch) {
-        case DLE:
-        case DLE|0x80:          /* even if high-bit set */
-        case XON:
-        case XON|0x80:
-        case XOFF:
-        case XOFF|0x80:
-        case ZDLE:
-            putcom(ZDLE);
-            ch^=0x40;
-            putcom(lastsent=ch);
-            break;
-        case CR:
-        case CR|0x80:
-            if(!(zmode&CTRL_ESC) && (lastsent&0x7f)!='@')
-                putcom(lastsent=ch);
-            else {
-                putcom(ZDLE);
-                ch^=0x40;
-                putcom(lastsent=ch); }
-            break;
-        default:
-            if(zmode&CTRL_ESC && !(ch&0x60)) {  /* it's a ctrl char */
-                putcom(ZDLE);
-                ch^=0x40; }
-            putcom(lastsent=ch);
-            break; }
-}
-
-/*
- * Read a byte, checking for ZMODEM escape encoding
- *  including CAN*5 which represents a quick abort
- */
-int getzcom()
-{
-	int i;
-
-while(1) {
-	/* Quick check for non control characters */
-	if((i=getcom(Rxtimeout))&0x60)
-		return(i);
-	if(i==ZDLE)
-		break;
-	if((i&0x7f)==XOFF || (i&0x7f)==XON)
-		continue;
-	if(zmode&CTRL_ESC && !(i&0x60))
-		continue;
-	return(i); }
-
-while(1) {	/* Escaped characters */
-	if((i=getcom(Rxtimeout))<0)
-		return(i);
-	if(i==CAN && (i=getcom(Rxtimeout))<0)
-		return(i);
-	if(i==CAN && (i=getcom(Rxtimeout))<0)
-        return(i);
-	if(i==CAN && (i=getcom(Rxtimeout))<0)
-        return(i);
-	switch (i) {
-		case CAN:
-			return(GOTCAN);
-		case ZCRCE:
-		case ZCRCG:
-		case ZCRCQ:
-		case ZCRCW:
-			return(i|GOTOR);
-		case ZRUB0:
-			return(0x7f);
-		case ZRUB1:
-			return(0xff);
-		case XON:
-		case XON|0x80:
-		case XOFF:
-		case XOFF|0x80:
-			continue;
-		default:
-			if (zmode&CTRL_ESC && !(i&0x60))
-				continue;
-			if ((i&0x60)==0x40)
-				return(i^0x40);
-			break; }
-	break; }
-return(ERROR);
-}
-
-
-
-/*
- * Read a character from the modem line with timeout.
- *  Eat parity, XON and XOFF characters.
- */
-int getcom7()
-{
-	int i;
-
-while(1) {
-	i=getcom(10);
-	switch(i) {
-		case XON:
-		case XOFF:
-			continue;
-		case CR:
-		case LF:
-		case NOINP:
-		case ZDLE:
-			return(i);
-		default:
-			if(!(i&0x60) && zmode&CTRL_ESC)
-				continue;
-			return(i); } }
-}
-
-
-#if 0
-
-int getzhdr()
-{
-	int done=0;
-
-while(!done) {
-	i=getcom(10);
-	switch(i) {
-		case NOINP:
-			done=1;
-			continue;
-		case XON:
-		case XON|0x80:
-			continue;
-		case ZPAD|0x80:
-		case ZPAD:
-			break;
-		case CAN:
-			cancount++;
-			if(cancount>=5) {
-				i=ZCAN;
-				done=1;
-				break; }
-			i=getcom(10);
-			switch(i) {
-				case NOINP:
-					continue;
-				case ZCRCW:
-					switch(getcom(10)) {
-						case NOINP:
-							i=ERROR
-							done=1;
-							break;
-						case RCDO:
-							done=1;
-							break;
-						default:
-							continue; }
-					break;
-				case RCDO:
-					done=1;
-					break;
-				case CAN:
-					cancount++;
-					if(cancount>=5) {
-						i=ZCAN;
-						done=1;
-					continue;
-				default:
-					break; }
-			continue;
-		default:
-			continue; }
-
-	i=Rxframeind=getcom7();
-	switch (i) {
-		case ZVBIN32:
-			if((Rxhlen=c=getzcom())<0)
-				goto fifi;
-			if(c>ZMAXHLEN)
-				goto agn2;
-			Crc32r=1;
-			c=zrbhd32(hdr);
-			break;
-		case ZBIN32:
-			if(zmode&VAR_HDRS)
-				goto agn2;
-			Crc32r=1;
-			c=zrbhd32(hdr);
-			break;
-		case ZVBINR32:
-			if((Rxhlen=c=getzcom())<0)
-				goto fifi;
-			if(c>ZMAXHLEN)
-				goto agn2;
-			Crc32r=2;
-			c=zrbhd32(hdr);
-			break;
-		case ZBINR32:
-			if(zmode&VAR_HDRS)
-				goto agn2;
-			Crc32r=2;
-			c=zrbhd32(hdr);
-			break;
-		case RCDO:
-		case TIMEOUT:
-			goto fifi;
-		case ZVBIN:
-			if((Rxhlen=c=getzcom())<0)
-				goto fifi;
-			if(c>ZMAXHLEN)
-				goto agn2;
-			Crc32r=0;
-			c=zrbhdr(hdr);
-			break;
-		case ZBIN:
-			if(zmode&VAR_HDRS)
-				goto agn2;
-			Crc32r=0;
-			c=zrbhdr(hdr);
-			break;
-		case ZVHEX:
-			if((Rxhlen=c=zgethex()) < 0)
-				goto fifi;
-			if(c>ZMAXHLEN)
-				goto agn2;
-			Crc32r=0;
-			c=zrhhdr(hdr);
-			break;
-		case ZHEX:
-			if(zmode&VAR_HDRS)
-				goto agn2;
-			Crc32r=0;
-			c=zrhhdr(hdr);
-			break;
-		case CAN:
-			goto gotcan;
-		default:
-			goto agn2;
-		}
-
-
-
-/****************************************************************************/
-/* Get the receiver's init parameters                                       */
-/****************************************************************************/
-int getzrxinit()
-{
-	int i;
-	struct stat f;
-
-for(i=0;i<10;i++) {
-	switch(zgethdr(Rxhdr,1)) {
-		case ZCHALLENGE:	/* Echo receiver's challenge numbr */
-			ltohdr(Rxpos);
-			putzhhdr(ZACK);
-			continue;
-		case ZCOMMAND:		/* They didn't see out ZRQINIT */
-			ltohdr(0L);
-			putzhhdr(ZRQINIT);
-			continue;
-		case ZRINIT:
-			Rxflags=Rxhdr[ZF0]&0x7f;
-			if(Rxhdr[ZF1]&CANVHDR)
-                zmode|=VAR_HDRS;
-			Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
-			Zctlesc |= Rxflags & TESCCTL;
-			Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
-			if ( !(Rxflags & CANFDX))
-				Txwindow = 0;
-
-			/* Override to force shorter frame length */
-			if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
-				Rxbuflen = Tframlen;
-			if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
-				Rxbuflen = Tframlen;
-			vfile("Rxbuflen=%d", Rxbuflen);
-
-			/*
-			 * If input is not a regular file, force ACK's to
-			 *	prevent running beyond the buffer limits
-			 */
-			if ( !Command) {
-				fstat(fileno(in), &f);
-				if ((f.st_mode & S_IFMT) != S_IFREG) {
-					Canseek = -1;
-	ef TXBSIZE
-					Txwindow = TXBSIZE - 1024;
-					Txwspac = TXBSIZE/4;
-	e
-					return ERROR;
-	if
-				}
-			}
-
-			/* Set initial subpacket length */
-			if (blklen < 1024) {	/* Command line override? */
-				if (Effbaud > 300)
-					blklen = 256;
-				if (Effbaud > 1200)
-					blklen = 512;
-				if (Effbaud > 2400)
-					blklen = 1024;
-			}
-			if (Rxbuflen && blklen>Rxbuflen)
-				blklen = Rxbuflen;
-			if (blkopt && blklen > blkopt)
-				blklen = blkopt;
-			vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
-			vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
-
-
-			if (Lztrans == ZTRLE && (Rxflags & CANRLE))
-				Txfcs32 = 2;
-			else
-				Lztrans = 0;
-
-			return (sendzsinit());
-		case ZCAN:
-		case TIMEOUT:
-			return ERROR;
-		case ZRQINIT:
-			if (Rxhdr[ZF0] == ZCOMMAND)
-				continue;
-		default:
-			putzhhdr(ZNAK);
-			continue; } }
-return(ERROR);
-}
-
-
-getzdata(char *buf, int length)
-{
-	int c,d;
-	uint crc;
-	char *end;
-
-	switch (Crc32r) {
-	case 1:
-		return zrdat32(buf, length);
-	case 2:
-		return zrdatr32(buf, length);
-	}
-
-	crc = Rxcount = 0;  end = buf + length;
-	while (buf <= end) {
-		if ((c = getzcom()) & ~0377) {
-crcfoo:
-			switch (c) {
-			case GOTCRCE:
-			case GOTCRCG:
-			case GOTCRCQ:
-			case GOTCRCW:
-				crc = updcrc((d=c)&0377, crc);
-				if ((c = getzcom()) & ~0377)
-					goto crcfoo;
-				crc = updcrc(c, crc);
-				if ((c = getzcom()) & ~0377)
-					goto crcfoo;
-				crc = updcrc(c, crc);
-				if (crc & 0xFFFF) {
-					zperr(badcrc);
-					return ERROR;
-				}
-				Rxcount = length - (end - buf);
-#ifndef DSZ
-				vfile("zrdata: %d  %s", Rxcount,
-				 Zendnames[d-GOTCRCE&3]);
-#endif
-				return d;
-			case GOTCAN:
-				zperr("Sender Canceled");
-				return ZCAN;
-			case TIMEOUT:
-				zperr("TIMEOUT");
-				return c;
-			default:
-				garbitch(); return c;
-			}
-		}
-		*buf++ = c;
-		crc = updcrc(c, crc);
-	}
-#ifdef DSZ
-	garbitch(); 
-#else
-	zperr("Data subpacket too long");
-#endif
-	return ERROR;
-}
-
-#endif
-
-/************************************************/
-/* Dump the current blockm contents - for debug */
-/************************************************/
-void dump_block()
-{
-	long l;
-
-for(l=0;l<block_size;l++)
-	lprintf("%02X  ",block[l]);
-lputs("\r\n");
-}
-
-char	*usage=
-"usage: STP <port> [chan] [opts] <cmd> [file | path | +list]\r\n\r\n"
-"where:\r\n\r\n"
-"port   = COM port (1-4), D for DigiBoard, or UART I/O address (hex)\r\n"
-"chan   = IRQ channel (2-15) or DigiBoard channel (4+)\r\n"
-"opts   = b# to set DTE rate to #bps\r\n"
-"         t# to set time-slice API type (default=1)\r\n"
-"         o  to overwrite files when receiving\r\n"
-"         d  to disable dropped carrier detection\r\n"
-"         a  to sound alarm at start and stop of transfer\r\n"
-"         l  to disable local keyboard (Ctrl-C) checking\r\n"
-"cmd    = sx to send Xmodem     rx to recv Xmodem\r\n"
-"         sX to send Xmodem-1k  rc to recv Xmodem-CRC\r\n"
-"         sy to send Ymodem     ry to recv Ymodem\r\n"
-"         sY to send Ymodem-1k  rg to recv Ymodem-G\r\n"
-"         sz to send Zmodem     rz to recv Zmodem\r\n"
-"file   = filename to send or receive\r\n"
-"path   = path to receive files into\r\n"
-"list   = name of text file with list of filenames to send or receive\r\n";
-
-/***************/
-/* Entry Point */
-/***************/
-int main(int argc, char **argv)
-{
-	char	str[256],tmp[256],tmp2[256],irq,errors,*p,*p2,first_block
-			,*fname[MAX_FNAMES],fnames=0,fnum,success;
-	int 	ch,i,j,k,file,last,total_files=0,sent_files=0,can;
-	uint	base=0,baud=0,cps;
-	long	b,l,m,file_bytes_left,serial_num;
-	ulong	file_bytes=0,total_bytes=0,sent_bytes=0;
-	time_t	t,startall,startfile,ftime;
-	struct	ffblk ff;
-	struct	ftime ft;
-	struct	date dosdate;
-	struct	time dostime;
-	FILE	*stream,*log=NULL;
-
-mswtyp=TS_INT28;   /* default to int 28 only */
-
-ctrlbrk(cbreakh);
-
-if((asmrev=*(&riobp-1))!=19) {
-	printf("Wrong rciol.obj\n");
-    exit(1); }
-
-lclini(0xd<<8);
-
-lprintf("\r\nSynchronet Transfer Protocols v1.00"
-	"  Developed 1993-1997 Rob Swindell\r\n\r\n");
-
-lputs("Command line: ");
-for(i=1;i<argc;i++)
-	lprintf("%s ",argv[i]);
-lputs("\r\n");
-
-if(argc<3) {
-	lprintf(usage);
-	exit(1); }
-
-i=1;
-
-base=ahtoul(argv[i]);
-if(base>4 && base<0x100)	/* 'D' and 'FFFF' are the same */
-	base=0xffff;
-if(base!=0xffff && base<5)
-	switch(atoi(argv[i])) {
-		case 1:
-			base=0x3f8;
-			irq=4;
-			break;
-		case 2:
-			base=0x2f8;
-			irq=3;
-			break;
-		case 3:
-			base=0x3e8;
-			irq=4;
-			break;
-		case 4:
-			base=0x2e8;
-			irq=3;
-			break;
-		default:
-			lprintf("Invalid COM Port (%s)\r\n",argv[1]);
-			lprintf(usage);
-			exit(1); }
-
-if(base>4 || isdigit(argv[i+1][0]))
-	irq=atoi(argv[++i]);
-
-for(i++;i<argc;i++) {
-
-	if(!(mode&(SEND|RECV))) {
-		if(toupper(argv[i][0])=='S' || toupper(argv[i][0])=='R') { /* cmd */
-			if(toupper(argv[i][0])=='R')
-				mode|=RECV;
-			else
-				mode|=SEND;
-
-			block_size=1024;
-
-			switch(argv[i][1]) {
-				case 'c':
-				case 'C':
-					mode|=CRC;
-				case 'x':
-					block_size=128;
-				case 'X':
-					mode|=XMODEM;
-					break;
-				case 'y':
-					block_size=128;
-				case 'Y':
-					mode|=(YMODEM|CRC);
-					break;
-				case 'g':
-				case 'G':
-					mode|=(YMODEM|CRC|GMODE);
-					break;
-				case 'z':
-				case 'Z':
-					mode|=(ZMODEM|CRC);
-					break;
-				default:
-					lprintf("Unrecognized command '%s'\r\n\r\n",argv[i]);
-					lprintf(usage);
-					exit(1); } }
-
-		else if(toupper(argv[i][0])=='B')
-			baud=atoi(argv[i]+1);
-
-		else if(toupper(argv[i][0])=='T')
-			mswtyp=atoi(argv[i]+1);
-
-		else if(toupper(argv[i][0])=='O')
-			mode|=OVERWRITE;
-
-		else if(toupper(argv[i][0])=='D')
-			mode|=IGNORE_DCD;
-
-		else if(toupper(argv[i][0])=='A')
-			mode|=ALARM;
-
-		else if(toupper(argv[i][0])=='L')
-			mode|=NO_LOCAL;
-
-		else if(argv[i][0]=='*')
-			mode|=DEBUG; }
-
-	else if(argv[i][0]=='+') {
-		if(mode&DIR) {
-			lprintf("Cannot specify both directory and filename\r\n");
-			exit(1); }
-		sprintf(str,"%s",argv[i]+1);
-		if((file=nopen(str,O_RDONLY))==-1
-			|| (stream=fdopen(file,"rb"))==NULL) {
-			lprintf("Error opening filelist %s\r\n",str);
-			exit(1); }
-		while(!feof(stream) && !ferror(stream) && fnames<MAX_FNAMES) {
-			if(!fgets(str,128,stream))
-				break;
-			truncsp(str);
-			strupr(str);
-			if((fname[fnames]=(char *)malloc(strlen(str)+1))==NULL) {
-				lprintf("Error allocating memory for filename\r\n");
-				exit(1); }
-			strcpy(fname[fnames++],str); }
-		fclose(stream); }
-
-	else if(mode&(SEND|RECV)){
-		if((fname[fnames]=(char *)malloc(128))==NULL) {
-			lprintf("Error allocating memory for filename\r\n");
-			exit(1); }
-		strcpy(fname[fnames],argv[i]);
-		strupr(fname[fnames]);
-		j=strlen(fname[fnames]);
-		if(fname[fnames][j-1]=='\\'                 /* Ends in \ */
-			|| !strcmp(fname[fnames]+1,":")) {      /* Drive letter only */
-/*			  || !findfirst(fname[fnames],&ff,FA_DIREC)) {	  is a directory */
-			if(mode&DIR) {
-				lprintf("Only one directory can be specified\r\n");
-				exit(1); }
-			if(fnames) {
-				lprintf("Cannot specify both directory and filename\r\n");
-				exit(1); }
-			if(mode&SEND) {
-				lprintf("Cannot send directory '%s'\r\n",fname[fnames]);
-				exit(1);}
-			mode|=DIR; }
-		fnames++; } }
-
-if(!(mode&(SEND|RECV))) {
-	lprintf("No command specified\r\n");
-	lprintf(usage);
-	exit(1); }
-
-if(mode&(SEND|XMODEM) && !fnames) { /* Sending with any or recv w/Xmodem */
-	lprintf("Must specify filename or filelist\r\n");
-	lprintf(usage);
-	exit(1); }
-
-i=strlen(fname[0]); 	/* Make sure the directory ends in \ or : */
-if(mode&DIR && fname[0][i-1]!='\\' && fname[0][i-1]!=':')
-	strcat(fname[0],"\\");
-
-i=rioini(base,irq);
-if(i) {
-	lprintf("STP: Error (%d) initializing COM port base %x irq %d\r\n"
-		,i,base,irq);
-	exit(1); }
-
-if(mode&ALARM) {
-	sound(1000);
-	mswait(500);
-	sound(2000);
-	mswait(500);
-	nosound(); }
-
-if(baud) {
-	i=setbaud(baud);
-	if(i) {
-		lprintf("STP: Error setting baud rate to %u\r\n",baud);
-		bail(1); } }
-else
-	baud=rioctl(GBAUD);
-
-rioctl(IOSM|CTSCK|RTSCK);
-
-rioctl(TSTYPE|mswtyp);			/* set time-slice API type */
-
-if(!DCDHIGH) {
-	newline();
-	lprintf("No carrier\r\n");
-	bail(1); }
-
-p=getenv("DSZLOG");
-if(p) {
-	if((file=open(p,O_WRONLY|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1
-		|| (log=fdopen(file,"wb"))==NULL) {
-		lprintf("Error opening DSZLOG file '%s'\r\n",p);
-		bail(1); }
-	setvbuf(log,NULL,_IOFBF,16*1024); }
-
-startall=time(NULL);
-
-if(mode&RECV) {
-	if(fnames>1)
-		lprintf("Receiving %u files\r\n",fnames);
-	fnum=0;
-	while(1) {
-		if(mode&XMODEM) {
-			strcpy(str,fname[0]);
-			file_bytes=file_bytes_left=0x7fffffff;
-			serial_num=-1; }
-
-		else if(mode&YMODEM) {
-			lprintf("Fetching Ymodem header block\r\n");
-			for(errors=0;errors<MAXERRORS;errors++) {
-				if(errors>3 && mode&CRC && !(mode&GMODE))
-					mode&=~CRC;
-				if(mode&GMODE)		/* G for Ymodem-G */
-					putcom('G');
-				else if(mode&CRC)	/* C for CRC */
-					putcom('C');
-				else				/* NAK for checksum */
-					putcom(NAK);
-				for(i=60;i;i--) {
-					if(rioctl(RXBC))	/* no chars in-bound */
-						break;
-					mswait(100); }		/* so wait */
-
-				if(!i) {				/* none after 6 secs */
-					if(errors)
-						lprintf("Ymodem header timeout (%d)\r\n",errors);
-					continue; }
-				if(!get_block(1)) { 	 /* block received successfully */
-					putcom(ACK);
-					break; } }
-			if(errors==MAXERRORS) {
-				lprintf("Error fetching Ymodem header block\r\n");
-				cancel();
-				bail(1); }
-			if(!block[0]) {
-				lputs("Received Ymodem termination block\r\n");
-				bail(0); }
-			p=block+strlen(block)+1;
-			sscanf(p,"%ld %lo %lo %lo %d %ld"
-				,&file_bytes			/* file size (decimal) */
-				,&ftime 				/* file time (octal unix format) */
-				,&m 					/* file mode (not used) */
-				,&serial_num			/* program serial number */
-				,&total_files			/* remaining files to be sent */
-				,&total_bytes			/* remaining bytes to be sent */
-				);
-			if(!file_bytes)
-				file_bytes=0x7fffffff;
-			file_bytes_left=file_bytes;
-			if(!total_files)
-				total_files=fnames-fnum;
-			if(!total_files)
-				total_files=1;
-			if(total_bytes<file_bytes)
-				total_bytes=file_bytes;
-			if(!serial_num)
-				serial_num=-1;
-			strupr(block);
-			lprintf("Incoming filename: %.64s ",block);
-			if(mode&DIR)
-				sprintf(str,"%s%s",fname[0],justfname(block,tmp));
-			else {
-				justfname(block,str);
-				for(i=0;i<fnames;i++) {
-					if(!fname[i][0])	/* name blank or already used */
-						continue;
-					justfname(fname[i],tmp);
-					if(!stricmp(tmp,str)) {
-						strcpy(str,fname[i]);
-						fname[i][0]=0;
-						break; } }
-				if(i==fnames) { 				/* Not found in list */
-					if(fnames)
-						lputs(" - Not in receive list!");
-					if(!fnames || fnum>=fnames || !fname[fnum][0])
-						justfname(block,str);	/* worst case */
-					else {
-						strcpy(str,fname[fnum]);
-						fname[fnum][0]=0; } } }
-			lputs("\r\n"); }
-
-		else {	/* Zmodem */
-#if 0
-			tryzhdrtype=ZRINIT;
-			while(1) {
-				Txhdr[ZF0]=(CANFC32|CANFDX|CANOVIO|CANRLE);
-				/* add CANBRK if we can send break signal */
-				if(zmode&CTRL_ESC)
-					Txhdr[ZF0]|=TESCCTL;
-				Txhdr[ZF1]=CANVHDR;
-				Txhdr[ZP0]=0;
-				Txhdr[ZP1]=0;
-				putzhhdr(tryzhdrtype);
-				done=0;
-				while(!done) {
-					done=1;
-					switch(getzhdr()) {
-						case ZRQINIT:
-							if(Rxhdr[ZF3]&0x80)
-								zmode|=VAR_HDRS;   /* we can var header */
-							break;
-						case ZFILE:
-							zconv=Rxhdr[ZF0];
-							zmanag=Rxhdr[ZF1];
-							ztrans=Rxhdr[ZF2];
-							if(Rxhdr[ZF3]&ZCANVHDR)
-								zmode|=VAR_HDRS;
-							tryzhdrtype=ZRINIT;
-							if(getzdata(block, 1024)==GOTCRCW) {
-								/* something */
-								done=1; }
-							putzhhdr(ZNAK);
-							done=0;
-							break;
-						case ZSINIT:
-							if(Rxhdr[ZF0]&TESCCTL)
-								zmode|=CTRL_ESC;
-							if (getzdata(attn,ZATTNLEN)==GOTCRCW) {
-								ltohdr(1L);
-								putzhhdr(ZACK); }
-							else
-								putzhhdr(ZNAK);
-							done=0;
-							break;
-						case ZFREECNT:
-							ltohdr(0);			/* should be free disk space */
-							putzhhdr(ZACK);
-							done=0;
-							break;
-						case ZCOMMAND:
-/***
-							cmdzack1flg = Rxhdr[ZF0];
-							if(getzdata(block,1024)==GOTCRCW) {
-								if (cmdzack1flg & ZCACK1)
-									ltohdr(0L);
-								else
-									ltohdr((long)sys2(block));
-								purgeline();	/* dump impatient questions */
-								do {
-									zshhdr(4,ZCOMPL, Txhdr);
-								}
-								while (++errors<20 && zgethdr(Rxhdr,1)!=ZFIN);
-								ackbibi();
-								if (cmdzack1flg & ZCACK1)
-									exec2(block);
-								return ZCOMPL;
-							}
-***/
-							putzhhdr(ZNAK);
-							done=0;
-							break;
-						case ZCOMPL:
-							done=0;
-							break;
-						case ZFIN:
-							ackbibi();
-							return ZCOMPL;
-						case ZCAN:
-							return ERROR; } }
-#endif
-			}
-
-		fnum++;
-
-		if(!(mode&DIR) && fnames && fnum>fnames) {
-			newline();
-			lprintf("Attempt to send more files than specified\r\n");
-			cancel();
-			break; }
-
-		k=strlen(str);	/* strip out control characters and high ASCII */
-		for(i=j=0;i<k;i++)
-			if(str[i]>SP && (uchar)str[i]<0x7f)
-				str[j++]=str[i];
-		str[j]=0;
-		strupr(str);
-		if(fexist(str) && !(mode&OVERWRITE)) {
-			lprintf("%s already exists\r\n",str);
-			cancel();
-			bail(1); }
-		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1
-			|| (stream=fdopen(file,"wb"))==NULL) {
-			lprintf("Error creating %s\r\n",str);
-			cancel();
-			bail(1); }
-		setvbuf(stream,NULL,_IOFBF,8*1024);
-		startfile=time(NULL);
-		lprintf("Receiving %s (%lu bytes) via %s %s\r\n"
-			,str
-			,mode&XMODEM ? 0 : file_bytes
-			,mode&XMODEM ? "Xmodem" : mode&YMODEM ? mode&GMODE ? "Ymodem-G"
-			: "Ymodem" :"Zmodem"
-			,mode&CRC ? "CRC-16":"Checksum");
-
-		errors=0;
-		block_num=0;
-		if(mode&GMODE)		/* G for Ymodem-G */
-			putcom('G');
-		else if(mode&CRC)	/* C for CRC */
-			putcom('C');
-		else				/* NAK for checksum */
-			putcom(NAK);
-		while(errors<MAXERRORS) {
-			if(block_num && !(mode&GMODE))
-				putcom(ACK);
-			i=get_block(0); 	/* returns 0 if block okay */
-			if(i==EOT)			/* end of transfer */
-				break;
-			if(i) { 			/* other error */
-				cancel();
-				bail(1); }
-			if(file_bytes_left<=0L)  { /* No more bytes to send */
-				newline();
-				lputs("Attempt to send more than header specified\r\n");
-				break; }
-			if(hdr_block_num==((block_num+1)&0xff)) {	/* correct block */
-				block_num++;
-				if(file_bytes_left<block_size) {
-					if(fwrite(block,1,file_bytes_left,stream)
-						!=file_bytes_left) {
-						newline();
-						lprintf("Error writing to file\r\n");
-						cancel();
-						bail(1); } }
-				else {
-					if(fwrite(block,1,block_size,stream)
-						!=block_size) {
-						newline();
-						lprintf("Error writing to file\r\n");
-						cancel();
-						bail(1); } }
-				file_bytes_left-=block_size; }
-			else {
-				newline();
-				lprintf("Block number %u instead of %u\r\n"
-					,hdr_block_num,(block_num+1)&0xff);
-				// dump_block();
-				errors++; }
-			t=time(NULL)-startfile;
-			if(!t) t=1;
-			cps=(uint)((block_num*(long)block_size)/t); 	/* cps so far */
-			if(!cps) cps=1;
-			l=file_bytes/cps;  /* total transfer est time */
-			l-=t;				/* now, it's est time left */
-            if(l<0) l=0;
-			b=blocks(file_bytes);
-			if(mode&YMODEM)
-				lprintf("\rBlock (%lu%s): %lu/%lu  Byte: %lu  Time: %lu:%02lu  "
-					"Left: %lu:%02lu  CPS: %u  %lu%% "
-					,block_size%1024L ? block_size: block_size/1024L
-					,block_size%1024L ? "" : "k"
-					,block_num
-					,b
-					,block_num*(long)block_size
-					,t/60L
-					,t%60L
-					,l/60L
-					,l%60L
-					,cps
-					,(long)(((float)block_num/(float)b)*100.0)
-					);
-			else	/* Xmodem */
-				lprintf("\rBlock (%lu%s): %lu  Byte: %lu  Time: %lu:%02lu  "
-					"CPS: %u "
-					,block_size%1024L ? block_size: block_size/1024L
-					,block_size%1024L ? "" : "k"
-					,block_num
-					,block_num*(long)block_size
-					,t/60L
-					,t%60L
-					,cps
-                    );
-		}
-
-		putcom(ACK);
-		if(!(mode&XMODEM) && ftime) {
-			unixtodos(ftime,&dosdate,&dostime);
-			if(dosdate.da_year>=1980) {
-				ft.ft_min=dostime.ti_min;
-				ft.ft_hour=dostime.ti_hour;
-				ft.ft_tsec=dostime.ti_sec/2;
-				ft.ft_year=dosdate.da_year-1980;
-				ft.ft_day=dosdate.da_day;
-				ft.ft_month=dosdate.da_mon;
-				setftime(file,&ft); } }
-		fclose(stream);
-		t=time(NULL)-startfile;
-		if(!t) t=1;
-		l=(block_num-1)*(long)block_size;
-		if(l>file_bytes)
-			l=file_bytes;
-		newline();
-		lprintf("Successsful - Time: %lu:%02lu  CPS: %lu\r\n"
-			,t/60,t%60,l/t);
-		if(log) {
-			fprintf(log,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u "
-				"%s %d\r\n"
-				,mode&ZMODEM ? 'Z' : 'R'
-				,l
-				,baud
-				,l/t
-				,errors
-				,flows
-				,block_size
-				,str
-				,serial_num); }
-		if(mode&XMODEM)
-			break;
-		total_files--;
-		total_bytes-=file_bytes;
-		if(total_files>1 && total_bytes)
-			lprintf("Remaining - Time: %lu:%02lu  Files: %u  Bytes: %lu\r\n"
-				,(total_bytes/cps)/60
-				,(total_bytes/cps)%60
-				,total_files
-				,total_bytes
-                );
-		}
-	bail(0); }
-
-/********/
-/* SEND */
-/********/
-
-/****************************************************/
-/* Search through all to find total files and bytes */
-/****************************************************/
-for(fnum=0;fnum<fnames;fnum++) {
-	last=findfirst(fname[fnum],&ff,0);	/* incase wildcards are used */
-	if(last)
-		lprintf("%s not found\r\n",fname[fnum]);
-	while(!last) {
-		total_files++;
-		total_bytes+=ff.ff_fsize;
-		last=findnext(&ff); } }
-
-if(fnames>1)
-	lprintf("Sending %u files (%lu bytes total)\r\n"
-		,total_files,total_bytes);
-
-rioctl(IOFB);
-
-/***********************************************/
-/* Send every file matching names or filespecs */
-/***********************************************/
-for(fnum=0;fnum<fnames;fnum++) {
-	last=findfirst(fname[fnum],&ff,0);
-	while(!last) {
-		if(mode&ZMODEM) {
-#if 0
-			putcom('r'); putcom('z'); putcom(CR);       /* send rz\r */
-			ltohdr(0L); 	/* Zero the header */
-			putzhhdr(ZRQINIT);
-			getzrxinit();
-#endif
-			} /* Zmodem */
-		else {
-			mode&=~GMODE;
-			flows=0;
-			for(errors=can=0;errors<MAXERRORS;errors++) {
-				i=getcom(10);
-				if(can && i!=CAN)
-					can=0;
-				if(i==NAK) {		/* csum */
-					mode&=~CRC;
-					break; }
-				if(i=='C') {
-					mode|=CRC;
-					break; }
-				if(i=='G') {
-					mode|=(GMODE|CRC);
-					break; }
-				if(i==CAN) {
-					if(can) {
-						newline();
-						lprintf("Cancelled remotely\r\n");
-						bail(1); }
-					can=1; }
-				rioctl(IOFB);	/* flush buffers cause we have crap-o-la */
-				if(i!=NOINP) {
-					newline();
-					lprintf("Received %s  Expected NAK, C, or G\r\n"
-						,chr(i)); } }
-			if(errors==MAXERRORS) {
-				lprintf("Timeout starting transfer\r\n");
-				cancel();
-				bail(1); } } /* X/Ymodem */
-
-		strcpy(str,fname[fnum]);
-		if(strchr(str,'*') || strchr(str,'?')) {    /* wildcards used */
-			p=strrchr(str,'\\');
-			if(!p)
-				p=strchr(str,':');
-			if(p)
-				*(p+1)=NULL;
-			else
-				str[0]=0;
-			strcat(str,ff.ff_name); }
-
-		lprintf("Sending %s (%lu bytes) via %s %s\r\n"
-			,str,ff.ff_fsize
-			,mode&XMODEM ? "Xmodem" : mode&YMODEM ? mode&GMODE ? "Ymodem-G"
-			: "Ymodem" :"Zmodem"
-            ,mode&CRC ? "CRC-16":"Checksum");
-
-		if((file=nopen(str,O_RDONLY))==-1
-			|| (stream=fdopen(file,"rb"))==NULL) {
-			lprintf("Error opening %s for read\r\n",str);
-			cancel();
-			bail(1); }
-		setvbuf(stream,NULL,_IOFBF,8*1024);
-		rioctl(IOFB);	/* flush buffers cause extra 'G', 'C', or NAKs */
-		if(!(mode&XMODEM)) {
-			getftime(file,&ft);
-			dostime.ti_min=ft.ft_min;
-			dostime.ti_hour=ft.ft_hour;
-			dostime.ti_hund=0;
-			dostime.ti_sec=ft.ft_tsec*2;
-			dosdate.da_year=1980+ft.ft_year;
-			dosdate.da_day=ft.ft_day;
-			dosdate.da_mon=ft.ft_month;
-			t=dostounix(&dosdate,&dostime);
-			memset(block,NULL,128);
-			strcpy(block,ff.ff_name);
-			strlwr(block);
-			sprintf(block+strlen(block)+1,"%lu %lo 0 0 %d %ld"
-				,ff.ff_fsize,t,total_files-sent_files,total_bytes-sent_bytes);
-			/*
-			lprintf("Sending Ymodem block '%s'\r\n",block+strlen(block)+1);
-			*/
-			block_num=0;
-			i=block_size;
-			block_size=128; 	/* Always use 128 for first block */
-			for(errors=0;errors<MAXERRORS;errors++) {
-				put_block();
-				if(get_ack())
-					break; }
-			if(errors==MAXERRORS) {
-				newline();
-				lprintf("Failed to send header block\r\n");
-				cancel();
-				bail(1); }
-			block_size=i;		/* Restore block size */
-			mode&=~GMODE;
-			for(errors=can=0;errors<MAXERRORS;errors++) {
-				i=getcom(10);
-				if(can && i!=CAN)
-					can=0;
-				if(i==NAK) {		/* csum */
-					mode&=~CRC;
-					break; }
-				if(i=='C') {
-					mode|=CRC;
-					break; }
-				if(i=='G') {
-					mode|=(GMODE|CRC);
-					break; }
-				if(i==CAN) {
-					if(can) {
-						newline();
-						lprintf("Cancelled remotely\r\n");
-						bail(1); }
-					can=1; }
-				rioctl(IOFB);
-				if(i!=NOINP) {
-					newline();
-					lprintf("Received %s  Expected NAK, C, or G\r\n"
-						,chr(i)); } }
-			if(errors==MAXERRORS) {
-				newline();
-				lprintf("Too many errors waiting for receiver\r\n");
-				cancel();
-				bail(1); } }
-		last_block_num=block_num=1;
-		startfile=time(NULL);
-		errors=0;
-		while((block_num-1)*(long)block_size<ff.ff_fsize && errors<MAXERRORS) {
-			if(last_block_num==block_num) {  /* block_num didn't increment */
-				fseek(stream,(block_num-1)*(long)block_size,SEEK_SET);
-				i=fread(block,1,block_size,stream);
-				while(i<block_size)
-					block[i++]=CPMEOF; }
-			last_block_num=block_num;
-			put_block();
-			i=fread(block,1,block_size,stream); /* read next block from disk */
-			while(i<block_size)
-				block[i++]=CPMEOF;
-			t=time(NULL)-startfile;
-			if(!t) t=1; 		/* t is time so far */
-			cps=(uint)((block_num*(long)block_size)/t); 	/* cps so far */
-			if(!cps) cps=1;
-			l=ff.ff_fsize/cps;	/* total transfer est time */
-			l-=t;				/* now, it's est time left */
-			if(l<0) l=0;
-			b=blocks(ff.ff_fsize);
-			lprintf("\rBlock (%lu%s): %lu/%lu  Byte: %lu  "
-				"Time: %lu:%02lu  Left: %lu:%02lu  CPS: %u  %lu%% "
-				,block_size%1024L ? block_size: block_size/1024L
-				,block_size%1024L ? "" : "k"
-				,block_num
-				,b
-				,block_num*(long)block_size
-				,t/60L
-				,t%60L
-				,l/60L
-				,l%60L
-				,cps
-				,(long)(((float)block_num/(float)b)*100.0)
-				);
-			if(!get_ack())
-				errors++;
-			else
-				block_num++; }
-		fclose(stream);
-		success=0;
-		if((block_num-1)*(long)block_size>=ff.ff_fsize) {
-			sent_files++;
-			sent_bytes+=ff.ff_fsize;
-			riosync();
-			lprintf("\n");
-
-			for(i=0;i<10;i++) {
-				lprintf("\rSending EOT (%d)",i+1);
-				rioctl(IOFI);
-				putcom(EOT);
-				ch=getcom(10);
-				if(ch==ACK)
-					break;
-				if(ch==NAK && i==0 && (mode&(YMODEM|GMODE))==YMODEM)
-					continue;  /* chuck's double EOT trick so don't complain */
-				if(ch!=NOINP) {
-					newline();
-					lprintf("Received %s  Expected ACK\r\n"
-						,chr(ch)); } }
-			if(i==3)
-				lprintf("\rNo ACK on EOT   \n");
-			t=time(NULL)-startfile;
-			if(!t) t=1;
-			lprintf("\rSuccesssful - Time: %lu:%02lu  CPS: %lu\r\n"
-				,t/60,t%60,ff.ff_fsize/t);
-			success=1; }
-		else {
-			newline();
-			lputs("Unsuccessful!\r\n");
-			t=time(NULL)-startfile;
-			if(!t) t=1; }
-
-		if(total_files>1 && total_files-sent_files>1)
-			lprintf("Remaining - Time: %lu:%02lu  Files: %u  Bytes: %lu\r\n"
-				,((total_bytes-sent_bytes)/cps)/60
-				,((total_bytes-sent_bytes)/cps)%60
-				,total_files-sent_files
-				,total_bytes-sent_bytes
-				);
-		if(log) {
-			l=(block_num-1)*(long)block_size;
-			if(l>ff.ff_fsize)
-				l=ff.ff_fsize;
-			fprintf(log,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u "
-				"%s -1\r\n"
-				,success ? (mode&ZMODEM ? 'z':'S') : 'E'
-				,l
-				,baud
-				,l/t
-				,errors
-				,flows
-				,block_size
-				,fname[fnum]); }
-
-		last=findnext(&ff); } }
-if(mode&XMODEM)
-	bail(0);
-mode&=~GMODE;
-i=getcom(10);
-if(i==NAK)
-	mode&=~CRC;
-else if(i=='C')
-	mode|=CRC;
-else if(i=='G')
-	mode|=(GMODE|CRC);
-if(i!=NOINP && i!=NAK && i!='C' && i!='G') {
-	newline();
-	lprintf("Received %s  Expected NAK, C, or G\r\n",chr(i)); }
-else if(i!=NOINP) {
-	block_num=0;
-	block[0]=0;
-	block_size=128;
-	put_block();
-	if(!get_ack()) {
-		newline();
-		lprintf("Failed to receive ACK after terminating block\r\n"); } }
-if(total_files>1) {
-	t=time(NULL)-startall;
-	if(!t) t=1;
-	newline();
-	lprintf("Overall - Time %02lu:%02lu  Bytes: %lu  CPS: %lu\r\n"
-		,t/60,t%60,sent_bytes,sent_bytes/t); }
-bail(0);
-return(0);
-}
-
diff --git a/src/stp/zmodem.h b/src/stp/zmodem.h
deleted file mode 100644
index e04b4fca24691925dd27f9d4d0995f10dc686d61..0000000000000000000000000000000000000000
--- a/src/stp/zmodem.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *   Z M O D E M . H     Manifest constants for ZMODEM
- *    application to application file transfer protocol
- *    Copyright 1991 Omen Technology Inc All Rights Reserved
- *    04-17-89  Chuck Forsberg Omen Technology Inc
- */
-#define ZPAD '*'	/* 052 Padding character begins frames */
-#define ZDLE 030	/* Ctrl-X Zmodem escape - `ala BISYNC DLE */
-#define ZDLEE (ZDLE^0100)	/* Escaped ZDLE as transmitted */
-#define ZBIN 'A'	/* Binary frame indicator (CRC-16) */
-#define ZHEX 'B'	/* HEX frame indicator */
-#define ZBIN32 'C'	/* Binary frame with 32 bit FCS */
-#define ZBINR32 'D'	/* RLE packed Binary frame with 32 bit FCS */
-#define ZVBIN 'a'	/* Binary frame indicator (CRC-16) */
-#define ZVHEX 'b'	/* HEX frame indicator */
-#define ZVBIN32 'c'	/* Binary frame with 32 bit FCS */
-#define ZVBINR32 'd'	/* RLE packed Binary frame with 32 bit FCS */
-#define ZRESC	0176	/* RLE flag/escape character */
-#define ZMAXHLEN 16	/* Max header information length  NEVER CHANGE */
-#define ZMAXSPLEN 1024	/* Max subpacket length  NEVER CHANGE */
-
-/* Frame types (see array "frametypes" in zm.c) */
-#define ZRQINIT	0	/* Request receive init */
-#define ZRINIT	1	/* Receive init */
-#define ZSINIT 2	/* Send init sequence (optional) */
-#define ZACK 3		/* ACK to above */
-#define ZFILE 4		/* File name from sender */
-#define ZSKIP 5		/* To sender: skip this file */
-#define ZNAK 6		/* Last packet was garbled */
-#define ZABORT 7	/* Abort batch transfers */
-#define ZFIN 8		/* Finish session */
-#define ZRPOS 9		/* Resume data trans at this position */
-#define ZDATA 10	/* Data packet(s) follow */
-#define ZEOF 11		/* End of file */
-#define ZFERR 12	/* Fatal Read or Write error Detected */
-#define ZCRC 13		/* Request for file CRC and response */
-#define ZCHALLENGE 14	/* Receiver's Challenge */
-#define ZCOMPL 15	/* Request is complete */
-#define ZCAN 16		/* Other end canned session with CAN*5 */
-#define ZFREECNT 17	/* Request for free bytes on filesystem */
-#define ZCOMMAND 18	/* Command from sending program */
-#define ZSTDERR 19	/* Output to standard error, data follows */
-
-/* ZDLE sequences */
-#define ZCRCE 'h'	/* CRC next, frame ends, header packet follows */
-#define ZCRCG 'i'	/* CRC next, frame continues nonstop */
-#define ZCRCQ 'j'	/* CRC next, frame continues, ZACK expected */
-#define ZCRCW 'k'	/* CRC next, ZACK expected, end of frame */
-#define ZRUB0 'l'	/* Translate to rubout 0177 */
-#define ZRUB1 'm'	/* Translate to rubout 0377 */
-
-/* zdlread return values (internal) */
-/* -1 is general error, -2 is timeout */
-#define GOTOR 0400
-#define GOTCRCE (ZCRCE|GOTOR)	/* ZDLE-ZCRCE received */
-#define GOTCRCG (ZCRCG|GOTOR)	/* ZDLE-ZCRCG received */
-#define GOTCRCQ (ZCRCQ|GOTOR)	/* ZDLE-ZCRCQ received */
-#define GOTCRCW (ZCRCW|GOTOR)	/* ZDLE-ZCRCW received */
-#define GOTCAN	(GOTOR|030)	/* CAN*5 seen */
-
-/* Byte positions within header array */
-#define ZF0	3	/* First flags byte */
-#define ZF1	2
-#define ZF2	1
-#define ZF3	0
-#define ZP0	0	/* Low order 8 bits of position */
-#define ZP1	1
-#define ZP2	2
-#define ZP3	3	/* High order 8 bits of file position */
-
-/* Bit Masks for ZRINIT flags byte ZF0 */
-#define CANFDX	01	/* Rx can send and receive true FDX */
-#define CANOVIO	02	/* Rx can receive data during disk I/O */
-#define CANBRK	04	/* Rx can send a break signal */
-#define CANRLE	010	/* Receiver can decode RLE */
-#define CANLZW	020	/* Receiver can uncompress */
-#define CANFC32	040	/* Receiver can use 32 bit Frame Check */
-#define ESCCTL 0100	/* Receiver expects ctl chars to be escaped */
-#define ESC8   0200	/* Receiver expects 8th bit to be escaped */
-
-/* Bit Masks for ZRINIT flags byte ZF1 */
-#define CANVHDR	01	/* Variable headers OK */
-
-/* Parameters for ZSINIT frame */
-#define ZATTNLEN 32	/* Max length of attention string */
-#define ALTCOFF ZF1	/* Offset to alternate canit string, 0 if not used */
-/* Bit Masks for ZSINIT flags byte ZF0 */
-#define TESCCTL 0100	/* Transmitter expects ctl chars to be escaped */
-#define TESC8   0200	/* Transmitter expects 8th bit to be escaped */
-
-/* Parameters for ZFILE frame */
-/* Conversion options one of these in ZF0 */
-#define ZCBIN	1	/* Binary transfer - inhibit conversion */
-#define ZCNL	2	/* Convert NL to local end of line convention */
-#define ZCRESUM	3	/* Resume interrupted file transfer */
-/* Management include options, one of these ored in ZF1 */
-#define ZMSKNOLOC	0200	/* Skip file if not present at rx */
-/* Management options, one of these ored in ZF1 */
-#define ZMMASK	037	/* Mask for the choices below */
-#define ZMNEWL	1	/* Transfer if source newer or longer */
-#define ZMCRC	2	/* Transfer if different file CRC or length */
-#define ZMAPND	3	/* Append contents to existing file (if any) */
-#define ZMCLOB	4	/* Replace existing file */
-#define ZMNEW	5	/* Transfer if source newer */
-	/* Number 5 is alive ... */
-#define ZMDIFF	6	/* Transfer if dates or lengths different */
-#define ZMPROT	7	/* Protect destination file */
-#define ZMCHNG	8	/* Change filename if destination exists */
-/* Transport options, one of these in ZF2 */
-#define ZTLZW	1	/* Lempel-Ziv compression */
-#define ZTRLE	3	/* Run Length encoding */
-/* Extended options for ZF3, bit encoded */
-#define ZXSPARS	64	/* Encoding for sparse file operations */
-#define ZCANVHDR	01	/* Variable headers OK */
-/* Receiver window size override */
-#define ZRWOVR 4	/* byte position for receive window override/256 */
-
-/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */
-#define ZCACK1	1	/* Acknowledge, then do command */
-
-#ifndef STP
-
-long rclhdr();
-
-/* Globals used by ZMODEM functions */
-extern Rxframeind;	/* ZBIN ZBIN32, or ZHEX type of frame */
-extern Rxtype;		/* Type of header received */
-extern Rxcount;		/* Count of data bytes received */
-extern Rxtimeout;	/* Tenths of seconds to wait for something */
-extern long Rxpos;	/* Received file position */
-extern long Txpos;	/* Transmitted file position */
-extern Txfcs32;		/* TURE means send binary frames with 32 bit FCS */
-extern Crc32t;		/* Display flag indicating 32 bit CRC being sent */
-extern Crc32;		/* Display flag indicating 32 bit CRC being received */
-extern Znulls;		/* Number of nulls to send at beginning of ZDATA hdr */
-extern char Attn[ZATTNLEN+1];	/* Attention string rx sends to tx on err */
-extern char *Altcan;	/* Alternate canit string */
-
-#endif
-
-/* End of ZMODEM.H */
diff --git a/src/tone/Makefile b/src/tone/Makefile
deleted file mode 100644
index c6111eb31ac41bbd87182aac2344bb6400bfa4b9..0000000000000000000000000000000000000000
--- a/src/tone/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-
-tone:		tone.o
-	gcc -lm tone.o -o tone
-
-tone.o:		tone.c
-	gcc -c -o tone.o tone.c
-
-
-all:
-	tone
-
-clean:
-	rm -f *.o tone
-
-
-
diff --git a/src/tone/cvt$$a.c b/src/tone/cvt$$a.c
deleted file mode 100644
index 07589cc3c2ab966b448797096d1dbfa0a2a02b3d..0000000000000000000000000000000000000000
--- a/src/tone/cvt$$a.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* CVT$$A*/
-
-/* Converts OS/2 tune editor files to tone format */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-void main()
-{
-	char str[128]
-		,*note="abcdefgabcdefgabcdefgabcdefg"
-		,*flat="GABCDEFGABCDEFGABCDEFGABCDEFG";
-	unsigned int  bt=200,o,n,t,i;
-
-while(1) {
-	fprintf(stderr,"top\n");
-	if(!fgets(str,81,stdin))
-		break;
-	if(str[1]==':') {
-		printf("%s",str+1);
-		continue; }
-	if(str[2]!=' ') {
-		str[4]=0;
-		bt=atoi(str);
-		continue; }
-	t=atoi(str);
-	if(!t)
-		continue;
-	fprintf(stderr,"rest\n");
-	if(t>=10) {
-		if(t==10)
-			t=bt*4;
-		else if(t==11)
-			t=bt*2;
-		else if(t==12)
-			t=bt;
-		else if(t==13)
-			t=bt/2;
-		else if(t==14)
-			t=bt/4;
-		else if(t==14)
-			t=bt/8;
-		printf("r %u\n",t);
-		continue; }
-	fprintf(stderr,"time\n");
-	t=(bt*4)/t;
-	i=atoi(str+3);
-	o=2;
-	fprintf(stderr,"note\n");
-	if(i<=20) {
-		n=note[20-i];
-		if(20-i)
-			o+=((20-i)/7); }
-	else if(i<=41) { /* flats */
-		n=flat[41-i];
-		if(41-i)
-			o+=((41-i)/7); }
-	else {
-		n=toupper(note[62-i]);
-		if(62-i)
-			o+=((62-i)/7); }
-	if(toupper(n)=='A' || toupper(n)=='B' || n=='G')
-		o--;
-	printf("%c%u %u\n",n,o,t); }
-}
-
diff --git a/src/tone/make.bat b/src/tone/make.bat
deleted file mode 100755
index 7d0c2958d7488abc028409cf31789545d435ff20..0000000000000000000000000000000000000000
--- a/src/tone/make.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-bcc -P-c -w-prot tone ..\mswait\dos\mswaits.obj
diff --git a/src/tone/tone.c b/src/tone/tone.c
deleted file mode 100644
index 915665094c04dd0f1e6f1fd2912950b38576fc59..0000000000000000000000000000000000000000
--- a/src/tone/tone.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* TONE.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Linux modifications by Casey Martin 2000.
-
-   Note:  Permissions on /dev/console must be at least 006 for this
-   to work properly
-*/
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Note: If this box doesn't appear square, then you need to fix your tabs.	*
- ****************************************************************************/
-
-/* Test sound freqs and durations from command line */
-
-#ifdef __OS2__
-	#define INCL_DOS
-	#include <os2.h>
-#endif
-
-#ifndef __unix__
-	#include <io.h>
-	#include <dos.h>
-#else
-	#include <unistd.h>
-	#include <math.h>
-	#include <time.h>
-	#include <sys/ioctl.h>
-	#include <sys/kd.h>
-	#include <sys/time.h>
-	#include <sys/types.h>
-	#include <termios.h>
-	#include <signal.h>
-#endif
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#ifdef __OS2__
-	#define mswait(x) DosSleep(x)
-	#define delay(x) DosSleep(x)
-	#define sound(x) DosBeep(x,0)
-	#define nosound() DosBeep(0,0)
-#endif
-
-#define NOT_ABORTABLE	(1<<0)
-#define SHOW_DOT		(1<<1)
-#define SHOW_FREQ		(1<<2)
-#define NO_VISUAL		(1<<3)
-#define USE_MSWAIT		(1<<4)
-
-#ifdef __unix__
-	#define nosound() ioctl(fd, KIOCSOUND, 0)
-	#define sound(f)  ioctl(fd, KIOCSOUND, (int) (1193180 / f))
-	#define mswait(x) delay(x)
-	#define kbhit()   select(1, &inp, NULL, NULL, &timeout)
-	#define delay(ms) usleep(ms * 1000)
-	#define OPENARGS O_RDONLY
-#else
-	#define OPENARGS (O_RDONLY | O_BINARY | O_DENYNONE)
-#endif
-
-
-#if defined __OS2__ || defined __unix__
-	int mswtyp;
-#else
-	extern mswtyp;
-#endif
-
-int aborted=0;	/* Ctrl-C hit? */
-int mode=0; 	/* Optional modes */
-int t=1;		/* Timing */
-int s=0;		/* Stacato */
-int octave=4;	/* Default octave */
-
-
-#ifdef __unix__
-	int fd = 0;              // file descriptor for the console
-	struct termios stored;   // for storing old term settings
-	struct timeval timeout = {0, 0}; // passed in select() call
-	fd_set inp;              // passes in select() call
-#endif
-
-double pitch=523.50/32.0;	 /* low 'C' */
-
-
-
-void play(char *freq, char *dur)
-{
-	char *notes="c d ef g a b";
-	char *sharp="BC D EF G A ";
-	int i,n,d,o=octave;
-	double f;
-
-	d=atoi(dur);
-	if(isdigit(freq[0]))
-		f=atoi(freq);
-  
-	else
-		switch(toupper(freq[0])) {
-			case 'O':               /* default octave */
-				if(isdigit(dur[0]))
-					octave=d;
-				else
-					octave+=d;
-				return;
-			case 'P':               /* pitch variation */
-				if(isdigit(dur[0]))
-					pitch=atof(dur)/32.0;
-				else
-					pitch+=atof(dur);
-				return;
-			case 'Q':               /* quit */
-				nosound();
-				exit(0);
-			case 'R':               /* rest */
-				f=0;
-				break;
-			case 'S':               /* stacato */
-				if(isdigit(dur[0]))
-					s=d;
-				else
-					s+=d;
-				return;
-			case 'T':               /* time adjust */
-				t=d;
-				return;
-			case 'V':
-				if(mode&NO_VISUAL)
-					return;
-				n=strlen(dur);
-				while(n && dur[n]<=' ')
-					n--;
-				dur[n+1]=0;
-				if(dur[n]=='\\') {
-					dur[n]=0;
-					printf("%s",dur); }
-				else
-					printf("%s\r\n",dur);
-				return;
-			case 'X':               /* exit */
-				exit(1);
-			default:
-				for(n=0;notes[n];n++)
-					if(freq[0]==notes[n] || freq[0]==sharp[n])
-						break;
-				if(isdigit(freq[1]))
-					o=(freq[1]&0xf);
-				else
-					o=octave;
-				f=pitch*pow(2,o+(double)n/12);
-				break; }
-	if(!f)
-		nosound();
-	else
-		sound(f);
-	if(f && mode&SHOW_FREQ) {
-		for(i=0;freq[i]>' ';i++)
-			;
-		freq[i]=0;
-		printf("%-4.4s",freq); }
-	if(mode&SHOW_DOT)
-		printf(".");
-	if(t>10) {
-		if(mode&USE_MSWAIT)
-			mswait((d*t)-(d*s));
-		else
-			delay((d*t)-(d*s)); }
-	else {
-		if(mode&USE_MSWAIT)
-			mswait(d*t);
-		else
-			delay(d*t); }
-	if(s) {
-		nosound();
-		if(t>10) {
-			if(mode&USE_MSWAIT)
-				mswait(d*s);
-			else
-				delay(d*s); }
-		else {
-			if(mode&USE_MSWAIT)
-				mswait(s);
-			else
-				delay(s); } }
-}
-
-void usage(void)
-{
-	printf("usage: tone [/opts] [(note[oct]|freq) dur | (cmd val) [...]] "
-		"[+filename]\n\n");
-	printf("where: note  = a,b,c,d,e,f, or g (naturals) or A,B,C,D,E,F, or "
-		"G (sharps)\n");
-	printf("       oct   = octave 1 through 9 (default=%d)\n",octave);
-	printf("       freq  = frequency (in Hz) or 0 for silence\n");
-	printf("       dur   = duration (in timer counts)\n");
-	printf("       cmd   = o set default octave (+/- to adjust) "
-		"(default=%d)\n",octave);
-	printf("               p set middle c pitch (+/- to adjust) "
-		"(default=%.2f)\n",pitch*32.0);
-	printf("               q quit program immediately\n");
-	printf("               r rest (silence) for val timer counts\n");
-	printf("               s set stacato duration (in ms) (+/- to adjust) "
-		"(default=%d)\n",s);
-	printf("               t set timer count value (in ms) "
-		"(default=%d)\n",t);
-	printf("               v visual text diplay of val (no val=cr/lf)\n");
-	printf("               x quit program immediately (leave tone on)\n");
-	printf("       opts  = d display dot for each note\n");
-	printf("               f display frequency or note value\n");
-	printf("               n not abortable with key-stroke\n");
-	printf("               v disable visual text commands\n");
-	printf("               t use time-slice aware delays\n");
-	exit(0);
-}
-
-#ifdef __unix__
-
-void cbreakh(int sig)
-{
-	nosound();
-	exit(0);
-}
-
-#else /* !unix */
-
-int cbreakh()	/* ctrl-break handler */
-{
-	aborted=1;
-	return(1);		/* 1 to continue, 0 to abort */
-}
-
-#endif
-
-int main(int argc, char **argv)
-{
-	char *p,str[128];
-	int i,j,file;
-	FILE *stream;
-
-#ifdef __unix__
-
-	// sets up the terminal for one key entry (to cancel playback)
-	struct termios newterm;
-	tcgetattr(0,&stored);
-  
-	memcpy(&newterm,&stored,sizeof(struct termios));
-	newterm.c_lflag &= (~ICANON);
-	newterm.c_cc[VTIME] = 0;
-	newterm.c_cc[VMIN] = 1;
-	tcsetattr(0,TCSANOW,&newterm);
-
-	// set up select() args
-	FD_ZERO(&inp);
-	FD_SET(0, &inp);
-
-	// install Ctrl-C handler...
-	signal(SIGINT, cbreakh);
-
-#endif
-  
-#ifndef __OS2__
-	#ifndef __unix__
-		ctrlbrk(cbreakh);
-	#else
-  		fd = open("/dev/console", O_NOCTTY);
-		if (fd < 0) {
-    		perror("open(\"/dev/console\"");
-    		exit(-1);
-		}
-	#endif
-#endif
-
-	printf("\nTone Generation Utility  v1.01  Developed 1993 Rob Swindell\n\n");
-
-	if(argc<2)
-		usage();
-
-	mswtyp=0;
-	delay(0);
-	for(i=1;i<argc;i++) {
-		if(argv[i][0]=='/') {
-			for(j=1;argv[i][j];j++)
-				switch(toupper(argv[i][j])) {
-					case 'D':
-						mode^=SHOW_DOT;
-						break;
-					case 'F':
-						mode^=SHOW_FREQ;
-						break;
-					case 'N':
-						mode^=NOT_ABORTABLE;
-						break;
-					case 'V':
-						mode^=NO_VISUAL;
-						break;
-					case 'T':
-						mode^=USE_MSWAIT;
-						mswtyp=atoi(argv[i]+j+1);
-						while(isdigit(argv[i][j+1]))
-							j++;
-						break;
-					default:
-						usage(); }
-			continue; }
-		if(argv[i][0]=='+') {
-			if((file=open(argv[i]+1, OPENARGS))==-1 || (stream=fdopen(file,"rb"))==NULL) {
-				strcpy(str,argv[0]);
-				p=strrchr(str,'\\');
-				if(p)
-					*(p+1)=0;
-				strcat(str,argv[i]+1);
-				if((file=open(str, OPENARGS))==-1
-					|| (stream=fdopen(file,"rb"))==NULL) {
-					printf("\7Error opening %s\n",argv[i]+1);
-					exit(1); } }
-			while(mode&NOT_ABORTABLE || !kbhit()) {
-				if(!fgets(str,81,stream))
-					break;
-				if(!isalnum(str[0]))
-					continue;
-				p=str;
-				while(*p>' ')
-					p++;
-				while(*p && *p<=' ')
-					p++;
-				play(str,p); }
-			fclose(stream);
-			continue; }
-		play(argv[i],argv[i+1]);
-		i++;
-		if(aborted)
-			break; }
-	nosound();
-
-#ifdef __unix__
-	close(fd);                      // close /dev/console
-	tcsetattr(0,TCSANOW,&stored);   // reset terminal to previous state
-#endif
-
-return(0);
-}
diff --git a/src/wmakeall.bat b/src/wmakeall.bat
deleted file mode 100755
index a11b4e41faead7ce1f4e6d08913cb5cf7ea5639d..0000000000000000000000000000000000000000
--- a/src/wmakeall.bat
+++ /dev/null
@@ -1,38 +0,0 @@
-@echo off
-rem
-rem Makes all Watcom compiled Synchronet projects - April 1997 Rob Swindell
-rem
-cd sbbs\addfiles
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\delfiles
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\dupefind
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\echo
-wmake -f sbbsecho.wat OS=OS2  %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-wmake -f sbbsecho.wat OS=DOS4G  %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-wmake -f sbbsecho.wat OS=NT  %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\filelist
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\smb\smbutil
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-cd ..\..\smbactiv
-call makeall.bat %1 %2 %3 %4 %5
-if errorlevel 1 goto err
-rem End of makes
-cd ..\..
-goto end
-:err
-rem Error occurred
-echo.
-echo There was an error!
-echo.
-:end
diff --git a/text/answer.asc b/text/answer.asc
deleted file mode 100644
index 33e72461b6054bdc6a7f5f3a3bd79da740a313e9..0000000000000000000000000000000000000000
--- a/text/answer.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-ncConnection established at h@BPS@ncbps on h@DATE@nc at h@TIME@
-
-b@SYSOP@ welcomes you to y@BBS@b (Node @NODE@)
-
-If you are a new user to the system, type c"New"b now.
-Otherwise, enter your user name or number now.
-yh
diff --git a/text/answer.wip b/text/answer.wip
deleted file mode 100644
index 1440290a3ca8b53fdfc448996d4dc87dc96090fc..0000000000000000000000000000000000000000
--- a/text/answer.wip
+++ /dev/null
@@ -1,18 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=@BBS@
-!|L=2505
-!|T=105
-!|W=3750
-!|H=5100
-!|B=16777215
-!|
-!|[Form]
-!|001=0B`c`70`265`100`30`1`Login to BBS`0`12632256`MS Sans Serif`8.25`Continue`
-!|002=0T`text`1`20`240`40`1``0`16777215`MS Sans Serif`8.25`Synchronet BBS Software Version @VER@|mDeveloped 1990-1997 Rob Swindell`1`0
-!|003=0P`wiplogo`45`65`150`180`3``-2147483643`WIPLOGO.BMP
-!|
-$0E
diff --git a/text/bullseye.asc b/text/bullseye.asc
deleted file mode 100644
index e9ee2574b94766c9fc4758088d5aa09e5c07d9b1..0000000000000000000000000000000000000000
--- a/text/bullseye.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-l0nc4��������������k�0
-4c�  hyBulletins  nk4�0
-4c�k��������������b0������������������������������������������������
-���
-� hy1 ngFrequently asked questions regarding hSynchronet v3.0n      b�
-� hy2 ngNew features added in Synchronet v3                       b�
-� hy3 ngFrequently asked questions re: configuring Synchronet v3  b�
-���������������������������������������������������������������n
diff --git a/text/bullseye.cfg b/text/bullseye.cfg
deleted file mode 100644
index c5563b3ee751bf8508aa59b989aea112fdf45d9e..0000000000000000000000000000000000000000
--- a/text/bullseye.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-0 #######################
-/sbbs/docs/sbbs3faq.txt
-/sbbs/docs/v300_new.txt
-/sbbs/docs/v3cfgfaq.txt
diff --git a/text/computer.sif b/text/computer.sif
deleted file mode 100644
index 13bac67083f31ffc984e273b419de566ff3c4a00..0000000000000000000000000000000000000000
--- a/text/computer.sif
+++ /dev/null
@@ -1,109 +0,0 @@
-This is the Synchronet Computer Information Questionaire.
-
-
-n
-hMicroprocessorn
-
-A) 8088 (XT)
-B) 80286 (AT)
-C) 80386SX
-D) 80386DX
-E) 80486
-
-yhWhich:n c"ABCDE"
-
-hClock Speedn
-
-A) 4.77mhz
-B) 6mhz
-C) 8mhz
-D) 10mhz
-E) 12mhz
-F) 16mhz
-G) 20mhz
-H) 25mhz
-I) 33mhz
-J) 40mhz
-K) 50mhz
-
-yhWhich: nc"ABCDEFGHIJK"
-
-hArchitecturen
-
-A) 8bit (XT)
-B) ISA (AT)
-C) MCA (PS/2)
-D) EISA
-
-yhWhich: nc"ABCD"
-
-hDisplayn
-
-A) MDA (Monochrome - no graphics)
-B) Hercules (Monochrome - graphics)
-C) CGA
-D) EGA
-E) MCGA
-F) VGA
-G) SVGA (640x480x256)
-H) MVGA (Monochrome VGA)
-I) 8514/A (1024x768x256)
-J) XGA
-K) TIGA (34010)
-
-yhWhich: nc"ABCDEFGHIJK"
-
-hSystem RAMn
-
-A) <1mb
-B) 1mb
-C) 2mb
-D) 3mb
-E) 4mb
-F) 5mb
-G) 6mb
-H) 8mb
-I) 10mb
-J) 12mb
-K) 16mb
-L) 18mb
-M) 24mb
-N) 32mb
-O) 64mb
-
-yhWhich: nc"ABCDEFGHIJKLMNO"
-
-hTotal Hard Disk Capacityn
-
-A) None
-B) 10mb
-C) 20mb
-D) 30mb
-E) 40mb
-F) 60mb
-G) 80mb
-H) 100mb
-I) 120mb
-J) 150mb
-K) 200mb
-L) 250mb
-M) 300mb
-N) 400mb
-O) 500mb
-P) 600mb
-Q) 700mb
-R) 800mb
-S) 900mb
-T) 1gb or more
-
-yhWhich: nc"ABCDEFGHIJKLMNOPQRST"
-
-hHard Disk Interfacen
-
-A) ST506 (Standard)
-B) SCSI
-C) SCSI2
-D) ESDI
-E) IDE
-
-yhWhich: nc"ABCDE"
diff --git a/text/example.sif b/text/example.sif
deleted file mode 100644
index e8af4378cfe40081b8b5f5c69e7f5c7477bd26cd..0000000000000000000000000000000000000000
--- a/text/example.sif
+++ /dev/null
@@ -1,68 +0,0 @@
-This is an example of the Synchronet Interface File (SIF) Format:
-
-To execute this SIF, yype ;SIF at the main prompt and enter EXAMPLE as the 
-filename.
-
-Only text between STX (Start of text / Ctrl-B) and ETX (End of text / Ctrl-C)
-will be displayed to the user. After each ETX is the input mode specifier
-('c'haracter or 's'tring), then an optional mode modifier ('u'ppercase,
-'n'umeric, or 'f'orced captialization), then an optional 'l' for an input line
-to be displayed, then an optional 'r' if the data file should contain a CRLF
-after this field, then the maximum length of the string (if 's'tring mode and a
-template isn't specified), then an optional . followed by the minimum length
-of the string, and last an optional string in double-quotes that either
-specifies what keys will be accepted ('c'haracter mode) or an input template
-('s'tring mode).
-
-Inside the text area, we should use Synchronet Ctrl-A sequences for changing
-the text attributes and clearing the screen. Embeded ANSI sequences can be used
-but are not suggested as they will be displayed to ALL users (ANSI or not), and
-Ctrl-A sequences are filtered for non-ANSI users, and modified for Monochrome
-ANSI users. See SBBS\TEXT\MENU\ATTR.ALL for more information on Ctrl-A codes.
-
-Text is going to start here: 
-n
-Hello, this is an example hSIFn file.
-
-Please answer the following input prompts.
-
-mhSelect Onen
-
-A) Selection A
-B) Selection B
-C) Selection C
-
-yhWhich: nc"ABC" Text in this area is just for comments
-
-yhEnter any character: rc
-
-yhEnter any character (converted to uppercase automatically): ncu
-
-yhEnter any number (allows CR): cnl
-
-yhEnter any number (disallows CR): bc"0123456789"
-
-bhEnter a string: ws30
-
-yhEnter a string of at least 4 characters: sl8.4
-
-yhEnter a string (converted to uppercase automatically): nsu10
-
-yhEnter a numeric value of at least one digit: snl5.1
-
-yhEnter your name (forced capitalization): nsf30
-
-yhEnter your phone number (must be complete): ws.12"NNN-NNN-NNNN"
-                                                    ^ notice that the max 
-		length wasn't needed because the template was specified
-
-yhEnter your birthdate (can be incomplete): sl"NN/NN/NN"
-
-bhAre you sure (Y/N) ? wc"YN"
-
-chAll done!
-
-everything after this point doesn't matter..... (cause we're not between STX
-and ETX)
-
-See Customization chapter in the sysop manual for more information.
diff --git a/text/feedback.msg b/text/feedback.msg
deleted file mode 100644
index d08c65cb60b885974f1cefa09bf0ab393ae683f8..0000000000000000000000000000000000000000
--- a/text/feedback.msg
+++ /dev/null
@@ -1,10 +0,0 @@
-hy
-As a new user, your access to some of the system's facilities will be 
-restricted until the letter you are about to write has been reviewed by a
-sysop and your account has been "validated."
-
-ngPlease include in your letter:
-
-	ho ngWhere you found the number to this BBS
-	ho ngWhat prompted you to call
-        ho ngWhat your expectations are
diff --git a/text/menu/allmail.asc b/text/menu/allmail.asc
deleted file mode 100644
index 6bd691f938d5d88471f29df8d7c959088e1732c4..0000000000000000000000000000000000000000
--- a/text/menu/allmail.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-                           yh��� wReading All Mail y���
-�����������������������������������������������������������������������������ͻ
-�w<CR> bNext Message                        wR  bReread Last Message              y�
-�  w-  bPrevious Message                    wD  bDelete Last Message              y�
-�  wL  bList All Messages                   wS  bSave Last Message to File        y�
-�  wT  bList Ten More Messages              wE  bEdit Last Message                y�
-�  wU  bEdit Author of Last Message         wC  bChange Last Message's Flag       y�
-�  wQ  bQuit to Main Section                w#  bGo to Message #                  y�
-�����������������������������������������������������������������������������ͼ
diff --git a/text/menu/attr.asc b/text/menu/attr.asc
deleted file mode 100644
index ca29b7d6f749fe0a4b57eb1095c3cc3adcc459e4..0000000000000000000000000000000000000000
--- a/text/menu/attr.asc
+++ /dev/null
@@ -1,18 +0,0 @@
-                        Synchronet Text Attribute Menu
-              (All attribute codes must be preceeded by a Ctrl-A)
-
-		 Foreground		     Background
-Black       K   k(Low) h(High)n            0   hWhite on Blackn
-Red         R   r(Low) h(High)n            1   k1Black on Redn
-Green       G   g(Low) h(High)n            2   k2Black on Greenn
-Yellow      Y   y(Low) h(High)n            3   k3Black on Yellown
-Blue        B   b(Low) h(High)n            4   wh4White on Bluen
-Magenta     M   m(Low) h(High)n            5   wh5White on Magentan
-Cyan        C   c(Low) h(High)n            6   k6Black on Cyann
-White       W   w(Low) h(High)n            7   k7Black on Whiten
-
-High        H   hHigh Intensityn
-Blink       I   iBlinkingn
-Normal      N   No Special Attributes
-Pause       P   Insert a Pause Prompt into message
-CLS         L   Insert a Form Feed into message
diff --git a/text/menu/batchxfr.asc b/text/menu/batchxfr.asc
deleted file mode 100644
index 59ad69c75930c1d0df9febbb5ec523fe959c77b0..0000000000000000000000000000000000000000
--- a/text/menu/batchxfr.asc
+++ /dev/null
@@ -1,13 +0,0 @@
-0lnc4���������������������������k�0
-4c� hyBatch/Bidirectional Menu nk4�0
-4c�k���������������������������0
-4b0�����4  0�4 hwUpload/Downloadnb�hw4Filesnb�����������������4 hwBatch Queue Managementnb���������
-�����
-� hyU ngUpload files in upload queue�b� hyL ngList files in batch queues�b�
-� hyD ngDownload files in download queue    b� hyR ngRemove files from batch queues    b�
-��� hyC ngClear batch queues�b�
-�������4 hwBidirectional Transfersnb������������
-�����������������������������������������
-� hyB ngBidirectional file transfer�b� hyQ ngQuit to File Transfer menu�b�
-�����
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
diff --git a/text/menu/batchxfr.rip b/text/menu/batchxfr.rip
deleted file mode 100644
index 466931069f9e0a383c0bb98f07c5babe0480fa5e..0000000000000000000000000000000000000000
--- a/text/menu/batchxfr.rip
+++ /dev/null
@@ -1,13 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Batch Transfers<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2S0000<><>
-!|1B0000020QPC010E000F080200000000000000|Y00000100|1U0M161K1G0000<>U<>U
-!|1U0M1K1K1U0000<>D<>D|1U0M1Y1K280000<>B<>B
-!|1B0000020QPE010E000F080400000000000000|1U0M2C1K2M0000<>Q<>Q
-!|1B0000020QPC010E000F080200000000000000|1U9616A41G0000<>L<>L
-!|1U961KA41U0000<>R<>R|1U961YA4280000<>C<>C|c00|@1Y16Upload|@1Y1KDownload
-!|@1Y1YBidirectional Transfer|@1Y2CQuit to the Transfer Section
-!|@AK1YClear Batch Queue|@AK16List Files in Batch Queue
-!|@AK1KRemove Files from Batch Queue|w000G271610|10000$ETW$|#|#|#
-
diff --git a/text/menu/batdprot.asc b/text/menu/batdprot.asc
deleted file mode 100644
index 4e32fe9013177cbb52226fbfbba2d9783d182332..0000000000000000000000000000000000000000
--- a/text/menu/batdprot.asc
+++ /dev/null
@@ -1 +0,0 @@
-hwY bYmodem  wZ bZmodem  wG bYmodem-G  wH bHS/Link
diff --git a/text/menu/batflag.asc b/text/menu/batflag.asc
deleted file mode 100644
index 6300697723bb10cffb8ba9da2a5e9c9b8fca41e4..0000000000000000000000000000000000000000
--- a/text/menu/batflag.asc
+++ /dev/null
@@ -1,23 +0,0 @@
-lnhcFile Listing:
-
-�nc���������If nhc+ ncthen extended description exists, but not displayed
-����������File flag for fast tagging
-�Filename   ��    ���File size
-� Extension���    � �If nhc- ncthen file is offline
-�����    � ���Description
-nhbSBBS200G.ZIP+ngA  nm851k-ngSynchronet v2.00g Multinode BBS Software
-
-nhcBatch Flagging Commands:
-
-nhb[nhcBnhb]atch Download�ncAdd file(s) to batch download queue
-nhb[nhcVnhb]iew Files�ncView archive listing or contents of file(s)
-nhb[nhcEnhb]xtended Info�ncDisplay extended information on file(s)
-nhb[nhcSnhb]kip Directory�ncSkip this directory (during scans)
-nhb[nhcPnhb]revious�ncMove backwards through this directory
-nhb[nhcQnhb]uit�ncStop listing files
-(
-nhcSysop Commands:
-
-nhb[nhcDnhb]elete Files�ncDelete file(s) from disk and/or database
-nhb[nhcMnhb]ove Files�ncMove file(s) to another directoryn
-)
diff --git a/text/menu/batuprot.asc b/text/menu/batuprot.asc
deleted file mode 100644
index 4e32fe9013177cbb52226fbfbba2d9783d182332..0000000000000000000000000000000000000000
--- a/text/menu/batuprot.asc
+++ /dev/null
@@ -1 +0,0 @@
-hwY bYmodem  wZ bZmodem  wG bYmodem-G  wH bHS/Link
diff --git a/text/menu/biprot.asc b/text/menu/biprot.asc
deleted file mode 100644
index 26816be463811c8a085f091e95bfee524b9d0e9e..0000000000000000000000000000000000000000
--- a/text/menu/biprot.asc
+++ /dev/null
@@ -1 +0,0 @@
-nhH bHS/Link
diff --git a/text/menu/chat.asc b/text/menu/chat.asc
deleted file mode 100644
index f6351c8cf907c167b495d8c87af559b98775d8e3..0000000000000000000000000000000000000000
--- a/text/menu/chat.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-nlc4��������������������nk4�0
-nc4� nhy4Chat Command Menu nk4�0
-nc4�nk4��������������������0
-nb��������������������nb4 nh4Join a Chat nb�����������������������nb4 nb����nb4 nh4Togglesnb����������
-�����
-� nhyJ ngJoin/initiate multinode chat�nb� nhyD ngAllow paging off/on�nb�
-� nhyP ngJoin/initiate private node to node chat�nb� nhyA ngActivity alerts off/on  nb�
-� nhyC ngChat with the sysop�nb� nhyS ngSplit screen pvt chat   nb�
-� nhyT ngTalk with the system Guru (Artificial Person) nb� nhyQ ngQuit from Chat section  nb�
-�����
-nb4  nhy4Anytime: nhc4Ctrl-U nc4Who's online  nhc4Ctrl-P nc4Send private msg  nhc4Ctrl-C nc4Abort cmd/text n
diff --git a/text/menu/chat.rip b/text/menu/chat.rip
deleted file mode 100644
index ee1325867524e001406b6c9f25f6d018995755ac..0000000000000000000000000000000000000000
--- a/text/menu/chat.rip
+++ /dev/null
@@ -1,14 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Chat Section<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2S0000<><>
-!|1B0000020QPC010E000F080500000000000000|Y00000100|1U0M161K1G0000<>D<>D
-!|1U0M1K1K1U0000<>A<>A|1U0M1Y1K280000<>J<>J
-!|1B0000020QPE010E000F080400000000000000|1U0M2C1K2M0000<>Q<>Q
-!|1B0000020QPC010E000F080500000000000000|1U9616A41G0000<>T<>T
-!|1U961KA41U0000<>P<>P|1U961YA4280000<>C<>C|w000E271610|c00
-!|@1Y16Disable/Enable Paging|@1Y1KActivity Alert Disable/Enable
-!|@1Y1YJoin/Initiate Multinode Chat|@1Y2CQuit from Chat Section
-!|@AK16Talk with the Guru|@AK1KPrivate Node to Node Chat|@AK1YChat with Sysop
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/chat.wip b/text/menu/chat.wip
deleted file mode 100644
index 5e5d48173bb6c8b7ca381716b07787e9e02fccab..0000000000000000000000000000000000000000
--- a/text/menu/chat.wip
+++ /dev/null
@@ -1,23 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=Chat
-!|L=1665
-!|T=555
-!|W=4050
-!|H=4500
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`p`20`20`100`60`1`Private User-to-User Chat`0`12632256`MS Sans Serif`8.25`Private`ORDER.ICO
-!|002=0B`j`140`20`100`60`2``0`12632256`MS Sans Serif`8.25`Multinode`EAR.ICO
-!|003=0B`c`20`100`100`60`3``0`12632256`MS Sans Serif`8.25`Sysop`CONTACT.ICO
-!|004=0B`t`140`100`100`60`4``0`12632256`MS Sans Serif`8.25`Guru`SOUND.ICO
-!|005=0B`d`20`180`100`30`5``0`12632256`MS Sans Serif`8.25`Pager`
-!|006=0B`a`20`225`100`30`6``0`12632256`MS Sans Serif`8.25`Activity`
-!|007=0B`s`140`180`100`30`7``0`12632256`MS Sans Serif`8.25`Split-screen`
-!|008=0B`q`140`225`100`30`8``0`12632256`MS Sans Serif`8.25`Quit`
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/dlprot.asc b/text/menu/dlprot.asc
deleted file mode 100644
index 2339a77346c8a37ed5535ff3dfb3a9961fd0074e..0000000000000000000000000000000000000000
--- a/text/menu/dlprot.asc
+++ /dev/null
@@ -1 +0,0 @@
-hwX bXmodem  wY bYmodem  wZ bZmodem  wG bYmodem-G
diff --git a/text/menu/e-mail.asc b/text/menu/e-mail.asc
deleted file mode 100644
index 6e61c7ffb688a2d528aa6ce5f7943a35345eade9..0000000000000000000000000000000000000000
--- a/text/menu/e-mail.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-0lnc4�����������������������k�0
-4c� hyElectronic Mail Menu nk4�0
-4c�k�����������������������0
-b��������4 hwSend Mail      nb���������������4 hwRead Mail   nb��������
-�����
-� hyS ngSend mail�b� hyR ngRead mail sent to you   b�
-��hy0N ngSend NetMail�b� hyK ngRead mail you have sent b�
-������������������������������������������������������������
-� hyF ngSend feedback to the sysop b� hyQ ngQuit back to Main menu  b�
-� hyU ngUpload file to a mailbox   b���
-������������������������������������������������������������n
diff --git a/text/menu/e-mail.rip b/text/menu/e-mail.rip
deleted file mode 100644
index f98a4b507a5216829d8574c9f8676e8d7633ad43..0000000000000000000000000000000000000000
--- a/text/menu/e-mail.rip
+++ /dev/null
@@ -1,12 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Electronic Mail Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2E0000<><>
-!|1B0000020QPE010E000F080200000000000000|Y00000100|1U0M161K1G0000<>S<>S
-!|1U0M1K1K1U0000<>N<>N|1U9616A41G0000<>R<>R|1U961KA41U0000<>K<>K
-!|1U0M1Y1K280000<>F<>F|1B0000020QPE010E000F080400000000000000
-!|1U961YA4280000<>Q<>Q|c00|@1Y16Send Mail|@1Y1KSend NetMail
-!|@1Y1YSend Feedback to the Sysop|@AK16Read Your Mail
-!|@AK1KRead Mail You Have Sent|@AK1YQuit to the Main Menu|w000C271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/e-mail.wip b/text/menu/e-mail.wip
deleted file mode 100644
index 451e6cacfa5e612fd491ec9ebec1326c0ae4a0ba..0000000000000000000000000000000000000000
--- a/text/menu/e-mail.wip
+++ /dev/null
@@ -1,21 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=E-mail
-!|L=1425
-!|T=195
-!|W=4050
-!|H=4350
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`s`20`20`100`60`1``0`12632256`MS Sans Serif`8.25`Send E-mail`EDIT.ICO
-!|002=0B`r`140`20`100`60`2``0`12632256`MS Sans Serif`8.25`Read E-mail`DETAIL.ICO
-!|003=0B`k`140`100`100`60`3``0`12632256`MS Sans Serif`8.25`Read Sent E-mail`SEARCH.ICO
-!|004=0B`f`20`100`100`60`4``0`12632256`MS Sans Serif`8.25`Feedback`CONTACT.ICO
-!|005=0B`n`20`180`100`60`5``0`12632256`MS Sans Serif`8.25`Send NetMail`EDIT.ICO
-!|006=0B`q`140`180`100`60`6``0`12632256`MS Sans Serif`8.25`Quit`EXIT.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/editor.asc b/text/menu/editor.asc
deleted file mode 100644
index e9ba7f799bd910d27cee1c38fa3a8700c10ae873..0000000000000000000000000000000000000000
--- a/text/menu/editor.asc
+++ /dev/null
@@ -1,19 +0,0 @@
-hy                    Synchronet Message Editor Commands
-                            (* ANSI users only)
-w
-/?     This Menu                    Ctrl-C       Cancel Line
-/S     Save Message                 Ctrl-V       Center Line
-/L     List Message                 Ctrl-R       Redraw Line
-/Lx    List Message from Line x     Ctrl-X       Delete Line
-/E     Edit Last Line               Ctrl-Y     * Delete to End of Line
-/Ex    Edit Line x                  Ctrl-W       Delete Word Left
-/D     Delete Last Line             Ctrl-D     * Delete Word Right
-/Dx    Delete Line x                Ctrl-B     * Move to Beginning of Line
-/I     Insert Line Before Last      Ctrl-E     * Move to End of Line
-/Ix    Insert Line Before Line x    Ctrl-N     * Move to Next Word
-/T     Edit Message Title           Ctrl-\     * Move to Previous Word
-                                    Ctrl-F     * Move Cursor Position Forward
-/ABT   Abort Message                Ctrl-[     * Move Cursor Position Backward
-/CLR   Clear Message (Start Over)   Ctrl-Minus * Toggle Insert/Overwrite Mode
-/ATTR  Menu for ^Ax Sequences       Ctrl-Ax    * Type /ATTR for more info
-n
\ No newline at end of file
diff --git a/text/menu/exempt.asc b/text/menu/exempt.asc
deleted file mode 100644
index 9473b704c3b5d671a06393ceda5c68e62c3123f0..0000000000000000000000000000000000000000
--- a/text/menu/exempt.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=Anonymous         H=                  O=                  V=
-B=                  I=Interrupt Nodes   P=Permanent         W=
-C=Chat Page	    J=Chat Cost 	Q=Quiet/Anon Node   X=Xtrn Program Cost
-D=Download Cost     K=                  R=Remove Files      Y=
-E=Expire by Time    L=Logons            S=NetMail Cost      Z=
-F=CR/FR/RR NetMail  M=Modem Rate        T=Time Online
-G=Multiple Nodes    N=Node Locking      U=
diff --git a/text/menu/flags1.asc b/text/menu/flags1.asc
deleted file mode 100644
index 582f3b131c593b2a08e327b6555ce4dbafd35312..0000000000000000000000000000000000000000
--- a/text/menu/flags1.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=                  H=                  O=                  V=
-B=                  I=                  P=                  W=
-C=                  J=                  Q=                  X=
-D=                  K=                  R=                  Y=
-E=                  L=                  S=                  Z=
-F=                  M=                  T=
-G=                  N=                  U=       
diff --git a/text/menu/flags2.asc b/text/menu/flags2.asc
deleted file mode 100644
index 582f3b131c593b2a08e327b6555ce4dbafd35312..0000000000000000000000000000000000000000
--- a/text/menu/flags2.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=                  H=                  O=                  V=
-B=                  I=                  P=                  W=
-C=                  J=                  Q=                  X=
-D=                  K=                  R=                  Y=
-E=                  L=                  S=                  Z=
-F=                  M=                  T=
-G=                  N=                  U=       
diff --git a/text/menu/flags3.asc b/text/menu/flags3.asc
deleted file mode 100644
index 582f3b131c593b2a08e327b6555ce4dbafd35312..0000000000000000000000000000000000000000
--- a/text/menu/flags3.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=                  H=                  O=                  V=
-B=                  I=                  P=                  W=
-C=                  J=                  Q=                  X=
-D=                  K=                  R=                  Y=
-E=                  L=                  S=                  Z=
-F=                  M=                  T=
-G=                  N=                  U=       
diff --git a/text/menu/flags4.asc b/text/menu/flags4.asc
deleted file mode 100644
index 582f3b131c593b2a08e327b6555ce4dbafd35312..0000000000000000000000000000000000000000
--- a/text/menu/flags4.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=                  H=                  O=                  V=
-B=                  I=                  P=                  W=
-C=                  J=                  Q=                  X=
-D=                  K=                  R=                  Y=
-E=                  L=                  S=                  Z=
-F=                  M=                  T=
-G=                  N=                  U=       
diff --git a/text/menu/info.wip b/text/menu/info.wip
deleted file mode 100644
index 3e5f12920cfdfd18ade091074f136f3b56b63351..0000000000000000000000000000000000000000
--- a/text/menu/info.wip
+++ /dev/null
@@ -1,21 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=Information
-!|L=4590
-!|T=180
-!|W=4050
-!|H=4350
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`t`20`20`100`60`1`Text Files`0`12632256`MS Sans Serif`8.25`Text Files`DETAIL.ICO
-!|002=0B`y`140`20`100`60`2`Your Statistics`0`12632256`MS Sans Serif`8.25`Your Stats`CATPLUS.ICO
-!|003=0B`i`20`100`100`60`3`System Information`0`12632256`MS Sans Serif`8.25`System`INFO.ICO
-!|004=0B`l`140`100`101`59`4``0`12632256`MS Sans Serif`8.25`Calls Today`PHONE.ICO
-!|005=0B`u`20`180`100`60`5`List Users`0`12632256`MS Sans Serif`8.25`List Users`LIST.ICO
-!|006=0B`q`140`180`100`60`6`Quit to Main Menu`0`12632256`MS Sans Serif`8.25`Quit`EXIT.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/keyboard.wip b/text/menu/keyboard.wip
deleted file mode 100644
index a26ff6777023a8706c926d3ddc472d22af127c10..0000000000000000000000000000000000000000
--- a/text/menu/keyboard.wip
+++ /dev/null
@@ -1,42 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=8
-!|M=Keyboard
-!|L=2910
-!|T=1440
-!|W=4725
-!|H=1875
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`q`10`10`20`20`1``0`255`MS Sans Serif`8.25`Q`
-!|002=0B`w`40`10`20`20`2``0`12632256`MS Sans Serif`8.25`W`
-!|003=0B`E`70`10`20`20`3``0`12632256`MS Sans Serif`8.25`E`
-!|004=0B`r`100`10`20`20`4``0`12632256`MS Sans Serif`8.25`R`
-!|005=0B`T`130`10`20`20`5``0`12632256`MS Sans Serif`8.25`T`
-!|006=0B`y`160`10`20`20`5``0`12632256`MS Sans Serif`8.25`Y`
-!|007=0B`u`190`10`20`20`6``0`12632256`MS Sans Serif`8.25`U`
-!|008=0B`i`220`10`20`20`7``0`12632256`MS Sans Serif`8.25`I`
-!|009=0B`o`250`10`20`20`8``0`12632256`MS Sans Serif`8.25`O`
-!|010=0B`p`280`10`20`20`9``0`12632256`MS Sans Serif`8.25`P`
-!|011=0B`a`20`40`20`20`10``0`12632256`MS Sans Serif`8.25`A`
-!|012=0B`S`50`40`20`20`11``0`12632256`MS Sans Serif`8.25`S`
-!|013=0B`d`80`40`20`20`12``0`12632256`MS Sans Serif`8.25`D`
-!|014=0B`f`110`40`20`20`13``0`12632256`MS Sans Serif`8.25`F`
-!|015=0B`g`140`40`20`20`14``0`12632256`MS Sans Serif`8.25`G`
-!|016=0B`h`170`40`20`20`15``0`12632256`MS Sans Serif`8.25`H`
-!|017=0B`j`200`40`20`20`16``0`12632256`MS Sans Serif`8.25`J`
-!|018=0B`k`230`40`20`20`17``0`12632256`MS Sans Serif`8.25`K`
-!|019=0B`l`260`40`20`20`18``0`12632256`MS Sans Serif`8.25`L`
-!|020=0B`Z`30`70`20`20`20``0`12632256`MS Sans Serif`8.25`Z`
-!|021=0B`x`60`70`20`20`21``0`12632256`MS Sans Serif`8.25`X`
-!|022=0B`c`90`70`20`20`22``0`12632256`MS Sans Serif`8.25`C`
-!|023=0B`v`120`70`20`20`23``0`12632256`MS Sans Serif`8.25`V`
-!|024=0B`b`150`70`20`20`24``0`12632256`MS Sans Serif`8.25`B`
-!|025=0B`n`180`70`20`20`25``0`12632256`MS Sans Serif`8.25`N`
-!|026=0B`m`210`70`20`20`26``0`12632256`MS Sans Serif`8.25`M`
-!|027=0B`|M`240`70`40`20`27``0`12632256`MS Sans Serif`8.25`Enter`
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/login.wip b/text/menu/login.wip
deleted file mode 100644
index 66a7da29d3553c8d628bbaf2b899287dc387435e..0000000000000000000000000000000000000000
--- a/text/menu/login.wip
+++ /dev/null
@@ -1,20 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=@BBS@
-!|L=1650
-!|T=525
-!|W=4050
-!|H=3225
-!|B=12632256
-!|
-!|[Form]
-!|001=0T`rate`20`20`220`20`1``0`12632256`MS Sans Serif`8.25`Connected at @BPS@bps`1`2
-!|002=0B`l`20`60`100`60`0`Test`0`12632256`MS Sans Serif`8.25`Login`WELCOME.ICO
-!|003=0B`h`140`60`100`60`1`Test`0`12632256`MS Sans Serif`8.25`Hang-up`CANCEL.ICO
-!|004=0B`g`20`140`100`30`2`Test`0`12632256`MS Sans Serif`8.25`Guest`
-!|005=0B`n`140`140`100`30`3`Test`0`12632256`MS Sans Serif`8.25`New Account`
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/logoff.asc b/text/menu/logoff.asc
deleted file mode 100644
index 21495b84aa0acab72f8c9821728436992072ae4e..0000000000000000000000000000000000000000
--- a/text/menu/logoff.asc
+++ /dev/null
@@ -1,6 +0,0 @@
-lnbhLog off requested on c@DATE@b at c@TIME@
-
-Time used: w@TUSED@
-
-gThank you for calling y@BBS@g, another fine Synchronet BBS...
-n
diff --git a/text/menu/logoff.msg b/text/menu/logoff.msg
deleted file mode 100644
index d0e0fe764a021a902ae522b1c8e2d3e331b70e9e..0000000000000000000000000000000000000000
--- a/text/menu/logoff.msg
+++ /dev/null
@@ -1,28 +0,0 @@
-l
-nk0c1��3��1�y7�������hr2�w1���ny7��hr6�w3��r7��w3��r7�w3�y5�r7�y5����7�5���w1�y5�����������������������������������������nk
-h3��nc3�1�y7�c3�y7�������hw1�����r6�w3��y5�w3��y5���w3�y5��w1�y5�����w1�y5��������������������������������������r7�y5���nk
-h1���3�1�3�nc1���3�y7���r�y�r�y���hw1��r7�6�w3��y5�w3�����y5�r7�y5�w3�y5����w3�y5������w3�y5��������w3�y5���������r7�y5�����������r7�y5�nk
-h0�1��0��r�k1��������3�ny7�c3�1�hk3�nc1�y7�c3�y7���r�y��hr6�ny7�hw1�ny7�hw1�3�����y5�w3����y5�r7�w3����r7�w3�r7�w3�r7����y5����������������������nk
-h0��r�k�nk3�h0�1��0��nk3��h1��������3�1��3��1��3�1�3�nc1���3�1��r7�y��c3�y7�r�y������hw1��r2�w1��r6��w1�r6�7��w3�r7�w3�y5����������w3��y5��w3�y5��nk
-h1������0�1�����0�1����0����1���0���nk3�����h0�nk3�h0�nk3��hr0�k��r�k1�������3�1�3�����nc1�r7��y��hr2�w1�r6�7�w3�y5�r7��w3�y5�r7�w3�y5����r7�y5��nk
-h3�nc1�hk3�1�3��1�3���1�������0���1��0�1�0�1�0��nk3�h0�����nk3�h0���nk3��h0���nk3��h0�r�nk3��hr0�k�1�������nc1�3�r7�y��hr6�w3�r7�w3�r7�w3�r7�w3�y5�r7����w3�y5��nk
-h3������1��3�1�3�����nc1�hk�3�1��������0����nk3��������h0���nk3�h0�r�k����r�k�1���r0�k1��r0�k1����3�nc1�r7�y�hw1�r6�w3�r7��y5�r7��y5��r7��y5��nk
-h3�nc1�hk3�nc1�hk3���1�����r0���nk3�h0�nk3�h0���nk0������������������h�nk0��������h�����nk3��h0�1��3���nc1�hk3�nc1�r7�y����hr6��7��y5��w3�r7�y5��nk
-h1�����r0���k�nk3��h0��nk0����������������h����nk0�h����������nk0�����h�����������1�3�nc1��y7�c3�r7�y�����hw1�r7���y5��w3�nk
-hr0������nk3�h0����nk0��h�nk0�����������h��n�r6�c7�w�nk7�h0���4���6�w�n�0�7�nc7�hk0�nk0�����h��6�4��0��7�c1�w3�r7�ny7�r�c1��3�r7��y���r�y��r�hw1�3�r7�y5�nk
-hr0���nk3��h0�������nk0����������h��nk7�y�hw3�6�0�7�0�k7�4������0�4��0�nk0�������h��4�nb7�hk6�4�0�nk7�hr�w�y�w1��y5�w3��nw7�hn�y7�nr7�y�hw1�r6����w1�r6�w3��nk
-hr0��nk3�hr0�nk3��h0�����nk0���������h��3�ny7�hw3�7�����6�c7�nk7�h4���nb7���hk4�0����nk0��h���4�nb7�hk4�6�nb7�hk6�nk7�c�hw�1��3�1�7�1�nw7�h1��3�y5��w1�r6�7�y5�r6�y5�w3��r7�nk
-hr0�k1�r0��nk3��h0���nk0�������h���nk3�h�nr7�y�hw�0�1����7�1�7��c1�k6�4��nb7�hk4�nb7�hk6�4���6�4�����6�4���r6�w7�1�7��1�7�1�y7�w1�3�r6��7�y5�r6�7�w3��y5����w1�y5�nk
-h3�1�r0�nk3��h0����nk0�����h�nk3�h�nc1�hk�r0�k3�r6�7�w3�1�0�1��3�7��1�7����r6�k7�4��nb7�hk4�nb7��hk6�4����6�4�7�nw7�h0�7�1���3�r7�w3�r7�ny7�r�y�hr6���y5��w1�3�1������3�nk
-y7���hk3��1��r0�k1�r0�k����nk3��hr0��k3�ny7���r�h�w3��7�0��1��7�������6�0�7��c���nc7�hw6�7���1�0�7�1�r7�y5�r7�w3�r6��7����y5�w1���3��1��3�1���y5�w1�y5�nk
-hr7�6�w1�r6�2�w1�nc1�hk���3�1�r0�nk3�h0��nk3��hr0�k1�3�nc3�y7�r�h6�7��nw7�h1�nw7�h��0��7��0�7���0���7�0��7��1�r7�6�ny7�hw1�ny7�r�h6�7�w1�r7�w1�r7��y5�w1�r7�y5��w1��r7�y5����r7��y5�w1��nk
-hw3���r7�6�7�w3�nr7�h6�y5�r6�ny7�c1�hk3�1�r0�nk3�h0�����r�k1��3�nc3�1�r7����h6�w3�nr7��h6��nr7�h6�c1�nr7�c1�k7�h1��3�ny7�r��c1�r7�hw1�nc1�hw3�r6�7�w3��nr7�h6��w3�y5�w3�r6�w1�r6�w3�r6�w3��r7�w1������nk
-hw3�y5�r7�w3�y5�r7�y5�r7�w3���nr7�y���hk3�nc3�hk1��0�nk3�h0���nk3�h0�nk3���h0��nk3���h0��nk3�h�1�nc3�hk1�3��ny7�c1�hk3�nr7�y��hw1�3�r7�w1�3�nr7�y�hr6�ny7�hr6��w1�r6�w3�1�3���r7�y5��w1��3��1�3��1��nk
-hw3��y5��w3�y5�w3�y5��r7�w3����ny7�hw3�nc3�1���3�hk�1���nk3�h1���nc1�hk��0�1�3���w�nr7�hk3�r6�ny7��hw1�nr7�y�hw1�nr7���h6�nr7�h6�7��6�nr7�h6���7�6�7���w3��1����3���1��7�1��nk
-hr7��w3�y5���w3�y5��r7�w3�r7��w3���1�ny7�hw3�1�ny7�r�hw3�ny7��hw1��nr7�hy5�r7�ny7�hw3�ny7�hr6�ny7���hw1�ny7�r�hw3�1�ny7�r�h6�nr7�h6�ny7�hr6���ny7�hw1�r6��w1�r6�w1�3���y5��r7��w1����������3�1���nk
-hr7��w3�y5�������r7�y5�r7�y5�w3�y5�w3�r7�y5�w3���r6��w3��1��r6�w1�ny7�hr6��w1�r7�6�w1�r6��ny7�hw1��3��1�r6���w1�r6��w1�3�r6�7�w3��r7�y5��w1�y5��w1��y5�w1��3�1�7�1�3��1�3�1�3�1�nk
-hr7�6�7�w3�r7�w3�y5��r7�w3�r7�y5�r7�y5���r7��y5���nw7�hr�y5�r7�w3�r7�w3����r7�w3����r7�6�w3����r6�w3�r7�w3��r6�7�w3�r7�y5�w1�y5�r7�y5���w1�y5�w1����y5�w1�����3��1�������nk
-hw�r7���w3�r7�w3��y5�r7�y5��w3�y5�w1�y5��w1�y5��r7�y5��w1�r7�y5�r7���y5�r7��w3���r7�w3����r7�w3�r7��w3�r7��y5�w1�r7�y5�r7�y5�w1��������������������������nk
-hr6�w1�r7�y5�r7��y5�w3�y5�w3��r7�y5������w1�y5����w1�y5���nw7�hy5��r7�y5��w1����y5��w1��3�r7��w3�r7�y5�r7�y5�r7�w1����y5�w1�y5��w1������3�1�3�1����3�1������3�nk
-nw0
-lhyBig Brother is watching...
diff --git a/text/menu/logon.asc b/text/menu/logon.asc
deleted file mode 100644
index f98ccd8cb1da86073c0749f3658eb995c6b58a77..0000000000000000000000000000000000000000
--- a/text/menu/logon.asc
+++ /dev/null
@@ -1,23 +0,0 @@
-nl
-
-
-nhbWelcome to...
-
-
-n���nh��˿ n��   nh˿ n���nh� ˿ n���nh��˿ n��   nh˿ n���nh��˿ n���nh��˿ n���nh� ˿ n���nh��˿ n���nh��Ϳ
-nc���nhc��˿ nc��nhc����� nc�� nhc� �� nc������nhc��δ nc���nhc���� nc��   nhc�� nc�� nhc� �� nc���nhc��nc�nhc��
-nb���nhb����   nb�nhb��   nb�� nhb���� nb���nhb���� nb��   nhb�� nb��  nhb��� nb���nhb���� nb�� nhb���� nb���nhb����   nb�nhb��
-
-���������  ��������   �������
-����   ��� ���   ��� ���
-���������  ��������   �������
-����   ��� ���   �������
-���������  ��������   �������
-
-
-�nbڿ  nhb� nb��nhb�Ŀ nb��nhb�Ŀ nb��nhb�Ŀ nb�nhb� nb��nhb�Ŀ nb��nhbĿ �   nb��nhb�¿   nb��nhb�¿
-�nc��  nhc� nc��nhc�   nc��nhc��� nc��nhc�¿ nc�nhc� ncô  nhc� ncô nhc� �   nc��nhc���   nc��nhc���
-�n�nh��� n��nh��� n�� nh�  n��nh��� n�nh� n��nh��� n�� nh���   n��nh��� o n��nh���
-n
-
-
diff --git a/text/menu/mailread.asc b/text/menu/mailread.asc
deleted file mode 100644
index ec39e205fc6fe3e7a48003cbea7942e5da54318a..0000000000000000000000000000000000000000
--- a/text/menu/mailread.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-0lnc4������������������������k�0
-4c�  hyReading Mail Menu    nk4�0
-4c�k������������������������b0��������������������������
-�����
-� hy<CR> ngNext message�b� hyA ngReply to last message b�
-�    hy- ngPrevious message b� hyF ngForward mail�b�
-�    hyL ngList messages    b� hyD ngDelete last message   b�
-�    hyR ngReread last msg  b���������������������������
-�    hy# ngGo to message #  b�                         b�
-�    hyN ngNext unread msg  b� hyQ ngQuit to Main section  b�
-���������������������������������������������������n
diff --git a/text/menu/mailread.rip b/text/menu/mailread.rip
deleted file mode 100644
index bdd8279207e8ec8c3e8acdca348388e8a0e582aa..0000000000000000000000000000000000000000
--- a/text/menu/mailread.rip
+++ /dev/null
@@ -1,15 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Reading Mail<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL360000<><>
-!|1B0000020QPC010E000F080900000000000000|Y00000100|1U0M161K1G0000<><CR><>^M
-!|1U0M1K1K1U0000<>-<>-|1U0M1Y1K280000<>L<>L
-!|1B0000020QPE010E000F080400000000000000|1U0M2Q1K300000<>Q<>Q
-!|1B0000020QPC010E000F080900000000000000|1U0M2C1K2M0000<>#<>+ 
-!|1U9616A41G0000<>R<>R|1U961KA41U0000<>A<>A|1U961YA4280000<>F<>F
-!|1U962CA42M0000<>D<>D|c00|@1Y16Next Message|@1Y1KPrevious Message
-!|@1Y1YList Message Titles and Authors|@1Y2QQuit to Main Section
-!|@1Y2CGo to Message Number|@AK16Reread Last Message
-!|@AK1KAuto-Reply to Last Message|@AK1YForward Mail to Another User
-!|@AK2CDelete Last Message|w000F271610|10000$ETW$|#|#|#
-
diff --git a/text/menu/mailread.wip b/text/menu/mailread.wip
deleted file mode 100644
index 348d8ae5f90f5a8aa56ce174520bc5dcf1b0b75e..0000000000000000000000000000000000000000
--- a/text/menu/mailread.wip
+++ /dev/null
@@ -1,29 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=4
-!|M=Reading E-mail
-!|L=3885
-!|T=3960
-!|W=5550
-!|H=1470
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`-`10`10`40`40`1`Previous Message`0`12632256`MS Sans Serif`8.25``PREV.ICO
-!|002=0B`|M`60`10`40`40`2`Next Message`0`12632256`MS Sans Serif`8.25``NEXT.ICO
-!|003=0B`l`160`10`40`40`3``0`12632256`MS Sans Serif`8.25``LIST.ICO
-!|004=0B`r`110`10`40`40`4``0`12632256`MS Sans Serif`8.25``BACK.ICO
-!|005=0B`a`210`10`40`40`5`Reply to Last E-mail Message`0`12632256`MS Sans Serif`8.25``EDIT.ICO
-!|006=0B`q`310`10`40`40`7`Delete Last E-mail Message`0`12632256`MS Sans Serif`8.25``EXIT.ICO
-!|007=0B`d`260`10`40`40`7``0`12632256`MS Sans Serif`8.25``DELETE.ICO
-!|008=0T`prev`10`50`40`15`8``0`12632256`MS Sans Serif`8.25`Prev`1`0
-!|009=0T`Next`60`50`40`15`9``0`12632256`MS Sans Serif`8.25`Next`1`0
-!|010=0T`reread`110`50`40`15`10``0`12632256`MS Sans Serif`8.25`Again`1`0
-!|011=0T`list`160`50`40`15`11``0`12632256`MS Sans Serif`8.25`List`1`0
-!|012=0T`reply`210`50`40`15`12``0`12632256`MS Sans Serif`8.25`Reply`1`0
-!|013=0T`delete`260`50`40`15`13``0`12632256`MS Sans Serif`8.25`Delete`1`0
-!|014=0T`quit`310`50`40`15`14``0`12632256`MS Sans Serif`8.25`Quit`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/main.asc b/text/menu/main.asc
deleted file mode 100644
index d490a512c3e047fa612e41a0fcd95533eaad831d..0000000000000000000000000000000000000000
--- a/text/menu/main.asc
+++ /dev/null
@@ -1,20 +0,0 @@
-0lnc4�����������������������k�0
-4c� hySynchronet Main Menu nk4�0
-4c�k�����������������������0
-4b0����4 hwRead/Post Messages nb����4 hwMessage Area Selection nb�����4 hwElectronic Mail nb�����
-�������
-� hyN ngNew message scan�b� hyJ ngJump to new msg area  b� hyE ngRead/Send E-mail�b�
-� hyR ngRead message prompt   b�����������������������������
-� hyZ ngContinuous new scan   b��hy* ngList sub-boards  b������4 hwOther Commands nb�����
-� hyB ngBrowse new scan�b��hy/* ngList groups�b���
-� hyQ ngQWK packet transfer   b� hy{ }  # ngSelect sub-board b�  hyD ngDefault user config  b�
-��������������������������� hy[ ] /# ngSelect group�b�  hy& ngMessage scan config  b�
-� hyP ngPost a message�b���  hyU ngUser lists�b�
-� hyA ngPost auto-message�b����������4 hwGo to nb����������  hyI ngInformation�b�
-�����  hyM ngMinute Bank�b�
-������4 hwMessage Search nb����� hyT ngFile Transfer section b� hy/L ngNode activity�b�
-��� hyG ngText file section�b� hy^K ngCtrl-key Menu�b�
-� hyF ngFind text in messages b� hyC ngChat section�b���������������������������
-� hyS ngScan for msgs to you  b� hyX ngExternal programs�b�  hyO ngLogoff BBS (or /O)   b�
-�������
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
diff --git a/text/menu/main.rip b/text/menu/main.rip
deleted file mode 100644
index 3333ca77f916a4b7d60d6ccc8401fa8c6e714812..0000000000000000000000000000000000000000
--- a/text/menu/main.rip
+++ /dev/null
@@ -1,48 +0,0 @@
-
-!|1K|w0010271610|W00|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Synchronet Main Menu<>|1B0000020PWW050E000F080700000000000000
-!|1U0710HL7T0000<><>|c00|Y00000100|1B0000020QPI010E000F080900000000000000
-!|1U0Y1E1W1O2800<>  P  <>P|1U0Y1S1W222A00<>  R  <>R
-!|1U0Y261W2G2600<>  N  <>((Make a choice::ns@_S_ub-board,ng@_G_roup,na@_A_ll,^\
-M@_Q_uit))
-!|1U0Y2K1W2U2I00<>  Z  <>((Make a choice::zs@_S_ub-board,zg@_G_roup,za@_A_ll,^\
-M@_Q_uit))
-!|1U0Y2Y1W381U00<>  B  <>((Make a choice::bs@_S_ub-board,bg@_G_roup,ba@_A_ll,^\
-M@_Q_uit))
-!|1U0Y3C1W3M2900<>  Q  <>Q
-!|1U0Y3Q1W401YY0<>  F  <>((Make a choice::fs@_S_ub-board,fg@_G_roup,fa@_A_ll,^\
-M@_Q_uit))
-!|1U0Y441W4E2B00<>  S  <>((Make a choice::ss@_S_ub-board,sg@_G_roup,sa@_A_ll,^\
-M@_Q_uit))
-!|1U0Y4I1W4S1T00<>  A  <>((Choose one::ar@_R_ead,aw@_W_rite,^M@_Q_uit))
-!|1B0000020QPI010E000F080100000000000000|1U0Y5A1W5K1600<>  *  <>*
-!|1U0Y5O1W5Y2500<>  M  <>/*
-!|1U0Y621W6C2100<>  I  <>((Choose one::ii@_S_ystem,iv@_V_ersion,iy@_Y_our Stat\
-s,is@S_u_b-board,^M@_Q_uit))
-!|1U0Y6G1W6Q2D00<>  U  <>((Choose one::ul@_L_ogons Today,us@_S_ub-board,ua@_A_\
-ll,^M@_Q_uit))
-!|1U0Y6U1W742400<>  L  <>/L|1U0Y781W7I2200<>  J  <>J
-!|1B0000020QPI010E000F080300000000000000|1U8W1E9U1O1200<>&<>&
-!|1U8W1S9U222700<>O<>O$MKILL$|1U8W269U2G0L00<> ^U  <>^U
-!|1U8W2K9U2U0G00<> ^P  <>^P|1U8W2Y9U380B00<> ^K  <>^K
-!|1B0000020QPE010E000F080C00000000000000|1U7U3Y8S483G00<>{<>{
-!|1U8W3Y9U483I00<>}<>}|1U7U4C8S4M2K00<>[<>[|1U8W4C9U4M2L00<>]<>]
-!|1B0000020QPI010E000F080200000000000000|1U8W5A9U5K1X00<>  E  <>E
-!|1U8W5O9U5Y2C00<>  T  <>T|1U8W629U6C1Z00<>  G  <>G|1U8W6G9U6Q2G00<>  X  <>X
-!|1U8W6U9U741V00<>  C  <>C|1U8W789U7I1W00<>  D  <>D|@2S11Message Functions|c0F
-!|@2T12Message Functions|c00|@B111Control Functions|c0F|@B212Control Functions
-!|c00|@2N4VListing Functions|c0F|@2O4WListing Functions|c00
-!|@AV3HSub-board Selection|c0F|@AW3ISub-board Selection|c00
-!|@B44VOther Selections|c0F|@B54WOther Selections|c00|@281FPost Message
-!|@281TRead Messages|@2827New Message Scan|@282LContinuous Message Scan
-!|@282ZBrowse Message Scan|@283DQWK Packet Transfer|@283RFind Text in Messages
-!|@2845Search for Your Messages|@284JRead/Write Auto-Message
-!|@285BSub-boards within Group|@285PMessage Groups|@2863Information Commands
-!|@286HUser Lists|@286VList All Nodes|@2879Jump to a Message Area
-!|@AA1FConfiguration Commands|@AA1TLogoff (also /0)
-!|@AA27List Users Online (Anywhere)|@AA2LSend Message to Another Node
-!|@AA2ZControl Key Command Menu|@AA3YChange Sub, or Type Number
-!|@AA4CChange Group, or Type /Number|@AA5BElectronic Mail Commands
-!|@AA5PFile Transfers|@AA63General Text File Sections|@AA6HExternal Programs
-!|@AA6VChat Commands|@AA79Account Default Configuration|100AC$ETW$|#|#|#
-
diff --git a/text/menu/maincfg.asc b/text/menu/maincfg.asc
deleted file mode 100644
index f7182823ce01904e04d8eb21eb352cf67c6dde85..0000000000000000000000000000000000000000
--- a/text/menu/maincfg.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-lnc4�����������������������������k�0
-4c� hyMessage Scan Configuration nk4�0
-4c�k�����������������������������b0������������������������������������
-�����
-� hyN ngNew-scan configuration�b� hyS ngYour message scan config  b�
-� hyP ngSet new-scan pointers�b�������������������������������
-� hyI ngReinitialize new-scan pointers b� hyQ ngQuit to Main menu�b�
-������������������������������������������������������������������n
diff --git a/text/menu/maincfg.rip b/text/menu/maincfg.rip
deleted file mode 100644
index dacf7d2e587f4267d21f85870344d4891aa71843..0000000000000000000000000000000000000000
--- a/text/menu/maincfg.rip
+++ /dev/null
@@ -1,12 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Configuration Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2E0000<><>
-!|1B0000020QPE010E000F080300000000000000|Y00000100|1U0M161K1G0000<>C<>C
-!|1U0M1K1K1U0000<>R<>R|1U9616A41G0000<>N<>N|1U961KA41U0000<>P<>P
-!|1U961YA4280000<>I<>I|1B0000020QPE010E000F080400000000000000
-!|1U0M1Y1K280000<>Q<>Q|c00|@1Y16Convert Credits to Minutes
-!|@1Y1KUnfiltered (Raw) Input Mode|@AK1YReinitialize Message Pointers
-!|@AK16New Message Scan Configuration|@AK1KNew Message Scan Pointers
-!|@1Y1YQuit to the Main Menu|w000C271610|10000$ETW$|#|#|#
-
diff --git a/text/menu/maininfo.asc b/text/menu/maininfo.asc
deleted file mode 100644
index 40c0627e204a2eefc4372c40fdce6c6e2b640181..0000000000000000000000000000000000000000
--- a/text/menu/maininfo.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-0lnc4��������������������������������k�0
-4c� hyMain Section Information Menu nk4�0
-4c�k��������������������������������b0���������������������������
-�����
-� hyI ngSystem information�b� hyY ngYour statistics   b�
-��hy0V ngSynchronet version information   b�����������������������
-� hyS ngInformation on current sub-board b� hyQ ngQuit to Main menu b�
-������������������������������������������������������������n
diff --git a/text/menu/maininfo.rip b/text/menu/maininfo.rip
deleted file mode 100644
index 9c1ce1d85b91bd8d5b29b8631166091f2c23ea14..0000000000000000000000000000000000000000
--- a/text/menu/maininfo.rip
+++ /dev/null
@@ -1,10 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Information Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2E0000<><>
-!|1B0000020QPC010E000F080100000000000000|Y00000100|1U0M161K1G0000<>I<>I
-!|1U0M1K1K1U0000<>V<>V|1U961KA41U0000<>S<>S|1U9616A41G0000<>Y<>Y
-!|1B0000020QPE010E000F080400000000000000|1U0M1Y1K280000<>Q<>Q|c00|@1Y16System
-!|@1Y1KVersion|@AK1KSub-board|@AK16Your Statistics|@1Y1YQuit to the Main Menu
-!|w000F271610|10000$ETW$|#|#|#
-
diff --git a/text/menu/major/email.asc b/text/menu/major/email.asc
deleted file mode 100644
index 8d4c1495b9dec942254eb8e0254353814f2f026c..0000000000000000000000000000000000000000
--- a/text/menu/major/email.asc
+++ /dev/null
@@ -1,10 +0,0 @@
-ghThe following E-mail services are available:
-
-c   R y=> Read message(s)
-c   W y=> Write a message
-c   E y=> Erase a message
-
-c   S y=> Send NetMail
-c   U y=> Upload a file attachment
-cs
-Select a letter from this list, or X to exit: n
\ No newline at end of file
diff --git a/text/menu/major/file.asc b/text/menu/major/file.asc
deleted file mode 100644
index 61780b1b3aaed2ff7fbf47813267b6687239da78..0000000000000000000000000000000000000000
--- a/text/menu/major/file.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-ghThe following Library services are available:
-
-c   F y=> File directory
-c   D y=> Download a file
-c   U y=> Upload a file
-c   S y=> Select a LIB
-cs
-Current LIB: @LIB@ @DIR@
-Select a letter from this list (or X to exit): n
\ No newline at end of file
diff --git a/text/menu/major/main.asc b/text/menu/major/main.asc
deleted file mode 100644
index 912196055758d654dca65f4ca99dee774fddaeed..0000000000000000000000000000000000000000
--- a/text/menu/major/main.asc
+++ /dev/null
@@ -1,15 +0,0 @@
-ghPlease select one of the following:
-
-c   T y... Teleconference
-c   I y... Information Center
-c   F y... Forums (Public Message Bases)
-c   E y... Electronic Mail
-c   L y... Library of Files
-c   D y... Doors (External Programs)
-c   A y... Account Display/Edit
-c   R y... Registry of Users
-(c   S y... System Management
-)c   X y... Exit System (Logoff)
-cs
-(TOP)
-Make your selection (T,I,F,E,L,A,P,R,S,? for help, or X to exit): n
\ No newline at end of file
diff --git a/text/menu/major/msg.asc b/text/menu/major/msg.asc
deleted file mode 100644
index 673753a6ccd26d29d9bb6a274794aca42b27d04f..0000000000000000000000000000000000000000
--- a/text/menu/major/msg.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-ghWelcome, @NAME@, to @GRP@ @SUB@
-
-c   R y... Read messages
-c   W y... Write a message
-c   Q y... Quickscan Menu
-c   T y... Teleconference
-c   S y... Select a new Forum
-cs
-Select a letter from this list, or X to exit: n
\ No newline at end of file
diff --git a/text/menu/major/quickscn.asc b/text/menu/major/quickscn.asc
deleted file mode 100644
index 6282734acf854a54e4765b67f2bc1bc711da26f6..0000000000000000000000000000000000000000
--- a/text/menu/major/quickscn.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-ghQuickscan functions:
-
-c   S y... scan through messages
-c   L y... list messages to you
-c   K y... keyword-search for messages
-
-c   C y... configure your quickscan
-cs
-Select a letter from the above list, or X to exit: n
\ No newline at end of file
diff --git a/text/menu/major/userdefs.asc b/text/menu/major/userdefs.asc
deleted file mode 100644
index 355f83e3b7aa43ab648794abf09f004a9f95541f..0000000000000000000000000000000000000000
--- a/text/menu/major/userdefs.asc
+++ /dev/null
@@ -1,6 +0,0 @@
-gh   User-ID: @NAME@
-
-c   S y=> Display statistics on your account
-c   A y=> Display or edit account information
-cs
-Your choice (or 'X' to exit): n
\ No newline at end of file
diff --git a/text/menu/msgattr.asc b/text/menu/msgattr.asc
deleted file mode 100644
index 7d8a91ea6302243a9a3cda661e3690ce8bbc5e1d..0000000000000000000000000000000000000000
--- a/text/menu/msgattr.asc
+++ /dev/null
@@ -1 +0,0 @@
-nhb[nhRnhb]ead, [nhPnhb]rivate, [nhAnhb]non, [nhKnhb]ill, [nhMnhb]oderated, [nhVnhb]alidated, [nhNnhb]on-purgable:n z
diff --git a/text/menu/msgs.wip b/text/menu/msgs.wip
deleted file mode 100644
index b76df9a9c1e118784b283b9bb2b5feb9440d8568..0000000000000000000000000000000000000000
--- a/text/menu/msgs.wip
+++ /dev/null
@@ -1,21 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=Messages
-!|L=1770
-!|T=345
-!|W=4050
-!|H=4350
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`r`20`20`100`60`1`Read Messages`0`12632256`MS Sans Serif`8.25`Read`DETAIL.ICO
-!|002=0B`p`140`20`100`60`2`Post Message`0`12632256`MS Sans Serif`8.25`Post`EDIT.ICO
-!|003=0B`s`20`100`100`60`3`Search Messages for Specific Text`0`12632256`MS Sans Serif`8.25`Text Search`SEARCH.ICO
-!|004=0B`n`140`100`100`60`4`Search for New Messages`0`12632256`MS Sans Serif`8.25`New`FIND.ICO
-!|005=0B`q`20`180`100`60`5`QWK Message Upload/Download for Offline Readers`0`12632256`MS Sans Serif`8.25`QWK`SAVE.ICO
-!|006=0B`x`140`180`100`60`6`Quit to Main Menu`0`12632256`MS Sans Serif`8.25`Quit`EXIT.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/msgscan.asc b/text/menu/msgscan.asc
deleted file mode 100644
index 904ca0398d3b2f381d58a43e80b8e0606e4c827f..0000000000000000000000000000000000000000
--- a/text/menu/msgscan.asc
+++ /dev/null
@@ -1,19 +0,0 @@
-0lnc4������������������������k�0
-4c� hyReading Messages Menu nk4�0
-4c�k������������������������0
-4b0������4 hwRead Messages nb��������4 hwPost/Reply Messages nb������4 hwMessage Threading nb����
-�������
-� hy<CR> ngNext message�b� hyP ngPost a message�b� hy< > ng-/+ by Title�b�
-�    hy- ngPrevious message   b� hyD ngDelete a message�b� hy{ } ng-/+ by Author�b�
-�    hyC ngContiunous read    b��������������������������� hy[ ] ng-/+ by 'To User'    b�
-�    hyR ngReread last msg    b� hyA ngReply to last message b���
-�    hy# ngGo to message #    b� hyM ngReply in mail to last b������4 hwOther Commands nb�����
-�������
-�������4 hwList Titles nb�������������4 hwSearch/Find nb������� hyB ngBypass current sub    b�
-����� hyI ngInformation on sub    b�
-� hyL ngTitles and authors    b� hyY ngMessages to you�b���������������������������
-� hyT ngNext ten msg titles   b� hyF ngFind text in messages b� hyQ ngQuit to Main menu�b�
-�������
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
-(
-     hyO ngOperator Commandsn
diff --git a/text/menu/msgscan.rip b/text/menu/msgscan.rip
deleted file mode 100644
index 65985a8162c251a7821b3e7f113084749c201e63..0000000000000000000000000000000000000000
--- a/text/menu/msgscan.rip
+++ /dev/null
@@ -1,20 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0O0000<>Reading Messages<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL4G0000<><>
-!|1B0000020QPE010E000F080900000000000000|Y00000100|1U0M161K1G0000<><CR><>^M
-!|1U0M1K1K1U0000<>-<>-|1U0M1Y1K280000<>L<>L|1U0M2C1K2M0000<>T<>T
-!|1U0M2Q1K300000<>B<>B|1U9616A41G0000<>R<>R|1U961KA41U0000<>A<>A
-!|1U961YA4280000<>M<>M|1U962CA42M0000<>Y<>Y|1U0M341K3E0000<>C<>C
-!|1B0000020QPC010E000F080400000000000000|1U0M3W1K460000<>Q<>Q
-!|1B0000020QPC010E000F080900000000000000|1U0M3I1K3S0000<>#<>
-!|1U962QA4300000<>F<>F|1U9634A43E0000<>D<>D|1U963IA43S0000<>P<>P
-!|1U963WA4460000<>I<>I|c00|@1Y16Next Message|@1Y1KPrevious Message
-!|@1Y1YList Message Titles and Authors|@1Y2CTitles of Next Ten Messages
-!|@1Y2QBypass Current Sub-Board|@1Y34Continuous Read|@1Y3WQuit to Main Section
-!|@1Y3IGo to Message Number|@AK16Reread Last Message|@AK1KReply to Last Message
-!|@AK1YReply in Mail to Last Message|@AK2CTitles of Your Messages
-!|@AK2QFind Text in All Messages|@AK34Delete Message|@AK3IPost a Message
-!|@AK3WInformation on Sub-board|w000L271610|L1V2Z1V2Z|L1D2U1D2U|100AC$ETW$|#|#
-!|#
-
diff --git a/text/menu/msgscan.wip b/text/menu/msgscan.wip
deleted file mode 100644
index 9cacaacd7958247d311c41057a57aed5e6310fe3..0000000000000000000000000000000000000000
--- a/text/menu/msgscan.wip
+++ /dev/null
@@ -1,39 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=4
-!|M=Reading Messages
-!|L=90
-!|T=3960
-!|W=9300
-!|H=1500
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`-`10`10`40`40`1`Previous Message`0`12632256`MS Sans Serif`8.25``PREV.ICO
-!|002=0B`|M`60`10`40`40`2`Next Message`0`12632256`MS Sans Serif`8.25``NEXT.ICO
-!|003=0B`l`210`10`40`40`3``0`12632256`MS Sans Serif`8.25``LIST.ICO
-!|004=0B`r`110`10`40`40`4``0`12632256`MS Sans Serif`8.25``BACK.ICO
-!|005=0B`a`260`10`40`40`5`Reply to Last E-mail Message`0`12632256`MS Sans Serif`8.25``EDIT.ICO
-!|006=0B`m`360`10`40`40`7`Delete Last E-mail Message`0`12632256`MS Sans Serif`8.25``NOTEPAD.ICO
-!|007=0B`d`310`10`40`40`7``0`12632256`MS Sans Serif`8.25``DELETE.ICO
-!|008=0T`prev`10`50`40`15`8``0`12632256`MS Sans Serif`8.25`Prev`1`0
-!|009=0T`Next`60`50`40`15`9``0`12632256`MS Sans Serif`8.25`Next`1`0
-!|010=0T`reread`110`50`40`15`10``0`12632256`MS Sans Serif`8.25`Again`1`0
-!|011=0T`list`210`50`40`15`11``0`12632256`MS Sans Serif`8.25`List`1`0
-!|012=0T`reply`260`50`40`15`12``0`12632256`MS Sans Serif`8.25`Reply`1`0
-!|013=0T`delete`310`50`40`15`13``0`12632256`MS Sans Serif`8.25`Delete`1`0
-!|014=0T`e-mail`360`50`40`15`14``0`12632256`MS Sans Serif`8.25`E-mail`1`0
-!|015=0B`t`160`10`40`40`15``0`12632256`MS Sans Serif`8.25``2NDPAGE.ICO
-!|016=0T`ten`160`50`40`15`16``0`12632256`MS Sans Serif`8.25`Titles`1`0
-!|017=0B`p`410`10`40`40`17``0`12632256`MS Sans Serif`8.25``EDIT.ICO
-!|018=0T`post`410`50`40`15`18``0`12632256`MS Sans Serif`8.25`Post`1`0
-!|019=0B`y`460`10`40`40`19``0`12632256`MS Sans Serif`8.25``CONTACT.ICO
-!|020=0T`yours`460`50`40`15`20``0`12632256`MS Sans Serif`8.25`Yours`1`0
-!|021=0B`f`510`10`40`40`21``0`12632256`MS Sans Serif`8.25``SEARCH.ICO
-!|022=0T`find`510`50`40`15`22``0`12632256`MS Sans Serif`8.25`Find`1`0
-!|023=0B`q`560`10`40`40`23``0`12632256`MS Sans Serif`8.25``EXIT.ICO
-!|024=0T`quit`560`50`40`15`24``0`12632256`MS Sans Serif`8.25`Quit`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/multchat.asc b/text/menu/multchat.asc
deleted file mode 100644
index bb022f20289e59131d012cce14062d26744a588f..0000000000000000000000000000000000000000
--- a/text/menu/multchat.asc
+++ /dev/null
@@ -1,10 +0,0 @@
-nlc4����������������������k�0
-4c� hyMultinode Chat Menu nk4�0
-4c�k����������������������b0��������������������������������������������������������
-�����
-� hy/W ngWhisper to another user  �b� hy/E ngToggle echo status�b�
-� hy/L ngList all node activity�b� hy/A ngToggle action commands b�
-� hy/* ngList Chat channels�b� hy/C ngList action commands   b�
-� hy/# ngChange Chat channel (# is channel number)    b� hy/Q ngQuit multinode chat    b�
-�����
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
diff --git a/text/menu/multchat.rip b/text/menu/multchat.rip
deleted file mode 100644
index bd0e9484c9ea660485380741ff42c3af7caabea9..0000000000000000000000000000000000000000
--- a/text/menu/multchat.rip
+++ /dev/null
@@ -1,13 +0,0 @@
-
-!|1K|*|e|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Multinode Chat<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2S0000<><>
-!|1B0000020QPE010E000F080500000000000000|Y00000100|1U0M161K1G0000<>/W<>^M/P
-!|1U0M1K1K1U0000<>/L<>^M/L|1U961KA41U0000<>/#<>|1U961YA4280000<>^U<>^U
-!|1U962CA42M0000<>^P<>^P|1U0M1Y1K280000<>/E<>^M/E|1U9616A41G0000<>/*<>^M/*
-!|1B0000020QPE010E000F080400000000000000|1U0M2C1K2M0000<>/Q<>^M/Q|c00
-!|@1Y16Whisper to another user|@1Y1KList All Nodes|@1Y1YToggle Echo Status
-!|@1Y2CQuit Chat Session|@AK16List Channels|@AK1KChange Channel Number
-!|@AK1YList Users Online|@AK2CSend Message to Another Node|w000E271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/namepass.wip b/text/menu/namepass.wip
deleted file mode 100644
index 1965ae1c11164759ed64c7f8b59276533607ac71..0000000000000000000000000000000000000000
--- a/text/menu/namepass.wip
+++ /dev/null
@@ -1,20 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=8
-!|M=Login
-!|L=3555
-!|T=225
-!|W=3375
-!|H=3375
-!|B=12632256
-!|
-!|[Form]
-!|001=1T`name`10`30`200`30`1``0`12632256`MS Sans Serif`8.25`0`2
-!|002=0T`label`10`10`200`20`2``0`12632256`MS Sans Serif`8.25`Please enter your user name`0`0
-!|003=0B`|M`60`130`100`60`3``0`12632256`MS Sans Serif`8.25`Login`WELCOME.ICO
-!|004=1T`password`10`90`200`30`2``12632256`12632256`MS Sans Serif`8.25`0`2
-!|005=0T`enter pass`10`70`160`20`5``0`12632256`MS Sans Serif`8.25`Please enter your password`0`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/noyes.wip b/text/menu/noyes.wip
deleted file mode 100644
index cccb3c7a7322879f5701ffb0a1cf5c12381f11cb..0000000000000000000000000000000000000000
--- a/text/menu/noyes.wip
+++ /dev/null
@@ -1,20 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=8
-!|M=No or Yes
-!|L=1815
-!|T=510
-!|W=3000
-!|H=2100
-!|B=12632256
-!|
-!|[Form]
-!|001=0T`question`10`10`170`35`1``0`12632256`MS Sans Serif`8.25`@QUESTION@`1`0
-!|002=0B`n`50`50`40`40`2``0`12632256`MS Sans Serif`8.25``CANCEL.ICO
-!|003=0B`y`100`50`40`40`3``0`12632256`MS Sans Serif`8.25``DONE.ICO
-!|004=0T`no`50`90`40`15`4``0`12632256`MS Sans Serif`8.25`No`1`0
-!|005=0T`yes`100`90`40`15`5``0`12632256`MS Sans Serif`8.25`Yes`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/number.wip b/text/menu/number.wip
deleted file mode 100644
index 0730b2f393ad1ee34fa5ffff43fcec7042a477e2..0000000000000000000000000000000000000000
--- a/text/menu/number.wip
+++ /dev/null
@@ -1,26 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=8
-!|M=Pick a Number
-!|L=1605
-!|T=555
-!|W=1575
-!|H=2475
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`1`10`10`20`20`1``0`12632256`MS Sans Serif`8.25`1`
-!|002=0B`2`40`10`20`20`2``0`12632256`MS Sans Serif`8.25`2`
-!|003=0B`3`70`10`20`20`3``0`12632256`MS Sans Serif`8.25`3`
-!|004=0B`4`10`40`20`20`4``0`12632256`MS Sans Serif`8.25`4`
-!|005=0B`5`40`40`20`20`5``0`12632256`MS Sans Serif`8.25`5`
-!|006=0B`6`70`40`20`20`6``0`12632256`MS Sans Serif`8.25`6`
-!|007=0B`7`10`70`20`20`7``0`12632256`MS Sans Serif`8.25`7`
-!|008=0B`8`40`70`20`20`8``0`12632256`MS Sans Serif`8.25`8`
-!|009=0B`9`70`70`20`20`9``0`12632256`MS Sans Serif`8.25`9`
-!|010=0B`q`10`100`32`32`10``0`12632256`MS Sans Serif`8.25``CANCEL.ICO
-!|011=0B`|M`60`100`32`32`11``0`12632256`MS Sans Serif`8.25``DONE.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/pause.wip b/text/menu/pause.wip
deleted file mode 100644
index 5f4a9dadd993a10a488d848b3e9d023e9add9127..0000000000000000000000000000000000000000
--- a/text/menu/pause.wip
+++ /dev/null
@@ -1,15 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=12
-!|M=Continue
-!|L=1695
-!|T=615
-!|W=2925
-!|H=1275
-!|B=12632256
-!|[Form]
-!|001=0B`|M`10`10`80`40`1``0`12632256`MS Sans Serif`8.25`OK`
-!|002=0B`n`100`10`80`40`2``0`12632256`MS Sans Serif`8.25`Cancel`
-$0E
\ No newline at end of file
diff --git a/text/menu/pcboard/brdm.asc b/text/menu/pcboard/brdm.asc
deleted file mode 100644
index 67c74c8c1f0edc290eff047aa3edbc2cad62a9ab..0000000000000000000000000000000000000000
--- a/text/menu/pcboard/brdm.asc
+++ /dev/null
@@ -1,21 +0,0 @@
-nlk4������������������������������������������������������������������������������nhb4�0
-nk4� nhc4Date: nhg4@SYSDATE@               nh4M a i n   M e n u               nhc4Time: nhg4@SYSTIME@0nhb4 �0
-nk4�nc4� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �nhb4�0
-nk4� nh4(nhr4Fnh4)ile Directories      (nhr4Lnh4)ocate a filename       (nhr4EXTnh4)ended file info      nhb4�0
-nk4� nh4(nhr4Dnh4)ownload a file       (nhr4Nnh4)ew file scan           (nhr4VIEWnh4) a file before d/l  nhb4�0
-nk4� nh4(nhr4Unh4)pload a file         (nhr4Znh4)ippy Text Search       (nhr4BATCHnh4) transfer menu     nhb4�0
-nk4�                         nh4(nhr4Tnh4)emp archive menu       (nhr4REMOVEnh4) or edit a file   nhb4�0
-nk4�                                                                             nhb4�0
-nk4� nh4(nhr4Jnh4)oin a conference     (nhr4Anh4)djust pointers         (nhr4TSnh4) Text search msgs.    nhb4�0
-nk4� nh4(nhr4Enh4)nter a message       (nhr4Cnh4)omment to SysOp        (nhr4QWKnh4) Transfer QWK mail   nhb4�0
-nk4� nh4(nhr4Rnh4)ead messages         (nhr4Ynh4)our messages           (nhr4AUTOnh4) message            nhb4�0
-nk4� nh4(nhr4RNnh4) Read New messages  (nhr4RCnh4) Read New Continuous  (nhr4SELECTnh4) confs. to scan   nhb4�0
-nk4�                                                                             nhb4�0
-nk4� nh4(nhr4Mnh4)ail Send/Receive     (nhr4Xnh4)pert mode toggle       (nhr4Onh4) Page SysOp            nhb4�0
-nk4� nh4(nhr4Bnh4)ulletins             (nhr4Gnh4)oodbye (Logoff)        (nhr4Inh4)nitial logon screen    nhb4�0
-nk4� nh4(nhr4Snh4)ystem Information    (nhr4Wnh4) Change your info      (nhr4Pnh4)rivate node message    nhb4�0
-nk4� nh4(nhr4Vnh4)iew your statistics                                                      nhb4�0
-nk4�                                                                             nhb4�0
-nk4� nh4(nhy4CHATnh4) with other users                 (nhy4OPENnh4) a door                       nhb4�0
-nk4� nh4(nhy4NEWSnh4) Display system news              (nhy4USERnh4) List conference members      nhb4�0
-nk4�nhb4������������������������������������������������������������������������������n
diff --git a/text/menu/pcboard/welcome.asc b/text/menu/pcboard/welcome.asc
deleted file mode 100644
index 9a52c68c2483941461960d3c4e068caeca2655a5..0000000000000000000000000000000000000000
--- a/text/menu/pcboard/welcome.asc
+++ /dev/null
@@ -1,22 +0,0 @@
-nl
-nh�n������������������������������������������
-�������������������������������������������
-�������������������������������������������
-�������������������������������������������
-    nk5�����������������������������������������������������������������������nhm5�0
-nhnh nh nh nh nk5�                           nh5����   ���  ����   ���  �                  nhm5�0
-nhnh nh nh nh nk5�                            nh5�  � �   �  �  � �   � �                  nhm5�0
-nhnh nh nh nh nk5�   nh5S Y N C H R O N E T      ���� �      ���� �     � ���� ���� ����   nhm5�0
-nhnh nh nh nh nk5�     V e r s i o n 2        nh5�    �   �  �  � �   � � �  � �  � ���    nhm5�0
-nhnh nh nh nh nk5�                           nh5���    ���  ����   ���  �  ��  �  �  ��    nhm5�0
-nhnh nh nh nh nk5�nhm5�����������������������������������������������������������������������0
-nh�nhk������������������������������������������
-�������������������������������������������
-�n������������������������������������������
-�������������������������������������������
-�������������������������������������������
-
-�nhk2�����������������������������������������nhg2�0
-nh�nhk2� nh2Your SysOp is: { this space for rent } nhg2�0
-nh�nhk2�nhg2�����������������������������������������0
-n
\ No newline at end of file
diff --git a/text/menu/privchat.asc b/text/menu/privchat.asc
deleted file mode 100644
index c3fc712358b52e1eee0acb250c710fb786a84328..0000000000000000000000000000000000000000
--- a/text/menu/privchat.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-0lnc4��������������������k�0
-4c� hyPrivate Chat Menu nk4�0
-4c�k��������������������b0���������������������������������������
-�����
-� hy/L ngList all node activity b� hyCtrl-U ngWho's online�b�
-� hy/E ngToggle echo status�b� hyCtrl-P ngSend private message  b�
-� hy/Q ngQuit private chat�b���
-������������������������������������������������������������n
diff --git a/text/menu/privchat.rip b/text/menu/privchat.rip
deleted file mode 100644
index 1bde8bc1487f41ab6b69bd755c1c2fd679f471ca..0000000000000000000000000000000000000000
--- a/text/menu/privchat.rip
+++ /dev/null
@@ -1,11 +0,0 @@
-
-!|1K|*|e|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Private Chat<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2E0000<><>
-!|1B0000020QPE010E000F080500000000000000|Y00000100|1U0M161K1G0000<>/L<>^M/L
-!|1U9616A41G0000<>^U<>^U|1U961KA41U0000<>^P<>^P|1U0M1K1K1U0000<>/E<>^M/E
-!|1B0000020QPE010E000F080400000000000000|1U0M1Y1K280000<>/Q<>^M/Q|c00
-!|@1Y16List All Nodes|@1Y1KToggle Echo Status|@1Y1YQuit Chat Session
-!|@AK16List Users Online|@AK1KSend Message to Another Node|w000E271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/qwk.asc b/text/menu/qwk.asc
deleted file mode 100644
index c0d080a10105760cd3383a5956eb3f34d379edea..0000000000000000000000000000000000000000
--- a/text/menu/qwk.asc
+++ /dev/null
@@ -1,13 +0,0 @@
-lnc4����������������������������k�0
-4c�  hyQWK Offline Reader Menu  nk4�0
-4c�k����������������������������b0�������
-���
-� hyC ngChange Packet Configuration    b�
-� hyS ngSelect Message Areas to Scan   b�
-� hyP ngModify New-message Pointers    b�
-� hyU ngUpload REP reply packet�b�
-� hyD ngDownload QWK message packet    b�
-� hyB ngBidirectional REP/QWK transfer b�
-������������������������������������
-� hyQ ngQuit back to Main menu�b�
-������������������������������������n
diff --git a/text/menu/qwk.rip b/text/menu/qwk.rip
deleted file mode 100644
index 9834eb1cbc784349f7e05f789d2603d6c79f31d2..0000000000000000000000000000000000000000
--- a/text/menu/qwk.rip
+++ /dev/null
@@ -1,11 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>QWK Packet Transfer Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL200000<><>
-!|1B0000020QPE010E000F080100000000000000|Y00000100|1U0M161K1G0000<>U<>U
-!|1U0M1K1K1U0000<>D<>D|1U9616A51G0000<>B<>B
-!|1B0000020QPE010E000F080400000000000000|1U961KA51U0000<>Q<>Q|c00
-!|@1Y16Upload REP Reply Packet|@1Y1KDownload QWK Message Packet
-!|@AK16Bidirectional REP/QWK Transfer|@AK1KQuit to the Main Menu|w000A271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/qwk.wip b/text/menu/qwk.wip
deleted file mode 100644
index 8f93eed81a89bf9e66acd25ad00c1cd9238be879..0000000000000000000000000000000000000000
--- a/text/menu/qwk.wip
+++ /dev/null
@@ -1,21 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=QWK Offline Reader
-!|L=1425
-!|T=195
-!|W=4050
-!|H=4350
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`d`20`20`100`60`1``0`12632256`MS Sans Serif`8.25`Download QWK`DOWNLOAD.ICO
-!|002=0B`u`140`20`100`60`2``0`12632256`MS Sans Serif`8.25`Upload REP`EDIT.ICO
-!|003=0B`s`140`100`100`60`3``0`12632256`MS Sans Serif`8.25`Select Areas`LIST.ICO
-!|004=0B`c`20`100`100`60`4``0`12632256`MS Sans Serif`8.25`Setup`DETAIL.ICO
-!|005=0B`p`20`180`100`60`5``0`12632256`MS Sans Serif`8.25`MSG Pointers`CATPLUS.ICO
-!|006=0B`q`140`180`100`60`6``0`12632256`MS Sans Serif`8.25`Quit`EXIT.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/renegade/email.asc b/text/menu/renegade/email.asc
deleted file mode 100644
index aa27a7d26da0cfca426558b852ec11fcf6411334..0000000000000000000000000000000000000000
--- a/text/menu/renegade/email.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-�nhr������������������������������������������������������Ŀ
-��4         wSynchronet Reneclone Email System Menu       r0�
-���������������������������������������������������������
-  c4��������������������������������������������������������������������������Ŀ0
-  4� [yRc]ead Email       [yEc]nter Email                                         �0
-  4� [yVc]iew Outgoing    [yQc]uit to Main     [yGc]oodbye        [y/Gc]oodbye Fast!  �0
-  4����������������������������������������������������������������������������0n
diff --git a/text/menu/renegade/main.asc b/text/menu/renegade/main.asc
deleted file mode 100644
index 03aa3e1342eac9673eef1de3ec64358a01da0593..0000000000000000000000000000000000000000
--- a/text/menu/renegade/main.asc
+++ /dev/null
@@ -1,10 +0,0 @@
-�nhr������������������������������������������������������Ŀ
-��4         wSynchronet Reneclone Main System Menu        r0�
-���������������������������������������������������������
-  c4��������������������������������������������������������������������������Ŀ0
-  4� [yMc]essage System   [yFc]ile System      [yOc]nline System  [yEc]mail System    �0
-  4� [ySc]ystem Bulletins [yUc]ser Listing     [yYc]our Info      [yAc]uto-message    �0
-  4� [yWc]ho's online     [yLc]ist of Callers  [y!c]Offline Mail  [yPc]ersonal Info   �0
-  4� [yNc]ote to SysOp    [yCc]hat System      [yIc]nfo on System [yXc]pert Toggle    �0
-  4� [yGc]oodbye & Logoff [y/Gc]oodbye Fast!   [y$c]Time Bank     [y/Lc]ist Nodes     �0
-  4����������������������������������������������������������������������������0n
diff --git a/text/menu/renegade/message.asc b/text/menu/renegade/message.asc
deleted file mode 100644
index 8fcb58d5e94de600f73ea5f331c89506e2eb38b4..0000000000000000000000000000000000000000
--- a/text/menu/renegade/message.asc
+++ /dev/null
@@ -1,10 +0,0 @@
-�nhr������������������������������������������������������Ŀ
-��4        wSynchronet Reneclone Message System Menu      r0�
-���������������������������������������������������������
-  c4�������������������������������������������������������������������������Ŀ0
-  4� [y#c]Sub Change      [y/#c]Group Change   [y[c]Previous Sub  [y]c]Next Sub      �0
-  4� [yCc]hat System      [yRc]ead Messages    [ySc]can Messages  [yPc]ost Message   �0
-  4� [yFc]ile Menu        [yGc]oodbye          [y/Gc]oodbye       [yUc]sers w/Access �0
-  4� [yNc]ew Message Scan [yQc]uit to Main     [yEc]nter Email    [yZc]Set Scan Areas�0
-  4� [yAc]rea List        [yJc]ump to Area     [y/Lc]ist Nodes    [yYc]our Messages  �0
-  4���������������������������������������������������������������������������0n
diff --git a/text/menu/renegade/transfer.asc b/text/menu/renegade/transfer.asc
deleted file mode 100644
index 8f8fb5007d7c5b468c7df308a08cf67dea32322a..0000000000000000000000000000000000000000
--- a/text/menu/renegade/transfer.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-�nhr������������������������������������������������������Ŀ
-��4         wSynchronet Reneclone File System Menu        r0�
-���������������������������������������������������������
-  c4��������������������������������������������������������������������������Ŀ0
-  4� [y#c]Dir Change      [y/#c]Lib Change     [y[c]Previous Dir  [y]c]Next Dir       �0
-  4� [y/Ac]rchive Menu    [yAc]rea List        [yCc]hat System    [yDc]ownload        �0
-  4� [yEc]nter Batch Mode [yFc]ind Description [yGc]oodbye        [y/Gc]oodbye        �0
-  4� [yPc]ointer Date     [yLc]ist Files       [yMc]essage Menu   [yNc]ew Files       �0
-  4� [yUc]pload!          [yQc]uit to Main     [yVc]iew Archive   [ySc]earch Filespec �0
-  4� [yYc]our File info   [yJc]ump to Area     [y/Lc]ist Nodes                      �0
-  4����������������������������������������������������������������������������0n
diff --git a/text/menu/restrict.asc b/text/menu/restrict.asc
deleted file mode 100644
index fd796cd5be70288f0fb338b8062a3d26be2371a2..0000000000000000000000000000000000000000
--- a/text/menu/restrict.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-A=ANSI              H=                  O=                  V=
-B=Beep              I=                  P=Post              W=Auto-message
-C=Chat              J=Quoting           Q=QWK Network Node  X=External Programs
-D=Download          K=Read Mail Sent    R=Remove Files      Y=Are you sure?
-E=E-mail	    L=Logon one/day	S=Email Sysop	    Z=
-F=Forward mail      M=Networked Mail    T=Transfers
-G=Edit Defaults     N=Networked Subs    U=Upload
diff --git a/text/menu/sdos/files.asc b/text/menu/sdos/files.asc
deleted file mode 100644
index 4ebd352de512a0f14151f2388ad0b2fec9e14803..0000000000000000000000000000000000000000
--- a/text/menu/sdos/files.asc
+++ /dev/null
@@ -1,21 +0,0 @@
- Volume in drive C is BBS
- Volume Serial Number is 8317-6BE8
- Directory of C:\FILES
-
-.	     <DIR>     08/01/94  02:34 pm
-..	     <DIR>     08/01/94  02:34 pm
-DOWNLOAD EXE     24343 06/02/94  08:36 am
-UPLOAD   EXE	 48321 06/02/94  08:36 am
-REMOVE   COM      2377 06/04/94  04:55 pm
-BATCH    EXE	 30566 06/02/94  08:36 am
-VIEW	 EXE	 10485 06/02/94  08:36 am
-TEMP     EXE	114705 06/02/94  08:37 am
-LIST	 EXE	 81380 06/04/94  04:56 pm
-NEWSCAN  COM	  3146 06/02/94  08:36 am
-EXTENDED EXE	287347 06/04/94  04:56 pm
-SEARCH   COM	  1969 06/04/94  04:56 pm
-FIND	 COM	  5193 06/04/94  04:57 pm
-AREA	 COM	   905 06/02/94  08:35 am
-CONFIG	 COM	  2517 06/02/94  08:35 am
-       15 file(s)    1350784 bytes
-                    @FREESPACE@ bytes free
diff --git a/text/menu/sdos/mail.asc b/text/menu/sdos/mail.asc
deleted file mode 100644
index 45afc742f950766166e9ba58d52127ee68416c4e..0000000000000000000000000000000000000000
--- a/text/menu/sdos/mail.asc
+++ /dev/null
@@ -1,21 +0,0 @@
- Volume in drive C is BBS
- Volume Serial Number is 8317-6BE8
- Directory of C:\MAIL
-
-.	     <DIR>     08/01/94  02:34 pm
-..	     <DIR>     08/01/94  02:34 pm
-SEND	 EXE	 54343 06/02/94  08:36 am
-SENDFILE EXE	 58981 06/02/94  08:36 am
-NETMAIL  EXE	 30566 06/02/94  08:36 am
-READ	 EXE	102485 06/02/94  08:36 am
-READSENT EXE	114705 06/02/94  08:37 am
-POST	 EXE	 81380 06/04/94  04:56 pm
-NEWSCAN  COM	  3146 06/02/94  08:36 am
-READMSGS EXE	287347 06/04/94  04:56 pm
-YOURMSGS COM	  1969 06/04/94  04:56 pm
-FIND	 COM	  5193 06/04/94  04:57 pm
-QWK	 EXE	159876 06/02/94  08:35 am
-AREA	 COM	   905 06/02/94  08:35 am
-CONFIG	 COM	  2517 06/02/94  08:35 am
-       15 file(s)    1350784 bytes
-                    @FREESPACE@ bytes free
diff --git a/text/menu/sdos/root.asc b/text/menu/sdos/root.asc
deleted file mode 100644
index f8896a1aa2cc846441300d9aeb92f1d4254d40e4..0000000000000000000000000000000000000000
--- a/text/menu/sdos/root.asc
+++ /dev/null
@@ -1,20 +0,0 @@
- Volume in drive C is BBS       
- Volume Serial Number is 8317-6BE8
- Directory of C:\
-
-FILES        <DIR>     08/01/94  02:34 pm       
-MAIL         <DIR>     08/01/94  02:34 pm    
-SETUP    EXE     54343 06/02/94  08:36 am        
-CHAT     EXE    102485 06/02/94  08:36 am    
-AUTOMSG  COM       894 06/04/94  04:55 pm       
-DOORS    EXE    326501 07/11/94  11:01 am       
-GFILES   EXE     31024 06/02/94  08:36 am
-LOGOFF   COM      2193 05/22/94  04:27 pm        
-NODES	 TXT	   593 @LASTDATEON@  @LASTTIMEON@
-LOGON	 LST	  1984 @LASTDATEON@  @LASTTIMEON@
-USERS	 LST	148394 @LASTDATEON@  @LASTTIMEON@
-SYSTEM	 NFO	   733 04/01/94  06:30 am        
-YOUR     NFO       252 @LASTDATEON@  @LASTTIMEON@
-(SYSOP    EXE    208419 01/01/80  00:00 am
-)       13 file(s)    1350784 bytes
-                    @FREESPACE@ bytes free
diff --git a/text/menu/sentmail.asc b/text/menu/sentmail.asc
deleted file mode 100644
index c6a942c0ba3987b8a9c605c8cfcd4bd1a8e43d4e..0000000000000000000000000000000000000000
--- a/text/menu/sentmail.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-0lnc4������������������������k�0
-4c�  hyRead Sent Mail Menu  nk4�0
-4c�k������������������������b0��������������������������
-�����
-� hy<CR> ngNext message�b� hyD ngDelete last message   b�
-�    hy- ngPrevious message b� hyR ngReread last message   b�
-�    hyL ngList messages    b� hyE ngEdit last message     b�
-�    hy# ngGo to message #  b� hyQ ngQuit to Main section  b�
-���������������������������������������������������n
diff --git a/text/menu/sentmail.rip b/text/menu/sentmail.rip
deleted file mode 100644
index 3fe25f80ee522102cc9df841f70b21d1cad2a7c5..0000000000000000000000000000000000000000
--- a/text/menu/sentmail.rip
+++ /dev/null
@@ -1,13 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Reading Sent Mail<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2S0000<><>
-!|1B0000020QPC010E000F080900000000000000|Y00000100|1U0M161K1G0000<><CR><>^M
-!|1U0M1K1K1U0000<>-<>-|1U0M1Y1K280000<>L<>L
-!|1B0000020QPE010E000F080400000000000000|1U0M2C1K2M0000<>Q<>Q
-!|1B0000020QPC010E000F080900000000000000|1U961YA4280000<>#<>+ 
-!|1U9616A41G0000<>R<>R|1U961KA41U0000<>D<>D|c00|@1Y16Next Message
-!|@1Y1KPrevious Message|@1Y1YList Messages|@1Y2CQuit to Main Section
-!|@AK1YGo to Message #|@AK16Reread Last Message|@AK1KDelete Last Message
-!|w000G271610|10000$ETW$|#|#|#
-
diff --git a/text/menu/sentmail.wip b/text/menu/sentmail.wip
deleted file mode 100644
index 8e71d3444f732a4dde7e6953e48f08a0e4bee357..0000000000000000000000000000000000000000
--- a/text/menu/sentmail.wip
+++ /dev/null
@@ -1,29 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=4
-!|M=Reading Sent E-mail
-!|L=3885
-!|T=3960
-!|W=5550
-!|H=1470
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`-`10`10`40`40`1`Previous Message`0`12632256`MS Sans Serif`8.25``PREV.ICO
-!|002=0B`|M`60`10`40`40`2`Next Message`0`12632256`MS Sans Serif`8.25``NEXT.ICO
-!|003=0B`l`160`10`40`40`3``0`12632256`MS Sans Serif`8.25``LIST.ICO
-!|004=0B`r`110`10`40`40`4``0`12632256`MS Sans Serif`8.25``BACK.ICO
-!|005=0B`e`210`10`40`40`5`Reply to Last E-mail Message`0`12632256`MS Sans Serif`8.25``EDIT.ICO
-!|006=0B`q`310`10`40`40`7`Delete Last E-mail Message`0`12632256`MS Sans Serif`8.25``EXIT.ICO
-!|007=0B`d`260`10`40`40`7``0`12632256`MS Sans Serif`8.25``DELETE.ICO
-!|008=0T`prev`10`50`40`15`8``0`12632256`MS Sans Serif`8.25`Prev`1`0
-!|009=0T`Next`60`50`40`15`9``0`12632256`MS Sans Serif`8.25`Next`1`0
-!|010=0T`reread`110`50`40`15`10``0`12632256`MS Sans Serif`8.25`Again`1`0
-!|011=0T`list`160`50`40`15`11``0`12632256`MS Sans Serif`8.25`List`1`0
-!|012=0T`edit`210`50`40`15`12``0`12632256`MS Sans Serif`8.25`Edit`1`0
-!|013=0T`delete`260`50`40`15`13``0`12632256`MS Sans Serif`8.25`Delete`1`0
-!|014=0T`quit`310`50`40`15`14``0`12632256`MS Sans Serif`8.25`Quit`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/simple/filelist.asc b/text/menu/simple/filelist.asc
deleted file mode 100644
index 0b0e8f3654958aa1742603e59f4b9288b0c5a2b2..0000000000000000000000000000000000000000
--- a/text/menu/simple/filelist.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-nhm�nhc� nhySynchronet Listing Files nhc�
-�nhg2����������������������������������������ķ0
-nhm�nhg2� nhy2Anh2) All files in a directory            nhg2�0
-nhm�nhg2�                                        �0
-nhm�nhg2� nhy2Nnh2) New since @NEWFILETIME@ nhg2 �0
-nhm�nhg2� nhy2Snh2) Search for a filename               nhg2�0
-nhm�nhg2� nhy2Fnh2) Find text in file descriptions      nhg2�0
-nhm�nhg2�                                        �0
-�nhg2� nhy2Qnh2) Quit to Main Menu                   nhg2�0
\ No newline at end of file
diff --git a/text/menu/simple/main.asc b/text/menu/simple/main.asc
deleted file mode 100644
index f399de8eaafdc1fc44c790b7e6d8df3ca867e878..0000000000000000000000000000000000000000
--- a/text/menu/simple/main.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-nh�nhc� nhySynchronet Main nhc�
-�nhg2����������������������������������������ķ0
-nh�nhg2� nhy2Fnh2)ile list         nhy2Rnh2)ead messages/mail nhg2�0
-nh�nhg2� nhy2Dnh2)ownload file     nhy2Snh2)end messages/mail nhg2�0
-�nhg2� nhy2Unh2)pload a file     nhy2Lnh2)ist users online  nhg2�0
-nh�nhg2� nhy2Qnh2)WK offline msgs  nhy2Pnh2)age user          nhg2�0
-nh�nhg2�                                        �0
-nh�nhg2� nhy2Onh2)nline programs   nhy2Cnh2)hat menu          nhg2�0
-nh�nhg2�                                        �0
-nh�nhg2� nhy2Anh2)ccount configuration                 nhg2�0
-�nhg2� nhy2Gnh2)ood-bye (hang-up)                    nhg2�0
\ No newline at end of file
diff --git a/text/menu/simple/prompt.ans b/text/menu/simple/prompt.ans
deleted file mode 100644
index c098e78e0e716f1bcb7b1b4dd2d183e129740c7f..0000000000000000000000000000000000000000
--- a/text/menu/simple/prompt.ans
+++ /dev/null
@@ -1,2 +0,0 @@
-�nhg2����������������������������������������Ķ
-�nhg2� n                                      hg2 �[�nhg2����������������������������������������Ľ[nmhCommand: n
\ No newline at end of file
diff --git a/text/menu/simple/prompt.asc b/text/menu/simple/prompt.asc
deleted file mode 100644
index e2f3b7e7907771044511df72a1af5d7e80ba48c0..0000000000000000000000000000000000000000
--- a/text/menu/simple/prompt.asc
+++ /dev/null
@@ -1,2 +0,0 @@
-�nhg2����������������������������������������Ľ
-�  mhCommand: n
\ No newline at end of file
diff --git a/text/menu/simple/readmsg.asc b/text/menu/simple/readmsg.asc
deleted file mode 100644
index 73f3c6f4ebf65836b69dfbc0272a0642f6e07316..0000000000000000000000000000000000000000
--- a/text/menu/simple/readmsg.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-nhm�nhc� nhySynchronet Reading Messages nhc�
-�nhg2����������������������������������������ķ0
-nhm�nhg2� nhy2Enh2) Email TO: YOU   nhy2Fnh2) Email FROM: YOU  nhg2�0
-nhm�nhg2�                                        �0
-nhm�nhg2� nhy2Bnh2) Bulletins                           nhg2�0
-nhm�nhg2� nhy2Anh2) All messages in a conference        nhg2�0
-nhm�nhg2� nhy2Nnh2) New messages in all conferences     nhg2�0
-nhm�nhg2� nhy2Ynh2) New messages TO: YOU in all conf's  nhg2�0
-nhm�nhg2� nhy2Cnh2) Configure new message scan          nhg2�0
-nhm�nhg2�                                        �0
-�nhg2� nhy2Qnh2) Quit to Main Menu                   nhg2�0
\ No newline at end of file
diff --git a/text/menu/simple/sendmsg.asc b/text/menu/simple/sendmsg.asc
deleted file mode 100644
index f0914a8b43ddd18855fc5a4ad65310b06e3056cb..0000000000000000000000000000000000000000
--- a/text/menu/simple/sendmsg.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-nhm�nhc� nhySynchronet Sending Messages nhc�
-�nhy2����������������������������������������ķ0
-nhm�nhy2� Enh2) Send Email      nhy2Nnh2) Send Netmail     nhy2�0
-nhm�nhy2�                                        �0
-nhm�nhy2� Pnh2) Post a message in a conference      nhy2�0
-nhm�nhy2�                                        �0
-nhm�nhy2� Qnh2) Quit to Main Menu                   nhy2�0
\ No newline at end of file
diff --git a/text/menu/sysmailr.asc b/text/menu/sysmailr.asc
deleted file mode 100644
index 0c92196b89019845fe0de2a1dab7df9d98cafa8b..0000000000000000000000000000000000000000
--- a/text/menu/sysmailr.asc
+++ /dev/null
@@ -1,4 +0,0 @@
-nk4������������������������������������������������������������������������������c�0
-4k�     hyS n4Save/Append last message to file      hyU n4Edit author of last message   c�0
-4k�     hyC n4Change attributes of last message     hyP n4Purge author of last message  c�0
-4k�c������������������������������������������������������������������������������n
diff --git a/text/menu/sysmain.asc b/text/menu/sysmain.asc
deleted file mode 100644
index 9bda1e705309765e8812ddcde5ba8d68d33af700..0000000000000000000000000000000000000000
--- a/text/menu/sysmain.asc
+++ /dev/null
@@ -1,22 +0,0 @@
-0l�nhSynchronet Sysop Main Menu
-   b(All commands preceeded by a 'w;b')�(Optional parameters shown in m[]b)
-   (Required parameters shown in r<>b)�(Required exemptions shown in y()b)
-
-yNode Display/Control:�Editing:
-wNODE m[args]   cNode Utility�wUEDIT m[user]  cEdit User Account
-wDOWN r<nodes>  cToggle Down Flag�wEDIT�cEdit Text/MSG File
-wLOCK r<nodes>  cLock/Unlock m(N)
-wINTR r<nodes>  cToggle Interrupt m(I)�yViewing:
-wANON�cToggle Anonymous m(Q)�wLIST m[file]   cView Text/ANSI/MSG File
-wQUIET�cToggle Quiet�m(Q)�wLOG�cToday's Log
-�wYLOG�cYesterday's Log
-yMiscellaneous:�wNS m[node]�cNode Statistics
-wCHUSER�cChange into Another User   wSS�cSystem Statistics
-wBULKMAIL�cSend Bulk E-mail�wNLOG�cNode Statistics Log
-wSHELL�cOS Command Shell�wSLOG�cSystem Statistics Log
-wCALL r<hub>    cForce QWKnet Call-out�wERR�cCritical Error Log
-wCHAT�cPage sysop m(C)�wGURU�cDiscussions w/The Guru
-wLOAD r<file>   cLoad alternate text.dat    wMAIL�cAll Mail on System
-wEXEC r<cmd>    cExecute DOS Program�wSPY m[node]    cSpy/control Node
-wEXEC *r<mod>   cExecute Baja Module
-wFOSSIL r<cmd>  cExecute FOSSIL Program
diff --git a/text/menu/sysmscan.asc b/text/menu/sysmscan.asc
deleted file mode 100644
index 16846c01a321ffd3775f71b9bc56bcde40df2bb5..0000000000000000000000000000000000000000
--- a/text/menu/sysmscan.asc
+++ /dev/null
@@ -1,15 +0,0 @@
-nlc4����������������������������k�0
-4c�  hySub-board Operator Menu  nk4�0
-4c�k����������������������������b0�������
-���
-� hyC ngChange Message Attributes�b�
-� hyE ngEdit Message Text�b�
-� hyH ngView Message Header�b�
-� hyM ngMove Message to Another Sub    b�
-� hyS ngSave Message to Text File�b�
-� hyU ngEdit Author's User Account�b�
-� hyP ngPurge Author's User Account    b�
-� hyV ngValidate Previous Message�b�
-������������������������������������
-� hyQ ngQuit back to Main menu�b�
-������������������������������������n
diff --git a/text/menu/syssmail.asc b/text/menu/syssmail.asc
deleted file mode 100644
index b2484e597e4fa0501ee92a002f8aad2934edbe64..0000000000000000000000000000000000000000
--- a/text/menu/syssmail.asc
+++ /dev/null
@@ -1,3 +0,0 @@
-nk4������������������������������������������������������������������������������c�0
-4k�     hwE n4Edit Last Message                                                     c�0
-4k�c������������������������������������������������������������������������������n
diff --git a/text/menu/sysxfer.asc b/text/menu/sysxfer.asc
deleted file mode 100644
index 895c330e0c149f0559a6727a652655433165a84e..0000000000000000000000000000000000000000
--- a/text/menu/sysxfer.asc
+++ /dev/null
@@ -1,15 +0,0 @@
-                        Synchronet Sysop Transfer Menu
-                     (All commands are preceeded by a ';')
-
-PUT [s]         Direct upload file s to any drive or directory (remote)
-GET [s]         Direct download file s from any drive or directory (remote)
-OLD           *	Remove, Edit, or Move files not downloaded since new-scan date
-OLDUL         *	Remove, Edit, or Move files uploaded before new-scan date
-CLOSE         *	Search for and optionally close open file records
-ALTUL [x]	Perform uploads using alternate file path number x
-UPLOAD        *	Bulk local upload - add files on disk to database
-RESORT        *	Re-sort files by sort value and compress empty slots
-OFFLINE       *	Remove, Edit, or Move files in database that aren't on disk
-
-* Commands can be followed by LIB or ALL to specify the action to take place
-on all directories of the current library, or all directories in all libraries.
diff --git a/text/menu/tempxfer.asc b/text/menu/tempxfer.asc
deleted file mode 100644
index dbf5a8fa465a49a1934da62d3fc5cfa11b406cb4..0000000000000000000000000000000000000000
--- a/text/menu/tempxfer.asc
+++ /dev/null
@@ -1,14 +0,0 @@
-0lnc4������������������������������k�0
-4c� hyTemp Directory Command Menu nk4�0
-4c�k������������������������������0
-4b0����������������hw4Extract from Archive  nb������������������hw4Other Commands   nb������
-�����
-� hyE ngExtract from archive in any directory�b� hyL ngList files in temp dir   b�
-� hyX ngExtract from archive in temp directory�b������������������������������
-��� hyI ngInformation on files�b�
-�������hw4Create Listnb�����������4 hwTemp Archive   nb����� hyV ngView archive contents    b�
-����� hyR ngRemove files from temp   b�
-� hyN ngList of new files  b� hyA ngCreate/add to archive b������������������������������
-� hyF ngList of all files  b� hyD ngDownload temp archive b� hyQ ngQuit to transfer menu    b�
-�������
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
diff --git a/text/menu/tempxfer.rip b/text/menu/tempxfer.rip
deleted file mode 100644
index d246bb9210b84abd9c65c9e4664de4227788584e..0000000000000000000000000000000000000000
--- a/text/menu/tempxfer.rip
+++ /dev/null
@@ -1,17 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Temp Directory<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL3K0000<><>
-!|1B0000020QPC010E000F080100000000000000|Y00000100|1U0M161K1G0000<>E<>E
-!|1U0M1K1K1U0000<>N<>N|1U0M1Y1K280000<>F<>F|1U0M2C1K2M0000<>A<>A
-!|1U0M2Q1K300000<>D<>D|1B0000020QPE010E000F080400000000000000
-!|1U0M341K3E0000<>Q<>Q|1B0000020QPC010E000F080100000000000000
-!|1U9616A41G0000<>I<>I|1U961KA41U0000<>V<>V|1U961YA4280000<>L<>L
-!|1U962CA42M0000<>X<>X|1U962QA4300000<>R<>R|c00|@1Y16Extract from an Archive
-!|@1Y1KCreate a List of New Files|@1Y1YCreate a List of All Files
-!|@1Y2CAdd to/Create Temp Archive|@1Y2QDownload Temp Archive
-!|@1Y34Quit to the Transfer Section|@AK1YList Files in Temp Directory
-!|@AK16Information on Files|@AK1KView Contents in Archives
-!|@AK2CExtract From Archive in Temp|@AK2QRemove Files from Temp|w000G271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/transfer.asc b/text/menu/transfer.asc
deleted file mode 100644
index 416807d7fc13f4b9361b9fd66fb536d3627f3bf0..0000000000000000000000000000000000000000
--- a/text/menu/transfer.asc
+++ /dev/null
@@ -1,19 +0,0 @@
-0lnc4��������������������������������k�0
-4c� hySynchronet File Transfer Menu nk4�0
-4c�k��������������������������������0
-4b0�����4 hwList/Flag Files nb�������4 hwFile Area Selection nb���������4 hwFile Search  nb������
-�������
-� hyL ngList files in dir�b� hyJ ngJump to new file area b� hyF ngFind text in descrp   b�
-� hyN ngNew file scan�b��������������������������� hyS ngSearch for filename   b�
-� hyE ngExtended file info    b��hy* ngList directories b���
-����hy/* ngList libraries   b������4 hwOther Commands nb�����
-�����4 hwUpload/Download nb����� hy{ }  # ngSelect directory b���
-��� hy[ ] /# ngSelect library   b�  hy& ngFile scan config�b�
-�  hyD ngDownload file�b���  hyR ngRemove/edit file�b�
-�  hyU ngUpload file�b����������4 hwGo to nb����������  hyI ngInformation�b�
-� hy/D ngDownload from user   b���  hyV ngView file contents   b�
-� hy/U ngUpload to user�b� hyQ ngMain/Message section  b� hy/L ngNode activity�b�
-�  hyZ ngUpload to sysop�b� hyC ngChat section�b� hy^K ngCtrl-key menu�b�
-�  hyB ngBatch/Bi-dir xfers   b� hyT ngTemp dir/Archive cmds b�  hyO ngLogoff BBS (or /O)   b�
-�������
-4  hyAnytime: cCtrl-U nc4Who's online  hCtrl-P nc4Send private msg  hCtrl-C nc4Abort cmd/text n
diff --git a/text/menu/transfer.rip b/text/menu/transfer.rip
deleted file mode 100644
index 1501d23d4be84fc7b21a22ac9883f1a8bf6900bd..0000000000000000000000000000000000000000
--- a/text/menu/transfer.rip
+++ /dev/null
@@ -1,37 +0,0 @@
-
-!|1K|w0010271610|W00|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Synchronet File Transfer Menu<>
-!|1B0000020PWW050E000F080700000000000000|1U0710HL7T0000<><>|c00|Y00000100
-!|1B0000020QPI010E000F080900000000000000|1U0Y1E1W1O1600<>*<>*
-!|1U0Y1S1W221T00<> A <>/*|1U0Y261W2G2400<>L<>L|1U0Y2K1W2U1X00<>E<>E
-!|1U0Y2Y1W382E00<>V<>V|1U0Y3C1W3M2600<>N<>N|1U0Y3Q1W402BY0<>S<>S
-!|1U0Y441W4E1Y00<>F<>F|1U0Y4I1W4S2100<>I<>I|1U0Y4W1W560000<> /L  <>/L
-!|1U0Y5A1W5K2200<>J<>J|1B0000020QPI010E000F080100000000000000
-!|1U0Y6G1W6Q2C00<>T<>T|1U0Y6U1W741V00<>C<>C
-!|1B0000020QPI010E000F080400000000000000|1U0Y781W7I2900<>Q<>Q
-!|1B0000020QPI010E000F080300000000000000|1U8W1E9U1O1200<>&<>&
-!|1U8W1S9U222A00<>  R  <>R|1B0000020QPE010E000F080300000000000000
-!|1U8W269U2G2700<>O<>O$MKILL$|1B0000020QPI010E000F080300000000000000
-!|1U8W2K9U2U0L00<> ^U  <>^U|1U8W2Y9U380G00<> ^P  <>^P|1U8W3C9U3M0B00<> ^K  <>^K
-!|1B0000020QPE010E000F080C00000000000000|1U7U3Y8S483G00<>{<>{
-!|1U8W3Y9U483I00<>}<>}|1U7U4C8S4M2K00<>[<>[|1U8W4C9U4M2M00<>]<>]
-!|1B0000020QPI010E000F080200000000000000|1U8W5A9U5K1W00<>  D  <>D
-!|1U8W5O9U5Y0000<> /D  <>/D|1U8W629U6C1U00<>B<>B|1U8W6G9U6Q2D00<>U<>U
-!|1U8W6U9U740000<> /U  <>/U|1U8W789U7I2I00<>Z<>Z|@2S11Listing Functions|c0F
-!|@2T12Listing Functions|c00|@B111Control Functions|c0F|@B212Control Functions
-!|c00|@2N62Other Sections|c0F|@2O63Other Sections|c00|@B44VTransfer Functions
-!|c0F|@B54WTransfer Functions|c00|@281EDirectories within Library
-!|@281SFile Libraries|@2826Files in Current Directory
-!|@282KExtended File Information|@282YView Contents of File|@283CNew File Scan
-!|@283QSearch for Filename|@2844Find Text in Description
-!|@284IInformation Commands|@284WList All Nodes|@285AJump to a File Area
-!|@286GTemp Dir/Archive Commands|@286UChat Commands|@2878Quit to Main Menu
-!|@AA1EConfiguration Commands|@AA1SRemove/Edit File, Any Directory
-!|@AA26Logoff (also /O)|@AA2KList Users Online (Anywhere)
-!|@AA2YSend Message to Another Node|@AA3CControl Key Command Menu
-!|@AA3YChange Directory, or Type Number|@A94BChange Library, or Type /Number
-!|@AA5ADownload File from Any Directory|@AA5ODownload User to User
-!|@AA62Batch/Bidirectional|@AA6GUpload File to Current Directory
-!|@AA6UUpload File User to User|@AA78Upload File to Sysop Directory|10000$ETW$
-!|#|#|#
-
diff --git a/text/menu/uedit.asc b/text/menu/uedit.asc
deleted file mode 100644
index 1ccf24a2b8bd82a580611b4dad2f72de8f995c27..0000000000000000000000000000000000000000
--- a/text/menu/uedit.asc
+++ /dev/null
@@ -1,21 +0,0 @@
-                           yh��� wUser Edit Menu y���
-�����������������������������������������������������������������������������Ŀ
-�  wA  bAlias and Handle                    wS  bSex (Gender)                     y�
-�  wB  bBirthday                            wT  bSet Text Search String           y�
-�  wC  bComputer                            wU  bUpload and Download Stats        y�
-�  wD  bDelete/Deactivate/Restore           wV  bQuick-Validate User              y�
-�  wE  bExemptions                          wW  bPassword                         y�
-�  wF  bFlags                               wX  bView Extended Comment            y�
-�  wG  bGo to a User                        wY  bCopy User to Another Slot        y�
-�  wH  bEdit/Create Extended Comment        wZ  bRestrictions                     y�
-�  wI  bInspect/Edit User's Defaults        w]  bGo Up One User                   y�
-�  wJ  bEdit Minutes                        w[  bGo Down One User                 y�
-�  wK  bEdit Dates                          w}  bSearch Up (Text or ARS)          y�
-�  wL  bLocation, Address, and Zip Code     w{  bSearch Down (Text or ARS)        y�
-�  wM  bMain Security Level                 w/  bSet AR String for Search         y�
-�  wN  bNote                                w~  bSet Leech Download Counter       y�
-�  wO  bComment                             w+  bAdjust Credits                   y�
-�  wP  bPhone Number                        w*  bAdjust Minutes                   y�
-�  wQ  bQuit                                w$  bEdit Credits                     y�
-�  wR  bReal Name                           w#  bView User Questionnaire          y�
-�������������������������������������������������������������������������������
diff --git a/text/menu/ulprot.asc b/text/menu/ulprot.asc
deleted file mode 100644
index 2339a77346c8a37ed5535ff3dfb3a9961fd0074e..0000000000000000000000000000000000000000
--- a/text/menu/ulprot.asc
+++ /dev/null
@@ -1 +0,0 @@
-hwX bXmodem  wY bYmodem  wZ bZmodem  wG bYmodem-G
diff --git a/text/menu/wfc.asc b/text/menu/wfc.asc
deleted file mode 100644
index 5ab9a55135fac81d2763e3ed0dbfaa72dfbd1ba8..0000000000000000000000000000000000000000
--- a/text/menu/wfc.asc
+++ /dev/null
@@ -1,3 +0,0 @@
-�nc4�������������������������������k�0
-47������������������������c4�   hSynchronet Multinode BBS   nk4�7�����������������������hw�nk7�                       c4�       hyWaiting for Call       nk4�7                       hw�nk7�                       c4�k�������������������������������7                       hw�nk7�                                                                              hw�nk7�   hw����nk7�                    hw����nk7�                    hw����nk7�                    hw�nk7�   hw� yL nk7� bToday's caller log hw� yC nk7� bConfigure BBS      hw� yM nk7� bRead all mail      hw�nk7�   hw�nk7����                    hw�nk7����                    hw�nk7����                    hw�nk7�   hw����nk7�                    hw����nk7�                    hw����nk7�                    hw�nk7�   hw� yY nk7� bYesterday's log    hw� yU nk7� bUser editor        hw� yR nk7� bRead feedback      hw�nk7�   hw�nk7����                    hw�nk7����                    hw�nk7����                    hw�nk7�   hw����nk7�                    hw����nk7�                    hw����nk7�                    hw�nk7�   hw� yN nk7� bNode statistics    hw� yT nk7� bTerminal mode      hw� yE nk7� bSend mail/netmail  hw�nk7�   hw�nk7����                    hw�nk7����                    hw�nk7����                    hw�nk7�   hw����nk7�                    hw����nk7�                    hw����nk7�                    hw�nk7�   hw� yS nk7� bSystem statistics  hw� yD nk7� bDOS shell          hw� yX nk7� bQuit (on-hook)     hw�nk7�   hw�nk7����                    hw�nk7����                    hw�nk7����                    hw�nk7�   hw����nk7�                    hw����nk7�                    hw����nk7�                    hw�nk7�   hw� yA nk7� bForce answer       hw� yF nk7� bForce QWKnet       hw� yQ nk7� bQuit (off-hook)    hw�nk7�   hw�nk7����                    hw�nk7����                    hw�nk7����                    hw�nk7�                                                                              hw�nk7�                          c4�������������������������k�7                          hw�nk7�hw��������������������������nc4�   hySpace Bar n4to logon   k�hw7���������������������������nk.�c4�k�������������������������0
-g0Synchronet BBS Version 2�(C) 1995 Digital Dynamicsn
\ No newline at end of file
diff --git a/text/menu/wildcat/file.asc b/text/menu/wildcat/file.asc
deleted file mode 100644
index 7a12f146af960c5d24a8896c141be29e4a0a3c74..0000000000000000000000000000000000000000
--- a/text/menu/wildcat/file.asc
+++ /dev/null
@@ -1,20 +0,0 @@
-0
-nh�nh��������������������������������������������������Ŀ
-��   ���ķ��ķ�ķ��
-��   ���  � �    ��ķ ��ķ  � �� � ��ķ ��ķ �  �   �
-��   �    � �    ���  ��ķ  � ӽ � ���  �  � �  �   �
-��   �    � ��Ľ ��Ľ ��Ľ  �    � ��Ľ �  � ��Ľ   �
-����������������������������������������������������������������Ĵn���nh����������
-nhg��������������nh��nhySynchronet Wildclone�nh�ng���nhg����������
-nhy��������������nh����������������������������������������������������n���nhy����������
-nhc������������������nc���������������������������������������������������nhc����������
-nhb���nh��������������������Ŀnhb�nh�������������������������Ŀnhb�nh��������������������Ŀnb���
-nh��ܳ nhyQ nhuit to Main��ܳ nhyL nhist Available Files   �ܳ nhyD nhownload a File   �n���
-nhg���nh� nhyU nhpload a File��nhg�nh� nhyN nhew Files Since [N]    �nhg�nh� nhyV nhiew a ZIP File   �ng���
-nhy���nh� nhyM nhessage Menu��nhy�nh� nhyS nhearch for Files��nhy�nh� nhyG nhoodbye & Logoff  �n���
-   nh� nhyI nhnfo on a File    � � nhyJ nhoin a Conference�� � nhyP nhersonal Stats    �
-   � nhyE nhdit Marked List  � � nhyF nhile Transfer Info�� � nhyH nhelp Level��
-   ���������������������� ��������������������������� ����������������������
-                                (nhy1 nhSysop Menu )
-nhyConference: nh@LIB@ @DIR@   nhyTime On: nh@TIMEON@  nhyTime Remaining: nh@LEFT@
-n
\ No newline at end of file
diff --git a/text/menu/wildcat/main.asc b/text/menu/wildcat/main.asc
deleted file mode 100644
index 9c17a85ced5869820a2bcce2a1dc6f2baebc2dcb..0000000000000000000000000000000000000000
--- a/text/menu/wildcat/main.asc
+++ /dev/null
@@ -1,20 +0,0 @@
-0
-nh�nh��������������������������������������������������Ŀ
-��   �ķ�ķ��ķ�ķ��
-��   � �� � ��ķ � ��ķ    � �� � ��ķ ��ķ �  �    �
-��   � ӽ � ��Ķ � �  �    � ӽ � ���  �  � �  �    �
-��   �    � �  � � �  �    �    � ��Ľ �  � ��Ľ    �
-����������������������������������������������������������������Ĵn���nh����������
-nhg��������������nh��nhySynchronet Wildclone�nh�ng���nhg����������
-nhy��������������nh����������������������������������������������������n���nhy����������
-nhc������������������nc���������������������������������������������������nhc����������
-nhb���nh������������������Ŀnhb�nh�������������Ŀnhb�nh�������������Ŀnhb�nh������������������Ŀnb���
-nh��ܳ nhyM nhessage Menu    �ܳ nhyE nhmail��ܳ nhyU nhser List  �ܳ nhyA nhuto-message    �n���
-nhg���nh� nhyC nhomments��nhg�nh� nhyN nhewsletter �nhg�nh� nhyF nhiles Menu �nhg�nh� nhyT nhalk to Nodes   �ng���
-nhy���nh� nhyJ nhoin Conference �nhy�nh� nhyG nhoodbye    �nhy�nh� nhyP nhage Sysop �nhy�nh� nhyI nhnitial Welcome �n���
-   nh� nhyY nhour Settings   � � nhyW nhhos Online� � nhyV nherify User� � nhyR nhead Your Stats �
-   � nhyS nhystem Stats    � � nhyB nhulletins  � � nhyD nhoors�� � nhyH nhelp Level��
-   �������������������� ��������������� ��������������� ��������������������
-� (nhy1 nhSysop Menu )
-  nhyConference: nh@CONF@   nhyTime On: nh@TIMEON@  nhyTime Remaining: nh@LEFT@
-n
\ No newline at end of file
diff --git a/text/menu/wildcat/msg.asc b/text/menu/wildcat/msg.asc
deleted file mode 100644
index 4405ba83e05520dfedae449c98737afb5bf2ff85..0000000000000000000000000000000000000000
--- a/text/menu/wildcat/msg.asc
+++ /dev/null
@@ -1,18 +0,0 @@
-0
-nh�nh��������������������������������������������������������������Ŀ
-�� �ķ�ķ��ķ�ķ��
-�� � �� � ��ķ ��ķ ��ķ ��ķ ��ķ ��ķ   � �� � ��ķ ��ķ �  � �
-�� � ӽ � ���  ��ķ ��ķ ��Ķ � ķ ���    � ӽ � ���  �  � �  � �
-�� �    � ��Ľ ��Ľ ��Ľ �  � ��Ľ ��Ľ   �    � ��Ľ �  � ��Ľ �
-����������������������������������������������������������������������Ĵn���nh����
-nhg��������nh��nhySynchronet Wildclone�nh�ng���nhg����
-nhy��������nh����������������������������������������������������������������n���nhy����
-nhc������������nc���������������������������������������������������������������nhc����
-nhb���nh��������������������Ŀnhb�nh�������������������������Ŀnhb�nh��������������������Ŀnb���
-nh��ܳ nhyR nhead Messages��ܳ nhyE nhnter a New Message    �ܳ nhyF nhiles Section��n���
-nhg���nh� nhyS nhearch Messages   �nhg�nh� nhyQ nhuit to Main Menu��nhg�nh� nhyG nhoodbye & Logoff  �ng���
-nhy���nh� nhyC nhheck Personal Msg�nhy�nh� nhyU nhpdate Conf Scan/Read  �nhy�nh� nhyH nhelp Level��n���
-   nh� nhyJ nhoin a Conference � � nhyT nhQWK Message Menu�� � nhy? nhCommand Help��
-   ���������������������� ��������������������������� ����������������������
-                                (nhy1 nhSysop Menu  )
-  nhyConference: nh@CONF@   nhyTime On: nh@TIMEON@  nhyTime Remaining: nh@LEFT@n
diff --git a/text/menu/wildcat/sysop.asc b/text/menu/wildcat/sysop.asc
deleted file mode 100644
index ce3537ade8f8ae11f9392c9fbaba4d19bba25cec..0000000000000000000000000000000000000000
--- a/text/menu/wildcat/sysop.asc
+++ /dev/null
@@ -1,16 +0,0 @@
-�nh����������������������������������������������������Ŀ
-��  ���ķ��ķ�ķ��
-��  ���ķ �  � ��ķ ��ķ ��ķ  � �� � ��ķ ��ķ �  �  �
-���� ��Ľ ��ķ �  � ��Ľ  � ӽ � ���  �  � �  �  �
-��  ���Ľ  �   ��Ľ ��Ľ ���    � ��Ľ �  � ��Ľ  �
-�����������������������������������������������������������������Ĵn���nh���������
-nhg�������������nh��nhySynchronet Wildclone�nh�ng���nhg���������
-nhy�������������nh������������������������������������������������������n���nhy���������
-nhc�����������������nc���������nh�������������������������Ŀnc�����������������nhc���������
-nhb���nh��������������������Ŀnhb�nh� nhyJ nhoin Conference��nhb�nh��������������������Ŀnb���
-nh��ܳ nhyU nhser Database��ܳ nhyQ nhuit to Main Menu��ܳ nhy? nhCommand Help��n���
-nhg���nh� nhyN nhode Management   �nhg�nh� nhyA nhctivity Log Listing   �nhg�nh� nhy1 nhMessage Menu��ng���
-nhy���nh� nhyD nhrop to DOS��nhy�nh� nhy2 nhFile Menu��nhy�nh� nhyG nhoodbye & Logoff  �n���
-   nh���������������������� ��������������������������� ����������������������
-  nhyConference: nh@CONF@   nhyTime On: nh@TIMEON@  nhyTime Remaining: nh@LEFT@
-n
\ No newline at end of file
diff --git a/text/menu/wipfile.wip b/text/menu/wipfile.wip
deleted file mode 100644
index 76ad5bc648e13a5dde42241040a041b1558cbe3f..0000000000000000000000000000000000000000
--- a/text/menu/wipfile.wip
+++ /dev/null
@@ -1,27 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=File Transfers
-!|L=2055
-!|T=360
-!|W=5175
-!|H=4725
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`d`10`10`100`60`1`Read/Write E-mail Messages`0`12632256`MS Sans Serif`8.25`Download`SAVE.ICO
-!|002=0B`l`120`10`100`60`2``0`12632256`MS Sans Serif`8.25`List Files`LIST.ICO
-!|003=0B`u`230`10`100`60`3``0`12632256`MS Sans Serif`8.25`Upload`ADD.ICO
-!|004=0B`b`10`80`100`60`4``0`12632256`MS Sans Serif`8.25`Batch Queue`DOWNLOAD.ICO
-!|005=0B`n`120`80`100`60`5``0`12632256`MS Sans Serif`8.25`New Files`DONE.ICO
-!|006=0B`c`230`80`100`60`6``0`12632256`MS Sans Serif`8.25`Setup`DETAIL.ICO
-!|007=0B`v`10`150`100`60`7``0`12632256`MS Sans Serif`8.25`View File`PCAL.ICO
-!|008=0B`s`120`150`100`60`8``0`12632256`MS Sans Serif`8.25`Find Filename`FIND.ICO
-!|009=0B`e`230`150`100`60`9``0`12632256`MS Sans Serif`8.25`File Info`NOTEPAD.ICO
-!|010=0B`r`10`220`100`60`10``0`12632256`MS Sans Serif`8.25`Remove File`CANCEL.ICO
-!|011=0B`f`120`220`100`60`11``0`12632256`MS Sans Serif`8.25`Find Text`SEARCH.ICO
-!|012=0B`q`230`220`100`60`12``0`12632256`MS Sans Serif`8.25`Quit`EXIT.ICO
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/wipmain.wip b/text/menu/wipmain.wip
deleted file mode 100644
index 07f2b70992206efd8fba13047c3d27f328f630ab..0000000000000000000000000000000000000000
--- a/text/menu/wipmain.wip
+++ /dev/null
@@ -1,33 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=15
-!|M=Main Menu
-!|L=570
-!|T=3855
-!|W=8400
-!|H=1650
-!|B=12632256
-!|
-!|[Form]
-!|001=0B`e`10`10`50`50`1`Read/Write E-mail Messages`0`12632256`MS Sans Serif`8.25``EDIT.ICO
-!|002=0B`f`70`10`50`50`2`File Transfers (Upload/Download)`0`12632256`MS Sans Serif`8.25``DOWNLOAD.ICO
-!|003=0B`c`130`10`50`50`3``0`12632256`MS Sans Serif`8.25``ORDER.ICO
-!|004=0B`m`190`10`50`50`4``0`12632256`MS Sans Serif`8.25``NEWS.ICO
-!|005=0B`s`250`10`50`50`5``0`12632256`MS Sans Serif`8.25``MMD.ICO
-!|006=0B`i`310`10`50`50`6``0`12632256`MS Sans Serif`8.25``INFO.ICO
-!|007=0B`x`370`10`50`50`7`Run External Programs (doors)`0`12632256`MS Sans Serif`8.25``WELCOME.ICO
-!|008=0B`d`430`10`50`50`8``0`12632256`MS Sans Serif`8.25``DETAIL.ICO
-!|009=0B`o`490`10`50`50`9``0`12632256`MS Sans Serif`8.25``EXITSGN.ICO
-!|010=0T`email`10`60`50`15`10``0`12632256`MS Sans Serif`8.25`E-mail`1`0
-!|011=0T`files`70`60`50`15`11``0`12632256`MS Sans Serif`8.25`Files`1`0
-!|012=0T`chat`130`60`50`15`11``0`12632256`MS Sans Serif`8.25`Chat`1`0
-!|013=0T`msgs`190`60`50`15`12``0`12632256`MS Sans Serif`8.25`Msgs`1`0
-!|014=0T`match`250`60`50`15`13``0`12632256`MS Sans Serif`8.25`Match`1`0
-!|015=0T`info`310`60`50`15`14``0`12632256`MS Sans Serif`8.25`Info`1`0
-!|016=0T`doors`370`60`50`15`16``0`12632256`MS Sans Serif`8.25`Doors`1`0
-!|017=0T`config`430`60`50`15`17``0`12632256`MS Sans Serif`8.25`Setup`1`0
-!|018=0T`logoff`490`60`50`15`18``0`12632256`MS Sans Serif`8.25`Logoff`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/menu/xfercfg.asc b/text/menu/xfercfg.asc
deleted file mode 100644
index dd85dbbf4cfb03e3f3065d0fa4a694c98639f97f..0000000000000000000000000000000000000000
--- a/text/menu/xfercfg.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-0lnc4��������������������������k�0
-4c� hyFile Scan Configuration nk4�0
-4c�k��������������������������b0������������
-���
-� hyP ngSet new-scan pointer �b�
-��hy0B ngToggle batch file flagging on/off b�
-� hyE ngToggle extended descriptions      b�
-� hyQ ngQuit to File Transfer menu�b�
-���������������������������������������n
diff --git a/text/menu/xfercfg.rip b/text/menu/xfercfg.rip
deleted file mode 100644
index 48a36c55fd2bf609435804978db89adc2e6719a6..0000000000000000000000000000000000000000
--- a/text/menu/xfercfg.rip
+++ /dev/null
@@ -1,10 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Transfer Configuration Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL200000<><>
-!|1B0000020QPE010E000F080300000000000000|Y00000100|1U0M161K1G0000<>B<>B
-!|1U9616A41G0000<>P<>P|1B0000020QPE010E000F080400000000000000
-!|1U0M1K1K1U0000<>Q<>Q|c00|@1Y16Batch Download File Flagging
-!|@AK16New File Scan Pointers|@1Y1KQuit to the Main Menu|w000A271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/xferinfo.asc b/text/menu/xferinfo.asc
deleted file mode 100644
index 8ed16973bb1137a59d68e6f53c42ed914c665ffe..0000000000000000000000000000000000000000
--- a/text/menu/xferinfo.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-0lnc4��������������������������������k�0
-4c� hyFile Section Information Menu nk4�0
-4c�k����������������������������������b0�������������������������������������
-�����
-� hyT ngFile transfer policy�b� hyY ngYour file transfer statistics b�
-��hy0D ngInformation on current directory b�����������������������������������
-� hyU ngUsers with access to current dir b� hyQ ngQuit to File Transfer menu    b�
-������������������������������������������������������������������������n
diff --git a/text/menu/xferinfo.rip b/text/menu/xferinfo.rip
deleted file mode 100644
index 94ad01176a86031dffffb432c0a312bbee201786..0000000000000000000000000000000000000000
--- a/text/menu/xferinfo.rip
+++ /dev/null
@@ -1,11 +0,0 @@
-
-!|1K|w0010271610|W0|=00000001|1B0000020PX4050E000F080700000000000000
-!|1U0707HL0P0000<>Transfer Information Menu<>|c0F|S0107
-!|1B0000020PWW050E000F080700000000000000|1U0710HL2E0000<><>
-!|1B0000020QPE010E000F080900000000000000|Y00000100|1U0M161K1G0000<>T<>T
-!|1U0M1K1K1U0000<>D<>D|1U9616A41G0000<>U<>U|1U961KA41U0000<>Y<>Y
-!|1B0000020QPE010E000F080400000000000000|1U0M1Y1K280000<>Q<>Q|c00
-!|@1Y16Transfer Policy|@1Y1KDirectory|@AK16Users with Access to Directory
-!|@AK1KYour Transfer Statistics|@1Y1YQuit to the Main Menu|w000C271610
-!|10000$ETW$|#|#|#
-
diff --git a/text/menu/yesno.wip b/text/menu/yesno.wip
deleted file mode 100644
index b1c077883c993c2e22cffb8e42597732118d50ed..0000000000000000000000000000000000000000
--- a/text/menu/yesno.wip
+++ /dev/null
@@ -1,20 +0,0 @@
-$00000D
-!|[Startup]
-!|V=1.10
-!|D=`
-!|O=8
-!|M=Yes or No
-!|L=1815
-!|T=510
-!|W=3000
-!|H=2100
-!|B=12632256
-!|
-!|[Form]
-!|001=0T`question`10`10`170`35`5``0`12632256`MS Sans Serif`8.25`@QUESTION@`1`0
-!|002=0B`y`50`50`40`40`1``0`12632256`MS Sans Serif`8.25``DONE.ICO
-!|003=0B`n`100`50`40`40`2``0`12632256`MS Sans Serif`8.25``CANCEL.ICO
-!|004=0T`yes`50`90`40`15`3``0`12632256`MS Sans Serif`8.25`Yes`1`0
-!|005=0T`no`100`90`40`15`4``0`12632256`MS Sans Serif`8.25`No`1`0
-!|
-$0E
\ No newline at end of file
diff --git a/text/name.can b/text/name.can
deleted file mode 100644
index b42d651356fb2e0f90ad222e1ae9eeea4b82c539..0000000000000000000000000000000000000000
--- a/text/name.can
+++ /dev/null
@@ -1,33 +0,0 @@
-new
-all
-sysop~
-netmail
-@~
-#~
-!~
-a
-b
-c
-d
-e
-f
-g
-h
-i
-j
-k
-l
-m
-n
-o
-p
-q
-r
-s
-t
-u
-v
-w
-x
-y
-z
diff --git a/text/newuser.msg b/text/newuser.msg
deleted file mode 100644
index b2466a562aaf60dcd3a12a8ffed1f307ca031f74..0000000000000000000000000000000000000000
--- a/text/newuser.msg
+++ /dev/null
@@ -1,8 +0,0 @@
-ngThe rules of the BBS are normally displayed here, but the sysop has not
-yet defined them. So in the meantime, please use common sense and follow the
-golden rule: "hTreat others as you yourself wish to be treatedng."
-
-Of course technical rules like "hDo not upload commercial softwareng" and
-"hDo not upload virus or trojan horse filesng" also apply, so please ask the
-sysop for details.
-
diff --git a/text/phone.can b/text/phone.can
deleted file mode 100644
index ebdfcaa4d40893ce1a04a733d7fda31655f31b46..0000000000000000000000000000000000000000
--- a/text/phone.can
+++ /dev/null
@@ -1,20 +0,0 @@
-0-^
-1-^
-000-~
-111-~
-123-^
-222-^
-333-^
-444-^
-555-~
-666-^
-777-^
-888-^
-999-^
-900-^
-411-~
-911-~
-976-~
-411^
-911^
-
diff --git a/text/sbbs.msg b/text/sbbs.msg
deleted file mode 100644
index e867b882543d3df3d74da19e92fce6d2ce409a19..0000000000000000000000000000000000000000
--- a/text/sbbs.msg
+++ /dev/null
@@ -1,19 +0,0 @@
-			       nch1 � Synchronet � n
-			    yhMultinode BBS Software
-
-		      bDeveloped 1990-1997 by Rob Swindell
-
-			     ng������������������͸
-			     � hKeys to Rememberng �
-			     ������������������͵
-			     �	whCtrl-C ngAbort    �
-			     �	whCtrl-S ngPause    �
-			     �	whCtrl-Q ngContinue �
-			     �       wh? ngMenu     �
-			     ��������������������
-
-		     hExample Prompt: wOngne, hwTngwo, or [Three]:
-
-			  hIndicates: wO ngOne
-				     whT ngTwo
-				 whEnter ngThree
diff --git a/text/system.msg b/text/system.msg
deleted file mode 100644
index 244aae3ce7a3990c4ef281ad3dcd8400442bcc7e..0000000000000000000000000000000000000000
--- a/text/system.msg
+++ /dev/null
@@ -1,8 +0,0 @@
-ncThis is h@BBS@nc BBS...
-
-	with your sysop, h@SYSOP@nc here to serve you.
-
-This system has received h@TCALLS@nc calls to date. 
-
-Other system information will be available in this space soon.
-
diff --git a/text/zipmsg.txt b/text/zipmsg.txt
deleted file mode 100644
index 44da951b3f498a697e6f6430d54a3b7515ff8f31..0000000000000000000000000000000000000000
--- a/text/zipmsg.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-This file was downloaded from a Synchronet BBS - use PKUNZIP -D <filename>
-
diff --git a/xtrn/sbj/Makefile.gnu b/xtrn/sbj/Makefile.gnu
deleted file mode 100644
index 1dee963d4dec01e795a9cfe4cdeb1001517b47fb..0000000000000000000000000000000000000000
--- a/xtrn/sbj/Makefile.gnu
+++ /dev/null
@@ -1,50 +0,0 @@
-# Makefile.gnu
-
-#########################################################################
-# Makefile for Synchronet Blackjack										#
-# For use with GNU make and GNU C Compiler								#
-# @format.tab-size 4, @format.use-tabs true								#
-#																		#
-# Linux: make -f Makefile.gnu											#
-# Win32: make -f Makefile.gnu os=win32									#
-# FreeBSD: make -f Makefile.gnu os=freebsd								#
-#########################################################################
-
-# $Id$
-
-# Macros
-CC		=	gcc
-LD		=	ld
-
-ifeq ($(os),win32)	# Windows
-
-EXEFILE	=	.exe
-LIBDIR	:=	/gcc/i386-mingw32/lib
-CFLAGS	:=	-mno-cygwin
-LFLAGS  :=	--target=i386-mingw32 -mno-cygwin
-DELETE	=	echo y | del 
-LIBS	=	$(LIBDIR)/libwsock32.a
-
-else	# Linux
-
-EXEFILE	=	
-LIBODIR	:=	gcc.linux.lib
-EXEODIR	:=	gcc.linux.exe
-LIBDIR	:=	/usr/lib
-CFLAGS	:=	
-LFLAGS  :=	
-DELETE	=	rm -f -v
-ifeq ($(os),freebsd)	# FreeBSD
-LIBS	=	-pthread
-else
-LIBS	=	$(LIBDIR)/libpthread.a
-endif	#! FreeBSD
-
-endif
-
-CFLAGS	:=	$(CFLAGS) -I../sdk
-
-SBJ: sbj$(EXEFILE)
-
-sbj$(EXEFILE) : sbj.c ../sdk/xsdk.c ../sdk/xsdkvars.c ../sdk/xsdkwrap.c
-	$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
diff --git a/xtrn/sbj/sbj.bpf b/xtrn/sbj/sbj.bpf
deleted file mode 100644
index d58a17ed049e8bdecb3deca77f67e27f1b2369a4..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.bpf
+++ /dev/null
@@ -1,8 +0,0 @@
-USEUNIT("Sbj.c");
-USEUNIT("..\SDK\Xsdkvars.c");
-USEUNIT("..\SDK\Xsdk.c");
-USEUNIT("..\sdk\xsdkwrap.c");
-//---------------------------------------------------------------------------
-This file is used by the project manager only and should be treated like the project file
-
-
main
\ No newline at end of file
diff --git a/xtrn/sbj/sbj.bpr b/xtrn/sbj/sbj.bpr
deleted file mode 100644
index 71b1ef5126b3fa23bfc20cc38f2222ec8ace3ef4..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.bpr
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version='1.0' encoding='utf-8' ?>
-<!-- C++Builder XML Project -->
-<PROJECT>
-  <MACROS>
-    <VERSION value="BCB.05.03"/>
-    <PROJECT value="sbj.exe"/>
-    <OBJFILES value="Sbj.obj ..\SDK\Xsdkvars.obj ..\SDK\Xsdk.obj ..\sdk\xsdkwrap.obj"/>
-    <RESFILES value=""/>
-    <IDLFILES value=""/>
-    <IDLGENFILES value=""/>
-    <DEFFILE value=""/>
-    <RESDEPEN value="$(RESFILES)"/>
-    <LIBFILES value=""/>
-    <LIBRARIES value=""/>
-    <SPARELIBS value=""/>
-    <PACKAGES value="VCL50.bpi VCLX50.bpi bcbsmp50.bpi VCLDB50.bpi VCLADO50.bpi ibsmp50.bpi 
-      VCLBDE50.bpi VCLDBX50.bpi QRPT50.bpi TEEUI50.bpi TEEDB50.bpi TEE50.bpi 
-      DSS50.bpi TEEQR50.bpi VCLIB50.bpi VCLMID50.bpi VCLIE50.bpi INETDB50.bpi 
-      INET50.bpi NMFAST50.bpi WEBMID50.bpi bcbie50.bpi dclocx50.bpi"/>
-    <PATHCPP value=".;..\SDK"/>
-    <PATHPAS value=".;"/>
-    <PATHRC value=".;"/>
-    <PATHASM value=".;"/>
-    <DEBUGLIBPATH value="$(BCB)\lib\debug"/>
-    <RELEASELIBPATH value="$(BCB)\lib\release"/>
-    <LINKER value="tlink32"/>
-    <USERDEFINES value="_DEBUG"/>
-    <SYSDEFINES value="NO_STRICT;_NO_VCL"/>
-    <MAINSOURCE value="sbj.bpf"/>
-    <INCLUDEPATH value="..\SDK;$(BCB)\include;$(BCB)\include\vcl"/>
-    <LIBPATH value="..\SDK;$(BCB)\lib\obj;$(BCB)\lib"/>
-    <WARNINGS value="-w-par"/>
-  </MACROS>
-  <OPTIONS>
-    <IDLCFLAGS value="-I..\SDK -I$(BCB)\include -I$(BCB)\include\vcl -src_suffix cpp -D_DEBUG -boa"/>
-    <CFLAG1 value="-Od -H=$(BCB)\lib\vcl50.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -tWC 
-      -tWM -c"/>
-    <PFLAGS value="-$YD -$W -$O- -v -JPHNE -M"/>
-    <RFLAGS value=""/>
-    <AFLAGS value="/mx /w2 /zd"/>
-    <LFLAGS value="-D&quot;&quot; -ap -Tpe -x -Gn -v"/>
-  </OPTIONS>
-  <LINKER>
-    <ALLOBJ value="c0x32.obj $(OBJFILES)"/>
-    <ALLRES value="$(RESFILES)"/>
-    <ALLLIB value="$(LIBFILES) $(LIBRARIES) import32.lib cw32mt.lib"/>
-  </LINKER>
-  <IDEOPTIONS>
-[Version Info]
-IncludeVerInfo=0
-AutoIncBuild=0
-MajorVer=1
-MinorVer=0
-Release=0
-Build=0
-Debug=0
-PreRelease=0
-Special=0
-Private=0
-DLL=0
-Locale=1033
-CodePage=1252
-
-[Version Info Keys]
-CompanyName=
-FileDescription=
-FileVersion=1.0.0.0
-InternalName=
-LegalCopyright=
-LegalTrademarks=
-OriginalFilename=
-ProductName=
-ProductVersion=1.0.0.0
-Comments=
-
-[Debugging]
-DebugSourceDirs=$(BCB)\source\vcl
-
-[Parameters]
-RunParams=
-HostApplication=
-RemoteHost=
-RemotePath=
-RemoteDebug=0
-
-[Compiler]
-ShowInfoMsgs=0
-LinkDebugVcl=0
-LinkCGLIB=0
-
-[CORBA]
-AddServerUnit=1
-AddClientUnit=1
-PrecompiledHeaders=1
-  </IDEOPTIONS>
-</PROJECT>
\ No newline at end of file
diff --git a/xtrn/sbj/sbj.c b/xtrn/sbj/sbj.c
deleted file mode 100644
index 36966cac7176dd42b63cade4fc595cb7c5371778..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.c
+++ /dev/null
@@ -1,1907 +0,0 @@
-/* SBJ.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/************************/
-/* Synchronet Blackjack */
-/************************/
-
-/*******************************************************/
-/* Multiuser Blackjack game for Synchronet BBS systems */
-/*******************************************************/
-
-/****************************************************************************/
-/* This source code is completely Public Domain and can be modified and 	*/
-/* distributed freely (as long as changes are documented).					*/
-/* It is meant as an example to programmers of how to use the XSDK			*/
-/****************************************************************************/
-
-/***********/
-/* History */
-/****************************************************************************\
-
-		Many bugs. Especially multiplayer.
-v1.0
-		Many bugs fixed. Timing problems still exist.
-v1.01
-		Fixed yet more bugs. No more timing problems. Appears bullet-proof.
-v1.02
-		Fixed dealer card up always showing card symbol (even when symbols off).
-		Added ctrl-e answer detection and user notification.
-		Fixed three 7's bug.
-		Raised maximum number of decks to 100 for large multinode systems.
-		Fixed /<CR> bug.
-		Fixed multiple split bug.
-		Fixed non-symbols being sent to other nodes bug.
-		Changed this node's hands to say "You" instead of the user name.
-v1.03
-		Changed the warning and timeout times
-v1.04
-		Fixed symbols being displayed on dealer's hand even when disabled.
-		Made different inactivity warning and timeout values for the main
-		menu and when in play.
-v1.05
-		Fixed invalid (usually negative) card bug. THELP random() doc error.
-		Card now actually contains all the cards minus one.
-		Fixed multinode play join and hang bug.
-v1.06
-		If player gets blackjack and dealer gets 21, player wins. Used to push.
-v1.07
-		Fixed split, then double bug.
-v1.08
-		Replaced bioskey(1) calls with inkey() and used XSDK v2.0 with node
-		intercommunication with users on BBS or in other external programs.
-v2.00
-		Fixed problem with loosing first character of chat lines
-		Added DESQview awareness
-v2.01
-		Replaced all calls to delay() with fdelay()
-v2.02
-		Listing users now displays what external program they're running.
-		Fixed problem with max bet being too small when users have over
-		65mb of credit.
-v2.02
-		XSDK (and consequently SBJ) now supports shrinking Synchronet to run
-		(available in v1b r1).
-		SBBSNODE environment variable will be used for the current node's dir
-		if the node dir is not specified on the command line.
-v2.03
-		XSDK and SBJ now support the new message services of Synchronet
-		(added in v1b r2) for more full-proof internode messaging.
-v2.10
-		New XSDK that supports new file retrieval node status display.
-v2.11
-		Changed getnodemsg to eliminate tiny void where messages could fall.
-
-
-\****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#include "xsdk.h"
-
-#define MAX_DECKS	100
-#define MAX_CARDS	10		/* maximum number of cards per hand */
-#define MAX_HANDS	4		/* maximum number of hands per player */
-
-#define DEBUG 0
-
-#define J 11	/* jack */
-#define Q 12	/* queen */
-#define K 13	/* king */
-#define A 14	/* ace */
-
-#define H 0		/* heart */
-#define D 1 	/* diamond */
-#define C 2		/* club */
-#define S 3		/* spade */
-									/* bits used in misc variable */
-#define INPLAY		(1<<0)			/* hand in play */
-
-enum {								/* values for status bytes */
-	 BET							/* betting */
-	,WAIT							/* waiting for turn */
-	,PLAY							/* playing his hand */
-	,SYNC_P 						/* In sync area - player */
-	,SYNC_D 						/* In sync area - dealer */
-	};
-
-typedef struct { char value, suit; } card_t;
-
-card_t newdeck[52]={
-	 2,H, 2,D, 2,C, 2,S,
-	 3,H, 3,D, 3,C, 3,S,
-	 4,H, 4,D, 4,C, 4,S,
-	 5,H, 5,D, 5,C, 5,S,
-	 6,H, 6,D, 6,C, 6,S,
-	 7,H, 7,D, 7,C, 7,S,
-	 8,H, 8,D, 8,C, 8,S,
-	 9,H, 9,D, 9,C, 9,S,
-	10,H,10,D,10,C,10,S,
-	 J,H, J,D, J,C, J,S,
-	 Q,H, Q,D, Q,C, Q,S,
-	 K,H, K,D, K,C, K,S,
-	 A,H, A,D, A,C, A,S };
-
-uchar	misc;
-uchar	curplayer;
-uchar	total_decks,sys_decks;
-uchar	total_nodes;
-int 	cur_card;
-uchar	dc;
-card_t	dealer[MAX_CARDS];
-int 	gamedab;					 /* file handle for data file */
-card_t	card[MAX_DECKS*52];
-card_t	player[MAX_HANDS][MAX_CARDS];
-char	hands,pc[MAX_HANDS];
-uchar	total_players;
-uchar	symbols=1;
-char	autoplay=0;
-int 	logit=0,tutor=0;
-uint	node[MAX_NODES];   /* the usernumber in each node */
-char	status[MAX_NODES];
-ulong	credits;
-uint	bet[MAX_HANDS],ibet,min_bet,max_bet;
-char	tmp[81];
-char	*UserSays="\1n\1m\1h%s \1n\1msays \"\1c\1h%s\1n\1m\"\r\n";
-char	*UserWhispers="\1n\1m\1h%s \1n\1mwhispers \"\1c\1h%s\1n\1m\"\r\n";
-char	*ShoeStatus="\r\n\1_\1w\1hShoe: %u/%u\r\n";
-
-#ifndef SBJCLEAN
-
-void play(void);
-char *cardstr(card_t card);
-char hand(card_t card[MAX_CARDS], char count);
-char soft(card_t card[MAX_CARDS], char count);
-char pair(card_t card[MAX_CARDS], char count);
-void getgamedat(char lockit);
-void putgamedat(void);
-void getcarddat(void);
-void putcarddat(void);
-void shuffle(void);
-void waitturn(void);
-void nextplayer(void);
-char lastplayer(void);
-char firstplayer(void);
-void getnodemsg(void);
-void putnodemsg(char *msg, uint nodenumber);
-void putallnodemsg(char *msg);
-void syncplayer(void);
-void syncdealer(void);
-void moduserdat(void);
-char *hit(void);
-char *stand(void);
-char *doubit(void);
-char *split(void);
-void open_gamedab(void);
-void create_gamedab(void);
-char *activity(char status_type);
-void chat(void);
-void listplayers(void);
-char *joined(void);
-char *left(void);
-void strip_symbols(char *str);
-void debug(void);
-
-int my_random(int n)
-{
-	float f;
-
-	if(n<2)
-		return(0);
-	f=(float)rand()/(float)RAND_MAX;
-
-	return((int)(n*f));
-}
-
-/****************************************************************************/
-/* Entry point																*/
-/****************************************************************************/
-int main(int argc, char **argv)
-{
-	char str[81],compiler[32],*p;
-	int i,file;
-	FILE *stream;
-
-	node_dir[0]=0;
-	for(i=1;i<argc;i++)
-		if(!stricmp(argv[i],"/L"))
-			logit=1;
-		else if(!stricmp(argv[i],"/T"))
-			tutor=2;
-		else if(!stricmp(argv[i],"/S"))
-			tutor=1;
-		else strcpy(node_dir,argv[i]);
-
-	p=getenv("SBBSNODE");
-	if(!node_dir[0] && p)
-		strcpy(node_dir,p);
-
-	if(!node_dir[0]) {	  /* node directory not specified */
-		printf("usage: sbj <node directory> [/options]\r\n");
-		printf("\r\noptions: L = log wins/losses for each day\r\n");
-		getch();
-		return(1); }
-
-	if(node_dir[strlen(node_dir)-1]!='\\'
-		&& node_dir[strlen(node_dir)-1]!='/')  /* make sure node_dir ends in '\' */
-		strcat(node_dir,"/");
-
-	initdata(); 								/* read XTRN.DAT and more */
-	credits=user_cdt;
-	total_nodes=sys_nodes;
-
-	remove("debug.log");
-
-	if((file=nopen("sbj.cfg",O_RDONLY))==-1) {  /* open config file */
-		bputs("Error opening sbj.cfg\r\n");
-		pause();
-		return(1); }
-	if((stream=fdopen(file,"rb"))==NULL) {      /* convert to stream */
-		bputs("Error converting sbj.cfg handle to stream\r\n");
-		pause();
-		return(1); }
-	fgets(str,81,stream);						/* number of decks in shoe */
-	total_decks=sys_decks=atoi(str);
-	fgets(str,81,stream);						/* min bet (in k) */
-	min_bet=atoi(str);
-	fgets(str,81,stream);						/* max bet (in k) */
-	max_bet=atoi(str);
-	fgets(str,81,stream);						/* default bet (in k) */
-	ibet=atoi(str);
-	fclose(stream);
-	if(!total_decks || total_decks>MAX_DECKS) {
-		bputs("Invalid number of decks in sbj.cfg\r\n");
-		pause();
-		return(1); }
-	if(!max_bet) {
-		bputs("Invalid max bet in sbj.cfg\r\n");
-		pause();
-		return(1); }
-	if(min_bet>max_bet) {
-		bputs("Invalid min bet in sbj.cfg\r\n");
-		pause();
-		return(1); }
-	if(ibet>max_bet || ibet<min_bet) {
-		bputs("Invalid default bet in sbj.cfg\r\n");
-		pause();
-		return(1); }
-
-	if(!fexist("card.dab")) {
-		cur_card=0;
-		dc=0;
-		memset(dealer,0,sizeof(dealer));
-		memset(card,0,sizeof(card));
-		putcarddat(); }
-	else {
-		getcarddat();
-		if(total_decks!=sys_decks) {
-			remove("card.dab");
-			total_decks=sys_decks;
-			putcarddat(); } }
-
-	if(!fexist("game.dab"))         /* File's not there */
-		create_gamedab();
-
-	open_gamedab();
-
-	getgamedat(0);
-	if(total_nodes!=sys_nodes) {  /* total nodes changed */
-		close(gamedab);
-		total_nodes=sys_nodes;
-		create_gamedab();
-		open_gamedab(); }
-
-	srand((unsigned)time(NULL));
-
-#ifdef __16BIT__
-	while(_bios_keybrd(1))	 /* clear input buffer */
-		_bios_keybrd(0);
-#endif
-
-	putchar(5); /* ctrl-e */
-	mswait(500);
-	if(kbhit()) {
-#ifdef __16BIT__
-		while(_bios_keybrd(1))
-			_bios_keybrd(0);
-#else
-		getkey(0);
-#endif
-		bputs("\r\n\1r\1h\1i*** ATTENTION ***\1n\1h\r\n");
-		bputs("\r\nSynchronet Blackjack uses Ctrl-E (ENQ) for the 'club' card "
-			"symbol.");
-		bputs("\r\nYour terminal responded to this control character with an "
-			"answerback string.");
-		bputs("\r\nYou will need to disable all Ctrl-E (ENQ) answerback "
-			"strings (Including \r\nCompuserve Quick B transfers) if you wish to "
-			"toggle card symbols on.\r\n\r\n");
-		symbols=0;
-		pause(); }
-
-	getgamedat(1);
-	node[node_num-1]=0;
-	putgamedat();
-
-	/* Override default mnemonic colors */
-	mnehigh=RED|HIGH;
-	mnelow=CYAN|HIGH;
-
-	/* Override default inactivity timeout values */
-	sec_warn=120;	
-	sec_timeout=180;
-
-	COMPILER_DESC(compiler);
-
-#define SBJ_INDENT "                                "
-	while(1) {
-		cls();
-		sprintf(str,"\1n\1h\1cSynchronet \1rBlackjack! \1cv3.11 for %s\r\n"
-			,PLATFORM_DESC);
-		center(str);
-		sprintf(str,"\1w(XSDK v%s %s %s)\r\n\r\n"
-            ,xsdk_ver,compiler,__DATE__);
-		center(str);
-
-		aborted=0;
-		mnemonics(SBJ_INDENT"~Instructions\r\n");
-		mnemonics(SBJ_INDENT"~Join/Begin Game\r\n");
-		mnemonics(SBJ_INDENT"~List Players\r\n");
-		mnemonics(SBJ_INDENT"~Rules of the Game\r\n");
-		mnemonics(SBJ_INDENT"~Toggle Card Symbols\r\n");
-		sprintf(str,SBJ_INDENT"~Quit to %s\r\n",sys_name);
-		mnemonics(str);
-		nodesync();
-		bprintf("\1_\r\n"SBJ_INDENT"\1y\1hWhich: \1n");
-		switch(getkeys("IJBLRTQ|!",0)) {
-			#if DEBUG
-			case '!':
-				if(!com_port)
-					autoplay=1;
-				break;
-			case '|':
-				debug();
-				break;
-			#endif
-			case 'I':
-				cls();
-				printfile("sbj.msg");
-				break;
-			case 'L':
-				listplayers();
-				bprintf(ShoeStatus,cur_card,total_decks*52);
-				break;
-			case 'R':
-				bprintf("\1n\1c\r\nMinimum bet: \1h%uk",min_bet);
-				bprintf("\1n\1c\r\nMaximum bet: \1h%uk\r\n",max_bet);
-				bprintf("\1w\1h\r\nCard decks in shoe: \1h%u\r\n",sys_decks);
-				break;
-			case 'T':
-				symbols=!symbols;
-				bprintf("\1_\1w\r\nCard symbols now: %s\r\n",symbols ? "ON":"OFF");
-				break;
-			case 'Q':
-				exit(0);
-			case 'J':
-			case 'B':
-				sec_warn=60;	/* Override default inactivity timeout values */
-				sec_timeout=90;
-				play();
-				sec_warn=120;
-				sec_timeout=180;
-				break; 
-		} 
-	}
-}
-
-#if DEBUG
-void debug()
-{
-	int i;
-
-if(user_level<90)
-	return;
-getgamedat(0);
-getcarddat();
-
-bprintf("\r\nDeck (%d) Current: %d\r\n\r\n",total_decks,cur_card);
-for(i=0;i<total_decks*52;i++) {
-	if(!(i%11))
-		bputs("\r\n");
-	bprintf("%3d:%-11s",i,cardstr(card[i])); }
-
-pause();
-bprintf("\1n\r\nDealer (%d)\r\n\r\n",dc);
-for(i=0;i<dc;i++)
-	bprintf("%s ",cardstr(dealer[i]));
-bprintf("\1n\r\nNodes (%d) Current: %d\r\n\r\n"
-	,total_nodes,curplayer);
-for(i=0;i<total_nodes;i++)
-	bprintf("%d: node=%d status=%d %s\r\n",i+1,node[i]
-		,status[i],activity(status[i]));
-}
-
-void debugline(char *line)
-{
-	char str[256];
-	int file;
-	time_t now;
-	struct dosdate_t date;
-	struct dostime_t curtime;
-
-#if 1
-now=time(NULL);
-unixtodos(now,&date,&curtime);
-if((file=nopen("debug.log",O_WRONLY|O_APPEND|O_CREAT))==-1)
-	return;
-sprintf(str,"%d %02u:%02u:%02u %s\r\n"
-	,node_num,curtime.ti_hour,curtime.ti_min,curtime.ti_sec,line);
-write(file,str,strlen(str));
-close(file);
-#endif
-}
-
-#endif
-
-void suggest(char action)
-{
-bputs("Dealer suggests you ");
-switch(action) {
-	case 'H':
-		bputs("hit");
-		break;
-	case 'S':
-		bputs("stand");
-		break;
-	case 'D':
-		bputs("double");
-		break;
-	case 'P':
-		bputs("split");
-		break; }
-bputs("\r\n");
-}
-
-void wrong(char action)
-{
-#ifdef __16BIT__
-sound(100);
-mswait(500);
-nosound();
-#endif
-bputs("Dealer says you should have ");
-switch(action) {
-	case 'H':
-		bputs("hit");
-		break;
-	case 'S':
-		bputs("stood");
-		break;
-	case 'D':
-		bputs("doubled");
-		break;
-	case 'P':
-		bputs("split");
-		break; }
-bputs("\r\n");
-}
-
-/****************************************************************************/
-/* This function is the actual game playing loop.							*/
-/****************************************************************************/
-void play()
-{
-	char str[256],str2[256],log[81],done,doub,dh,split_card,suggestion
-		,*YouWereDealt="\1n\1k\0015 You \1n\1m were dealt: %s\r\n"
-		,*UserWasDealt="\1n\1m\1h%s\1n\1m was dealt: %s\r\n"
-		,*YourHand="\1n\1k\0015 You \1n\1m                     (%2d) %s"
-		,*UserHand="\1n\1m\1h%-25s \1n\1m(%2d) %s"
-		,*DealerHand="\1n\1hDealer                    \1n\1m(%2d) "
-		,*Bust="\1n\1r\1hBust\1n\r\n"
-		,*Natural="\1g\1h\1iNatural "
-		,*Three7s="\1r\1h\1iThree 7's "
-		,*Blackjack="\1n\0011\1k Blackjack! \1n\r\n"
-		,*TwentyOne="\1n\0012\1k Twenty-one \1n\r\n";
-	int h,i,j,file;
-	uint max;
-	long val;
-	time_t start,now;
-	struct tm* tm;
-
-sprintf(str,"MESSAGE.%d",node_num);         /* remove message if waiting */
-if(fexist(str))
-    remove(str);
-
-getgamedat(0);
-if(node[node_num-1]) {
-	getgamedat(1);
-	node[node_num-1]=0;
-	putgamedat();
-	getgamedat(0); }
-
-if(total_players && misc&INPLAY) {
-	bputs("\r\n\1hWaiting for end of hand (^A to abort)...\1n");
-	start=now=time(NULL);
-	getgamedat(0);
-	while(total_players && misc&INPLAY) {
-		if((i=inkey(0))!=0) {	 /* if key was hit */
-			if(i==1) {		 /* if ctrl-a */
-				bputs("\r\n");
-				return; } }  /* return */
-		mswait(100);
-		getgamedat(0);
-		now=time(NULL);
-		if(now-start>300) { /* only wait up to 5 minutes */
-			bputs("\r\ntimeout\r\n");
-			return; } }
-	bputs("\r\n"); }
-
-getgamedat(1);
-node[node_num-1]=user_number;
-putgamedat();
-
-if(!total_players)
-    shuffle();
-else
-	listplayers();
-
-sprintf(str,"\1n\1m\1h%s \1n\1m%s\r\n",user_name,joined());
-putallnodemsg(str);
-
-while(1) {
-	aborted=0;
-	#if DEBUG
-	debugline("top of loop");
-	#endif
-	if(autoplay)
-		lncntr=0;
-	bprintf(ShoeStatus,cur_card,total_decks*52);
-	if(cur_card>(total_decks*52)-(total_players*10)-10 && lastplayer())
-		shuffle();
-	getgamedat(1);
-	misc&=~INPLAY;
-	status[node_num-1]=BET;
-	node[node_num-1]=user_number;
-	putgamedat();
-
-	bprintf("\r\n\1n\1cYou have \1h%s\1n\1ck credits\r\n"
-		,ultoac(credits/1024L,str));
-	if(credits<min_bet/1024) {
-		bprintf("\1n\1cMinimum bet: \1h%uk\r\n",min_bet);
-		bputs("\1n\1r\1hCome back when you have more credits.\r\n");
-        break; }
-	if(credits/1024L>(ulong)max_bet)
-		max=max_bet;
-	else
-		max=credits/1024L;
-	sprintf(str,"\r\nBet amount (in kilobytes) or ~Quit [%u]: "
-		,ibet<credits/1024L ? ibet : credits/1024L);
-	chat();
-	mnemonics(str);
-	if(autoplay && kbhit())
-		autoplay=0;
-	if(autoplay)
-		i=ibet;
-	else
-		i=getnum(max);
-	if(i==-1)	/* if user hit ^C or 'Q' */
-		break;
-	bputs("\r\n");
-	if(i)		/* if user entered a value */
-		bet[0]=i;
-	else		/* if user hit enter */
-		bet[0]=ibet<credits/1024L ? ibet : credits/1024L;
-	if(bet[0]<min_bet) {
-		bprintf("\1n\1cMinimum bet: \1h%uk\r\n",min_bet);
-		bputs("\1n\1r\1hCome back when you're ready to bet more.\r\n");
-		break; }
-	ibet=bet[0];
-	getgamedat(0);	/* to get all new arrivals */
-	sprintf(str,"\1m\1h%s\1n\1m bet \1n\1h%u\1n\1mk\r\n",user_name,bet[0]);
-	putallnodemsg(str);
-
-	pc[0]=2;						/* init player's 1st hand to 2 cards */
-	for(i=1;i<MAX_HANDS;i++)		/* init player's other hands to 0 cards */
-		pc[i]=0;
-	hands=1;						/* init total player's hands to 1 */
-
-	getgamedat(1);					/* first come first serve to be the */
-	for(i=0;i<total_nodes;i++)		/* dealer in control of sync */
-		if(node[i] && status[i]==SYNC_D)
-			break;
-	if(i==total_nodes) {
-		#if DEBUG
-		debugline("syncdealer");
-		#endif
-		syncdealer();  }			/* all players meet here */
-	else {							/* first player is current after here */
-		#if DEBUG
-		debugline("syncplayer");
-		#endif
-		syncplayer(); } 			/* game is closed (INPLAY) at this point */
-
-	#if DEBUG
-	debugline("waitturn 1");
-	#endif
-    waitturn();
-	getnodemsg();
-										/* Initial deal card #1 */
-	getcarddat();
-	player[0][0]=card[cur_card++];
-	putcarddat();
-	sprintf(str,YouWereDealt,cardstr(card[cur_card-1]));
-	if(!symbols)
-		strip_symbols(str);
-    bputs(str);
-	sprintf(str,UserWasDealt,user_name,cardstr(card[cur_card-1]));
-    putallnodemsg(str);
-	
-	if(lastplayer()) {
-		getcarddat();
-		dealer[0]=card[cur_card++];
-		dc=1;
-		putcarddat(); }
-	nextplayer();
-	#if DEBUG
-	debugline("waitturn 2");
-	#endif
-	waitturn();
-	getnodemsg();
-
-	getcarddat();					   /* Initial deal card #2 */
-	player[0][1]=card[cur_card++];
-	putcarddat();
-	sprintf(str,YouWereDealt,cardstr(card[cur_card-1]));
-	if(!symbols)
-		strip_symbols(str);
-	bputs(str);
-	sprintf(str,UserWasDealt,user_name,cardstr(card[cur_card-1]));
-    putallnodemsg(str);
-	
-	if(lastplayer()) {
-		getcarddat();
-		dealer[1]=card[cur_card++];
-		dc=2;
-		putcarddat(); }
-	nextplayer();
-	#if DEBUG
-	debugline("waitturn 3");
-	#endif
-	waitturn();
-	getnodemsg();
-	getcarddat();
-
-	for(i=0;i<hands;i++) {
-		if(autoplay)
-			lncntr=0;
-		done=doub=0;
-		while(!done && pc[i]<MAX_CARDS && cur_card<total_decks*52) {
-			h=hand(player[i],pc[i]);
-			str[0]=0;
-			for(j=0;j<pc[i];j++) {
-				strcat(str,cardstr(player[i][j]));
-				strcat(str," "); }
-			j=bstrlen(str);
-			while(j++<19)
-				strcat(str," ");
-			if(h>21) {
-				strcat(str,Bust);
-				sprintf(str2,YourHand,h,str);
-				if(!symbols)
-					strip_symbols(str2);
-				bputs(str2);
-				sprintf(str2,UserHand,user_name,h,str);
-				putallnodemsg(str2);
-				break; }
-			if(h==21) {
-				if(pc[i]==2) {	/* blackjack */
-					if(player[i][0].suit==player[i][1].suit)
-						strcat(str,Natural);
-					strcat(str,Blackjack); }
-				else {
-					if(player[i][0].value==7
-						&& player[i][1].value==7
-						&& player[i][2].value==7)
-						strcat(str,Three7s);
-					strcat(str,TwentyOne); }
-				sprintf(str2,YourHand,h,str);
-				if(!symbols)
-					strip_symbols(str2);
-				bputs(str2);
-				sprintf(str2,UserHand,user_name,h,str);
-                putallnodemsg(str2);
-				// fdelay(500);
-				break; }
-			strcat(str,"\r\n");
-			sprintf(str2,YourHand,h,str);
-			if(!symbols)
-				strip_symbols(str2);
-			bputs(str2);
-			sprintf(str2,UserHand,user_name,h,str);
-			putallnodemsg(str2);
-			if(doub)
-				break;
-			sprintf(str,"\1n\1hDealer\1n\1m card up: %s\r\n"
-				,cardstr(dealer[1]));
-			if(!symbols)
-				strip_symbols(str);
-			bputs(str);
-
-			if(tutor) {
-				if(pc[i]==2)
-					split_card=pair(player[i],pc[i]);
-				else
-					split_card=0;
-                if(split_card==A
-					|| (split_card==9 && (dealer[1].value<7
-						|| (dealer[1].value>7 && dealer[1].value<10)))
-                    || split_card==8
-					|| (split_card==7 && dealer[1].value<9)
-					|| (split_card==6 && dealer[1].value<7)
-					|| (split_card==4 && dealer[1].value==5)
-					|| (split_card && split_card<4 && dealer[1].value<8))
-					suggestion='P';
-                else if(soft(player[i],pc[i])) {
-                    if(h>18)
-						suggestion='S';
-					else if(pc[i]==2
-						&& ((h==18
-							&& dealer[1].value>3 && dealer[1].value<7)
-                        || (h==17
-							&& dealer[1].value>2 && dealer[1].value<7)
-                        || (h>13
-							&& dealer[1].value>3 && dealer[1].value<7)
-                        || (h==12
-							&& dealer[1].value>4 && dealer[1].value<7)))
-						suggestion='D';
-                    else
-						suggestion='H'; }
-                else { /* hard */
-					if(h>16 || (h>13 && dealer[1].value<7)
-						|| (h==12 && dealer[1].value>3 && dealer[1].value<7))
-						suggestion='S';
-					else if(pc[i]==2
-						&& (h==11 || (h==10 && dealer[1].value<10)
-						|| (h==9 && dealer[1].value<7)))
-						suggestion='D';
-                    else
-						suggestion='H'; } }
-
-			if(tutor==1)
-				suggest(suggestion);
-			strcpy(str,"\r\n~Hit");
-			strcpy(tmp,"H\r");
-			if(bet[i]+ibet<=credits/1024L && pc[i]==2) {
-				strcat(str,", ~Double");
-				strcat(tmp,"D"); }
-			if(bet[i]+ibet<=credits/1024L && pc[i]==2 && hands<MAX_HANDS
-				&& player[i][0].value==player[i][1].value) {
-				strcat(str,", ~Split");
-				strcat(tmp,"S"); }
-			strcat(str,", or [Stand]: ");
-			chat();
-			mnemonics(str);
-			if(autoplay && kbhit())
-				autoplay=0;
-
-
-			if(autoplay) {
-				lncntr=0;
-				bputs("\r\n");
-				strcpy(str,stand());
-				bputs(str);
-				putallnodemsg(str);
-				done=1; }
-			else
-			switch(getkeys(tmp,0)) {
-				case 'H':     /* hit */
-					if(tutor==2 && suggestion!='H')
-						wrong(suggestion);
-					strcpy(str,hit());
-					bputs(str);
-					putallnodemsg(str);
-					getcarddat();
-					player[i][pc[i]++]=card[cur_card++];
-					putcarddat();
-					break;
-				case 'D':   /* double down */
-					if(tutor==2 && suggestion!='D')
-                        wrong(suggestion);
-					strcpy(str,doubit());
-					bputs(str);
-					putallnodemsg(str);
-					getcarddat();
-					player[i][pc[i]++]=card[cur_card++];
-					putcarddat();
-					doub=1;
-					bet[i]+=ibet;
-					break;
-				case 'S':   /* split */
-					if(tutor==2 && suggestion!='P')
-                        wrong(suggestion);
-					strcpy(str,split());
-					bputs(str);
-					putallnodemsg(str);
-					player[hands][0]=player[i][1];
-					getcarddat();
-					player[i][1]=card[cur_card++];
-					player[hands][1]=card[cur_card++];
-					putcarddat();
-					pc[hands]=2;
-					bet[hands]=ibet;
-					hands++;
-					break;
-				case CR:
-					if(tutor==2 && suggestion!='S')
-                        wrong(suggestion);
-					strcpy(str,stand());
-					bputs(str);
-					putallnodemsg(str);
-					done=1;
-					break; } } }
-
-	if(lastplayer()) {	/* last player plays the dealer's hand */
-		getcarddat();
-		while(hand(dealer,dc)<17 && dc<MAX_CARDS && cur_card<total_decks*52)
-			dealer[dc++]=card[cur_card++];
-		putcarddat(); }
-
-	nextplayer();
-	#if DEBUG
-	debugline("waitturn 4");
-	#endif
-	waitturn();
-	getnodemsg();
-
-	if(firstplayer()==node_num) {
-		strcpy(str,"\1n\0014\1h Final \1n\r\n");
-		bputs(str);
-		putallnodemsg(str); }
-	getcarddat();
-	dh=hand(dealer,dc); 					/* display dealer's hand */
-	sprintf(str,DealerHand,dh);
-	for(i=0;i<dc;i++) {
-		strcat(str,cardstr(dealer[i]));
-		strcat(str," "); }
-	i=bstrlen(str);
-	while(i++<50)				/* was 50 */
-		strcat(str," ");
-	if(dh>21) {
-		strcat(str,Bust);
-		if(!symbols)
-			strip_symbols(str);
-		bputs(str); }
-	else if(dh==21) {
-		if(dc==2) { 	/* blackjack */
-			if(dealer[0].suit==dealer[1].suit)
-				strcat(str,Natural);
-			strcat(str,Blackjack); }
-		else {			/* twenty-one */
-			if(dc==3 && dealer[0].value==7 && dealer[1].value==7
-				&& dealer[2].value==7)
-				strcat(str,Three7s);
-			strcat(str,TwentyOne); }
-		if(!symbols)
-            strip_symbols(str);
-		bputs(str); }
-	else {
-		if(!symbols)
-            strip_symbols(str);
-		bprintf("%s\r\n",str); }
-
-	for(i=0;i<hands;i++) {						/* display player's hand(s) */
-		h=hand(player[i],pc[i]);
-		str[0]=0;
-		for(j=0;j<pc[i];j++) {
-			strcat(str,cardstr(player[i][j]));
-			strcat(str," "); }
-		j=bstrlen(str);
-		while(j++<19)
-			strcat(str," ");
-		if(logit) {
-			now=time(NULL);
-			tm=localtime(&now);
-			sprintf(log,"%02d%02d%02d.log"                  /* log winnings */
-				,tm->tm_mon+1,tm->tm_mday,tm->tm_year%100);
-			if((file=nopen(log,O_RDONLY))!=-1) {
-				read(file,tmp,filelength(file));
-				tmp[filelength(file)]=0;
-				val=atol(tmp);
-				close(file); }
-			else
-				val=0L;
-			if((file=nopen(log,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-				bprintf("error opening %s\r\n",log);
-				return; } }
-		if(h<22 && (h>dh || dh>21	/* player won */
-			|| (h==21 && pc[i]==2 && dh==21 && dh>2))) {	/* blackjack */
-			j=bet[i];								  /* and dealer got 21 */
-			if(h==21 && 	/* natural blackjack or three 7's */
-				((player[i][0].value==7 && player[i][1].value==7
-				&& player[i][2].value==7)
-				|| (pc[i]==2 && player[i][0].suit==player[i][1].suit)))
-				j*=2;
-			else if(h==21 && pc[i]==2)	/* regular blackjack */
-				j*=1.5; /* blackjack pays 1 1/2 to 1 */
-			sprintf(tmp,"\1n\1h\1m\1iWon!\1n\1h %u\1n\1mk",j);
-			strcat(str,tmp);
-			credits+=j*1024L;
-			val-=j*1024L;
-			moduserdat(); }
-		else if(h<22 && h==dh)
-			strcat(str,"\1n\1hPush");
-		else {
-			strcat(str,"\1nLost");
-			credits-=bet[i]*1024L;
-			val+=bet[i]*1024L;
-			moduserdat(); }
-		if(logit) {
-			sprintf(tmp,"%ld",val);
-			write(file,tmp,strlen(tmp));
-			close(file); }					/* close winning log */
-		strcat(str,"\1n\r\n");
-		sprintf(str2,YourHand,h,str);
-		if(!symbols)
-			strip_symbols(str2);
-		bputs(str2);
-		sprintf(str2,UserHand,user_name,h,str);
-		putallnodemsg(str2); }
-
-	nextplayer();
-	if(!lastplayer()) {
-		#if DEBUG
-		debugline("lastplayer waitturn");
-		#endif
-		waitturn();
-		nextplayer(); }
-	#if DEBUG
-	debugline("end of loop");
-	#endif
-	getnodemsg(); }
-
-getgamedat(1);
-node[node_num-1]=0;
-putgamedat();
-sprintf(str,"\1n\1m\1h%s \1n\1m%s\r\n",user_name,left());
-putallnodemsg(str);
-}
-
-/****************************************************************************/
-/* This function returns a static string that describes the status byte 	*/
-/****************************************************************************/
-char *activity(char status_type)
-{
-	static char str[50];
-
-switch(status_type) {
-	case BET:
-		strcpy(str,"betting");
-		break;
-	case WAIT:
-		strcpy(str,"waiting for turn");
-		break;
-	case PLAY:
-		strcpy(str,"playing");
-		break;
-	case SYNC_P:
-		strcpy(str,"synchronizing");
-		break;
-	case SYNC_D:
-		strcpy(str,"synchronizing (dealer)");
-        break;
-	default:
-		strcat(str,"UNKNOWN");
-		break; }
-return(str);
-}
-
-/****************************************************************************/
-/* This function returns the string that represents a playing card. 		*/
-/****************************************************************************/
-char *cardstr(card_t card)
-{
-	static char str[20];
-	char tmp[20];
-
-strcpy(str,"\1n\0017"); /* card color - background always white */
-if(card.suit==H || card.suit==D)
-	strcat(str,"\1r");  /* hearts and diamonds - foreground red */
-else
-	strcat(str,"\1k");  /* spades and clubs - foreground black */
-if(card.value>10)	/* face card */
-	switch(card.value) {
-		case J:
-			strcat(str,"J");
-			break;
-		case Q:
-			strcat(str,"Q");
-			break;
-		case K:
-			strcat(str,"K");
-			break;
-		case A:
-			strcat(str,"A");
-			break; }
-else {
-	sprintf(tmp,"%d",card.value);
-	strcat(str,tmp); }
-switch(card.suit) {  /* suit */
-	case H:
-		strcat(str,"\3");
-		break;
-	case D:
-		strcat(str,"\4");
-		break;
-	case C:
-		strcat(str,"\5");
-		break;
-	case S:
-		strcat(str,"\6");
-		break; }
-strcat(str,"\1n");
-return(str);
-}
-
-
-/****************************************************************************/
-/* This function returns the best value of a given hand.					*/
-/****************************************************************************/
-char hand(card_t card[MAX_CARDS],char count)
-{
-	char c,total=0,ace=0;
-
-for(c=0;c<count;c++) {
-	if(card[c].value==A) {		/* Ace */
-		if(total+11>21)
-			total++;
-		else {
-			ace++;
-			total+=11; } }
-	else if(card[c].value>=J)	/* Jack, Queen, King */
-		total+=10;
-	else						/* Number cards */
-		total+=card[c].value; }
-while(total>21 && ace) { /* ace is low if bust */
-	total-=10;
-	ace--; }
-return(total);
-}
-
-/****************************************************************************/
-/* This function returns number of soft aces in a given hand				*/
-/****************************************************************************/
-char soft(card_t card[MAX_CARDS],char count)
-{
-	char c,total=0,ace=0;
-
-for(c=0;c<count;c++) {
-	if(card[c].value==A) {		/* Ace */
-		if(total+11>21)
-			total++;
-		else {
-			ace++;
-			total+=11; } }
-	else if(card[c].value>=J)	/* Jack, Queen, King */
-		total+=10;
-	else						/* Number cards */
-		total+=card[c].value; }
-while(total>21 && ace) { /* ace is low if bust */
-	total-=10;
-	ace--; }
-return(ace);
-}
-
-/****************************************************************************/
-/* This function returns card that is paired in the hand					*/
-/****************************************************************************/
-char pair(card_t card[MAX_CARDS],char count)
-{
-	char c,d;
-
-for(c=0;c<count;c++)
-	for(d=c+1;d<count;d++)
-		if(card[c].value==card[d].value)	   /* Ace */
-			return(card[c].value);
-return(0);
-}
-
-
-/****************************************************************************/
-/* This function shuffles the deck. 										*/
-/****************************************************************************/
-void shuffle()
-{
-	char str[81];
-	uint i,j;
-	card_t shufdeck[52*MAX_DECKS];
-
-
-getcarddat();
-
-sprintf(str,"\1_\1w\1h\r\nShuffling %d Deck Shoe...",total_decks);
-bputs(str);
-strcat(str,"\r\n");     /* add crlf for other nodes */
-putallnodemsg(str);
-
-for(i=0;i<total_decks;i++)
-	memcpy(shufdeck+(i*52),newdeck,sizeof(newdeck));	  /* fresh decks */
-
-i=0;
-while(i<(uint)(total_decks*52)-1) {
-	j=my_random((total_decks*52)-1);
-	if(!shufdeck[j].value)	/* card already used */
-		continue;
-	card[i]=shufdeck[j];
-	shufdeck[j].value=0;	/* mark card as used */
-	i++; }
-
-cur_card=0;
-for(i=0;i<MAX_HANDS;i++)
-	pc[i]=0;
-hands=0;
-dc=0;
-putcarddat();
-bputs("\r\n");
-}
-
-/****************************************************************************/
-/* This function reads and displays a message waiting for this node, if 	*/
-/* there is one.															*/
-/****************************************************************************/
-void getnodemsg()
-{
-	char str[81], *buf;
-	int file;
-	ulong length;
-
-nodesync();
-sprintf(str,"message.%d",node_num);
-if(flength(str)<1L) 					/* v1.02 fix */
-	return;
-if((file=nopen(str,O_RDWR))==-1) {
-	bprintf("Couldn't open %s\r\n",str);
-	return; }
-length=filelength(file);
-if((buf=malloc(length+1L))==NULL) {
-	close(file);
-	bprintf("\7\r\ngetnodemsg: Error allocating %lu bytes of memory for %\r\n"
-		,length+1L,str);
-	return; }
-buf[read(file,buf,length)]=0;
-chsize(file,0);
-close(file);
-if(!symbols)
-	strip_symbols(buf);
-bputs(buf);
-free(buf);
-}
-
-/****************************************************************************/
-/* This function creates a message for a certain node.						*/
-/****************************************************************************/
-void putnodemsg(char *msg, uint nodenumber)
-{
-	char str[81];
-	int file;
-
-sprintf(str,"message.%d",nodenumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	bprintf("\r\n\7putnodemsg: error opening/creating %s\r\n",str);
-	return; }
-write(file,msg,strlen(msg));
-close(file);
-}
-
-/****************************************************************************/
-/* This function creates a message for all nodes in the game.				*/
-/****************************************************************************/
-void putallnodemsg(char *msg)
-{
-	int i;
-
-for(i=0;i<total_nodes;i++)
-	if(node[i] && i+1!=node_num)
-		putnodemsg(msg,i+1);
-}
-
-/****************************************************************************/
-/* This function waits until it is the current player.						*/
-/****************************************************************************/
-void waitturn()
-{
-	time_t start,now;
-
-start=now=time(NULL);
-getgamedat(1);
-status[node_num-1]=WAIT;
-putgamedat();
-while(curplayer!=node_num) {
-	chat();
-	mswait(100);
-	getgamedat(0);
-	if(curplayer && !node[curplayer-1] /*  || status[curplayer-1]==BET */ )
-		nextplayer();		/* current player is not playing? */
-
-	if(!node[node_num-1]) { /* current node not in game? */
-		getgamedat(1);
-		node[node_num-1]=user_number;	/* fix it */
-		putgamedat(); }
-
-	now=time(NULL);
-	if(now-start>300) { /* only wait upto 5 minutes */
-		bputs("\r\nwaitturn: timeout\r\n");
-		break; } }
-getgamedat(1);
-status[node_num-1]=PLAY;
-putgamedat();
-}
-
-/****************************************************************************/
-/* This is the function that is called to see if the user has hit a key,	*/
-/* and if so, read in a line of chars and send them to the other nodes. 	*/
-/****************************************************************************/
-void chat()
-{
-	char str1[150],str2[256],ch;
-	int i;
-
-aborted=0;
-if((ch=inkey(0))!=0 || wordwrap[0]) {
-	if(ch=='/') {
-		bputs("\1n\1y\1hCommand: \1n");
-		ch=getkeys("?LS|%\r",0);
-		switch(ch) {
-			case CR:
-				return;
-			#if DEBUG
-			case '|':
-				debug();
-				return;
-			#endif
-			case '%':
-				if(!com_port)	/* only if local */
-					exit(0);
-				break;
-			case '?':
-				mnemonics("\r\n~List Players");
-				mnemonics("\r\n~Send Private Message to Player");
-				bputs("\r\n");
-				return;
-			case 'L':
-				listplayers();
-				bprintf(ShoeStatus,cur_card,total_decks*52);
-				return;
-			case 'S':
-				listplayers();
-				bputs("\1n\r\n\1y\1hWhich node: \1n");
-				i=getnum(sys_nodes);
-				getgamedat(0);
-				if(i>0 && i!=node_num && node[i-1]) {
-					bputs("\r\n\1n\1y\1hMessage: ");
-					if(getstr(str1,50,K_LINE)) {
-						sprintf(str2,UserWhispers,user_name
-							,str1);
-						putnodemsg(str2,i); } }
-				else
-					bputs("\1n\r\n\1r\1hInvalid node.\1n\r\n");
-				return; } }
-	ungetkey(ch);
-	if(!getstr(str1,50,K_CHAT|K_WRAP))
-		return;
-	sprintf(str2,UserSays,user_name,str1);
-	putallnodemsg(str2); }
-getnodemsg();
-}
-
-/****************************************************************************/
-/* This function returns 1 if the current node is the highest (or last) 	*/
-/* node in the game, or 0 if there is another node with a higher number 	*/
-/* in the game. Used to determine if this node is to perform the dealer   */
-/* function 															  */
-/****************************************************************************/
-char lastplayer()
-{
-	int i;
-
-getgamedat(0);
-if(total_players==1 && node[node_num-1])	/* if only player, definetly */
-	return(1);								/* the last */
-
-for(i=node_num;i<total_nodes;i++)			  /* look for a higher number */
-	if(node[i])
-		break;
-if(i<total_nodes)							  /* if one found, return 0 */
-	return(0);
-return(1);									/* else return 1 */
-}
-
-/****************************************************************************/
-/* Returns the node number of the lower player in the game					*/
-/****************************************************************************/
-char firstplayer()
-{
-	int i;
-
-for(i=0;i<total_nodes;i++)
-	if(node[i])
-		break;
-if(i==total_nodes)
-	return(0);
-return(i+1);
-}
-
-/****************************************************************************/
-/* This function is only run on the highest node number in the game. It 	*/
-/* waits until all other nodes are waiting in their sync routines, and then */
-/* releases them by changing the status byte from SYNC_P to PLAY			*/
-/* it is assumed that getgamedat(1) is called immediately prior.			*/
-/****************************************************************************/
-void syncdealer()
-{
-	char *Dealing="\1n\1hDealing...\r\n\1n";
-	int i;
-	time_t start,now;
-
-status[node_num-1]=SYNC_D;
-putgamedat();
-start=now=time(NULL);
-// fdelay(1000);				 /* wait for stragglers to join game v1.02 */
-getgamedat(0);
-while(total_players) {
-	for(i=0;i<total_nodes;i++)
-		if(i!=node_num-1 && node[i] && status[i]!=SYNC_P)
-			break;
-	if(i==total_nodes)		  /* all player nodes are waiting */
-		break;
-	chat();
-	mswait(100);
-	getgamedat(0);
-	if(!node[node_num-1]) { /* current node not in game? */
-		getgamedat(1);
-		node[node_num-1]=user_number;	/* fix it */
-		putgamedat(); }
-	now=time(NULL);
-	if(now-start>300) { /* only wait upto 5 minutes */
-		bputs("\r\nsyncdealer: timeout\r\n");
-        break; } }
-
-getgamedat(1);
-misc|=INPLAY;
-curplayer=firstplayer();
-putgamedat();
-
-getnodemsg();
-bputs(Dealing);
-putallnodemsg(Dealing);
-
-getgamedat(1);
-for(i=0;i<total_nodes;i++)		  /* release player nodes */
-	if(node[i])
-		status[i]=PLAY;
-putgamedat();
-}
-
-
-/****************************************************************************/
-/* This function halts this node until the dealer releases it by changing	*/
-/* the status byte from SYNC_P to PLAY										*/
-/* it is assumed that getgamedat(1) is called immediately prior.			*/
-/****************************************************************************/
-void syncplayer()
-{
-	time_t start,now;
-
-status[node_num-1]=SYNC_P;
-putgamedat();
-start=now=time(NULL);
-while(node[node_num-1] && status[node_num-1]==SYNC_P) {
-	chat();
-	mswait(100);
-	getgamedat(0);
-	if(!node[node_num-1]) { /* current node not in game? */
-		getgamedat(1);
-		node[node_num-1]=user_number;	/* fix it */
-		putgamedat(); }
-	now=time(NULL);
-	if(now-start>300) { /* only wait upto 5 minutes */
-		bputs("\r\nsyncplayer: timeout\r\n");
-        break; } }
-}
-
-/****************************************************************************/
-/* Updates the MODUSER.DAT file that SBBS reads to ajust the user's credits */
-/* This function is called whenever the user's credits are adjust so that   */
-/* the file will be current in any event.									*/
-/****************************************************************************/
-void moduserdat()
-{
-	char str[128];
-	FILE *stream;
-
-sprintf(str,"%sMODUSER.DAT",node_dir);
-if((stream=fopen(str,"wt"))==NULL) {
-	bprintf("Error opening %s for write\r\n",str);
-	return; }
-fprintf(stream,"%ld",credits-user_cdt);
-fclose(stream);
-
-}
-
-/****************************************************************************/
-/* This function reads the entire shoe of cards and the dealer's hand from  */
-/* the card database file (CARD.DAB)										*/
-/****************************************************************************/
-void getcarddat()
-{
-	int file;
-
-if((file=nopen("card.dab",O_RDONLY))==-1) {
-	bputs("getcarddat: Error opening card.dab\r\n");
-	return; }
-read(file,&dc,1);
-read(file,dealer,sizeof(dealer));
-read(file,&total_decks,1);
-read(file,&cur_card,2);
-read(file,card,total_decks*52*sizeof(card_t));
-close(file);
-}
-
-/****************************************************************************/
-/* This function writes the entire shoe of cards and the dealer's hand to   */
-/* the card database file (CARD.DAB)										*/
-/****************************************************************************/
-void putcarddat()
-{
-	int file;
-
-if((file=nopen("card.dab",O_WRONLY|O_CREAT))==-1) {
-	bputs("putcarddat: Error opening card.dab\r\n");
-	return; }
-write(file,&dc,1);
-write(file,dealer,sizeof(dealer));
-write(file,&total_decks,1);
-write(file,&cur_card,2);
-write(file,card,total_decks*52*sizeof(card_t));
-close(file);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "hit"                           */
-/****************************************************************************/
-char *hit()
-{
-	static char str[81];
-
-strcpy(str,"\1n\1r\1h");
-switch(rand()%10) {
-	case 1:
-		strcat(str,"Hit it.");
-		break;
-	case 2:
-		strcat(str,"Hit me, Baby!");
-		break;
-	case 3:
-		strcat(str,"Give me an ace.");
-		break;
-	case 4:
-		strcat(str,"One more.");
-		break;
-	case 5:
-		strcat(str,"Just one more.");
-		break;
-	case 6:
-		strcat(str,"Give me a baby card.");
-		break;
-	case 7:
-		strcat(str,"Hit it, Dude.");
-		break;
-	case 8:
-		strcat(str,"Hit.");
-		break;
-	case 9:
-		strcat(str,"Um... Hit.");
-		break;
-	case 10:
-		strcat(str,"Thank you Sir, may I have another.");
-		break;
-	default:
-		strcat(str,"Face card, please.");
-		break; }
-strcat(str,"\1n\r\n");
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "double"                        */
-/****************************************************************************/
-char *doubit()
-{
-	static char str[81];
-
-strcpy(str,"\1n\1b\1h");
-switch(rand()%10) {
-	case 1:
-		strcat(str,"Double.");
-		break;
-	case 2:
-		strcat(str,"Double Down, Man.");
-		break;
-	case 3:
-		strcat(str,"Double it, Dude.");
-		break;
-	case 4:
-		strcat(str,"One more card for double the dough.");
-		break;
-	case 5:
-		strcat(str,"Double me.");
-		break;
-	case 6:
-		strcat(str,"Oh yeah... Double!");
-		break;
-	case 7:
-		strcat(str,"I shouldn't do it, but... Double!");
-		break;
-	case 8:
-		strcat(str,"Double my bet and give me one more card.");
-		break;
-	case 9:
-		strcat(str,"Um... Double.");
-		break;
-	case 10:
-		strcat(str,"Thank you Sir, may I Double?");
-		break;
-	default:
-		strcat(str,"Double - face card, please.");
-		break; }
-strcat(str,"\1n\r\n");
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "stand"                         */
-/****************************************************************************/
-char *stand()
-{
-	static char str[81];
-
-strcpy(str,"\1n\1c\1h");
-switch(rand()%10) {
-	case 1:
-		strcat(str,"Stand.");
-		break;
-	case 2:
-		strcat(str,"Stay.");
-		break;
-	case 3:
-		strcat(str,"No more.");
-		break;
-	case 4:
-		strcat(str,"Just right.");
-		break;
-	case 5:
-		strcat(str,"I should hit, but I'm not gonna.");
-		break;
-	case 6:
-		strcat(str,"Whoa!");
-		break;
-	case 7:
-		strcat(str,"Hold it.");
-		break;
-	case 8:
-		strcat(str,"No way, Jose!");
-		break;
-	case 9:
-		strcat(str,"Um... Stand.");
-		break;
-	case 10:
-		strcat(str,"Thanks, but no thanks.");
-		break;
-	default:
-		strcat(str,"No card, no bust.");
-		break; }
-strcat(str,"\1n\r\n");
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "split"                         */
-/****************************************************************************/
-char *split()
-{
-	static char str[81];
-
-strcpy(str,"\1n\1y\1h");
-switch(rand()%10) {
-	case 1:
-		strcat(str,"Split.");
-		break;
-	case 2:
-		strcat(str,"Split 'em.");
-		break;
-	case 3:
-		strcat(str,"Split it.");
-		break;
-	case 4:
-		strcat(str,"Split, please.");
-		break;
-	case 5:
-		strcat(str,"I should hit, but I'm gonna split instead.");
-		break;
-	case 6:
-		strcat(str,"Whoa! Split them puppies...");
-		break;
-	case 7:
-		strcat(str,"Split 'em, Dude.");
-		break;
-	case 8:
-		strcat(str,"Double the cards, for double the money.");
-		break;
-	case 9:
-		strcat(str,"Um... Split.");
-		break;
-	case 10:
-		strcat(str,"Thank you Sir, I think I'll split 'em.");
-		break;
-	default:
-		strcat(str,"Banana Split.");
-		break; }
-strcat(str,"\1n\r\n");
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "joined"                        */
-/****************************************************************************/
-char *joined()
-{
-	static char str[81];
-
-switch(rand()%10) {
-	case 1:
-		strcpy(str,"joined.");
-		break;
-	case 2:
-		strcpy(str,"sat down to play.");
-		break;
-	case 3:
-		strcpy(str,"plopped on the chair next to you.");
-		break;
-	case 4:
-		strcpy(str,"belched loudly to announce his entrance.");
-		break;
-	case 5:
-		strcpy(str,"dropped in.");
-		break;
-	case 6:
-		strcpy(str,"joined our game.");
-		break;
-	case 7:
-		strcpy(str,"fell on his face entering the casino!");
-		break;
-	case 8:
-		strcpy(str,"slams a roll of credits on the table.");
-		break;
-	case 9:
-		strcpy(str,"rolled in to join the game.");
-		break;
-	case 10:
-		strcpy(str,"smiles widely as he takes your wife's seat.");
-		break;
-	default:
-		strcpy(str,"spills a drink on your pants while sitting down.");
-		break; }
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates random ways to say "left"                          */
-/****************************************************************************/
-char *left()
-{
-	static char str[81];
-
-switch(rand()%10) {
-	case 1:
-		strcpy(str,"left abruptly.");
-		break;
-	case 2:
-		strcpy(str,"sneaked away.");
-		break;
-	case 3:
-		strcpy(str,"took the credits and ran.");
-		break;
-	case 4:
-		strcpy(str,"fell out of the chair.");
-		break;
-	case 5:
-		strcpy(str,"left the game.");
-		break;
-	case 6:
-		strcpy(str,"slipped out the door.");
-		break;
-	case 7:
-		strcpy(str,"giggled as he left the table.");
-		break;
-	case 8:
-		strcpy(str,"left clenching empty pockets.");
-		break;
-	case 9:
-		strcpy(str,"went to the pawn shop to hawk a watch.");
-		break;
-	case 10:
-		strcpy(str,"bailed out the back door.");
-		break;
-	default:
-		strcpy(str,"made like a train and left.");
-		break; }
-return(str);
-}
-
-/****************************************************************************/
-/* This function creates the file "GAME.DAB" in the current directory.      */
-/****************************************************************************/
-void create_gamedab()
-{
-
-if((gamedab=sopen("game.dab"
-	,O_WRONLY|O_CREAT|O_BINARY,SH_DENYNO))==-1) {
-	bputs("Error creating game.dab\r\n");
-	pause();
-	exit(1); }
-misc=0;
-curplayer=0;
-memset(node,0,sizeof(node));
-memset(status,0,sizeof(status));
-write(gamedab,&misc,1);
-write(gamedab,&curplayer,1);
-write(gamedab,&total_nodes,1);
-write(gamedab,node,total_nodes*2);
-write(gamedab,status,total_nodes);
-close(gamedab);
-}
-
-/****************************************************************************/
-/* This function opens the file "GAME.DAB" in the current directory and     */
-/* leaves it open with deny none access. This file uses record locking		*/
-/* for shared access.														*/
-/****************************************************************************/
-void open_gamedab()
-{
-if((gamedab=sopen("game.dab",O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-    bputs("Error opening game.dab\r\n");                /* open deny none */
-    pause();
-	exit(1); }
-}
-
-/****************************************************************************/
-/* Lists the players currently in the game and the status of the shoe.		*/
-/****************************************************************************/
-void listplayers()
-{
-	int i;
-
-getgamedat(0);
-bputs("\r\n");
-if(!total_players) {
-	bputs("\1_\1w\1hNo game in progress\r\n");
-	return; }
-for(i=0;i<total_nodes;i++)
-	if(node[i])
-		bprintf("\1-\1mNode %2d: \1h%s \1n\1m%s\r\n"
-			,i+1,username(node[i]),activity(status[i]));
-getcarddat();
-/***
-bprintf("\r\nCurrent player=Node %d user #%d\r\n",curplayer,node[curplayer-1]);
-***/
-}
-
-/****************************************************************************/
-/* This function replaces the card symbols in 'str' with letters to         */
-/* represent the different suits.											*/
-/****************************************************************************/
-void strip_symbols(char *str)
-{
-	int i,j;
-
-j=strlen(str);
-for(i=0;i<j;i++)
-	if(str[i]>=3 && str[i]<=6)
-		switch(str[i]) {
-			case 3:
-				str[i]='H';
-				break;
-			case 4:
-				str[i]='D';
-				break;
-			case 5:
-				str[i]='C';
-				break;
-			case 6:
-				str[i]='S';
-				break; }
-}
-
-#endif	/* end of function not needed for SBJCLEAN.C */
-
-/****************************************************************************/
-/* Reads information from GAME.DAB file. If 'lockit' is 1, the file is      */
-/* and putgamedat must be called to unlock it. If your updating the info	*/
-/* in GAME.DAB, you must first call getgamedat(1), then putgamedat().		*/
-/****************************************************************************/
-void getgamedat(char lockit)
-{
-    int i=0;
-
-/* retry 100 times taking at least 3 seconds */
-while(lock(gamedab,0L,filelength(gamedab))==-1 && i++<100)
-	mswait(30);  /* lock the whole thing */
-if(i>=100) {
-//	  printf("gamedab=%d %04X:%p %04X\r\n",gamedab,_psp,&gamedab,_DS);
-	printf("\7getgamedat: error locking game.dab\r\n"); }
-
-lseek(gamedab,0L,SEEK_SET);
-read(gamedab,&misc,1);
-read(gamedab,&curplayer,1);
-read(gamedab,&total_nodes,1);
-read(gamedab,node,total_nodes*2);	   /* user number playing for each node */
-read(gamedab,status,total_nodes);	   /* the status of the player */
-total_players=0;
-for(i=0;i<total_nodes;i++)
-    if(node[i])
-        total_players++;
-if(!lockit)
-	unlock(gamedab,0L,filelength(gamedab));
-}
-
-/****************************************************************************/
-/* Writes information to GAME.DAB file. getgamedat(1) MUST be called before  */
-/* this function is called.                                                 */
-/****************************************************************************/
-void putgamedat()
-{
-
-lseek(gamedab,0L,SEEK_SET);
-write(gamedab,&misc,1);
-write(gamedab,&curplayer,1);
-write(gamedab,&total_nodes,1);
-write(gamedab,node,total_nodes*2);
-write(gamedab,status,total_nodes);
-unlock(gamedab,0L,filelength(gamedab));
-}
-
-/***************************************************************/
-/* This function makes the next active node the current player */
-/***************************************************************/
-void nextplayer()
-{
-    int i;
-
-getgamedat(1);                      /* get current info and lock */
-
-if((!curplayer						/* if no current player */
-    || total_players==1)            /* or only one player in game */
-    && node[node_num-1]) {          /* and this node is in the game */
-	curplayer=node_num; 			/* make this node current player */
-    putgamedat();                   /* write data and unlock */
-    return; }                       /* and return */
-
-for(i=curplayer;i<total_nodes;i++)	/* search for the next highest node */
-    if(node[i])                     /* that is active */
-        break;
-if(i>=total_nodes) {				/* if no higher active nodes, */
-	for(i=0;i<curplayer-1;i++)		/* start at bottom and go up  */
-        if(node[i])
-            break;
-	if(i==curplayer-1)				/* if no active nodes found */
-		curplayer=0;				/* make current player 0 */
-    else
-		curplayer=i+1; }
-else
-	curplayer=i+1;					/* else active node current player */
-
-putgamedat();                       /* write info and unlock */
-}
-
-/* End of SBJ.C */
diff --git a/xtrn/sbj/sbj.cfg b/xtrn/sbj/sbj.cfg
deleted file mode 100644
index 9e5236e6ed78c03c3743f109abd513151bd2308a..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-6					Number of decks
-10					Minimum bet (in kilobytes)
-1000					Maximum bet (in kilobytes)
-100					Default bet (in kilobytes)
diff --git a/xtrn/sbj/sbj.doc b/xtrn/sbj/sbj.doc
deleted file mode 100644
index 8066b29359739102e2da37ed88d4cfdb2047633b..0000000000000000000000000000000000000000
Binary files a/xtrn/sbj/sbj.doc and /dev/null differ
diff --git a/xtrn/sbj/sbj.dsp b/xtrn/sbj/sbj.dsp
deleted file mode 100644
index 567f753f3983a786b472bd1be9ab3df402762248..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.dsp
+++ /dev/null
@@ -1,102 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sbj" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=sbj - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sbj.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sbj.mak" CFG="sbj - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sbj - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "sbj - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sbj - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "c:\sbbs\xtrn\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /map /machine:I386
-
-!ELSEIF  "$(CFG)" == "sbj - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /map /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sbj - Win32 Release"
-# Name "sbj - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\Sbj.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Sdk\Xsdk.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Sdk\Xsdkvars.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\sdk\xsdkwrap.c
-# End Source File
-# End Target
-# End Project
diff --git a/xtrn/sbj/sbj.msg b/xtrn/sbj/sbj.msg
deleted file mode 100644
index 3c4d55db67eeec6b6162b336a0e406e15b9d6e84..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbj.msg
+++ /dev/null
@@ -1,23 +0,0 @@
-                                  chSynchronet
-                                 r Blackjack! 
-w
-        As you might have guessed, this is a blackjack game. But not just any
-blackjack game. With Synchronet Blackjack, you play against the house for
-credits and your friends can play along side you simultaneously from the same
-card shoe. You can even carry on a conversation while a hand is in play!
-
-        Beware, you are gambling with your credits if you choose to play, but
-the odds are pretty good. House pays double on a natural blackjack or three
-sevens, 1� to 1 on regular blackjack, even money on other winning hands and 
-ties (pushes) break even. You can double down if you have enough dough and even
-split pairs!
-
-        If you choose to play, note that it is much more enjoyable with a
-friend at the table with you. While the dealer is fast and curteous, he doesn't
-make a very good conversationalist.
-
-	If you notice that you're not seeing the card symbols for 'clubs' you
-may have Compuserve Quick B transfers enabled or another answerback to Ctrl-E.
-This should be disabled, or you should toggle card symbols OFF.
-
-
diff --git a/xtrn/sbj/sbjclean.c b/xtrn/sbj/sbjclean.c
deleted file mode 100644
index 814f3edba80f9e58918c9c01703bd4a719860729..0000000000000000000000000000000000000000
--- a/xtrn/sbj/sbjclean.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SBJCLEAN.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Clean-up program for Synchronet Blackjack Online External Program */
-
-#define SBJCLEAN
-
-#include "sbj.c"
-
-
-int main(int argc, char **argv)
-{
-	char *p;
-	int i;
-
-node_dir[0]=0;
-for(i=1;i<argc;i++)
-	if(!stricmp(argv[i],"/L"))
-		logit=1;
-	else strcpy(node_dir,argv[i]);
-
-p=getenv("SBBSNODE");
-if(!node_dir[0] && p)
-	strcpy(node_dir,p);
-
-if(!node_dir[0]) {	  /* node directory not specified */
-	printf("usage: sbjclean <node directory>\r\n");
-	getch();
-	return(1); }
-
-if(node_dir[strlen(node_dir)-1]!='\\')  /* make sure node_dir ends in '\' */
-    strcat(node_dir,"\\");
-
-initdata();                                 /* read XTRN.DAT and more */
-
-if((gamedab=open("GAME.DAB",O_RDWR|O_DENYNONE|O_BINARY))==-1) {
-	printf("Error opening GAME.DAB\r\n");                /* open deny none */
-    return(1); }
-getgamedat(1);
-node[node_num-1]=0;
-status[node_num-1]=0;
-putgamedat();
-if(curplayer==node_num)
-	nextplayer();
-close(gamedab);
-return(0);
-}
diff --git a/xtrn/sbl/Makefile.gnu b/xtrn/sbl/Makefile.gnu
deleted file mode 100644
index ce3996ed49f7e2e4b13b9e08f721ec7a5d93750d..0000000000000000000000000000000000000000
--- a/xtrn/sbl/Makefile.gnu
+++ /dev/null
@@ -1,50 +0,0 @@
-# Makefile.gnu
-
-#########################################################################
-# Makefile for Synchronet BBS List										#
-# For use with GNU make and GNU C Compiler								#
-# @format.tab-size 4, @format.use-tabs true								#
-#																		#
-# Linux: make -f Makefile.gnu											#
-# Win32: make -f Makefile.gnu os=win32									#
-# FreeBSD: make -f Makefile.gnu os=freebsd								#
-#########################################################################
-
-# $Id$
-
-# Macros
-CC		=	gcc
-LD		=	ld
-
-ifeq ($(os),win32)	# Windows
-
-EXEFILE	=	.exe
-LIBDIR	:=	/gcc/i386-mingw32/lib
-CFLAGS	:=	-mno-cygwin
-LFLAGS  :=	--target=i386-mingw32 -mno-cygwin
-DELETE	=	echo y | del 
-LIBS	=	$(LIBDIR)/libwsock32.a
-
-else	# Linux
-
-EXEFILE	=	
-LIBODIR	:=	gcc.linux.lib
-EXEODIR	:=	gcc.linux.exe
-LIBDIR	:=	/usr/lib
-CFLAGS	:=	
-LFLAGS  :=	
-DELETE	=	rm -f -v
-ifeq ($(os),freebsd)	# FreeBSD
-LIBS	=	-pthread
-else
-LIBS	=	$(LIBDIR)/libpthread.a
-endif
-
-endif
-
-CFLAGS	:=	$(CFLAGS) -I../sdk
-
-SBL: sbl$(EXEFILE)
-
-sbl$(EXEFILE) : sbl.c ../sdk/xsdk.c ../sdk/xsdkvars.c ../sdk/xsdkwrap.c
-	$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
diff --git a/xtrn/sbl/makefile.bor b/xtrn/sbl/makefile.bor
deleted file mode 100644
index 71c853b6c61745b8c470cb236a2901440decd25c..0000000000000000000000000000000000000000
--- a/xtrn/sbl/makefile.bor
+++ /dev/null
@@ -1,40 +0,0 @@
-##################################################################
-# Makefile for SBL (Synchronet BBS List Online External Program) #
-# For use with Turbo C++ 			  		 #
-# Tabstop=8				 	  		 #
-##################################################################
-
-# Macros
-CC	= \bc31\bin\bcc
-LD	= \bc31\bin\tlink
-SDK	= ..\sdk
-INCLUDE = \bc31\include;$(SDK)
-LIB     = \bc31\lib
-MODEL	= l
-CFLAGS	= -N -d -C -m$(MODEL) -I$(INCLUDE)
-LFLAGS  = /n /c
-OBJS    = xsdk.obj xsdkvars.obj $(SDK)\mswait$(MODEL).obj
-HEADERS = $(SDK)\xsdk.h $(SDK)\xsdkdefs.h $(SDK)\xsdkvars.c sbldefs.h
-
-# Implicit C Compile Rule
-.c.obj:
-    	@echo Compiling $*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $*.c
-
-# Main EXE Link Rule
-sbl.exe: $(OBJS) sbl.obj
-    	@echo Linking $< ...
-	$(LD) $(LFLAGS) @&&!
-$(LIB)\c0$(MODEL) $(OBJS) sbl.obj
-!, $*, $*, $(LIB)\c$(MODEL).lib $(LIB)\math$(MODEL).lib $(LIB)\emu.lib
-
-# All .obj modules
-sbl.obj: $(HEADERS)
-
-xsdk.obj: $(SDK)\xsdk.c $(HEADERS)
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $(SDK)\$*.c
-
-xsdkvars.obj: $(SDK)\xsdkvars.c $(SDK)\xsdkdefs.h
-	@echo Compiling $(SDK)\$*.c to $*.obj ...
-	$(CC) $(CFLAGS) -c $(SDK)\$*.c
diff --git a/xtrn/sbl/sbbslist.c b/xtrn/sbl/sbbslist.c
deleted file mode 100644
index dc2fdd7644a9d4dc8640f8d7bc0de1b48ff7c478..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbbslist.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/* SBBSLIST.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Converts Synchronet BBS List (SBL.DAB) to text file */
-
-#include "xsdk.h"
-#include "telnet.h"
-#include "sbldefs.h"
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-char *nulstr="";
-char tmp[256];
-
-extern int daylight=0;
-extern long timezone=0L;
-
-#undef  ERROR_VALUE
-#define ERROR_VALUE			(GetLastError()-WSABASEERR)
-
-#define SORT	TRUE
-#define VERIFY	TRUE
-
-typedef struct {
-
-	time_t	date;
-	ulong	count;
-	ulong	attempts;
-	short	offset;
-
-    } sort_t;
-
-
-int sort_cmp(sort_t **str1, sort_t **str2)
-{
-	int diff;
-	
-	/* sort descending by date */
-	diff=((*str2)->date&0xffff0000)-((*str1)->date&0xffff0000);
-
-	if(diff)
-		return(diff);
-
-	/* sort descending by verfication counter */
-	diff=(((*str2)->count)-((*str1)->count));
-
-	if(diff)
-		return(diff);
-
-	/* sort ascending by verification attempts */
-	return(((*str1)->attempts)-((*str2)->attempts));
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str'								*/
-/****************************************************************************/
-void truncsp(uchar *str)
-{
-	uint c;
-
-	c=strlen(str);
-	while(c && (uchar)str[c-1]<=SP) c--;
-	str[c]=0;
-}
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()										*/
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-	static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-	gm=localtime(intime);
-
-	if(gm==NULL) {
-		sprintf(str,"Invalid time: %08lX",*intime);
-		return(str);
-	}
-
-	if(gm->tm_hour>=12) {
-		if(gm->tm_hour==12)
-			hour=12;
-		else
-			hour=gm->tm_hour-12;
-		strcpy(mer,"pm"); }
-	else {
-		if(gm->tm_hour==0)
-			hour=12;
-		else
-			hour=gm->tm_hour;
-		strcpy(mer,"am"); }
-	sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-		,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-		,hour,gm->tm_min,mer);
-	return(str);
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-	struct tm* tm;
-
-	if(!unix)
-		strcpy(str,"00/00/00");
-	else {
-		tm=gmtime(&unix);
-		if(tm==NULL)
-			strcpy(str,"00/00/00");
-		else {
-			if(tm->tm_mon>11) {	  /* DOS leap year bug */
-				tm->tm_mon=0;
-				tm->tm_year++; }
-			if(tm->tm_mday>31)
-				tm->tm_mday=1;
-			sprintf(str,"%02u/%02u/%02u",tm->tm_mon+1,tm->tm_mday
-				,tm->tm_year%100); }
-		}
-	return(str);
-}
-
-
-void long_bbs_info(FILE *out, bbs_t bbs)
-{
-	int i;
-
-fprintf(out,"BBS Name: %s since %s\r\n"
-	,bbs.name,unixtodstr(bbs.birth,tmp));
-fprintf(out,"Operator: ");
-for(i=0;i<bbs.total_sysops && i<MAX_SYSOPS;i++) {
-	if(i) {
-		if(bbs.total_sysops>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(!(i%4))
-			fprintf(out,"\r\n          ");
-		if(i+1==bbs.total_sysops)
-			fprintf(out,"and "); }
-	fprintf(out,"%s",bbs.sysop[i]); }
-fprintf(out,"\r\n");
-fprintf(out,"Software: %-15.15s Nodes: %-5u "
-	"Users: %-5u Doors: %u\r\n"
-	,bbs.software,bbs.nodes,bbs.users,bbs.xtrns);
-fprintf(out,"Download: %lu files in %u directories of "
-	"%luMB total space\r\n"
-	,bbs.files,bbs.dirs,bbs.megs);
-fprintf(out,"Messages: %lu messages in %u sub-boards\r\n"
-	,bbs.msgs,bbs.subs);
-fprintf(out,"Networks: ");
-for(i=0;i<bbs.total_networks && i<MAX_NETS;i++) {
-	if(i) {
-		if(bbs.total_networks>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(!(i%3))
-			fprintf(out,"\r\n          ");
-		if(i+1==bbs.total_networks)
-			fprintf(out,"and "); }
-	fprintf(out,"%s [%s]",bbs.network[i],bbs.address[i]); }
-fprintf(out,"\r\n");
-fprintf(out,"Terminal: ");
-for(i=0;i<bbs.total_terminals && i<MAX_TERMS;i++) {
-	if(i) {
-		if(bbs.total_terminals>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(i+1==bbs.total_terminals)
-			fprintf(out,"and "); }
-	fprintf(out,"%s",bbs.terminal[i]); }
-fprintf(out,"\r\n\r\n");
-for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
-	fprintf(out,"%-30.30s "
-	   ,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
-			? nulstr : bbs.number[i].modem.location);
-	if(bbs.number[i].modem.min_rate==0xffff)
-		fprintf(out,"%s:%d\r\n"
-			,bbs.number[i].telnet.addr
-			,bbs.number[i].telnet.port);
-	else
-		fprintf(out,"%12.12s %5u %-15.15s "
-			"Minimum: %u\r\n"
-			,bbs.number[i].modem.number
-			,bbs.number[i].modem.max_rate,bbs.number[i].modem.desc
-			,bbs.number[i].modem.min_rate);
-}
-fprintf(out,"\r\n");
-for(i=0;i<5;i++) {
-	if(!bbs.desc[i][0])
-		break;
-	fprintf(out,"%15s%s\r\n",nulstr,bbs.desc[i]); }
-
-fprintf(out,"\r\n");
-fprintf(out,"Entry created on %s by %s\r\n"
-	,timestr(&bbs.created),bbs.user);
-if(bbs.updated && bbs.userupdated[0])
-	fprintf(out," Last updated on %s by %s\r\n"
-		,timestr(&bbs.updated),bbs.userupdated);
-if(bbs.verified && bbs.userverified[0])
-	fprintf(out,"Last verified on %s by %s\r\n"
-        ,timestr(&bbs.verified),bbs.userverified);
-}
-
-u_long resolve_ip(char *addr)
-{
-	HOSTENT*	host;
-
-	if(isdigit(addr[0]))
-		return(inet_addr(addr));
-	if ((host=gethostbyname(addr))==NULL) {
-//		printf("!ERROR resolving hostname: %s\n",addr);
-		return(0);
-	}
-	return(*((ulong*)host->h_addr_list[0]));
-}
-
-int telnet_negotiate(SOCKET sock, uchar* buf, int rd, int max_rd)
-{
-	int		i;
-	int		rsplen;
-	uchar	rsp[512];
-
-	return(rd);
-
-	do {
-		rsplen=0;
-		for(i=0; i<rd && rsplen<sizeof(rsp)-2;i++) {
-			if(buf[i]!=TELNET_IAC)
-				continue;
-			i++;
-			printf("telnet cmd: %02X %02X\n"
-				,buf[i],buf[i+1]);
-			if(buf[i]==TELNET_DO) {
-				rsp[rsplen++]=TELNET_IAC;
-				rsp[rsplen++]=TELNET_WILL;
-				rsp[rsplen++]=buf[i+1];
-			}
-			if(buf[i]==TELNET_DONT) {
-				rsp[rsplen++]=TELNET_IAC;
-				rsp[rsplen++]=TELNET_WONT;
-				rsp[rsplen++]=buf[i+1];
-			}
-			i++;
-		}
-		if(!rsplen)
-			break;
-		printf("telnet rsp: ");
-		for(i=0; i<rsplen; i++) 
-			printf("%02X  ",rsp[i]);	
-		printf("\n");
-		send(sock,rsp,rsplen,0);
-		Sleep(3000);
-		rd=recv(sock,buf,max_rd,0);
-
-	} while(rd>0);
-
-	return(rd);
-
-}
-
-int main(int argc, char **argv)
-{
-	char	str[128],name[128],*location,nodes[32],*sysop;
-	char	sysop_email[128];
-	char	buf[256];
-	char	verify_result[128];
-	char	version[128];
-	char*	p;
-	char*	sp;
-	char*	tp;
-	char*	for_os;
-	char*	fontstr="<FONT FACE=\"Arial\" SIZE=\"-1\">";
-	char	telnet_addr_buf[128];
-	char*	telnet_addr;
-	char	telnet_portstr[32];
-	ushort	telnet_port;
-	BOOL	verified;
-	ushort	index;
-	int		i,j,file,ff,rd;
-	long	l;
-	ulong	ip_addr;
-	ulong	total_systems;
-	ulong	total_attempts=0;
-	ulong	total_verified=0;
-	FILE	*in,*shrt,*lng,*html;
-	bbs_t	bbs;
-	sort_t **sort=NULL;
-	time_t	now;
-
-	/* socket stuff */
-	SOCKET	sock;
-	SOCKADDR_IN	addr;
-	int		status;             /* Status Code */
-	WSADATA WSAData;
-
-    if((status = WSAStartup(MAKEWORD(1,1), &WSAData))!=0) {
-	    printf("!WinSock startup ERROR %d\n", status);
-		return(1);
-	}
-
-	if(_putenv("TZ=UCT0"))
-		printf("!putenv() FAILED");
-	tzset();
-
-	now=time(NULL);
-
-	if((i=_sopen("SBL.DAB",O_RDWR|O_BINARY,SH_DENYNO,S_IREAD|S_IWRITE))==-1) {
-		printf("error opening SBL.DAB\n");
-		return(1); }
-
-	if((in=fdopen(i,"rb"))==NULL) {
-		printf("error opening SBL.DAB\n");
-		return(1); }
-
-	if((shrt=fopen("SBBS.LST","wb"))==NULL) {
-		printf("error opening/creating SBBS.LST\n");
-		return(1); }
-
-	if((lng=fopen("SBBS_DET.LST","wb"))==NULL) {
-		printf("error opening/creating SBBS_DET.LST\n");
-		return(1); }
-
-	if((html=fopen("sbbslist.html","w"))==NULL) {
-		printf("error opening/creating sbbslist.html\n");
-		return(1); }
-
-	fprintf(shrt,"Synchronet BBS List exported from Vertrauen on %s\r\n"
-				 "======================================================="
-				 "\r\n\r\n"
-		,unixtodstr(time(NULL),str));
-
-	fprintf(lng,"Detailed Synchronet BBS List exported from Vertrauen on %s\r\n"
-				"================================================================"
-				"\r\n\r\n"
-		,unixtodstr(time(NULL),str));
-
-	fprintf(html,"<HTML><HEAD><TITLE>Synchronet BBS List</TITLE></HEAD>\n");
-	fprintf(html,"<BODY><FONT FACE=\"Arial\" SIZE=\"-1\">\n");
-
-	printf("Sorting...");
-	fseek(in,0L,SEEK_SET);
-	i=j=0;
-	while(1) {
-		if(!fread(&bbs,sizeof(bbs_t),1,in))
-			break;
-		j++;
-		printf("%4u\b\b\b\b",j);
-		if(!bbs.name[0] || strnicmp(bbs.software,"SYNCHRONET",10)) {
-//			printf("%s\n",bbs.software);
-			continue;
-		}
-		i++;
-		if((sort=(sort_t **)REALLOC(sort
-			,sizeof(sort_t *)*i))==NULL) {
-			printf("\r\n\7Memory allocation error\r\n");
-			return(1); }
-		if((sort[i-1]=(sort_t *)LMALLOC(sizeof(sort_t)
-			))==NULL) {
-			printf("\r\n\7Memory allocation error\r\n");
-			return(1); }
-		sort[i-1]->date=bbs.verified;
-		sort[i-1]->count=bbs.verification_count;
-		sort[i-1]->attempts=bbs.verification_attempts;
-		sort[i-1]->offset=j-1; 
-	}
-	total_systems=i;
-
-#if SORT
-	qsort((void *)sort,total_systems,sizeof(sort[0])
-		,(int(*)(const void *, const void *))sort_cmp);
-#endif
-	printf(" Done.\n");
-		
-	printf("Creating index...");
-	sprintf(str,"SBBSSORT.NDX");
-	if((file=open(str,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE|S_IREAD))==-1) {
-		printf("\n\7Error creating %s\n",str);
-		return(1); }
-	for(j=0;j<(int)total_systems;j++)
-		write(file,&sort[j]->offset,2);
-	lseek(file,0L,SEEK_SET);
-	printf(" Done.\n");
-
-
-	printf("Creating lists...\n");
-
-	fprintf(html,"<CENTER>");
-	fprintf(html,"<H1><I><A HREF=http://www.synchro.net>Synchronet"
-		"</A> BBS List</H1></I>\n");
-	
-	fprintf(html,"(%d systems) exported from "
-		"<B><A HREF=http://vert.synchro.net>Vertrauen</A></B> on %s\n"
-		,total_systems ,timestr(&now));
-
-	fprintf(html,"<P></CENTER>\n");
-
-	fprintf(html,"<TABLE WIDTH=\"100%%\">\n");
-	fprintf(html,"<COLGROUP ALIGN=LEFT><COLGROUP ALIGN=LEFT>"
-		"<COLGROUP ALIGN=CENTER><COLGROUP ALIGN=CENTER>"
-		"<COLGROUP ALIGN=RIGHT><COLGROUP ALIGN=CENTER>\n");
-	fprintf(html,"<TR BGCOLOR=\"#000000\">\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">BBS Name\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Sysop\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Location\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Nodes\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Modem/Telnet Address\n");
-	fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Verification Results\n");
-	ff=0;
-	while(1) {
-		if(read(file,&index,2)!=2)
-			break;
-		fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
-		if(!fread(&bbs,sizeof(bbs_t),1,in))
-			break;
-		long_bbs_info(lng,bbs);
-		if(ff)
-			fprintf(lng,"\x0c\r\n");
-		else
-			fprintf(lng,"\r\n---------------------------------------------"
-				"----------------------------------\r\n\r\n");
-		ff=!ff;
-		verified=FALSE;
-		total_attempts++;
-		for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
-			if(!i) {
-				if(bbs.sysop_email[0]) {
-					sprintf(sysop_email,"<A HREF=mailto:%s>%s</A>",bbs.sysop_email,bbs.sysop[0]);
-					sysop=sysop_email;
-				} else
-					sysop=bbs.sysop[0];
-				sprintf(nodes,"%u",bbs.nodes);
-			} else {
-				sysop="";
-				nodes[0]=0;
-			}
-			if(i && !stricmp(bbs.number[i].modem.number,bbs.number[i-1].modem.number))
-				continue;	// duplicate
-			if(i && !stricmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location))
-				location="";
-			else
-				location=bbs.number[i].modem.location;
-			fprintf(shrt,"%-25.25s %-25.25s %s\r\n"
-				,i ? "" : bbs.name, location
-				,bbs.number[i].modem.number);
-			if(!i) {
-				fprintf(html,"<A NAME=\"%s.index\">",bbs.name);
-				fprintf(html,"<TR BGCOLOR=\"#EEEEEE\">");
-			} else
-				fprintf(html,"<TR>");
-				sprintf(name,"<A HREF=\"#%s\">%s</A>",bbs.name,bbs.name);
-
-			if(bbs.number[i].modem.min_rate==0xffff /* && bbs.name[0]=='E' */) {
-
-				telnet_port=bbs.number[i].telnet.port;
-				if(telnet_port==0)
-					telnet_port=23;
-				strcpy(telnet_addr_buf,bbs.number[i].telnet.addr);
-				telnet_addr=telnet_addr_buf;
-
-				if(!strnicmp(telnet_addr,"TELNET:",7))
-					telnet_addr+=7;
-				if(!strnicmp(telnet_addr,"//",2))
-					telnet_addr+=2;
-				p=strchr(telnet_addr,':');
-				if(p!=NULL) {
-					*p=0;
-					telnet_port=atoi(p+1);
-				}
-
-#if !VERIFY	/* set to 1 for no-verification */
-				verified=TRUE;
-				strcpy(verify_result,"<B>v3.00x for Win32</B>");
-#else
-				printf("Verifying %d/%d %s:%d "
-					,total_attempts,total_systems,telnet_addr,telnet_port);
-
-				ip_addr=resolve_ip(telnet_addr);
-				if(!ip_addr) 
-					strcpy(verify_result,"bad hostname");
-				else {
-
-					if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP)) == INVALID_SOCKET) {
-						printf("\n\7Error %d opening socket",ERROR_VALUE);
-						return(1);
-					}
-
-					memset(&addr,0,sizeof(addr));
-					addr.sin_family = AF_INET;
-
-					if(bind(sock, (struct sockaddr *) &addr, sizeof (addr))!=0) {
-						closesocket(sock);
-						printf("!ERROR %d binding to socket %d",ERROR_VALUE, sock);
-						return(1);
-					}
-
-					memset(&addr,0,sizeof(addr));
-					addr.sin_addr.S_un.S_addr = ip_addr;
-					addr.sin_family = AF_INET;
-					addr.sin_port   = htons(telnet_port);
-
-					if(connect(sock, (struct sockaddr *)&addr, sizeof(addr))!=0) 
-						sprintf(verify_result,"no connect (%ld)"
-							,ERROR_VALUE);
-					else {
-						l=1;
-						ioctlsocket(sock, FIONBIO, &l);
-						Sleep(3000);
-
-						buf[0]=0;
-						rd=recv(sock,buf,sizeof(buf)-1,0);
-						if((rd=telnet_negotiate(sock,buf,rd,sizeof(buf)-1))<1)
-							sprintf(verify_result,"no data (%ld)"
-								,rd==SOCKET_ERROR ? ERROR_VALUE : rd);
-						else {
-							
-							buf[rd]=0;
-							sp=buf+(rd-1);
-							while(*sp && sp!=buf) sp--;	// Skip garbage (with null)
-							if(*sp==0)
-								sp++;
-							p=strstr(sp,"Synchronet");
-							if(p!=NULL) {
-								verified=TRUE;
-								for_os=strstr(sp," for ");
-								if(for_os==NULL) 
-									for_os="";
-								p=strstr(sp,"Version ");
-								if(p==NULL)
-									version[0]=0;
-								else {
-									p+=8;
-									tp=strchr(p,'\r');
-									if(tp!=NULL) *tp=0;
-									truncsp(p);
-									for_os[11]=0;
-									truncsp(for_os);
-									sprintf(version,"v%s%s",p,for_os);
-								}
-								sprintf(verify_result,"<B>%s</B>"
-									,version[0] ? version : "Verified");
-							} else {
-								printf("rd=%d buf='%s' sp='%s'\n",rd,buf,sp);
-								sprintf(verify_result,"non-Synchronet");
-							}
-						}
-					}
-
-					closesocket(sock);
-				}
-
-				printf("%s\n",verify_result);
-				bbs.verification_attempts++;
-#endif
-
-				if(telnet_port==23)
-					telnet_portstr[0]=0;
-				else
-					sprintf(telnet_portstr,":%d",telnet_port);
-
-				fprintf(html,"<TD><B>%s%s</B><TD>%s%s<TD>%s%s<TD>%s%s<TD%s>"
-					"<A HREF=telnet://%s%s>%s%s%s%s%s</A><TD%s>%s%s\n"
-					,fontstr,i ? "":name
-					,fontstr,sysop
-					,fontstr,location
-					,fontstr,nodes
-					,i ? " BGCOLOR=\"#EEEEEE\"":""
-					,telnet_addr, telnet_portstr
-						,fontstr
-						,verified ? "<B>":"", telnet_addr, telnet_portstr
-						, verified ? "</B>":""
-					,i ? " BGCOLOR=\"#EEEEEE\"":""
-					,fontstr,verify_result);
-			} else
-				fprintf(html,"<TD><B>%s%s</B><TD>%s%s<TD>%s%s<TD>%s%s<TD%s>%s%s"
-					"<TD%s>%s%s\n"
-					,fontstr,i ? "":name
-					,fontstr,sysop
-					,fontstr,location
-					,fontstr,nodes
-					,i ? " BGCOLOR=\"#EEEEEE\"":""
-					,fontstr,bbs.number[i].modem.number
-					,i ? " BGCOLOR=\"#EEEEEE\"":""
-					,fontstr,"N/A");
-		} /* for(numbers) */
-#if VERIFY
-		if(verified) {
-			total_verified++;
-			bbs.verified=time(NULL);
-			bbs.verification_count++;
-			strcpy(bbs.userverified,"SBBS List Verifier");
-		}
-		fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
-		fwrite(&bbs,sizeof(bbs_t),1,in);
-#endif
-	}
-	fprintf(html,"</TABLE>\n");
-
-	now=time(NULL);
-	fprintf(html,"<CENTER>\n");
-	fprintf(html,"%d systems verified from "
-		"<B><A HREF=http://vert.synchro.net>Vertrauen</A></B> on %s\n"
-		,total_verified ,timestr(&now));
-	fprintf(html,"<H1><I>Detailed Synchronet BBS List</I></H1>\n");
-	fprintf(html,"</CENTER>\n");
-
-	/* Generate Detailed List */
-	lseek(file,0L,SEEK_SET);
-	while(1) {
-		if(read(file,&index,2)!=2)
-			break;
-		fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
-		if(!fread(&bbs,sizeof(bbs_t),1,in))
-			break;
-
-		fprintf(html,"<P><A NAME=\"%s\">\n",bbs.name);
-
-		fprintf(html,"<H2><A HREF=\"#%s.index\">%s</A></H2>",bbs.name,bbs.name);
-		fprintf(html,"<FONT FACE=\"Arial\" SIZE=\"-1\">\n");
-
-		fprintf(html,"Online since: %s<BR>\n",unixtodstr(bbs.birth,tmp));
-
-		if(bbs.sysop_email[0]) {
-			sprintf(sysop_email,"<A HREF=mailto:%s>%s</A>",bbs.sysop_email,bbs.sysop[0]);
-			sysop=sysop_email;
-		} else
-			sysop=bbs.sysop[0];
-
-		fprintf(html,"Operator: %s", sysop);
-
-		for(i=1;i<bbs.total_sysops && i<MAX_SYSOPS;i++) {
-			if(bbs.total_sysops>2)
-				fprintf(html,", ");
-			else
-				fputc(SP,html);
-			if(i+1==bbs.total_sysops)
-				fprintf(html,"and "); 
-			fprintf(html,"%s",bbs.sysop[i]); 
-		}
-		fprintf(html,"<BR>\n");
-
-		if(bbs.web_url[0]) 
-			fprintf(html,"Web-site: <A HREF=http://%s>%s</A><BR>\n",bbs.web_url,bbs.web_url);
-
-		fprintf(html,"Nodes: %u, "
-			"Users: %u, Doors: %u<BR>\n"
-			,bbs.nodes,bbs.users,bbs.xtrns);
-		fprintf(html,"Download: %lu files in %u directories of "
-			"%luMB total space<BR>\n"
-			,bbs.files,bbs.dirs,bbs.megs);
-		fprintf(html,"Messages: %lu messages in %u sub-boards<BR>\n"
-			,bbs.msgs,bbs.subs);
-
-		if(bbs.total_networks) {
-			fprintf(html,"Networks: ");
-			for(i=0;i<bbs.total_networks && i<MAX_NETS;i++) {
-				if(i) {
-					if(bbs.total_networks>2)
-						fprintf(html,", ");
-					else
-						fputc(SP,html);
-					if(!(i%2))
-						fprintf(html,"<BR>");
-					if(i+1==bbs.total_networks)
-						fprintf(html,"and "); 
-				}
-				fprintf(html,"%s [%s]",bbs.network[i],bbs.address[i]); }
-			fprintf(html,"<BR>\n");
-		}
-
-		if(bbs.total_terminals) {
-			fprintf(html,"Terminal: ");
-			for(i=0;i<bbs.total_terminals && i<MAX_TERMS;i++) {
-				if(i) {
-					if(bbs.total_terminals>2)
-						fprintf(html,", ");
-					else
-						fputc(SP,html);
-					if(i+1==bbs.total_terminals)
-						fprintf(html,"and "); }
-				fprintf(html,"%s",bbs.terminal[i]); }
-			fprintf(html,"<BR>\n");
-		}
-
-		fprintf(html,"<BR>\n");
-		for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
-			if(bbs.number[i].modem.min_rate==0xffff) {
-
-				telnet_port=bbs.number[i].telnet.port;
-				if(telnet_port==0)
-					telnet_port=23;
-				strcpy(telnet_addr_buf,bbs.number[i].telnet.addr);
-				telnet_addr=telnet_addr_buf;
-
-				if(!strnicmp(telnet_addr,"TELNET:",7))
-					telnet_addr+=7;
-				if(!strnicmp(telnet_addr,"//",2))
-					telnet_addr+=2;
-				p=strchr(telnet_addr,':');
-				if(p!=NULL) {
-					*p=0;
-					telnet_port=atoi(p+1);
-				}
-
-				if(telnet_port==23)
-					telnet_portstr[0]=0;
-				else
-					sprintf(telnet_portstr,":%d",telnet_port);
-
-				fprintf(html,"<A HREF=telnet://%s%s>telnet://%s%s</A>"
-					,telnet_addr
-					,telnet_portstr
-					,telnet_addr
-					,telnet_portstr);
-			} else
-				fprintf(html,"%s %u %s "
-					"Minimum: %u"
-					,bbs.number[i].modem.number
-					,bbs.number[i].modem.max_rate,bbs.number[i].modem.desc
-					,bbs.number[i].modem.min_rate);
-
-			fprintf(html," %s<BR>\n"
-			   ,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
-					? nulstr : bbs.number[i].modem.location);
-		}
-		fprintf(html,"<BR>\n");
-
-		fprintf(html,"<BLOCKQUOTE>\n");
-		for(i=0;i<5;i++) {
-			if(!bbs.desc[i][0])
-				break;
-			fprintf(html,"%s<BR>\n",bbs.desc[i]); 
-		}
-		fprintf(html,"</BLOCKQUOTE>\n");
-
-		fprintf(html,"<PRE>\n");
-		fprintf(html,"Entry created on %s by %s\n"
-			,timestr(&bbs.created),bbs.user);
-		if(bbs.updated && bbs.userupdated[0])
-			fprintf(html," Last updated on %s by %s\n"
-				,timestr(&bbs.updated),bbs.userupdated);
-		if(bbs.verified && bbs.userverified[0])
-			fprintf(html,"Last verified on %s by %s\n"
-				,timestr(&bbs.verified),bbs.userverified);
-
-		fprintf(html,"</PRE></P>\n");
-	}
-	fprintf(html,"<CENTER><H1>End</H1></CENTER>\n");
-
-	fprintf(html,"<P>If you are a sysop of a <B>Synchronet BBS</B> and you would "
-		"like to add your system to this list, please do one of the following:\n");
-	fprintf(html,"<UL>\n");
-	fprintf(html,"<LI>Install <I>Synchronet BBS List <B>v2.00+</B></I> on your BBS and "
-		"link it into the <B>SYNCDATA</B> message conference (on <B>DOVE-Net</B> or <B>FidoNet</B>)\n");
-	fprintf(html,"<LI><B>OR</B> log on to <A HREF=telnet://vert.synchro.net>Vertrauen</A> and "
-		"manually add your system into the online BBS List database.\n");
-	fprintf(html,"</UL>\n");
-	fprintf(html,"</BODY></HTML>\n");
-	printf(" Done.\n");
-	return(0);
-}
diff --git a/xtrn/sbl/sbl.bpf b/xtrn/sbl/sbl.bpf
deleted file mode 100644
index 4d4d9faa08980844713ed3f91c478a19f80780b7..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.bpf
+++ /dev/null
@@ -1,9 +0,0 @@
-USEUNIT("Sbl.c");
-USEUNIT("..\SDK\Xsdkvars.c");
-USEUNIT("..\SDK\Xsdk.c");
-USELIB("D:\Borland\CBuilder5\Lib\ws2_32.lib");
-USEUNIT("..\sdk\xsdkwrap.c");
-//---------------------------------------------------------------------------
-This file is used by the project manager only and should be treated like the project file
-
-
main
\ No newline at end of file
diff --git a/xtrn/sbl/sbl.bpr b/xtrn/sbl/sbl.bpr
deleted file mode 100644
index 00d8b4fdb9483164008b8b7b2af217ff88fb58c5..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.bpr
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version='1.0' encoding='utf-8' ?>
-<!-- C++Builder XML Project -->
-<PROJECT>
-  <MACROS>
-    <VERSION value="BCB.05.03"/>
-    <PROJECT value="sbl.exe"/>
-    <OBJFILES value="Sbl.obj ..\SDK\Xsdkvars.obj ..\SDK\Xsdk.obj ..\sdk\xsdkwrap.obj"/>
-    <RESFILES value=""/>
-    <IDLFILES value=""/>
-    <IDLGENFILES value=""/>
-    <DEFFILE value=""/>
-    <RESDEPEN value="$(RESFILES)"/>
-    <LIBFILES value="D:\Borland\CBuilder5\Lib\ws2_32.lib"/>
-    <LIBRARIES value=""/>
-    <SPARELIBS value=""/>
-    <PACKAGES value="VCL50.bpi VCLX50.bpi bcbsmp50.bpi VCLDB50.bpi VCLADO50.bpi ibsmp50.bpi 
-      VCLBDE50.bpi VCLDBX50.bpi QRPT50.bpi TEEUI50.bpi TEEDB50.bpi TEE50.bpi 
-      DSS50.bpi TEEQR50.bpi VCLIB50.bpi VCLMID50.bpi VCLIE50.bpi INETDB50.bpi 
-      INET50.bpi NMFAST50.bpi WEBMID50.bpi bcbie50.bpi dclocx50.bpi"/>
-    <PATHCPP value=".;..\SDK"/>
-    <PATHPAS value=".;"/>
-    <PATHRC value=".;"/>
-    <PATHASM value=".;"/>
-    <DEBUGLIBPATH value="$(BCB)\lib\debug"/>
-    <RELEASELIBPATH value="$(BCB)\lib\release"/>
-    <LINKER value="tlink32"/>
-    <USERDEFINES value="_DEBUG"/>
-    <SYSDEFINES value="NO_STRICT;_NO_VCL"/>
-    <MAINSOURCE value="sbl.bpf"/>
-    <INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\sdk"/>
-    <LIBPATH value="..\SDK;$(BCB)\lib\obj;$(BCB)\lib"/>
-    <WARNINGS value="-w-par"/>
-  </MACROS>
-  <OPTIONS>
-    <IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\sdk -src_suffix cpp -D_DEBUG -boa"/>
-    <CFLAG1 value="-Od -H=$(BCB)\lib\vcl50.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -tWC 
-      -tWM -c"/>
-    <PFLAGS value="-$YD -$W -$O- -v -JPHNE -M"/>
-    <RFLAGS value=""/>
-    <AFLAGS value="/mx /w2 /zd"/>
-    <LFLAGS value="-D&quot;&quot; -ap -Tpe -x -Gn -v"/>
-  </OPTIONS>
-  <LINKER>
-    <ALLOBJ value="c0x32.obj $(OBJFILES)"/>
-    <ALLRES value="$(RESFILES)"/>
-    <ALLLIB value="$(LIBFILES) $(LIBRARIES) import32.lib cw32mt.lib"/>
-  </LINKER>
-  <IDEOPTIONS>
-[Version Info]
-IncludeVerInfo=0
-AutoIncBuild=0
-MajorVer=1
-MinorVer=0
-Release=0
-Build=0
-Debug=0
-PreRelease=0
-Special=0
-Private=0
-DLL=0
-Locale=1033
-CodePage=1252
-
-[Version Info Keys]
-CompanyName=
-FileDescription=
-FileVersion=1.0.0.0
-InternalName=
-LegalCopyright=
-LegalTrademarks=
-OriginalFilename=
-ProductName=
-ProductVersion=1.0.0.0
-Comments=
-
-[HistoryLists\hlIncludePath]
-Count=3
-Item0=$(BCB)\include;$(BCB)\include\vcl;..\sdk
-Item1=$(BCB)\include;$(BCB)\include\vcl;c:\sbbs\xtrn\sdk
-Item2=$(BCB)\include;$(BCB)\include\vcl
-
-[HistoryLists\hlLibraryPath]
-Count=2
-Item0=..\SDK;$(BCB)\lib\obj;$(BCB)\lib
-Item1=$(BCB)\lib\obj;$(BCB)\lib
-
-[HistoryLists\hlDebugSourcePath]
-Count=1
-Item0=$(BCB)\source\vcl
-
-[HistoryLists\hlConditionals]
-Count=1
-Item0=_DEBUG
-
-[Debugging]
-DebugSourceDirs=$(BCB)\source\vcl
-
-[Parameters]
-RunParams=
-HostApplication=
-RemoteHost=
-RemotePath=
-RemoteDebug=0
-
-[Compiler]
-ShowInfoMsgs=0
-LinkDebugVcl=0
-LinkCGLIB=0
-
-[CORBA]
-AddServerUnit=1
-AddClientUnit=1
-PrecompiledHeaders=1
-
-[Language]
-ActiveLang=
-ProjectLang=
-RootDir=
-  </IDEOPTIONS>
-</PROJECT>
\ No newline at end of file
diff --git a/xtrn/sbl/sbl.c b/xtrn/sbl/sbl.c
deleted file mode 100644
index efa3b2f24c1b3eb750e8e92d8ec33986ddd48f1a..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.c
+++ /dev/null
@@ -1,1525 +0,0 @@
-/* sbl.c */
-
-/* Synchronet BBS List Door */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This program is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU General Public License				*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * 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.	*
- ****************************************************************************/
-
-/***********
- * History *
- ***********
-
-******************
-* RELEASE: v1.00 *
-******************
-
-07/03/93 03:16am
-Fixed bug with "Auto-deleting" already deleted entries. This would cause a
-long list of "Auto-deletion" messages once a day.
-
-07/03/93 03:30am
-The name of the user who last updated the entry is now stored and displayed.
-
-07/03/93 03:45am
-Adding/Updating entries is now much easier and user friendly.
-
-07/03/93 04:00am
-Added support for user "verification" of BBS entries.
-
-07/03/93 04:10am
-Users may now update or remove entries using partial system names.
-
-07/03/93 04:30am
-Sysops may now un-delete purged entries with the '*' key.
-
-******************
-* RELEASE: v1.10 *
-******************
-
-10/18/93 06:04pm
-Fixed bug that would cause entries to be purged almost immediately.
-
-10/18/93 07:01pm
-(F)ind text now searches user names who last updated and verified.
-
-10/19/93 01:34am
-Added option for users to change the format of BBS listings.
-
-******************
-* RELEASE: v1.20 *
-******************
-
-10/20/93 04:44pm
-Fixed cosmetic problem with opening menu (for users, not sysop).
-
-******************
-* RELEASE: v1.21 *
-******************
-
-11/29/93 09:40pm
-More cosmetic changes.	Added "Saving..." message.
-
-******************
-* RELEASE: v1.22 *
-******************
-
-02/02/94
-Added warning for pending auto-deletion of BBS entries.
-
-02/02/94
-Added option for turning screen pause off/on.
-
-02/03/94
-Added option in SBL.CFG for sysop/co-sysop notification of changes made to
-BBS list by users.
-
-02/03/94
-Converted all file operations from handles to streams for buffered i/o (speed).
-
-02/09/94
-Added options for generating a sort index and displaying sorted list based on
-various criteria.
-
-02/09/94
-Added nodesync() calls to display any messages waiting for this user/node.
-
-02/10/94
-Added search for duplicate names when adding new BBS entries.
-
-02/10/94
-Notification notice of actual auto-deletion sent to author of BBS entry upon
-auto-deletion.
-
-******************
-* RELEASE: v1.30 *
-******************
-
-03/14/94
-Added /M switch to force daily maintenance.
-
-03/22/94
-Fixed occasional double pause after listings.
-
-03/22/94
-Added total entries found to find text listings.
-
-03/22/94
-If a user verifies an entry, the user who created the entry is notified.
-
-03/29/94
-Sysop can define/change the "owner" of an entry when adding or updating.
-
-04/18/94
-Fixed bug in the sort-by-string functions that caused lock-ups when sorting
-more than 312 entries.
-
-04/18/94
-Lowered memory requirements for all sort functions.
-
-******************
-* RELEASE: v1.31 *
-******************
-
-08/23/94
-BBS entries now know whether they were created by a user or by SMB2SBL (via
-message base).
-
-08/23/94
-Fixed problem with hitting Ctrl-C locally during regular (not extended)
-listing. Returning to main menu would not clear screen or have correct colors.
-'aborted' variable is now reset in main() loop.
-
-******************
-* RELEASE: v1.32 *
-******************
-
-08/30/94
-Fixed stack overflow that would cause periodic lock-ups on some systems.
-
-******************
-* RELEASE: v1.33 *
-******************
-
-09/08/94
-When deleting an entry, the name of the BBS deleted wasn't being printed.
-
-02/01/95
-Import utility made mistake of ignoring READ messages to SBL. This has been
-fixed.
-
-12/16/99
-Fixed Y2K window bug in dstrtounix().
-
-12/16/99
-Fixed bug that caused SMB imported entries to never be autodeleted.
-
-06/01/00
-Added support for XSDK 3.0
-
-06/01/00
-Added support for MSVC 5+
-
-06/01/00
-Changed cosmetic appearance of main menu a bit
-
-06/14/99
-Added support for C++Builder 5
-*/
-
-#include <stddef.h>		/* offsetof() macro */
-#include <xsdk.h>
-#include "sbldefs.h"
-
-unsigned _stklen=16000; 		  /* Set stack size in code, not header */
-
-#define Y2K_2DIGIT_WINDOW	70
-#define VERIFICATION_MOD	FALSE
-
-typedef struct {
-
-	char	str[32];
-	short	offset;
-
-	} sortstr_t;
-
-typedef struct {
-
-	long	i;
-	short	offset;
-
-	} sortint_t;
-
-char *nulstr="";
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-char tmp[256];
-char list_fmt[128];
-uint del_days,add_ml,update_ml,remove_ml,verify_ml,sbl_pause=1,notify_user;
-time_t now;
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()										*/
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-	static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-gm=localtime(intime);
-if(gm->tm_hour>=12) {
-    if(gm->tm_hour==12)
-        hour=12;
-    else
-        hour=gm->tm_hour-12;
-    strcpy(mer,"pm"); }
-else {
-    if(gm->tm_hour==0)
-        hour=12;
-    else
-        hour=gm->tm_hour;
-    strcpy(mer,"am"); }
-sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-    ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
-    ,hour,gm->tm_min,mer);
-return(str);
-}
-
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *str)
-{
-	struct tm tm;
-
-	if(!strncmp(str,"00/00/00",8))
-		return(0);
-	memset(&tm,0,sizeof(tm));
-	tm.tm_year=((str[6]&0xf)*10)+(str[7]&0xf);
-	if (tm.tm_year<Y2K_2DIGIT_WINDOW)
-		tm.tm_year+=100;
-	tm.tm_mon=((str[0]&0xf)*10)+(str[1]&0xf);
-	tm.tm_mday=((str[3]&0xf)*10)+(str[4]&0xf); 
-	if (tm.tm_mon)
-		tm.tm_mon--;	/* zero-based month field */
-	return(mktime(&tm));
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char * unixtodstr(time_t t, char *str)
-{
-	struct tm* tm;
-
-	if(t==0)
-		strcpy(str,"00/00/00");
-	else {
-		tm=gmtime(&t);
-		if(tm==NULL) {
-			strcpy(str,"00/00/00");
-			return(str);
-		}
-		if(tm->tm_mon>11) {	  /* DOS leap year bug */
-			tm->tm_mon=0;
-			tm->tm_year++; }
-		if(tm->tm_mday>31)
-			tm->tm_mday=1;
-		sprintf(str,"%02u/%02u/%02u",tm->tm_mon+1,tm->tm_mday
-			,tm->tm_year%100); }
-	return(str);
-}
-
-void dots(int show)
-{
-	static int i;
-
-if(!show) {  /* reset */
-	i=0;
-	return; }
-if(++i>5) {
-	bputs("\b\b\b\b\b     \b\b\b\b\b");
-	i=0;
-	return; }
-outchar('.');
-}
-
-
-/* Displays short information about BBS. Returns 0 if aborted. */
-
-char short_bbs_info(bbs_t bbs)
-{
-	char	str[128];
-	int		i,j;
-
-for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
-	for(j=0;list_fmt[j];j++) {
-		if(j) bputs(" ");
-		switch(toupper(list_fmt[j])) {
-			case 'N':
-				bprintf("\1h\1m%-25.25s",i ? nulstr : bbs.name);
-				break;
-			case 'S':
-				bprintf("\1h\1c%-15.15s",i ? nulstr : bbs.software);
-				break;
-			case 'P':
-				if(bbs.number[i].modem.min_rate==0xffff) {
-					if(bbs.number[i].telnet.port!=0 
-						&& bbs.number[i].telnet.port!=IPPORT_TELNET)
-						sprintf(str,"%s:%hu"
-							,bbs.number[i].telnet.addr
-							,bbs.number[i].telnet.port);
-					else
-						strcpy(str,bbs.number[i].telnet.addr);
-					bprintf("\1h\1b%-28.28s",str);
-				} else
-					bprintf("\1n\1g%12.12s",bbs.number[i].modem.number);
-				break;
-			case 'B':
-				if(bbs.number[i].modem.min_rate!=0xffff)
-					bprintf("\1h\1g%5u",bbs.number[i].modem.max_rate);
-				break;
-			case 'M':
-				if(bbs.number[i].modem.min_rate!=0xffff)
-					bprintf("\1h\1b%-15.15s",bbs.number[i].modem.desc);
-				break;
-			case 'Y':
-				bprintf("\1h\1y%-25.25s",i ? nulstr : bbs.sysop[0]);
-				break;
-			case 'T':
-				if(i) bputs("   ");
-				else  bprintf("\1y\1h%3u",bbs.nodes);
-				break;
-			case 'U':
-				if(i) bputs("     ");
-				else  bprintf("\1n\1r%5u",bbs.users);
-                break;
-			case 'H':
-				if(i) bprintf("%10.10s",nulstr);
-				else  bprintf("\1h\1r%10u",bbs.megs);
-				break;
-			case 'L':
-				bprintf("\1n\1c%-20.20s",bbs.number[i].modem.location);
-				break;
-			case 'F':
-				bprintf("\1n\1b%s",i ? nulstr : unixtodstr(bbs.birth,tmp));
-				break;
-			case 'V':
-				bprintf("\1n\1m%s",i ? nulstr : unixtodstr(bbs.verified,tmp));
-				break;
-			case 'D':
-				bprintf("\1n%s",i ? nulstr : unixtodstr(bbs.updated,tmp));
-				break;
-			case 'C':
-				bprintf("\1n\1y%s",i ? nulstr : unixtodstr(bbs.created,tmp));
-                break;
-			default:
-				bprintf("%c",list_fmt[j]);
-				break;
-				} }
-	bputs("\r\n"); }
-if(kbhit())
-	return(0);
-return(1);
-}
-
-char long_bbs_info(bbs_t bbs)
-{
-	int i;
-
-cls();
-bprintf("\1n\1gBBS Name: \1h%s \1n\1gsince \1h%s\r\n"
-	,bbs.name,unixtodstr(bbs.birth,tmp));
-bprintf("\1n\1gOperator: ");
-for(i=0;i<bbs.total_sysops && i<MAX_SYSOPS;i++) {
-	if(i) {
-		if(bbs.total_sysops>2)
-			bputs(", ");
-		else
-			outchar(SP);
-		if(!(i%4))
-            bputs("\r\n          ");
-		if(i+1==bbs.total_sysops)
-			bputs("and "); }
-	bprintf("\1h%s\1n\1g",bbs.sysop[i]); 
-	if(!i && bbs.sysop_email[0])
-		bprintf(" <\1h%s\1n\1g>", bbs.sysop_email);
-}
-CRLF;
-bprintf("\1n\1gSoftware: \1h%-15.15s \1n\1gNodes: \1h%-5u \1n\1g"
-	"Users: \1h%-5u \1n\1gDoors: \1h%u\r\n"
-	,bbs.software,bbs.nodes,bbs.users,bbs.xtrns);
-bprintf("\1n\1gDownload: \1h%lu \1n\1gfiles in \1h%u \1n\1gdirectories of \1h"
-	"%luMB \1n\1gtotal space\r\n"
-	,bbs.files,bbs.dirs,bbs.megs);
-bprintf("Messages: \1h%lu \1n\1gmessages in \1h%u \1n\1gsub-boards\r\n"
-	,bbs.msgs,bbs.subs);
-bprintf("Networks: ");
-for(i=0;i<bbs.total_networks && i<MAX_NETS;i++) {
-	if(i) {
-		if(bbs.total_networks>2)
-			bputs(", ");
-		else
-			outchar(SP);
-		if(!(i%3))
-            bputs("\r\n          ");
-		if(i+1==bbs.total_networks)
-            bputs("and "); }
-	bprintf("\1h%s [%s]\1n\1g",bbs.network[i],bbs.address[i]); }
-CRLF;
-bprintf("Terminal: ");
-for(i=0;i<bbs.total_terminals && i<MAX_TERMS;i++) {
-	if(i) {
-		if(bbs.total_terminals>2)
-			bputs(", ");
-		else
-			outchar(SP);
-		if(i+1==bbs.total_terminals)
-            bputs("and "); }
-	bprintf("\1h%s\1n\1g",bbs.terminal[i]); }
-CRLF;
-if(bbs.web_url[0])
-	bprintf("Web-site: http://\1h%s\r\n",bbs.web_url);
-CRLF;
-for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
-	bprintf("\1h\1b%-30.30s "
-		,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
-				? nulstr : bbs.number[i].modem.location);
-	if(bbs.number[i].modem.min_rate==0xffff) {
-		if(bbs.number[i].telnet.port!=0
-			&& bbs.number[i].telnet.port!=IPPORT_TELNET)
-			bprintf("\1n\1mtelnet://\1h%s:%hu\r\n"
-				,bbs.number[i].telnet.addr
-				,bbs.number[i].telnet.port);
-		else
-			bprintf("\1n\1mtelnet://\1h%s\r\n"
-				,bbs.number[i].telnet.addr);
-	} else
-		bprintf("\1n\1g%12.12s \1h%5u \1b%-15.15s \1n\1cMinimum: \1h%u\r\n"
-			,bbs.number[i].modem.number
-			,bbs.number[i].modem.max_rate
-			,bbs.number[i].modem.desc
-			,bbs.number[i].modem.min_rate);
-}
-bputs("\r\n\1w\1h");
-for(i=0;i<DESC_LINES;i++) {
-	if(!bbs.desc[i][0])
-		break;
-	bprintf("%15s%s\r\n",nulstr,bbs.desc[i]); }
-
-CRLF;
-if(bbs.misc&FROM_SMB)
-	bputs("\1r\1hImported from message base.\r\n");
-bprintf("\1n\1cEntry created on \1h%s\1n\1c by \1h%s\r\n"
-	,timestr(&bbs.created),bbs.user);
-if(bbs.updated && bbs.userupdated[0])
-	bprintf("\1n\1c Last updated on \1h%s\1n\1c by \1h%s\r\n"
-		,timestr(&bbs.updated),bbs.userupdated);
-if(bbs.verified && bbs.userverified[0])
-	bprintf("\1n\1cLast verified on \1h%s\1n\1c by \1h%s"
-#if VERIFICATION_MOD
-	" \1y(%d/%d)"
-#endif
-	"\r\n"
-		,timestr(&bbs.verified),bbs.userverified
-		,bbs.verification_count,bbs.verification_attempts);
-CRLF;
-if(aborted) {
-	aborted=0;
-	return(0); }
-if(!sbl_pause) {
-	if(kbhit())
-		return(0);
-	return(1); }
-nodesync();
-#if VERIFICATION_MOD
-	bputs("More? Y/N/V ");
-switch(getkeys("YNV\r",0)) {
-	case '\r':
-	case 'Y':
-		return(1);
-	case 'V':
-		return(2);
-	default:
-		return(0);
-}
-#else
-	return(yesno("More"));
-#endif
-}
-
-/* Gets/updates BBS info from user. Returns 0 if aborted. */
-
-char get_bbs_info(bbs_t *bbs)
-{
-	char str[128];
-	int i;
-
-aborted=0;
-if(!(bbs->user[0]))
-	strcpy(bbs->user,user_name);
-if(SYSOP) {
-	bputs("\1y\1hUser Name (Creator/Owner of Entry): ");
-	if(!getstr(bbs->user,25,K_EDIT|K_LINE|K_AUTODEL))
-		return(0); }
-bputs("\1y\1hSystem Name: ");
-if(getstr(bbs->name,25,K_EDIT|K_LINE|K_AUTODEL)<2)
-	return(0);
-if(!bbs->software[0])
-	strcpy(bbs->software,"Synchronet");
-bprintf("\1y\1hSoftware: \1w",bbs->software);
-if(!getstr(bbs->software,15,K_AUTODEL|K_EDIT))
-	return(0);
-
-for(i=0;i<MAX_SYSOPS && !aborted;i++) {
-	bprintf("\1y\1hName of System Operator #%d [\1wNone\1y]: ",i+1);
-	if(!getstr(bbs->sysop[i],25,K_EDIT|K_LINE|K_AUTODEL))
-		break; 
-	if(!i) {
-		bprintf("\1y\1hInternet E-mail Address [\1wNone\1y]:\1w ");
-		getstr(bbs->sysop_email,40,K_EDIT|K_AUTODEL);
-	}
-}
-bbs->total_sysops=i;
-if(aborted)
-	return(0);
-
-unixtodstr(bbs->birth,str);
-bprintf("\1y\1hFirst Day Online (MM/DD/YY): \1w");
-if(getstr(str,8,K_UPPER|K_EDIT|K_AUTODEL))
-	bbs->birth=dstrtounix(str);
-if(aborted) return(0);
-
-for(i=0;i<MAX_NETS && !aborted;i++) {
-	bprintf("\1y\1hName of Message Network #%d [\1wNone\1y]: ",i+1);
-	if(!getstr(bbs->network[i],15,K_EDIT|K_AUTODEL|K_LINE))
-		break;
-	bprintf("\1y\1hNetwork Message \1wAddress\1y #%d [\1wNone\1y]: \1w",i+1);
-	getstr(bbs->address[i],25,K_EDIT|K_AUTODEL); }
-bbs->total_networks=i;
-if(aborted) return(0);
-
-for(i=0;i<MAX_TERMS && !aborted;i++) {
-	bprintf("\1y\1hSupported Terminal Type #%d (i.e. TTY, ANSI, RIP) "
-		"[\1wNone\1y]: ",i+1);
-	if(!getstr(bbs->terminal[i],15,K_EDIT|K_AUTODEL|K_LINE))
-		break; }
-bbs->total_terminals=i;
-if(aborted) return(0);
-
-bprintf("\1y\1hWeb-site [\1wNone\1y] http://\1w");
-getstr(bbs->web_url,60,K_EDIT|K_AUTODEL);
-
-if(!bbs->nodes)
-	bbs->nodes=1;
-bprintf("\1y\1hNodes (maximum number of simultaneous REMOTE users): \1w");
-sprintf(str,"%u",bbs->nodes);
-if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->nodes=atoi(str);
-if(!bbs->nodes)
-	bbs->nodes=1;
-if(aborted) return(0);
-
-for(i=0;i<MAX_NUMBERS;i++) {
-#if 0
-	if(!i && !bbs->number[i].modem.number[0])
-		sprintf(bbs->number[i].modem.number,"%.8s",user_phone);
-#endif
-	bprintf("\1y\1hPhone Number or \1mTelnet address\1y #%d [\1wNone\1y]: ",i+1);
-	if(!getstr(bbs->number[i].telnet.addr,28,K_EDIT|K_LINE))
-		break;
-	if(!bbs->number[i].modem.location[0]) {
-		if(!i)
-			strcpy(bbs->number[i].modem.location,user_location);
-		else
-			strcpy(bbs->number[i].modem.location,bbs->number[i-1].modem.location); }
-	if(aborted) return(0);
-	if(isalpha(bbs->number[i].telnet.addr[0]) 
-		|| yesno("Is the above a Telnet address")) {
-		bbs->number[i].modem.min_rate=0xffff;
-		if(bbs->number[i].telnet.port==0)
-			bbs->number[i].telnet.port=IPPORT_TELNET;
-		bprintf("\1y\1hTCP Port: \1w");
-		sprintf(str,"%u",bbs->number[i].telnet.port);
-		if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-			bbs->number[i].telnet.port=atoi(str);
-		if(aborted) return(0);
-
-	} else {
-		if(bbs->number[i].modem.min_rate==0xffff)
-			bbs->number[i].modem.min_rate=300;
-		bbs->number[i].modem.number[13]=0;
-		if(!bbs->number[i].modem.min_rate) {
-			if(i)
-				bbs->number[i].modem.min_rate=bbs->number[i-1].modem.min_rate;
-			else
-				bbs->number[i].modem.min_rate=300; }
-		bprintf("\1y\1hMinimum Connect Rate: \1w");
-		sprintf(str,"%u",bbs->number[i].modem.min_rate);
-		if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-			bbs->number[i].modem.min_rate=atoi(str);
-		if(aborted) return(0);
-
-		if(!bbs->number[i].modem.max_rate) {
-			if(i)
-				bbs->number[i].modem.max_rate=bbs->number[i-1].modem.max_rate;
-			else
-				bbs->number[i].modem.max_rate=2400; }
-		if(bbs->number[i].modem.max_rate<bbs->number[i].modem.min_rate)
-			bbs->number[i].modem.max_rate=bbs->number[i].modem.min_rate;
-		bprintf("\1y\1hMaximum Connect Rate (i.e. 2400, 9600, 14400, etc): \1w");
-		sprintf(str,"%u",bbs->number[i].modem.max_rate);
-		if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-			bbs->number[i].modem.max_rate=atoi(str);
-		if(aborted) return(0);
-		bprintf("\1y\1hModem Description (i.e. Hayes, HST, V.32, etc): \1w");
-		getstr(bbs->number[i].modem.desc,15,K_EDIT|K_AUTODEL);  
-	}
-
-	bprintf("\1y\1hLocation (City, State): \1w");
-	if(!getstr(bbs->number[i].modem.location,30,K_EDIT|K_AUTODEL))
-		break;
-
-}
-if(!i)
-	return(0);
-bbs->total_numbers=i;
-if(aborted)
-	return(0);
-
-if(!bbs->users)
-	bbs->users=100;
-bprintf("\1y\1hTotal Number of Users: \1w");
-sprintf(str,"%u",bbs->users);
-if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->users=atoi(str);
-if(aborted) return(0);
-
-if(!bbs->subs)
-	bbs->subs=10;
-bprintf("\1y\1hTotal Number of Sub-boards (Message Areas): \1w");
-sprintf(str,"%u",bbs->subs);
-if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->subs=atoi(str);
-if(aborted) return(0);
-
-if(!bbs->msgs)
-	bbs->msgs=500;
-bprintf("\1y\1hTotal Number of Public Messages: \1w");
-sprintf(str,"%lu",bbs->msgs);
-if(getstr(str,10,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->msgs=atol(str);
-if(aborted) return(0);
-
-if(!bbs->dirs)
-	bbs->dirs=5;
-bprintf("\1y\1hTotal Number of Directories (File Areas): \1w");
-sprintf(str,"%u",bbs->dirs);
-if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->dirs=atoi(str);
-if(aborted) return(0);
-
-if(!bbs->files)
-	bbs->files=250;
-bprintf("\1y\1hTotal Number of Downloadable Files: \1w");
-sprintf(str,"%lu",bbs->files);
-if(getstr(str,10,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->files=atol(str);
-if(aborted) return(0);
-
-if(!bbs->xtrns)
-    bbs->xtrns=5;
-bprintf("\1y\1hTotal Number of External Programs (Doors): \1w");
-sprintf(str,"%u",bbs->xtrns);
-if(getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL))
-    bbs->xtrns=atoi(str);
-if(aborted) return(0);
-
-if(!bbs->megs)
-	bbs->megs=40;
-bprintf("\1y\1hTotal Storage Space (in Megabytes): \1w");
-sprintf(str,"%lu",bbs->megs);
-if(getstr(str,10,K_NUMBER|K_EDIT|K_AUTODEL))
-	bbs->megs=atol(str);
-if(aborted) return(0);
-
-for(i=0;i<DESC_LINES;i++) {
-	bprintf("\1y\1hBBS Description (%d of %d): ",i+1,DESC_LINES);
-	if(!getstr(bbs->desc[i],50,K_EDIT|K_AUTODEL|K_LINE))
-		break; }
-
-return(1);
-}
-
-char partname(char *inname, char *inpart)
-{
-	char name[128],part[128],str[256];
-
-strcpy(name,inname);
-strupr(name);
-strcpy(part,inpart);
-strupr(part);
-if(inname[0] && (strstr(name,part) || strstr(part,name))) {
-	sprintf(str,"\r\nDo you mean %s",inname);
-	if(yesno(str))
-		return(1); }
-return(0);
-}
-
-int sortint_cmp(sortint_t *int1, sortint_t *int2)
-{
-
-if(int1->i>int2->i)
-	return(-1);
-if(int1->i<int2->i)
-	return(1);
-return(0);
-}
-
-int sortstr_cmp(sortstr_t *str1, sortstr_t *str2)
-{
-return(stricmp(str1->str,str2->str));
-}
-
-int main(int argc, char **argv)
-{
-	char	str[512],name[128],*p,ch;
-	short	i,j,file,done,sort_by_str;
-	int 	maint=0;
-	long	l,found;
-	bbs_t	bbs,tmpbbs;
-	FILE	*stream;
-	sortstr_t *sortstr;
-	sortint_t *sortint;
-
-	for(i=1;i<argc;i++)
-		if(argv[i][0]=='/')
-			switch(toupper(argv[i][1])) {
-				case 'M':
-					maint=1;
-					xsdk_mode&=~XSDK_MODE_NOCONSOLE;
-					break; }
-
-	p=getenv("SBBSNODE");
-	if(p)
-		strcpy(node_dir,p);
-	else {
-		printf("\nSBBSNODE environment variable must be set\n");
-		exit(0); }
-
-	if(node_dir[strlen(node_dir)-1]!='\\' && node_dir[strlen(node_dir)-1]!='/')
-		strcat(node_dir,"/");
-
-	strcpy(str,"sbl.cfg");
-	if((file=sopen(str,O_RDONLY,SH_DENYNO))==-1) {
-		printf("error opening %s\r\n",str);
-		exit(1); }
-	if((stream=fdopen(file,"rb"))==NULL) {
-		printf("fdopen error with %s\r\n",str);
-		exit(1); }
-	fgets(str,81,stream);
-	del_days=atoi(str);
-	fgets(str,81,stream);
-	add_ml=atoi(str);
-	fgets(str,81,stream);
-	update_ml=atoi(str);
-	fgets(str,81,stream);
-	remove_ml=atoi(str);
-	fgets(str,81,stream);
-	verify_ml=atoi(str);
-	fgets(str,81,stream);
-	notify_user=atoi(str);
-	fclose(stream);
-
-	initdata();
-	if(maint) 
-		client_socket=INVALID_SOCKET;
-
-	mnehigh=HIGH|LIGHTGRAY;
-	mnelow=HIGH|YELLOW;
-	if(maint)
-		user_misc=(ANSI|COLOR);
-
-	if((file=sopen("sbl.dab",O_RDWR|O_BINARY|O_CREAT,SH_DENYNO))==-1) {
-		bprintf("\r\n\7Error opening/creating sbl.dab\r\n");
-		exit(1); }
-	if((stream=fdopen(file,"w+b"))==NULL) {
-		bprintf("\r\n\7Error converting sbl.dab file handle to stream\r\n");
-		exit(1); }
-	setvbuf(stream,0L,_IOFBF,2048);
-
-	if(del_days) {
-		now=time(NULL);
-		strcpy(str,"sblpurge.dab");
-		if((file=nopen(str,O_RDWR|O_CREAT))==-1) {
-			printf("Error creating %s\r\n",str);
-			exit(1); }
-		l=0;
-		read(file,&l,4);
-		if(now-l>(24L*60L*60L) || maint) {	 /* more than a day since update */
-			bputs("\r\n\1n\1hRunning daily maintenance for Synchronet BBS List...");
-			lseek(file,0L,SEEK_SET);
-			write(file,&now,4);
-			close(file);
-			fseek(stream,0L,SEEK_SET);
-			while(!feof(stream)) {
-				if(!fread(&bbs,sizeof(bbs_t),1,stream))
-					break;
-				if(bbs.name[0]) {
-					if((now-bbs.updated)/(24L*60L*60L)>(time_t)del_days
-						&& (now-bbs.created)/(24L*60L*60L)>(time_t)del_days
-						&& (now-bbs.verified)/(24L*60L*60L)>(time_t)del_days) {
-						lncntr=0;
-						bprintf("\r\n\1n\1hAuto-deleting \1m%s\r\n",bbs.name);
-						if(!(bbs.misc&FROM_SMB)) {
-							sprintf(str,"\1n\1hSBL: \1mYour BBS entry for \1y%s\1m\r\n"
-								"     was auto-deleted from the \1cSynchronet BBS "
-								"List\r\n",bbs.name);
-							i=usernumber(bbs.user);
-							if(i) putsmsg(i,str);
-						}
-						bbs.name[0]=0;
-						fseek(stream,-(long)(sizeof(bbs_t)),SEEK_CUR);
-						fwrite(&bbs,sizeof(bbs_t),1,stream); 
-						fflush(stream); 
-					} else if (!(bbs.misc&FROM_SMB)) { /* Warn user */
-						l=bbs.created;
-						if(l<bbs.updated)
-							l=bbs.updated;
-						if(l<bbs.verified)
-							l=bbs.verified;
-						if((now-l)/(24L*60L*60L)>=(time_t)(del_days/2)) {
-							bprintf("\r\n\1n\1hWarning \1y%s\r\n",bbs.user);
-							lncntr=0;
-							sprintf(str,"\1n\1hSBL: \1mPlease verify your BBS "
-								"entry for \1y%s\1m\r\n     "
-								"in the \1cSynchronet BBS List "
-								"\1mor it will be deleted in \1i\1r%u "
-								"\1n\1h\1mdays.\r\n"
-								,bbs.name
-								,del_days-((now-l)/(24L*60L*60L)));
-							i=usernumber(bbs.user);
-							if(i) putsmsg(i,str); } } } } }
-		else
-			close(file); }
-
-	if(maint)
-		return(0);
-
-	strcpy(list_fmt,DEF_LIST_FMT);
-	while(1) {
-		aborted=0;
-		attr(LIGHTGRAY);
-		cls();
-		COMPILER_DESC(str);
-		bprintf("\1n\1m\1hSynchronet \1wBBS List \1mv3.11 for %s\r\n (XSDK v%s %s %s) "
-			"\r\n\r\n"
-			,PLATFORM_DESC
-			,xsdk_ver
-			,str
-			,__DATE__
-			);
-
-	#define SBL_INDENT "    "
-		sprintf(str,SBL_INDENT"~List all systems (condensed)\r\n"
-					SBL_INDENT"~Change list format\r\n"
-					SBL_INDENT"~Extended information on all systems\r\n"
-					SBL_INDENT"~Turn screen pause %s\r\n"
-					SBL_INDENT"~Find text in BBS entries\r\n"
-					SBL_INDENT"~Generate sorted list\r\n"
-					SBL_INDENT"~Display sorted list\r\n"
-					SBL_INDENT"~New entry scan\r\n"
-					SBL_INDENT"~Add a BBS entry\r\n"
-					SBL_INDENT"~Update a BBS entry\r\n"
-					SBL_INDENT"~Verify a BBS entry\r\n"
-					SBL_INDENT"~Remove a BBS entry\r\n"
-					SBL_INDENT"~Quit back to BBS\r\n"
-					,sbl_pause ? "OFF" : "ON");
-		mnemonics(str);
-		if(SYSOP)
-			mnemonics(SBL_INDENT"~* Undelete entries\r\n");
-
-		bputs("\r\n");
-
-		l=filelength(fileno(stream));
-		if(l>0)
-			bprintf(SBL_INDENT"\1n\1cThere are \1h%lu\1n\1c entries in the online BBS list "
-				"database.\r\n",l/(long)sizeof(bbs_t));
-
-		if(del_days) {
-			bprintf(SBL_INDENT"\1n\1cEntries are auto-deleted \1h%u\1n\1c days after "
-				"last update or verification.\r\n",del_days);
-			bputs(SBL_INDENT"Users are encouraged to \1hV\1n\1cerify (vouch for) any listed "
-				"systems they call.\r\n"); }
-
-		nodesync(); 			/* Display any waiting messages */
-
-		bputs("\r\n"SBL_INDENT"\1y\1hWhich: \1w");
-		switch(getkeys("CLGDEFSNAURTQV!*",0)) {
-			case '!':
-				bprintf("\r\nsizeof(bbs_t)=%u\r\n",sizeof(bbs_t));
-				bprintf("\r\noffsetof(verification_count=%x)\r\n",offsetof(bbs_t,verification_count));
-				pause();
-				break;
-			case '*':
-				cls();
-				if(!SYSOP)
-					break;
-				fseek(stream,0L,SEEK_SET);
-				while(!feof(stream) && !aborted) {
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] && bbs.total_numbers>0) {
-						bbs.name[0]='?';
-						bbs.verified=time(NULL);
-						sprintf(bbs.userverified,"%.25s",user_name);
-						if(yesno(bbs.name)) {
-							bprintf("\1n\1gFirst char: \1h");
-							bbs.name[0]=getkey(0);
-							bprintf("%s\r\n",bbs.name);
-							fseek(stream,-(long)sizeof(bbs_t),SEEK_CUR);
-							fwrite(&bbs,sizeof(bbs_t),1,stream); 
-							fflush(stream); 
-						} 
-					} 
-				}
-				break;
-			case 'L':
-				cls();
-				fseek(stream,0L,SEEK_SET);
-				i=0;
-				while(!feof(stream) && !aborted) {
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] || bbs.total_numbers<1)
-						continue;
-					i++;
-					if(!short_bbs_info(bbs))
-						break;
-					if(!sbl_pause)
-						lncntr=0; }
-				bprintf("\r\n\1n\1h%u systems listed.\r\n",i);
-				if(kbhit())
-					getch();
-				if(lncntr)
-					pause();
-				break;
-			case 'C':
-				cls();
-				bputs("\1n\1c\1hList Format Specifier Definitions:\1n\r\n\r\n");
-				bputs("\1h\1w(\1mN\1w) \1n\1mName of System\r\n");
-				bputs("\1h\1w(\1mS\1w) \1n\1mSoftware Used\r\n");
-				bputs("\1h\1w(\1mP\1w) \1n\1mPhone Number\r\n");
-				bputs("\1h\1w(\1mB\1w) \1n\1mMaximum Connect Rate (in bps)\r\n");
-				bputs("\1h\1w(\1mM\1w) \1n\1mModem Type\r\n");
-				bputs("\1h\1w(\1mY\1w) \1n\1mSysop's Name\r\n");
-				bputs("\1h\1w(\1mT\1w) \1n\1mTotal Number of Nodes\r\n");
-				bputs("\1h\1w(\1mU\1w) \1n\1mTotal Number of Users\r\n");
-				bputs("\1h\1w(\1mH\1w) \1n\1mTotal Storage Capacity (in megabytes)\r\n");
-				bputs("\1h\1w(\1mL\1w) \1n\1mLocation (City, State)\r\n");
-				bputs("\1h\1w(\1mF\1w) \1n\1mDate System was First Online\r\n");
-				bputs("\1h\1w(\1mC\1w) \1n\1mDate Entry was Created\r\n");
-				bputs("\1h\1w(\1mV\1w) \1n\1mDate Entry was Last Verified\r\n");
-				bputs("\1h\1w(\1mD\1w) \1n\1mDate Entry was Last Updated\r\n");
-				bprintf("\r\n\1n\1gDefault Format: \1h%s",DEF_LIST_FMT);
-				bprintf("\r\n\1n\1gCurrent Format: \1h%s\r\n",list_fmt);
-				bprintf("\r\n\1y\1hNew Format: ");
-				if(getstr(tmp,10,K_UPPER|K_LINE)) {
-					if(!strchr(tmp,'P') || !strchr(tmp,'N')) {
-						bputs("\r\n\1h\1mP\1n\1mhone and \1hN\1n\1mame specifiers "
-							"must be present in format.\r\n\r\n");
-						pause(); }
-					else
-						strcpy(list_fmt,tmp); }
-				break;
-			case 'E':
-				fseek(stream,0L,SEEK_SET);
-				while(!feof(stream) && !aborted) {
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] || bbs.total_numbers<1)
-						continue;
-					i=long_bbs_info(bbs);
-					if(bbs.name[0] && !i)
-						break;
-#if VERIFICATION_MOD
-					if(i==2) {
-						bbs.verification_count++;
-						fseek(stream,-(int)sizeof(bbs_t),SEEK_CUR);
-						fwrite(&bbs,sizeof(bbs_t),1,stream);
-						fflush(stream);
-						fseek(stream,-(int)sizeof(bbs_t),SEEK_CUR);
-					}
-#endif
-					if(!sbl_pause)
-						lncntr=0; }
-				break;
-			case 'F':   /* Find text */
-				cls();
-				bputs("\1y\1hText to search for: ");
-				if(!getstr(name,25,K_UPPER|K_LINE))
-					break;
-				ch=yesno("\r\nDisplay extended information");
-
-				found=0;
-				bputs("\1n\1h\r\nSearching...\r\n\r\n");
-				fseek(stream,0L,SEEK_SET);
-				while(!feof(stream) && !aborted) {
-					if(!sbl_pause)
-						lncntr=0;
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] || bbs.total_numbers<1)
-						continue;
-					tmpbbs=bbs;
-					strupr(tmpbbs.name);
-					strupr(tmpbbs.user);
-					strupr(tmpbbs.software);
-					strupr(tmpbbs.userverified);
-					strupr(tmpbbs.userupdated);
-					strupr(tmpbbs.web_url);
-					for(i=0;i<DESC_LINES;i++) {
-						strupr(tmpbbs.desc[i]);
-						if(strstr(tmpbbs.desc[i],name))
-							break;
-					}
-					if(i<DESC_LINES
-						|| strstr(tmpbbs.name,name)
-						|| strstr(tmpbbs.user,name)
-						|| strstr(tmpbbs.software,name)
-						|| strstr(tmpbbs.userverified,name)
-						|| strstr(tmpbbs.userupdated,name)
-						|| strstr(tmpbbs.web_url,name)
-						) {
-						found++;
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						continue; }
-
-					for(i=0;i<tmpbbs.total_sysops;i++) {
-						strupr(tmpbbs.sysop[i]);
-						if(strstr(tmpbbs.sysop[i],name))
-							break; }
-					if(i<tmpbbs.total_sysops) {
-						found++;
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						continue; }
-
-					for(i=0;i<tmpbbs.total_networks;i++) {
-						strupr(tmpbbs.network[i]);
-						strupr(tmpbbs.address[i]);
-						if(strstr(tmpbbs.network[i],name)
-							|| strstr(tmpbbs.address[i],name))
-							break; }
-					if(i<tmpbbs.total_networks) {
-						found++;
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						continue; }
-
-					for(i=0;i<tmpbbs.total_terminals;i++) {
-						strupr(tmpbbs.terminal[i]);
-						if(strstr(tmpbbs.terminal[i],name))
-							break; }
-					if(i<tmpbbs.total_terminals) {
-						found++;
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						continue; }
-
-					for(i=0;i<tmpbbs.total_numbers;i++) {
-						strupr(tmpbbs.number[i].modem.number);
-						strupr(tmpbbs.number[i].modem.desc);
-						strupr(tmpbbs.number[i].modem.location);
-						if(strstr(tmpbbs.number[i].modem.number,name)
-							|| strstr(tmpbbs.number[i].modem.desc,name)
-							|| strstr(tmpbbs.number[i].modem.location,name))
-							break; }
-					if(i<tmpbbs.total_numbers) {
-						found++;
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						continue; } }
-				if(!ch || !found) {
-					CRLF;
-					if(kbhit())
-						getch();
-					if(found)
-						bprintf("\1n\1h%u systems listed.\r\n",found);
-					pause(); }
-				break;
-			case 'G':   /* Generated sorted list */
-				cls();
-				if(!filelength(fileno(stream))) {
-					bprintf("No BBS list exists.\r\n");
-					pause();
-					break; }
-				bputs("\1n\1c\1hSort Options:\1n\r\n\r\n");
-				bputs("\1h\1w(\1mN\1w) \1n\1mName of System\r\n");
-				bputs("\1h\1w(\1mS\1w) \1n\1mSoftware Used\r\n");
-				bputs("\1h\1w(\1mP\1w) \1n\1mPhone Number\r\n");
-				bputs("\1h\1w(\1mB\1w) \1n\1mMaximum Connect Rate (in bps)\r\n");
-				bputs("\1h\1w(\1mM\1w) \1n\1mModem Type\r\n");
-				bputs("\1h\1w(\1mY\1w) \1n\1mSysop's Name\r\n");
-				bputs("\1h\1w(\1mT\1w) \1n\1mTotal Number of Nodes\r\n");
-				bputs("\1h\1w(\1mU\1w) \1n\1mTotal Number of Users\r\n");
-				bputs("\1h\1w(\1mH\1w) \1n\1mTotal Storage Capacity (in megabytes)\r\n");
-				bputs("\1h\1w(\1mL\1w) \1n\1mLocation (City, State)\r\n");
-				bputs("\1h\1w(\1mF\1w) \1n\1mDate System was First Online\r\n");
-				bputs("\1h\1w(\1mC\1w) \1n\1mDate Entry was Created\r\n");
-				bputs("\1h\1w(\1mV\1w) \1n\1mDate Entry was Last Verified\r\n");
-				bputs("\1h\1w(\1mD\1w) \1n\1mDate Entry was Last Updated\r\n");
-				bprintf("\r\n\1y\1hSort by (\1wQ\1y=Quit): \1w");
-				ch=getkeys("NSPBMYTUHLFCVDQ",0);
-				if(!ch || ch=='Q')
-					break;
-				cls();
-				bputs("\1n\1hSorting...     \1m");
-				fseek(stream,0L,SEEK_SET);
-				i=j=done=0;
-				sort_by_str=0;
-				sortstr=NULL;
-				sortint=NULL;
-				while(!feof(stream) && !done) {
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					j++;
-					bprintf("\b\b\b\b%4u",j);
-					if(!bbs.name[0])	/* don't sort deleted entries */
-						continue;
-					if(bbs.total_numbers<1)	/* don't sort corrupted entries */
-						continue;
-					i++;
-					switch(ch) {
-						case 'N':
-							sprintf(str,"%.30s",bbs.name);
-							sort_by_str=1;
-							break;
-						case 'S':
-							sprintf(str,"%.30s",bbs.software);
-							sort_by_str=1;
-							break;
-						case 'P':
-							sprintf(str,"%.30s",bbs.number[0].modem.number);
-							sort_by_str=1;
-							break;
-						case 'M':
-							sprintf(str,"%.30s",bbs.number[0].modem.desc);
-							sort_by_str=1;
-							break;
-						case 'Y':
-							sprintf(str,"%.30s",bbs.sysop[0]);
-							sort_by_str=1;
-							break;
-						case 'L':
-							sprintf(str,"%.30s",bbs.number[0].modem.location);
-							sort_by_str=1;
-							break;
-						case 'B':
-							l=bbs.number[0].modem.max_rate;
-							break;
-						case 'T':
-							l=bbs.nodes;
-							break;
-						case 'U':
-							l=bbs.users;
-							break;
-						case 'H':
-							l=bbs.megs;
-							break;
-						case 'F':
-							l=bbs.birth;
-							break;
-						case 'C':
-							l=bbs.created;
-							break;
-						case 'V':
-							l=bbs.verified;
-							break;
-						case 'D':
-							l=bbs.updated;
-							break; }
-					if(sort_by_str) {
-						if((sortstr=(sortstr_t *)REALLOC(sortstr
-							,sizeof(sortstr_t)*i))==NULL) {
-							bprintf("\r\n\7Memory allocation error\r\n");
-							LFREE(sortstr);
-							done=1;
-							continue; }
-						strcpy(sortstr[i-1].str,str);
-						sortstr[i-1].offset=j-1; }
-					else {
-						if((sortint=(sortint_t *)REALLOC(sortint
-							,sizeof(sortint_t)*i))==NULL) {
-							bprintf("\r\n\7Memory allocation error\r\n");
-							LFREE(sortint);
-							done=1;
-							continue; }
-						sortint[i-1].i=l;
-						sortint[i-1].offset=j-1; } }
-
-				if(done) {
-					pause();
-					break; }
-
-				if(sort_by_str)
-					qsort((void *)sortstr,i,sizeof(sortstr[0])
-						,(int(*)(const void *, const void *))sortstr_cmp);
-				else
-					qsort((void *)sortint,i,sizeof(sortint[0])
-						,(int(*)(const void *, const void *))sortint_cmp);
-
-				bprintf("\r\n\r\n\1h\1gCreating index...");
-				sprintf(str,"sort_%03d.ndx",node_num);
-				if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
-					bprintf("\r\n\7Error creating %s\r\n",str);
-					if(sort_by_str)
-						LFREE(sortstr);
-					else
-						LFREE(sortint);
-					pause();
-					break; }
-				for(j=0;j<i;j++)
-					if(sort_by_str)
-						write(file,&sortstr[j].offset,2);
-					else
-						write(file,&sortint[j].offset,2);
-				close(file);
-				if(sort_by_str)
-					LFREE(sortstr);
-				else
-					LFREE(sortint);
-				bputs("\r\n\r\n\1n\1hDone.\r\n");
-				pause();
-				break;
-			case 'D':
-				cls();
-				sprintf(str,"sort_%03d.ndx",node_num);
-				if((file=nopen(str,O_RDONLY))==-1) {
-					bputs("\1n\1r\1hSorted list not generated.\r\n");
-					pause(); }
-				ch=yesno("Display extended information");
-				cls();
-				while(/* !eof(file) && not on unix */ !aborted) {
-					if(read(file,&i,2)!=2)
-						break;
-					fseek(stream,(long)i*sizeof(bbs_t),SEEK_SET);
-					if(!sbl_pause)
-						lncntr=0;
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] || bbs.total_numbers<1)
-						continue;
-					if(ch && !long_bbs_info(bbs))
-						break;
-					if(!ch && !short_bbs_info(bbs))
-						break; }
-				close(file);
-				if(kbhit())
-					getch();
-				if(lncntr)
-					pause();
-				break;
-			case 'N':   /* New (updated) entry scan */
-				cls();
-				bputs("\1y\1hLast update (MM/DD/YY): ");
-				if(!getstr(str,8,K_UPPER|K_LINE))
-					break;
-				l=dstrtounix(str);
-				ch=yesno("\r\nDisplay extended information");
-				found=0;
-				bputs("\1n\1h\r\nSearching...\r\n\r\n");
-				fseek(stream,0L,SEEK_SET);
-				while(!feof(stream) && !aborted) {
-					if(!sbl_pause)
-						lncntr=0;
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!bbs.name[0] || bbs.total_numbers<1)
-						continue;
-					if(bbs.updated>=l || bbs.created>=l) {
-						if(ch && !long_bbs_info(bbs))
-							break;
-						if(!ch && !short_bbs_info(bbs))
-							break;
-						found++;
-						continue; } }
-				if(!ch || !found) {
-					CRLF;
-					pause(); }
-				break;
-			case 'A':
-				cls();
-				if((uint)user_level<add_ml) {
-					bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
-					pause();
-					break; }
-				bputs("\1g\1hAdding a BBS entry:\1n\r\n\r\n");
-				bputs("\1n\1gHit ENTER for unknown data items.\r\n\r\n");
-				memset(&bbs,0,sizeof(bbs_t));
-				if(!get_bbs_info(&bbs))
-					break;
-				bputs("\1n\1h\r\nSearching for duplicates...");
-				fseek(stream,0L,SEEK_SET);
-				i=0;
-				dots(0);
-				while(!feof(stream) && !i) {
-					dots(1);
-					if(!fread(&tmpbbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!stricmp(tmpbbs.name,bbs.name)) i=1; }
-				if(i) {
-					bprintf("\7\1n\1h\1r\1i\r\n\r\n%s \1n\1h\1ralready exists!"
-						"\r\n\r\n"
-						,bbs.name);
-					pause();
-					break; }
-
-				bputs("\1n\1h\r\nSaving...");
-				fseek(stream,0L,SEEK_SET);
-				dots(0);
-				while(!feof(stream)) {
-					dots(1);
-					if(!fread(&ch,1,1,stream))
-						break;
-					if(!ch) {			/* first byte is null */
-						fseek(stream,-1L,SEEK_CUR);
-						break; }
-					fseek(stream,(long)sizeof(bbs_t)-1L,SEEK_CUR); }
-				bbs.created=time(NULL);
-				fwrite(&bbs,sizeof(bbs_t),1,stream);
-				fflush(stream);
-				if(notify_user && notify_user!=user_number) {
-					sprintf(str,"\1n\1hSBL: \1y%s \1madded \1c%s\1m "
-						"to the BBS List\r\n",user_name,bbs.name);
-					putsmsg(notify_user,str); }
-				break;
-			case 'R':       /* Remove an entry */
-				cls();
-				if((uint)user_level<remove_ml) {
-					bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
-					pause();
-					break; }
-				bprintf("\1y\1hRemove which system: ");
-				if(!getstr(name,25,K_LINE|K_UPPER))
-					break;
-				bputs("\1n\1h\r\nSearching...");
-				fseek(stream,0L,SEEK_SET);
-				found=0;
-				dots(0);
-				while(!feof(stream) && !aborted) {
-					dots(1);
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!stricmp(bbs.name,name) || partname(bbs.name,name)) {
-						found=1;
-						for(i=0;i<bbs.total_sysops && i<MAX_SYSOPS;i++)
-							if(!stricmp(bbs.sysop[i],user_name))
-								break;
-						if(SYSOP || !stricmp(bbs.user,user_name)
-							|| i<bbs.total_sysops) {
-							fseek(stream,-(long)(sizeof(bbs_t)),SEEK_CUR);
-							strcpy(tmp,bbs.name);
-							bbs.name[0]=0;
-							bbs.updated=time(NULL);
-							fwrite(&bbs,sizeof(bbs_t),1,stream);
-							fflush(stream);
-							bprintf("\r\n\r\n\1m%s\1c deleted."
-								,tmp);
-							if(notify_user && notify_user!=user_number) {
-								sprintf(str,"\1n\1hSBL: \1y%s \1mremoved \1c%s\1m "
-									"from the BBS List\r\n",user_name,tmp);
-								putsmsg(notify_user,str); } }
-						else
-							bprintf("\r\n\r\n\1rYou did not create \1m%s\1n."
-								,bbs.name);
-						break; } }
-				if(!found)
-					bprintf("\r\n\r\n\1m%s\1c not found.",name);
-				CRLF;
-				CRLF;
-				pause();
-				break;
-			case 'T':
-				sbl_pause=!sbl_pause;
-				break;
-			case 'V':       /* Verify an entry */
-				cls();
-				if((uint)user_level<verify_ml) {
-					bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
-					pause();
-					break; }
-				bprintf("\1y\1hVerify which system: ");
-				if(!getstr(name,25,K_LINE|K_UPPER))
-					break;
-				bputs("\1n\1h\r\nSearching...");
-				fseek(stream,0L,SEEK_SET);
-				found=0;
-				dots(0);
-				while(!feof(stream) && !aborted) {
-					dots(1);
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!stricmp(bbs.name,name) || partname(bbs.name,name)) {
-						found=1;
-						bbs.verified=time(NULL);
-						sprintf(bbs.userverified,"%.25s",user_name);
-						fseek(stream,-(long)(sizeof(bbs_t)),SEEK_CUR);
-						fwrite(&bbs,sizeof(bbs_t),1,stream);
-						fflush(stream);
-						bprintf("\r\n\r\n\1m%s\1c verified. \1r\1h\1iThank you!"
-							,bbs.name);
-						sprintf(str,"\1n\1hSBL: \1y%s \1mverified \1c%s\1m "
-							"in the BBS List\r\n",user_name,bbs.name);
-						if(notify_user && notify_user!=user_number)
-							putsmsg(notify_user,str);
-						if(stricmp(bbs.user,user_name)) {
-							i=usernumber(bbs.user);
-							if(i && i!=(int)user_number) putsmsg(i,str); }
-						break; } }
-				if(!found)
-					bprintf("\r\n\r\n\1m%s\1c not found.",name);
-				CRLF;
-				CRLF;
-				pause();
-				break;
-			case 'U':       /* Update an entry */
-				cls();
-				if((uint)user_level<update_ml) {
-					bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
-					pause();
-					break; }
-				bprintf("\1y\1hUpdate which system: ");
-				if(!getstr(name,25,K_LINE|K_UPPER))
-					break;
-				bputs("\1n\1h\r\nSearching...");
-				fseek(stream,0L,SEEK_SET);
-				found=0;
-				dots(0);
-				while(!feof(stream) && !aborted) {
-					dots(1);
-					l=ftell(stream);
-					if(!fread(&bbs,sizeof(bbs_t),1,stream))
-						break;
-					if(!stricmp(bbs.name,name) || partname(bbs.name,name)) {
-						found=1;
-						break; } }
-				if(found) {
-					for(i=0;i<bbs.total_sysops && i<MAX_SYSOPS;i++)
-						if(!bbs.sysop[i][0] || !stricmp(bbs.sysop[i],user_name))
-							break;
-					if(SYSOP || !stricmp(bbs.user,user_name)
-						|| i<bbs.total_sysops) {
-						CRLF;
-						CRLF;
-						if(get_bbs_info(&bbs)) {
-							bbs.misc&=~FROM_SMB;
-							bbs.updated=time(NULL);
-							sprintf(bbs.userupdated,"%.25s",user_name);
-							fseek(stream,l,SEEK_SET);
-							fwrite(&bbs,sizeof(bbs_t),1,stream);
-							fflush(stream);
-							bprintf("\r\n\1h\1m%s\1c updated.",bbs.name);
-							if(notify_user && notify_user!=user_number) {
-								sprintf(str,"\1n\1hSBL: \1y%s \1mupdated \1c%s\1m "
-									"in the BBS List\r\n",user_name,bbs.name);
-								putsmsg(notify_user,str); } } }
-					else
-						bprintf("\r\n\r\n\1h\1rYou did not create \1m%s\1n."
-						   ,bbs.name); }
-				else
-					bprintf("\r\n\r\n\1h\1m%s\1c not found.",name);
-				CRLF;
-				CRLF;
-				pause();
-				break;
-			case 'Q':
-				return(0); } }
-	return(-1);
-}
-
-/* End of SBL.C */
diff --git a/xtrn/sbl/sbl.cfg b/xtrn/sbl/sbl.cfg
deleted file mode 100644
index 6b27510098b8ea9a8263a4eb90caa1e94b90af3d..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-90					Days to keep non-updated entries
-10					Minimum security level to add
-10 					Minimum security level to update
-10					Minimum security level to remove
-10					Minimum security level to verify
-1					User to notify of changes (0=none)
diff --git a/xtrn/sbl/sbl.doc b/xtrn/sbl/sbl.doc
deleted file mode 100644
index 642ba2b57324d579797f4595d0176a1caec38122..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.doc
+++ /dev/null
@@ -1,95 +0,0 @@
-Synchronet BBS List v3.11 for Win32
-===================================
-
-Create the directory: SBL off of your Synchronet XTRN directory.
-(Example: C:\SBBS\XTRN\SBL) 
-
-Make sure SBL.EXE and SBL.CFG are in this directory.
-
-Use an ASCII editor to edit the Synchronet BBS List config file (SBL.CFG) to 
-your liking.
-
-Under SCFG->External Programs->Online Programs->Main, hit INS and add 
-Synchronet BBS List with the following configuration:
-
-Name                       Synchronet BBS List
-Internal Code              SBL
-Start-up Directory         ..\XTRN\SBL
-Command Line               sbl
-Clean-up Command Line
-Execution Cost             None
-Access Requirements
-Execution Requirements
-Multiple Concurrent Users  Yes
-Intercept I/O Interrupts   No
-Swap BBS out of Memory     Yes
-Modify User Data           No
-Execute on Event           No
-BBS Drop File Type         Synchronet      XTRN.DAT
-Place Drop File In         Node Directory
-
-Since SBL v3 is a 32-bit program, you MUST add it ("SBL") to your native
-(OS/2) program list under SCFG->External Programs->OS/2 Program List.
-
-SBL Utilities
-=============
-
-SBLPACK.EXE	Remove deleted entries to save disk space and speed up listings
-SBL2TXT.EXE     Convert SBL listing to a text file
-
-Networking the Synchronet BBS List
-==================================
-
-If you wish to link your SBL database with other Synchronet BBSs, you must
-carry the Synchronet Data echo via DOVE-Net, FidoNet, or RIME and add
-the following two events in SCFG->External Programs->Timed Events:
-
-Internal Code			SMB2SBL
-Start-up Directory		..\XTRN\SBL
-Command Line			SMB2SBL %jSUBS\SYNCDATA SBL.DAB 
-Execution Node			1
-Execution Days			Sun Mon Tue Wed Thu Fri Sat
-Execution Time			04:30
-Requires Exclusive Execution	No
-Force Users Off-line for Event	No
-
-Internal Code			SBL2SMB
-Start-up Directory		..\XTRN\SBL
-Command Line			SBL2SMB SBL.DAB %jSUBS\SYNCDATA
-Execution Node			1
-Execution Days			Sun Mon Tue Wed Thu Fri Sat
-Execution Time			04:31
-Requires Exclusive Execution	No
-Force Users Off-line for Event  No
-
-Change "SYNCDATA" to the internal code of the Synchronet Data sub-board on
-your BBS. We used SYNCDATA, since that is the example given in the Synchronet
-manual for the DOVE-Net Synchronet Data sub-board internal code. It is okay
-if you used a completely different internal code, as long as you specify that
-code instead of "SYNCDATA" on the above command lines.
-
-Make note that all networked SBL entries will be deleted from Vertrauen
-(Home of the Synchronet BBS List) after 90 days unless the entry is
-retransmitted in the message base or updated manually on Vertrauen in that
-time. To cause a retransmission from your BBS, you must (U)pdate the entry
-using SBL and then SBL2SMB will re-export it automatically next time it is run
-(via Timed Event). (V)erified entries are not re-exported by SBL2SMB, only new
-and updated entries. You can also create a BBS entry message by hand (not
-using SBL). Download SBBSLIST.ZIP from Vertrauen for more details.
-
-Source Code
-===========
-
-If you are a C programmer, you may find the included source code interesting
-and/or useful as an example for writing your own XSDK and/or SMB utilities.
-
-MAKEFILE is for use with Borland C++ v3.x or v4.x and the Synchronet XSDK
-to create SBL.EXE. SBL.C and SBLDEFS.H must also in the current directory when
-MAKE is run.
-
-The SMB C library (SMB_120.ZIP) is required to compile SBL2SMB.C and SMB2SBL.C
-(MAKE.BAT included to compile them).
-
-SBL2TXT.C is included as an SBL.DAB to SBL.TXT converter.
-
-/* End of SBL.DOC */
diff --git a/xtrn/sbl/sbl.dsp b/xtrn/sbl/sbl.dsp
deleted file mode 100644
index 413b232b25628d33d0be6f65ebd28bfe6d822b5b..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl.dsp
+++ /dev/null
@@ -1,106 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sbl" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=sbl - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sbl.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sbl.mak" CFG="sbl - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sbl - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "sbl - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sbl - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "sbl___Win32_Release"
-# PROP BASE Intermediate_Dir "sbl___Win32_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "sbl - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "sbl___Win32_Debug"
-# PROP BASE Intermediate_Dir "sbl___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /map /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sbl - Win32 Release"
-# Name "sbl - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\sbl.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\sbldefs.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\Sdk\xsdk.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\Sdk\xsdkvars.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\sdk\xsdkwrap.c
-# End Source File
-# End Target
-# End Project
diff --git a/xtrn/sbl/sbl2smb.c b/xtrn/sbl/sbl2smb.c
deleted file mode 100644
index b67ae606c2367e16a084a971f5233fae4bb276e8..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl2smb.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/* sbl2smb.c */
-
-/* Scans SBL database and posts any additions/updates into the an SMB base */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This program is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU General Public License				*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * 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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-#define  uint unsigned int
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include <io.h>		/* access */
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <share.h>
-
-#include "sbbsdefs.h"
-#include "smblib.h"
-#include "smbwrap.h"
-#include "sbldefs.h"
-#include "xsdkwrap.h"	/* PLATFORM_DESC */
-
-#define SBL2SMB_VER "2.20/" PLATFORM_DESC
-
-smb_t		smb;
-extern int	daylight=0;
-extern long timezone=0L;
-
-unsigned	_stklen=16000;
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str'								*/
-/****************************************************************************/
-void truncsp(char *str)
-{
-	uint c;
-
-	c=strlen(str);
-	while(c && (uchar)str[c-1]<=SP) c--;
-	str[c]=0;
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char* unixtodstr(time_t unix_time, char *str)
-{
-	struct tm* tm;
-
-	if(!unix_time)
-		strcpy(str,"00/00/00");
-	else {
-		tm=gmtime(&unix_time);
-		if(tm==NULL) {
-			strcpy(str,"00/00/00");
-			return(str);
-		}
-		if(tm->tm_mon>11) {	  /* DOS leap year bug */
-			tm->tm_mon=0;
-			tm->tm_year++; }
-		if(tm->tm_mday>31)
-			tm->tm_mday=1;
-		sprintf(str,"%02u/%02u/%02u",tm->tm_mday,tm->tm_mon+1
-			,TM_YEAR(tm->tm_year));
-	}
-	return(str);
-}
-
-
-
-#define BUF_LEN 8192
-
-int main(int argc, char **argv)
-{
-	uchar	str[128],tmp[128],buf[BUF_LEN],*p,software[128];
-	int 	i,file;
-	ushort	xlat;
-	long	length;
-	ulong	offset;
-	time_t	last,t;
-	bbs_t	bbs;
-	smbmsg_t msg;
-	FILE	*stream;
-
-	fprintf(stderr,"\nSBL2SMB v%s - Write SBL to SMB - Developed 1994-2000 "
-		"Rob Swindell\n\n",SBL2SMB_VER);
-	if(argc<3) {
-		fprintf(stderr,"usage: sbl2smb <sbl.dab> <smb_file> [/s:software]\n\n");
-		fprintf(stderr,"ex: sbl2smb c:\\sbbs\\xtrn\\sbl\\sbl.dab "
-			"c:\\sbbs\\data\\subs\\syncdata /s:syn\n");
-		return(1); }
-
-	software[0]=0;
-	if(argc>3 && !strnicmp(argv[3],"/S:",3))
-		strcpy(software,argv[3]+3);
-
-	strcpy(smb.file,argv[2]);
-	strupr(smb.file);
-
-	strcpy(str,argv[1]);
-	strupr(str);
-	if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-		printf("error opening %s\n",str);
-		return(1); }
-	if((stream=fdopen(file,"rb"))==NULL) {
-		printf("error fdopening %s\n",str);
-		return(1); }
-	strcpy(tmp,str);
-	p=strrchr(tmp,'.');
-	if(p) {
-		(*p)=0;
-		strcat(tmp,"2smb.dab");
-		if((file=open(tmp,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-			printf("error opening %s\n",str);
-			return(1); }
-		t=time(NULL);
-		if(read(file,&last,sizeof(time_t))!=sizeof(time_t))
-			last=0;
-		lseek(file,0L,SEEK_SET);
-		write(file,&t,sizeof(time_t));
-		close(file); }
-
-	sprintf(str,"%s.SHD",smb.file);
-	if(!fexist(str)) {
-		printf("%s doesn't exist\n",smb.file);
-		return(0); }
-	fprintf(stderr,"Opening %s\n",smb.file);
-	smb.retry_time=30;
-	if((i=smb_open(&smb))!=0) {
-		printf("smb_open returned %d\n",i);
-		return(1); }
-	i=smb_locksmbhdr(&smb);
-	if(i) {
-		printf("smb_locksmbhdr returned %d\n",i);
-		return(1); }
-	i=smb_getstatus(&smb);
-	smb_unlocksmbhdr(&smb);
-	if(i) {
-		printf("smb_getstatus returned %d\n",i);
-		return(1); }
-
-	while(!feof(stream)) {
-		if(!fread(&bbs,sizeof(bbs_t),1,stream))
-			break;
-		if(bbs.total_numbers<1		/* corrupted? */
-			|| bbs.total_numbers>MAX_NUMBERS)
-			continue;
-		truncsp(bbs.name);
-		if(bbs.name[0]<=' '			/* corrupted? */
-			|| bbs.misc&FROM_SMB
-			|| (bbs.updated<last && bbs.created<last 
-				&& bbs.verified<last))
-			continue;
-		if(software[0] && strnicmp(software,bbs.software,strlen(software)))
-			continue;
-
-		truncsp(bbs.user);
-		if(bbs.user[0]<=' ')		/* corrupted? */
-			continue;
-		truncsp(bbs.software);
-		if(bbs.software[0]<=' ')	/* corrupted? */
-			continue;
-
-		printf("%s\r\n",bbs.name);
-		memset(buf,0,BUF_LEN);
-
-		sprintf(str,"%-15.15s%s\r\n"
-			,"Name:",bbs.name);
-		strcat(buf,str);
-
-		sprintf(str,"%-15.15s%s\r\n"
-			,"Birth:",unixtodstr(bbs.birth,tmp));
-		strcat(buf,str);
-
-		sprintf(str,"%-15.15s%s\r\n"
-			,"Software:",bbs.software);
-		strcat(buf,str);
-
-		for(i=0;i<bbs.total_sysops;i++) {
-			truncsp(bbs.sysop[i]);
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Sysop:",bbs.sysop[i]);
-			strcat(buf,str); }
-
-		strcat(buf,"\r\n");
-
-		truncsp(bbs.sysop_email);
-		if(bbs.sysop_email[0]) {
-			sprintf(str,"%-15.15s%s\r\n"
-				,"E-mail:",bbs.sysop_email);
-			strcat(buf,str);
-		}
-
-		truncsp(bbs.web_url);
-		if(bbs.web_url[0]) {
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Web-site:",bbs.web_url);
-			strcat(buf,str);
-		}
-
-		strcat(buf,"\r\n");
-
-		for(i=0;i<bbs.total_numbers;i++) {
-			truncsp(bbs.number[i].modem.number);
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Number:",bbs.number[i].modem.number);
-			strcat(buf,str);
-
-			sprintf(str,"%-15.15s%u\r\n"
-				,"MinRate:",bbs.number[i].modem.min_rate);
-			strcat(buf,str);
-
-			sprintf(str,"%-15.15s%u\r\n"
-				,"MaxRate:",bbs.number[i].modem.max_rate);
-			strcat(buf,str);
-
-			if(bbs.number[i].modem.min_rate!=0xffff) {
-
-				sprintf(str,"%-15.15s%s\r\n"
-					,"Modem:",bbs.number[i].modem.desc);
-				strcat(buf,str);
-			}
-			truncsp(bbs.number[i].modem.location);
-			sprintf(str,"%-15.15s%s\r\n"
-			   ,"Location:",bbs.number[i].modem.location);
-			strcat(buf,str);
-			if(i+1<bbs.total_numbers)
-				strcat(buf,"\r\n"); }
-
-		if(bbs.total_networks)
-			strcat(buf,"\r\n");
-		for(i=0;i<bbs.total_networks;i++) {
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Network:",bbs.network[i]);
-			strcat(buf,str);
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Address:",bbs.address[i]);
-			strcat(buf,str);
-			if(i+1<bbs.total_networks)
-				strcat(buf,"\r\n"); }
-
-		strcat(buf,"\r\n");
-		for(i=0;i<bbs.total_terminals;i++) {
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Terminal:",bbs.terminal[i]);
-			strcat(buf,str); }
-
-		strcat(buf,"\r\n");
-		sprintf(str,"%-15.15s%lu\r\n"
-			,"Megs:",bbs.megs);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%lu\r\n"
-			,"Msgs:",bbs.msgs);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%lu\r\n"
-			,"Files:",bbs.files);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%u\r\n"
-			,"Nodes:",bbs.nodes);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%u\r\n"
-			,"Users:",bbs.users);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%u\r\n"
-			,"Subs:",bbs.subs);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%u\r\n"
-			,"Dirs:",bbs.dirs);
-		strcat(buf,str);
-		sprintf(str,"%-15.15s%u\r\n"
-			,"Xtrns:",bbs.xtrns);
-		strcat(buf,str);
-
-		if(bbs.desc[0][0])
-			strcat(buf,"\r\n");
-		for(i=0;i<5;i++) {
-			if(!bbs.desc[i][0])
-				break;
-			sprintf(str,"%-15.15s%s\r\n"
-				,"Desc:",bbs.desc[i]);
-			strcat(buf,str); }
-
-		strcat(buf,"\r\n--- SBL2SMB v");
-		strcat(buf,SBL2SMB_VER);
-
-		length=strlen(buf);   /* +2 for translation string */
-
-		if(smb.status.attr&SMB_HYPERALLOC)
-			offset=smb_hallocdat(&smb);
-		else {
-			i=smb_open_da(&smb);
-			if(i) {
-				printf("smb_open_da returned %d\n",i);
-				exit(1); }
-			offset=smb_allocdat(&smb,length+2,1);
-			fclose(smb.sda_fp); }
-
-		fseek(smb.sdt_fp,offset,SEEK_SET);
-		xlat=XLAT_NONE;
-		fwrite(&xlat,2,1,smb.sdt_fp);
-		fwrite(buf,length,1,smb.sdt_fp);
-		length+=2;
-
-		memset(&msg,0,sizeof(smbmsg_t));
-		memcpy(msg.hdr.id,"SHD\x1a",4);
-		msg.hdr.version=smb_ver();
-		msg.hdr.when_written.time=time(NULL);
-    
-		msg.hdr.offset=offset;
-
-		strcpy(str,"SBL");
-		i=smb_hfield(&msg,RECIPIENT,(ushort)strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.to=crc16(str);
-
-		strcpy(str,bbs.user);
-		i=smb_hfield(&msg,SENDER,(ushort)strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.from=crc16(str);
-
-		strcpy(str,bbs.name);
-		i=smb_hfield(&msg,SUBJECT,(ushort)strlen(str),str);
-		if(i) {
-			printf("smb_hfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		strlwr(str);
-		msg.idx.subj=crc16(str);
-
-		i=smb_dfield(&msg,TEXT_BODY,length);
-		if(i) {
-			printf("smb_dfield returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-
-		i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
-		if(i) {
-			printf("smb_addmsghdr returned %d\n",i);
-			smb_freemsgdat(&smb,offset,length,1);
-			exit(1); }
-		smb_freemsgmem(&msg); }
-	return(0);
-}
-
-/* End of SBL2SMB.C */
diff --git a/xtrn/sbl/sbl2smb.dsp b/xtrn/sbl/sbl2smb.dsp
deleted file mode 100644
index 6af82f5bc1d6a001fac54c1844392a952aaa9112..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl2smb.dsp
+++ /dev/null
@@ -1,96 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sbl2smb" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=sbl2smb - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sbl2smb.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sbl2smb.mak" CFG="sbl2smb - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sbl2smb - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "sbl2smb - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sbl2smb - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "c:\src\sbbs3" /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "sbl2smb - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "sbl2smb___Win32_Debug"
-# PROP BASE Intermediate_Dir "sbl2smb___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ  /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "c:\src\sbbs3" /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ  /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sbl2smb - Win32 Release"
-# Name "sbl2smb - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\sbl2smb.c
-# End Source File
-# Begin Source File
-
-SOURCE=C:\src\sbbs3\smblib.c
-# End Source File
-# Begin Source File
-
-SOURCE=C:\src\sbbs3\smbwrap.c
-# End Source File
-# End Target
-# End Project
diff --git a/xtrn/sbl/sbl2txt.c b/xtrn/sbl/sbl2txt.c
deleted file mode 100644
index 8dd55531a0b83117236c06fe076099b8a0752a92..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbl2txt.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* SBL2TXT.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/* Converts Synchronet BBS List (SBL.DAB) to text file */
-
-#include "xsdk.h"
-#include "sbldefs.h"
-
-char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
-char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
-            ,"Jul","Aug","Sep","Oct","Nov","Dec"};
-char *nulstr="";
-char tmp[256];
-struct date date;
-struct time curtime;
-
-extern int daylight=0;
-extern long timezone=0L;
-
-/****************************************************************************/
-/* Generates a 24 character ASCII string that represents the time_t pointer */
-/* Used as a replacement for ctime()										*/
-/****************************************************************************/
-char *timestr(time_t *intime)
-{
-	static char str[256];
-    char mer[3],hour;
-    struct tm *gm;
-
-gm=localtime(intime);
-if(gm->tm_hour>=12) {
-    if(gm->tm_hour==12)
-        hour=12;
-    else
-        hour=gm->tm_hour-12;
-    strcpy(mer,"pm"); }
-else {
-    if(gm->tm_hour==0)
-        hour=12;
-    else
-        hour=gm->tm_hour;
-    strcpy(mer,"am"); }
-sprintf(str,"%s %s %02d %4d %02d:%02d %s"
-    ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,gm->tm_year%100
-    ,hour,gm->tm_min,mer);
-return(str);
-}
-
-/****************************************************************************/
-/* Converts unix time format (long - time_t) into a char str MM/DD/YY		*/
-/****************************************************************************/
-char *unixtodstr(time_t unix, char *str)
-{
-
-if(!unix)
-	strcpy(str,"00/00/00");
-else {
-	unixtodos(unix,&date,&curtime);
-	if((unsigned)date.da_mon>12) {	  /* DOS leap year bug */
-		date.da_mon=1;
-		date.da_year++; }
-	if((unsigned)date.da_day>31)
-		date.da_day=1;
-	sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
-		,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
-return(str);
-}
-
-
-void long_bbs_info(FILE *out, bbs_t bbs)
-{
-	int i;
-
-fprintf(out,"BBS Name: %s since %s\r\n"
-	,bbs.name,unixtodstr(bbs.birth,tmp));
-fprintf(out,"Operator: ");
-for(i=0;i<bbs.total_sysops;i++) {
-	if(i) {
-		if(bbs.total_sysops>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(!(i%4))
-			fprintf(out,"\r\n          ");
-		if(i+1==bbs.total_sysops)
-			fprintf(out,"and "); }
-	fprintf(out,"%s",bbs.sysop[i]); }
-fprintf(out,"\r\n");
-fprintf(out,"Software: %-15.15s Nodes: %-5u "
-	"Users: %-5u Doors: %u\r\n"
-	,bbs.software,bbs.nodes,bbs.users,bbs.xtrns);
-fprintf(out,"Download: %lu files in %u directories of "
-	"%luMB total space\r\n"
-	,bbs.files,bbs.dirs,bbs.megs);
-fprintf(out,"Messages: %lu messages in %u sub-boards\r\n"
-	,bbs.msgs,bbs.subs);
-fprintf(out,"Networks: ");
-for(i=0;i<bbs.total_networks;i++) {
-	if(i) {
-		if(bbs.total_networks>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(!(i%3))
-			fprintf(out,"\r\n          ");
-		if(i+1==bbs.total_networks)
-			fprintf(out,"and "); }
-	fprintf(out,"%s [%s]",bbs.network[i],bbs.address[i]); }
-fprintf(out,"\r\n");
-fprintf(out,"Terminal: ");
-for(i=0;i<bbs.total_terminals;i++) {
-	if(i) {
-		if(bbs.total_terminals>2)
-			fprintf(out,", ");
-		else
-			fputc(SP,out);
-		if(i+1==bbs.total_terminals)
-			fprintf(out,"and "); }
-	fprintf(out,"%s",bbs.terminal[i]); }
-fprintf(out,"\r\n\r\n");
-for(i=0;i<bbs.total_numbers;i++)
-	fprintf(out,"%-30.30s %12.12s %5u %-15.15s "
-		"Minimum: %u\r\n"
-		,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
-			? nulstr : bbs.number[i].modem.location
-		,bbs.number[i].modem.number
-		,bbs.number[i].modem.max_rate
-		,bbs.number[i].modem.desc
-		,bbs.number[i].modem.min_rate);
-
-fprintf(out,"\r\n");
-for(i=0;i<5;i++) {
-	if(!bbs.desc[i][0])
-		break;
-	fprintf(out,"%15s%s\r\n",nulstr,bbs.desc[i]); }
-
-fprintf(out,"\r\n");
-fprintf(out,"Entry created on %s by %s\r\n"
-	,timestr(&bbs.created),bbs.user);
-fprintf(out," Last updated on %s\r\n\r\n",timestr(&bbs.updated));
-}
-
-
-void main(int argc, char **argv)
-{
-	char	software[16]="";
-	char	telnet_port[16];
-	int i,in;
-	FILE *out;
-	bbs_t bbs;
-
-for(i=1;i<argc;i++)
-	if(argv[i][0]=='s' && argv[i][1]=='=')
-		sprintf(software,"%.15s",argv[i]+2);
-
-if((in=open("SBL.DAB",O_RDONLY|O_BINARY))==-1) {
-	printf("error opening SBL.DAB\n");
-	return; }
-
-if((out=fopen("SBL.TXT","wb"))==NULL) {
-	printf("error opening/creating SBL.TXT\n");
-	return; }
-
-while(!eof(in)) {
-	read(in,&bbs,sizeof(bbs_t));
-	if(!bbs.name[0])
-		continue;
-	if(software[0] && strnicmp(bbs.software,software,strlen(software)))
-		continue;
-	// long_bbs_info(out,bbs);
-	for(i=0;i<bbs.total_numbers;i++)
-		if(bbs.number[i].modem.min_rate==0xffff) {
-			if(bbs.number[i].telnet.port && bbs.number[i].telnet.port!=23)
-				sprintf(telnet_port,":%u",bbs.number[i].telnet.port);
-			else
-				telnet_port[0]=0;
-			fprintf(out,"%-25.25s  telnet://%s%s\r\n"
-					,bbs.name
-					,bbs.number[i].telnet.addr
-					,telnet_port);
-		} else
-			fprintf(out,"%-25.25s  %12.12s  %5u  %s\r\n"
-				,bbs.name,bbs.number[i].modem.number
-				,bbs.number[i].modem.max_rate
-				,bbs.number[i].modem.desc);
-	}
-close(in);
-fclose(out);
-}
diff --git a/xtrn/sbl/sbldefs.h b/xtrn/sbl/sbldefs.h
deleted file mode 100644
index ae1b7e25e465462a01afe93453f3206d2f17f459..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sbldefs.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* sbldefs.h */
-
-/* Synchronet BBS List Macros, constants, and type definitions */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This program is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU General Public License				*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * 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.	*
- ****************************************************************************/
-
-#define MAX_SYSOPS  5
-#define MAX_NUMBERS 20
-#define MAX_NETS	10
-#define MAX_TERMS	5
-#define DESC_LINES	5
-#define DEF_LIST_FMT "NSTP"
-
-#ifndef IPPORT_TELNET
-#define IPPORT_TELNET 23
-#endif
-
-#define Y2K_2DIGIT_WINDOW	70
-
-/* Misc bits */
-
-#define FROM_SMB	(1L<<0) 	/* BBS info imported from message base */
-
-#ifdef _WIN32	/* necessary for compatibility with SBL */
-#pragma pack(push)
-#pragma pack(1)
-#endif
-
-typedef union _PACK {
-
-		struct {
-			char	number[13]; 		/* Phone number */
-			char	desc[16];			/* Modem description */
-			char	location[31];		/* Location of phone number */
-			ushort	min_rate;			/* Minimum connect rate */
-			ushort	max_rate;			/* Maximum connect rate */
-		} modem;
-
-		struct {
-			char	addr[29];			/* Telnet address */
-			char	location[31];		/* Location  */
-			ushort	unused;				/* 0xffff */
-			ushort	port;				/* TCP port number */
-		} telnet;
-
-} number_t;
-
-typedef struct _PACK {
-	char	 name[26]					/* System name */
-			,user[26]					/* User who created entry */
-			,software[16]				/* BBS software */
-			,total_sysops
-			,sysop[MAX_SYSOPS][26]		/* Sysop names */
-			,total_numbers
-			,total_networks
-			,network[MAX_NETS][16]		/* Network names */
-			,address[MAX_NETS][26]		/* Network addresses */
-			,total_terminals
-			,terminal[MAX_TERMS][16]	/* Terminals supported */
-			,desc[DESC_LINES][51]		/* 5 line description */
-			;
-	ushort	 nodes						/* Total nodes */
-			,users						/* Total users */
-			,subs						/* Total sub-boards */
-			,dirs						/* Total file dirs */
-			,xtrns						/* Total external programs */
-			;
-	time_t	 created					/* Time/date entry was created */
-			,updated					/* Time/date last updated */
-			,birth						/* Birthdate of BBS */
-			;
-	ulong	 megs						/* Storage space in megabytes */
-			,msgs						/* Total messages */
-			,files						/* Total files */
-			,misc						/* Miscellaneous bits */
-			;
-	number_t number[MAX_NUMBERS];		/* Access numbers */
-
-	char	userupdated[26];			/* User who last updated */
-	time_t	verified;					/* Time/Date last vouched for */
-	char	userverified[26];			/* User who last vouched */
-	char	web_url[61];				/* Web-site address */
-	char	sysop_email[61];			/* Sysop's e-mail address */
-	time_t	exported;					/* Date last exported to SMB */
-	ulong	verification_count;			/* Number of successful auto-verifications */
-	ulong	verification_attempts;		/* Number of auto-verification attempts */
-	char	unused[310];				/* Unused space */
-} bbs_t;
-
-#ifdef _WIN32
-#pragma pack(pop)		/* original packing */
-#endif
-
-
-
-/* End of SBL.H */
-
diff --git a/xtrn/sbl/sblpack.c b/xtrn/sbl/sblpack.c
deleted file mode 100644
index 4e31ce01b5f1c793760dc30903d1f81b20f01951..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sblpack.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SBLPACK.C */
-
-/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
-
-/***************************************/
-/* Synchronet BBS List Database Packer */
-/***************************************/
-
-#include <stdio.h>
-#include <stdlib.h>		/* exit() */
-#include <share.h>
-#include <time.h>
-#include <io.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include "xsdkwrap.h"	/* PLATFORM_DESC */
-#include "xsdkdefs.h"
-#include "sbldefs.h"
-
-int main(void)
-{
-	int		file;
-	FILE *	in;
-	FILE *	out;
-	bbs_t	bbs;
-	ulong	records=0;
-	ulong	deleted=0;
-
-	printf("\nSBLPACK v1.10/%s  Developed 1995-2001 Rob Swindell\n\n"
-		,PLATFORM_DESC);
-
-	if((file=sopen("sbl.dab",O_RDWR|O_BINARY,SH_DENYNO))==-1) {
-		printf("\n\7Error opening/creating sbl.dab\n");
-		exit(1); }
-	if((in=fdopen(file,"w+b"))==NULL) {
-		printf("\n\7Error converting sbl.dab file handle to stream\n");
-		exit(1); }
-	setvbuf(in,0L,_IOFBF,2048);
-	if((out=fopen("sbl.tmp","wb"))==NULL) {
-		printf("\n\7Error opening sbl.tmp file\n");
-		exit(1); }
-
-	while(!feof(in)) {
-		if(!fread(&bbs,sizeof(bbs_t),1,in))
-			break;
-		records++;
-		putchar('.');
-		if(bbs.name[0]==0 
-			|| bbs.user[0]==0
-			|| bbs.total_numbers<1) {
-			deleted++;
-			continue;
-		}
-		fwrite(&bbs,sizeof(bbs_t),1,out); 
-	}
-	fcloseall();
-	putchar('\n');
-	if(remove("sbl.dab")) {
-		printf("\n\7Data file in use, can't remove.\n");
-		remove("sbl.tmp");
-		exit(1); 
-	}
-	rename("sbl.tmp","sbl.dab");
-	printf("\nDone.\n");
-	printf("\n%lu records in original file, %lu deleted (packed), new total = %lu.\n"
-		,records,deleted,records-deleted);
-	return(0);
-}
-
diff --git a/xtrn/sbl/sblpack.dsp b/xtrn/sbl/sblpack.dsp
deleted file mode 100644
index 6881368d1fbf07690d9b975211b02abc29c6dd69..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sblpack.dsp
+++ /dev/null
@@ -1,89 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sblpack" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=sblpack - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sblpack.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sblpack.mak" CFG="sblpack - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sblpack - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "sblpack - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sblpack - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "sblpack - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "sblpack___Win32_Debug"
-# PROP BASE Intermediate_Dir "sblpack___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sblpack - Win32 Release"
-# Name "sblpack - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\sblpack.c
-# End Source File
-# End Target
-# End Project
diff --git a/xtrn/sbl/smb2sbl.c b/xtrn/sbl/smb2sbl.c
deleted file mode 100644
index 4d33de6d03387169e20f1ef9d70f1ab752dd8b5d..0000000000000000000000000000000000000000
--- a/xtrn/sbl/smb2sbl.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/* smb2sbl.c */
-
-/* Scans SMB message base for messages to "SBL" and adds them to the SBL    */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This program is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU General Public License				*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * 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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-#define  uint unsigned int
-
-/* #include <dos.h> */
-#include <stdio.h>
-#include <time.h>
-#include <io.h>			/* open */
-#include <fcntl.h>		/* O_RDWR */
-#include <sys/stat.h>	/* S_IWRITE */
-#include <ctype.h>		/* isdigit */
-#include <stdlib.h>		/* atoi */
-#ifndef __FreeBSD__
-	#include <malloc.h>
-#endif
-#include <string.h>
-#include "smblib.h"
-#include "smbwrap.h"	/* fexist/flength */
-#include "sbldefs.h"
-#include "xsdkwrap.h"	/* PLATFORM_DESC */
-
-#define VERSION "2.20/" PLATFORM_DESC
-
-extern int	daylight=0;
-extern long timezone=0L;
-smb_t		smb;
-
-char *loadmsgtxt(smbmsg_t msg, int tails)
-{
-	char	*buf=NULL,*lzhbuf;
-	ushort	xlat;
-	int 	i,lzh;
-	long	l=0,lzhlen,length;
-
-for(i=0;i<msg.hdr.total_dfields;i++) {
-	if(!(msg.dfield[i].type==TEXT_BODY
-		|| (tails && msg.dfield[i].type==TEXT_TAIL)))
-		continue;
-	fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
-		,SEEK_SET);
-	fread(&xlat,2,1,smb.sdt_fp);
-	lzh=0;
-	if(xlat==XLAT_LZH) {
-		lzh=1;
-		fread(&xlat,2,1,smb.sdt_fp); }
-	if(xlat!=XLAT_NONE) 		/* no other translations supported */
-		continue;
-
-	length=msg.dfield[i].length-2;
-	if(lzh) {
-		length-=2;
-		if((lzhbuf=MALLOC(length))==NULL) {
-			printf("ERR_ALLOC lzhbuf of %lu\n",length);
-			return(buf); }
-		fread(lzhbuf,1,length,smb.sdt_fp);
-		lzhlen=*(long *)lzhbuf;
-		if((buf=REALLOC(buf,l+lzhlen+3))==NULL) {
-			FREE(lzhbuf);
-			printf("ERR_ALLOC lzhoutbuf of %l\n",l+lzhlen+1);
-			return(buf); }
-		lzh_decode(lzhbuf,length,buf+l);
-		FREE(lzhbuf);
-		l+=lzhlen; }
-	else {
-		if((buf=REALLOC(buf,l+msg.dfield[i].length+3))==NULL) {
-			printf("ERR_ALLOC of %lu\n",l+msg.dfield[i].length+1);
-			return(buf); }
-		l+=fread(buf+l,1,length,smb.sdt_fp); }
-	buf[l]=CR;
-	l++;
-	buf[l]=LF;
-	l++;
-	buf[l]=0; }
-return(buf);
-}
-
-
-/***************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first CR  */
-/****************************************************************************/
-void truncsp(char *str)
-{
-	char c;
-
-str[strcspn(str,"\r")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
-}
-
-/****************************************************************************/
-/* Converts a date string in format MM/DD/YY into unix time format			*/
-/****************************************************************************/
-time_t dstrtounix(char *instr)
-{
-	char*	p;
-	char*	day;
-	char	str[16];
-	struct tm tm;
-
-	if(!instr[0] || !strncmp(instr,"00/00/00",8))
-		return(0);
-
-	if(isdigit(instr[0]) && isdigit(instr[1])
-		&& isdigit(instr[3]) && isdigit(instr[4])
-		&& isdigit(instr[6]) && isdigit(instr[7]))
-		p=instr;	/* correctly formatted */
-	else {
-		p=instr;	/* incorrectly formatted */
-		while(*p && isdigit(*p)) p++;
-		if(*p==0)
-			return(0);
-		p++;
-		day=p;
-		while(*p && isdigit(*p)) p++;
-		if(*p==0)
-			return(0);
-		p++;
-		sprintf(str,"%02u/%02u/%02u"
-			,atoi(instr)%100,atoi(day)%100,atoi(p)%100);
-		p=str;
-	}
-
-	memset(&tm,0,sizeof(tm));
-	tm.tm_year=((p[6]&0xf)*10)+(p[7]&0xf);
-	if (tm.tm_year<Y2K_2DIGIT_WINDOW)
-		tm.tm_year+=100;
-	tm.tm_mon=((p[0]&0xf)*10)+(p[1]&0xf);
-	tm.tm_mday=((p[3]&0xf)*10)+(p[4]&0xf); 
-	if (tm.tm_mon)
-		tm.tm_mon--;	/* zero-based month field */
-	return(mktime(&tm));
-}
-
-/****************************************************************************/
-/* Updates 16-bit "rcrc" with character 'ch'                                */
-/****************************************************************************/
-void ucrc16(uchar ch, ushort *rcrc) {
-	ushort i, cy;
-    uchar nch=ch;
- 
-for (i=0; i<8; i++) {
-    cy=*rcrc & 0x8000;
-    *rcrc<<=1;
-    if (nch & 0x80) *rcrc |= 1;
-    nch<<=1;
-    if (cy) *rcrc ^= 0x1021; }
-}
-
-/****************************************************************************/
-/* Returns 16-crc of string (not counting terminating NULL) 				*/
-/****************************************************************************/
-ushort crc16(char *str)
-{
-	int 	i=0;
-	ushort	crc=0;
-
-ucrc16(0,&crc);
-while(str[i])
-	ucrc16(str[i++],&crc);
-ucrc16(0,&crc);
-ucrc16(0,&crc);
-return(crc);
-}
-
-time_t checktime()
-{
-	struct tm tm;
-
-memset(&tm,0,sizeof(tm));
-tm.tm_year=94;
-tm.tm_mday=1;
-return(mktime(&tm)^0x2D24BD00L);
-}
-
-int main(int argc, char **argv)
-{
-	uchar	str[128],*buf;
-	int 	i,file,sysop,number,network,terminal,desc;
-	ulong	l,last,high;
-	ushort	sbl;
-	bbs_t	bbs;
-	smbmsg_t msg;
-	FILE	*stream;
-
-	fprintf(stderr,"\nSMB2SBL v%s - Updates SBL via SMB - Developed 1994-2000 "
-		"Rob Swindell\n\n",VERSION);
-
-	if(putenv("TZ=UCT0"))
-		fprintf(stderr,"!putenv() FAILED\n");
-	tzset();
-
-	if(checktime()) {
-		printf("Time problem!\n");
-		return(-1); }
-
-	if(argc<3) {
-		fprintf(stderr,"usage: smb2sbl <smb_file> <sbl.dab>\n\n");
-		fprintf(stderr,"ex: smb2sbl /sbbs/data/subs/syncdata "
-			"/sbbs/xtrn/sbl/sbl.dab\n");
-		return(1); }
-
-	strcpy(smb.file,argv[1]);
-	strupr(smb.file);
-
-	strcpy(str,argv[2]);
-	strupr(str);
-	if((file=sopen(str,O_RDWR|O_BINARY|O_CREAT,SH_DENYNO))==-1) {
-		printf("error opening %s\n",str);
-		return(1); }
-	if((stream=fdopen(file,"r+b"))==NULL) {
-		printf("error fdopening %s\n",str);
-		return(1); }
-	setvbuf(stream,NULL,_IOFBF,4096);
-
-	sprintf(str,"%s.SBL",smb.file);
-	if((file=open(str,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
-		printf("error opening %s\n",str);
-		return(1); }
-	if(read(file,&last,4)!=4)
-		last=0;
-	high=last;
-
-	sprintf(str,"%s.SHD",smb.file);
-	if(!fexist(str)) {
-		printf("%s doesn't exist\n",smb.file);
-		return(0); }
-	sprintf(str,"%s.SID",smb.file);
-	if(!flength(str)) {
-		printf("%s is empty\n",smb.file);
-		return(0); }
-	fprintf(stderr,"Opening %s\n",smb.file);
-	smb.retry_time=30;
-	if((i=smb_open(&smb))!=0) {
-		printf("smb_open returned %d\n",i);
-		return(1); }
-
-	sbl=crc16("sbl");
-
-	if((i=smb_locksmbhdr(&smb))!=0) {				/* Be sure noone deletes or */
-		printf("Error locking %d\n",i);             /* adds while we're reading */
-		return(1); }
-
-	while(!feof(smb.sid_fp)) {
-		if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
-			break;
-		fprintf(stderr,"\r%lu  ",msg.idx.number);
-		if(msg.idx.number<=last || msg.idx.to!=sbl)
-			continue;
-		high=msg.idx.number;
-		if((i=smb_lockmsghdr(&smb,&msg))!=0) {
-			printf("\7Error %d locking msg #%lu\n",i,msg.idx.number);
-			continue; }
-		if((i=smb_getmsghdr(&smb,&msg))!=0) {
-			smb_unlockmsghdr(&smb,&msg);
-			printf("\7Error %d reading msg #%lu\n",i,msg.idx.number);
-			continue; }
-		smb_unlockmsghdr(&smb,&msg);
-		if(!msg.from_net.type			/* ignore local message */
-			|| msg.from[0]<=' '			/* corrupted? */
-			|| msg.subj[0]<=' '			/* corrupted */
-			) {
-			smb_freemsgmem(&msg);
-			continue; 
-		}
-
-		printf("\nMessage #%lu by %s on %.24s\n"
-			,msg.hdr.number,msg.from,ctime(&(time_t)msg.hdr.when_written.time));
-
-		truncsp(msg.subj);
-		if(!msg.subj[0]) {
-			smb_freemsgmem(&msg);
-			continue; }
-		fprintf(stderr,"Searching for %s...",msg.subj);
-		fseek(stream,0L,SEEK_SET);
-		memset(&bbs,0,sizeof(bbs_t));
-		while(1) {
-			l=ftell(stream);
-			if(!fread(&bbs,sizeof(bbs_t),1,stream)) {
-				memset(&bbs,0,sizeof(bbs_t));
-				break; }
-			if(msg.subj[0] && !stricmp(bbs.name,msg.subj)) {
-				fseek(stream,l,SEEK_SET);
-				break; } }
-		fprintf(stderr,"\n");
-		if(bbs.name[0] && strnicmp(bbs.user,msg.from,25)) {
-			printf("%s didn't create the entry for %s\n",msg.from,msg.subj);
-			smb_freemsgmem(&msg);
-			continue; }
-		if(!bbs.name[0]) {
-			fprintf(stderr,"Searching for unused record...");
-			fseek(stream,0L,SEEK_SET);
-			while(1) {					/* Find deleted record */
-				l=ftell(stream);
-				if(!fread(&bbs,sizeof(bbs_t),1,stream))
-					break;
-				if(!bbs.name[0]) {
-					fseek(stream,l,SEEK_SET);
-					break; } }
-			fprintf(stderr,"\n");
-			memset(&bbs,0,sizeof(bbs_t));
-			bbs.created=time(NULL);
-			if(!bbs.birth)
-				bbs.birth=bbs.created;
-			sprintf(bbs.user,"%-.25s",msg.from); }
-		sprintf(bbs.name,"%-.25s",msg.subj);
-		bbs.updated=time(NULL);
-		bbs.misc|=FROM_SMB;
-		sprintf(bbs.userupdated,"%-.25s",msg.from);
-		buf=loadmsgtxt(msg,0);
-		sysop=number=network=terminal=desc=0;
-		l=0;
-		while(buf[l]) {
-			while(buf[l] && buf[l]<=SP) 		/* Find first text on line */
-				l++;
-			if(!strnicmp(buf+l,"NAME:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.name,"%-.25s",buf+l);
-				truncsp(bbs.name); }
-			if(!strnicmp(buf+l,"BIRTH:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.birth=dstrtounix(buf+l); }
-			if(!strnicmp(buf+l,"SOFTWARE:",9)) {
-				l+=9;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.software,"%-.15s",buf+l);
-				truncsp(bbs.software); }
-			if(!strnicmp(buf+l,"WEB-SITE:",9)) {
-				l+=9;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.web_url,"%-.60s",buf+l);
-				truncsp(bbs.web_url); }
-			if(!strnicmp(buf+l,"E-MAIL:",7)) {
-				l+=7;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.sysop_email,"%-.60s",buf+l);
-				truncsp(bbs.sysop_email); }
-
-			if(!strnicmp(buf+l,"SYSOP:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.sysop[sysop],"%-.25s",buf+l);
-				truncsp(bbs.sysop[sysop]);
-				if(sysop<MAX_SYSOPS-1)
-					sysop++; }
-			if(!strnicmp(buf+l,"NUMBER:",7)) {
-				l+=7;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.number[number].modem.number,"%-.28s",buf+l);
-				truncsp(bbs.number[number].modem.number);
-				if(number<MAX_NUMBERS-1)
-					number++; }
-			if(!strnicmp(buf+l,"MODEM:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				i=number;
-				if(i) i--;
-				sprintf(bbs.number[i].modem.desc,"%-.15s",buf+l);
-				truncsp(bbs.number[i].modem.desc); }
-			if(!strnicmp(buf+l,"LOCATION:",9)) {
-				l+=9;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				i=number;
-				if(i) i--;
-				sprintf(bbs.number[i].modem.location,"%-.30s",buf+l);
-				truncsp(bbs.number[i].modem.location); }
-			if(!strnicmp(buf+l,"MINRATE:",8)) {
-				l+=8;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				i=number;
-				if(i) i--;
-				bbs.number[i].modem.min_rate=atoi(buf+l); }
-			if(!strnicmp(buf+l,"MAXRATE:",8)) {
-				l+=8;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				i=number;
-				if(i) i--;
-				bbs.number[i].modem.max_rate=atoi(buf+l); }
-			if(!strnicmp(buf+l,"NETWORK:",8)) {
-				l+=8;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.network[network],"%-.15s",buf+l);
-				truncsp(bbs.network[network]);
-				if(network<MAX_NETS-1)
-					network++; }
-			if(!strnicmp(buf+l,"ADDRESS:",8)) {
-				l+=8;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				i=network;
-				if(i) i--;
-				sprintf(bbs.address[i],"%-.25s",buf+l);
-				truncsp(bbs.address[i]); }
-			if(!strnicmp(buf+l,"TERMINAL:",9)) {
-				l+=9;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.terminal[terminal],"%-.15s",buf+l);
-				truncsp(bbs.terminal[terminal]);
-				if(terminal<MAX_TERMS-1)
-					terminal++; }
-			if(!strnicmp(buf+l,"DESC:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				sprintf(bbs.desc[desc],"%-.50s",buf+l);
-				truncsp(bbs.desc[desc]);
-				if(desc<4)
-					desc++; }
-
-			if(!strnicmp(buf+l,"MEGS:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.megs=atol(buf+l); }
-			if(!strnicmp(buf+l,"MSGS:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.msgs=atol(buf+l); }
-			if(!strnicmp(buf+l,"FILES:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.files=atol(buf+l); }
-			if(!strnicmp(buf+l,"NODES:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.nodes=atoi(buf+l); }
-			if(!strnicmp(buf+l,"USERS:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.users=atoi(buf+l); }
-			if(!strnicmp(buf+l,"SUBS:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.subs=atoi(buf+l); }
-			if(!strnicmp(buf+l,"DIRS:",5)) {
-				l+=5;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.dirs=atoi(buf+l); }
-			if(!strnicmp(buf+l,"XTRNS:",6)) {
-				l+=6;
-				while(buf[l] && buf[l]<=SP && buf[l]!=CR)
-					l++;
-				bbs.xtrns=atoi(buf+l); }
-			while(buf[l] && buf[l]>=SP) {	 /* Go to end of line */
-				putchar(buf[l]);
-				l++; }
-			printf("\n"); }
-	//	if(bbs.total_sysops<sysop)
-			bbs.total_sysops=sysop;
-	//	if(bbs.total_networks<network)
-			bbs.total_networks=network;
-	//	if(bbs.total_terminals<terminal)
-			bbs.total_terminals=terminal;
-	//	if(bbs.total_numbers<number)
-			bbs.total_numbers=number;
-		fwrite(&bbs,sizeof(bbs_t),1,stream);
-		FREE(buf);
-		smb_freemsgmem(&msg);
-		}
-	lseek(file,0L,SEEK_SET);
-	write(file,&high,4);
-	close(file);
-	return(0);
-}
-
diff --git a/xtrn/sbl/smb2sbl.dsp b/xtrn/sbl/smb2sbl.dsp
deleted file mode 100644
index c1029cfe2bf0549d7cba9ffffd673b8eb742e886..0000000000000000000000000000000000000000
--- a/xtrn/sbl/smb2sbl.dsp
+++ /dev/null
@@ -1,100 +0,0 @@
-# Microsoft Developer Studio Project File - Name="smb2sbl" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=smb2sbl - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "smb2sbl.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "smb2sbl.mak" CFG="smb2sbl - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "smb2sbl - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "smb2sbl - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "smb2sbl - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /O2 /I "c:\src\sbbs3" /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "smb2sbl - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "win32"
-# PROP Intermediate_Dir "msvc.win32.debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "c:\src\sbbs3" /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "smb2sbl - Win32 Release"
-# Name "smb2sbl - Win32 Debug"
-# Begin Source File
-
-SOURCE=C:\src\sbbs3\lzh.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\smb2sbl.c
-# End Source File
-# Begin Source File
-
-SOURCE=C:\src\sbbs3\smblib.c
-# End Source File
-# Begin Source File
-
-SOURCE=C:\src\sbbs3\smbwrap.c
-# End Source File
-# End Target
-# End Project
diff --git a/xtrn/sbl/sysop.txt b/xtrn/sbl/sysop.txt
deleted file mode 100644
index d3351eaf0abce9548b29193bd326ad60d205d670..0000000000000000000000000000000000000000
--- a/xtrn/sbl/sysop.txt
+++ /dev/null
@@ -1,139 +0,0 @@
-Synchronet BBS List Sysop Information
-=====================================
-
-This list is created and distributed every Monday. It is exported from the
-online BBS List database on Vertrauen and distributed via the SYNCMAIN FidoNet
-filebone file echo as SBBSLIST.ZIP.
-
-If you are a sysop of a Synchronet BBS and would like to have your BBS included
-in future versions of this list, do any one of the following:
-
-	o  Call Vertrauen at 714-529-9525 and use the Synchronet BBS List
-	   (external program) to add your system information.
-
-	o  See \SBBS\XTRN\SBL\SBL.DOC for instructions on networking your SBL
-	   database (v1.32+) with Vertrauen through DOVE-Net or  FidoNet.
-
-	o  Post a message on the Synchronet Data echo (via DOVE-Net or the
-	   SYNCDATA echo on FidoNet backbone) in the following format:
-
-To:		SBL
-Subj:		bbs name
-
-Body Text:
-------------------------------------------------------------------------------
-Name:		bbs name		(max length: 25)
-Birth:		MM/DD/YY		(first day online)
-Sysop:		your name		(max length: 25)
-Sysop:		co-sysop		(up to 5 sysops)
-Software:	Synchronet
-
-Desc:		description		(max length: 50)
-Desc:		more description	(up to 5 description lines)
-
-Nodes:		number of nodes 	(numbers only)
-Megs:		megabytes of storage	(numbers only)
-Users:		number of users 	(numbers only)
-Subs:		message areas		(numbers only)
-Msgs:		total messages		(numbers only)
-Dirs:		file directories	(numbers only)
-Files:		total files online	(numbers only)
-Xtrns:		externals (doors)	(numbers only)
-
-Network:	name of network 	(max length: 15)
-Address:	network address 	(max length: 25)
-Network:	another network 	(up to 10 networks)
-Address:	another address
-
-Terminal:	supported terminnal	(max length: 15)
-Terminal:	another terminal	(up to 5 terminals)
-
-Number: 	phone number		(max length: 12)
-Location:	city, state		(max length: 30)
-Modem:		modem description	(max length: 15)
-MaxRate:	maximum connect rate	(numbers only)
-MinRate:	minimum connect rate	(numbers only)
-					(up to 20 phone numbers)
--------------------------------------------------------------------------------
-
-The message must be posted to "SBL". If updating an existing entry, the message
-must be posted by the person who created the original entry. The title
-(subject) must be your BBS name. If changing the BBS name, the title must be
-the original name, and "NAME:" must be specified in the body text.
-
-All entry fields are optional. Only one field can be specified per line. The
-amount of whitespace between the colon and the data is irrelevant. All lines
-that do not begin with a valid field name and colon (like these) are ignored.
-Field names are not case sensitive (e.g. NAME: and Name: are equivalent).
-The order of the entry fields in the body text is not significant.
-
-Entries must be updated at least once every 90 days or they are automatically
-deleted. If you wish to delete your entry, send a message to SBL with the BBS
-name in the title and include a blank "Name:" field.
-
-If you want to just update an entry (to keep it from being auto-deleted), you
-do not have to specify any fields in the body text. But, it is suggested that
-you re-post all of your fields for all updates so that any new systems that are
-"watching" this sub-board can add your complete entry to their list.
-
-Up to 20 phone numbers can be specified. The number is limited to 12
-characters (so please use AAA-PPP-SSSS format), location is limited to 30
-characters, and modem description is limited to 15 characters. Do NOT put
-38400 or 57600 for maximum connect rate (MaxRate), as such standards do not
-yet exist.
-
-For all numeric files (noted as: "numbers only"), do not use commas, symbols,
-or letters. A MaxRate of 14,400bps must be specified as "14400".
-
-An example of a valid BBS post body text:
--------------------------------------------------------------------------------
-Name:		Vertrauen
-Birth:		08/01/88
-Software:	Synchronet
-Sysop: 		Digital Man
-Sysop: 		Ille Homine Albe
-
-Desc:		Home of Synchronet Multinode BBS Software
-
-Nodes:		6
-Megs: 		1800
-Users: 		1600
-Subs:		100
-Msgs:		45000
-Dirs:		150
-Files:		7000
-Xtrns:		10
-
-Network:	FidoNet
-Address:	1:103/705
-Network:	RIME
-Address:	5115
-Network:	DOVE-Net
-Address:	VERT
-
-Terminal:	TTY
-Terminal:	ANSI
-Terminal:	RIP
-
-Number: 	714-529-9525
-Location: 	Yorba Linda, Ca
-Modem: 		V.32bis
-MaxRate: 	14400
-MinRate:	300
-
-Number: 	714-529-9547
-Location: 	Yorba Linda, Ca
-Modem: 		V.FC
-MaxRate: 	28800
-MinRate:	16800
-
-Number: 	714-529-9721
-Location: 	Yorba Linda, Ca
-Modem: 		ZyXEL
-MaxRate: 	19200
-MinRate:        16800
--------------------------------------------------------------------------------
-
-Rob Swindell, Digital Dynamics
-(Keeper of the Synchronet BBS List)
-
diff --git a/xtrn/scb/instruct.msg b/xtrn/scb/instruct.msg
deleted file mode 100644
index 26b95fdb3681763bf2c1e4ece288c9f7c083866b..0000000000000000000000000000000000000000
--- a/xtrn/scb/instruct.msg
+++ /dev/null
@@ -1,22 +0,0 @@
-l                              chSynchronet Callback
-
-	ngWhen you continue the automatic validation process, chSynchronet Callback
-(SCB) ngwill ask you for your phone number.  This rhMUSTng be the phone number that 
-your modem is connected to and it must contain all of the digits necessary for
-chSCBng to call you back (including a '1' and area code if necessary).
-
-	If you choose not to continue with the validation process, answer hNOng
-to the 'hContinue with verification?ng' question that chSCBng will ask you next.
-
-	After you have entered an hACCEPTABLEng phone number, chSCBng will display a
-short message, and call you back.  When your phone rings you will need to
-answer it with your modem.  You should see a 'hRINGng' appear on your screen
-(and you may also hear your phone ring if one is connected to the same line as
-your modem), when this happens, you will need to type 'hATAng' and press hENTERng.
-rhDO NOTng answer the phone by voice!
-
-	The modems will then connect, and you will be given several chances to
-enter your correct password.  Once you have entered the hCORRECTng password, chSCBng
-will display a short message notifying you of this, validate your account,
-and then disconnect.  If you enter your password hINCORRECTLYng, chSCBng will rhNOTng
-validate your account.
diff --git a/xtrn/scb/ld_time.msg b/xtrn/scb/ld_time.msg
deleted file mode 100644
index cee29fdbf3194488a1f51c29ad521b8857faf822..0000000000000000000000000000000000000000
--- a/xtrn/scb/ld_time.msg
+++ /dev/null
@@ -1 +0,0 @@
-Please try again later. 
diff --git a/xtrn/scb/no_one.msg b/xtrn/scb/no_one.msg
deleted file mode 100644
index 6d72f2a2f9abcdfbbf031510ba6d53b7e7681d67..0000000000000000000000000000000000000000
--- a/xtrn/scb/no_one.msg
+++ /dev/null
@@ -1 +0,0 @@
-Phone numbers beginning with '1' are not allowed.
diff --git a/xtrn/scb/no_zero.msg b/xtrn/scb/no_zero.msg
deleted file mode 100644
index 2905d1f464fbbed24d8457bc5833a9ab1099e70b..0000000000000000000000000000000000000000
--- a/xtrn/scb/no_zero.msg
+++ /dev/null
@@ -1,2 +0,0 @@
-Phone numbers beginning with '0' are not allowed.
- 
\ No newline at end of file
diff --git a/xtrn/scb/phonecan.msg b/xtrn/scb/phonecan.msg
deleted file mode 100644
index 66ddf7f9f7586a07598b27fad9ff40229ee0f6bd..0000000000000000000000000000000000000000
--- a/xtrn/scb/phonecan.msg
+++ /dev/null
@@ -1,2 +0,0 @@
-The number you entered was found in a list of invalid or previously verified
-numbers.
diff --git a/xtrn/scb/refused.msg b/xtrn/scb/refused.msg
deleted file mode 100644
index 9b984fd684d8e67bc4012b31cfefb7a3c84506ca..0000000000000000000000000000000000000000
--- a/xtrn/scb/refused.msg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-	ngYou have chosen to refuse the callback verification process.  As a
-result, you may not be given access to the BBS.  If you intend to gain access
-to the system, you may wish to leave a note to the Sysop explaining that you
-refused the callback verification, and your reasons for doing so, as well as
-a number where you CAN be called at.
-
diff --git a/xtrn/scb/scb.cfg b/xtrn/scb/scb.cfg
deleted file mode 100644
index e8672699badc050c97e9fc19d81dc5ce2fb9879f..0000000000000000000000000000000000000000
--- a/xtrn/scb/scb.cfg
+++ /dev/null
@@ -1,32 +0,0 @@
-5
-NYNNNNNN
-\SBBS\TEXT\PHONE.CAN
-\SBBS\TEXT\PHONE.CAN
-
-
-
-
-
-
-
-
-
-
-
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-7
-11
-
diff --git a/xtrn/scb/scb.doc b/xtrn/scb/scb.doc
deleted file mode 100644
index 878b3e69839ee1341d9079a3956b4d5912dd11a2..0000000000000000000000000000000000000000
--- a/xtrn/scb/scb.doc
+++ /dev/null
@@ -1,329 +0,0 @@
-	   Synchronet Callback v1.32   Copyright 1995 Digital Dynamics
-	   -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-      Callback Verification Program for Synchronet Multinode BBS Software
-
-
-Installation:
-============
-
- 1. Create a directory called "SCB" off of your Synchronet XTRN directory.
-
-	Example:
-
-		MD C:\SBBS\XTRN\SCB
-
- 2. Copy all SCB files into this new directory.
-
-	Example:
-
-		COPY *.* C:\SBBS\XTRN\SCB
-
-	Note, SCB files include:
-
-		SCB.DOC 	This file
-		ORDER.TXT	Purchase order form
-		SCB.EXE 	Callback verifier external program
-		SCBCFG.EXE	Sysop configuration program for SCB
-		ALLOWED.DAT	List of allowable number prefixes
-		LDPREFIX.DAT	List of same-area prefixes that are long dist
-		SCB.MSG 	The opening screen for SCB
-		REFUSED.MSG	Verification refused
-		INSTRUCT.MSG	Instructions
-		NO_ONE.MSG	Long distance starting with 1 not allowed
-		NO_ZERO.MSG	Long distance starting with 0 not allowed
-		NO_LD.MSG	Long distance in same area code not allowed
-		LD_TIME.MSG	Not within long distance callback time range
-		TOOSHORT.MSG	Phone number less than minimum number of digits
-		TOOLONG.MSG	Phone number more than maximum number of digits
-		PHONECAN.MSG	Phone number found in trash can file
-		VERIFIED.MSG	Displayed to users after verification
-
- 3. Run SCFG from your NODE1 directory.
-
- 4. Go to the External Programs->Online Programs menu.
-
- 5. Hit the <INSERT> key and enter "Synchronet Callback".
-
- 6. Hit <ENTER> to edit the configuration for this new program.
-
- 7. Set the "Start-up Directory" to "..\XTRN\SCB".
-
- 8. Set "Multiuser" to "Yes".
-
- 9. Set "Modify Uesr Data" to "Yes".
-
-10. Set "BBS Drop File Type" to "Synchronet XTRN.DAT"
-
-11. If you wish to have SCB run automatically for new users or as a logon
-    event for unvalidated users, set the "Execute on Event" option to the
-    appropriate event type. Use "Access Requirements" if you wish SCB to be
-    only available to unvalidated users (i.e. "LEVEL NOT 20").
-
-Example SCFG screen:
-
-	�[�][?]���������������������������������������������������ͻ
-	�		     Synchronet Callback		   �
-	����������������������������������������������������������͹
-	� �Name 		      Synchronet Callback	   �
-	� �Internal Code	      SCB			   �
-	� �Start-up Directory	      ..\XTRN\SCB		   �
-	� �Command Line 	      scb			   �
-	� �Clean-up Command Line				   �
-	� �Cost in Credits	      0 			   �
-	� �Access Requirements	      LEVEL NOT 20		   �
-	� �Execution Requirements				   �
-	� �Multiple Concurrent Users  Yes			   �
-	� �Intercept I/O Interrupts   No			   �
-	� �Swap BBS out of Memory     No			   �
-	� �Modify User Data	      Yes			   �
-	� �Execute on Event	      Logon			   �
-	� �BBS Drop File Type	      Synchronet      XTRN.DAT	   �
-	� �Place Drop File In	      Node Directory		   �
-	����������������������������������������������������������ͼ
-
-
-Configuration:
-=============
-
- 1. Go into your SCB directory and run SCBCFG.
-
-	Example:
-
-		CD \SBBS\XTRN\SCB
-		SCBCFG
-
-    You will see a menu similar to the following:
-
-	�[�][?]���������������������������������������������������ͻ
-	�	      Synchronet Callback Configuration 	   �
-	����������������������������������������������������������͹
-	� �Toggle Options...					   �
-	� �Validation Values... 				   �
-	� �Allowed Prefix List...				   �
-	� �Long Distance Prefix List... 			   �
-	� �Long Distance Calling Times...			   �
-	� �Phone Number Trash Can   \SBBS\TEXT\PHONE.CAN	   �
-	� �Validated Phone List     \SBBS\TEXT\PHONE.CAN	   �
-	� �Callback Attempts	    4				   �
-	� �Minimum Phone Length     7				   �
-	� �Maximum Phone Length     11				   �
-	� �BBS Area Code	    714 			   �
-	� �Send Message to Sysop    User #1			   �
-	� �Registration Number	    UNREGISTERED		   �
-	����������������������������������������������������������ͼ
-
- 2. If your Synchronet text directory is in a directory or drive other
-    than "\SBBS\TEXT", change the Phone Can and Validated Phone List options
-    to reflect the correct location of your PHONE.CAN file.
-
-    If you want to allow duplicate validated phone numbers, change the
-    Validated Phone List to another path and/or filename. If left blank,
-    the validated phone numbers will not be written to a file at all
-    (other than the SCB.LOG and possibly the user data).
-
-    The phone number list(s) use the same syntax for trashcan files as
-    Synchronet BBS. Appending a '~' to a line specifies that the string
-    cannot be located anywhere within the phone number. Appending a '^'
-    indicates that the phone number cannot begin with the string.
-
-    The stock PHONE.CAN for Synchronet BBS contains the following:
-
-	0-^
-	1-^
-	000-~
-	111-~
-	123-^
-	222-^
-	333-^
-	444-^
-	555-~
-	666-^
-	777-^
-	888-^
-	999-^
-	900-^
-	411-~
-	911-~
-	976-~
-	411^
-	911^
-
-    Since SCB does not allow non-numeric characters in phone numbers, all
-    entries with the dash (-) character above are ignored.
-
- 3. SCB uses the dial string specified in the modem configuration in SCFG
-    for each node for dialing the remote user's modem. The default dial
-    string is "ATDT".
-
- 4. Use the "Toggle Options" sub-menu to configure your preferences.
-
-	�[�][?]����������������������������������������������ͻ
-	�		     Toggle Options		      �
-	�����������������������������������������������������͹
-	� �Validate if Unable to Verify 	   No	      �
-	� �Put Result in User Note		   Yes	      �
-	� �Long Distance if not an Allowed Prefix  No	      �
-	� �Allow Long Distance (Starting with 0)   No	      �
-	� �Allow Long Distance (Starting with 1)   Yes	      �
-	� �Allow Long Distance (Same Area Code)    Yes	      �
-	� �U.S. Style Phone Format (AAA-PPP-SSSS)  Yes	      �
-	� �Stay Connected After Callback	   No	      �
-	�����������������������������������������������������ͼ
-
-    If the "Validate if Unable to Verify" option is set to "Yes", users will
-    always be validated. Even if their number was not verified.
-
-    If the "Put Result in User Note" option is set to "Yes", the result of
-    the verification attempt will be placed in the user's note field
-    (in the Synchronet BBS user database).
-
-    If the "Long Distance if not an Allowed Prefix" option is set to "Yes",
-    then all numbers will be considered long distance unless the prefix
-    is specifically listed in the "Allowed Prefix List" off of the main
-    menu. If this option is set to "Yes", the "Long Distance Prefix List"
-    is not used.
-
-    If the "Allow Long Distance (starting with 0)" option is set to "Yes",
-    then numbers starting with '0' will be allowed. This option does not
-    effect numbers included in the "Allowed Prefix List".
-
-    If the "Allow Long Distance (starting with 1)" option is set to "Yes",
-    then numbers starting with '1' will be allowed. This option does not
-    effect numbers included in the "Allowed Prefix List".
-
-    If the "Allow Long Distance (same area code)" option is set to "Yes",
-    then numbers that begin with a prefix located in the "Long Distance
-    Prefix List" will not be allowed. This option does not effect numbers
-    included in the "Allowed Prefix List".
-
-    If the "U.S. Style Phone Format" option is set to "Yes", then SCB will
-    assume that phone numbers are in the AAA-PPP-SSSS format, and will
-    automatically strip the BBS area code from the prefix if the user
-    entered a number in the same area code as the BBS and included the
-    area code (both AAA and 1AAA will be stripped).
-
-    The "Stay Connected After Callback" option can be set to "Yes", "No",
-    or "Local Only". SCB will not disconnect after calling the user back
-    if this option is set to "Yes". If set to "Local Only", SCB will only
-    remain connected if the number verfied does not begin with a '1' or '0'.
-
- 5. Use the "Validation Values" sub-menu to configure how you want validated
-    users' accounts to be modified.
-
-	�[�][?]�������������������������������������������������������ͻ
-	�			Validation Values		       �
-	��������������������������������������������������������������͹
-	� �Security Level		   23			       �
-	� �Flag Set 1			   CDLN 		       �
-	� �Flag Set 2						       �
-	� �Flag Set 3						       �
-	� �Flag Set 4			   -V			       �
-	� �Exemptions						       �
-	� �Restrictions 		   -CX			       �
-	� �Days to Extend Expiration	   0			       �
-	� �Credits to Add					       �
-	� �Minutes to Add					       �
-	��������������������������������������������������������������ͼ
-
-    Note: The DEMO version will only set new security level and add credits.
-	  The other validation options are only available in the registered
-	  version.
-
- 6. Use the "Allowed Prefix List" sub-menu to set which prefixes will NOT be
-    affected by long distance restrictions (such as long distance
-    calling times, and numbers starting with 0 or 1). This option is useful
-    for specifying local numbers in other area codes. For example, in the
-    714 area code, 529 prefix, the following non-714 prefixes are local (*):
-
-	1310690 1310691 1310694 1310697 1310902 1310905 1310943 1310947
-	1818330 1818333 1818336 1818369 1818810 1818854 1818855 1818912
-	1818913 1818937 1818961 1818964 1818965 1818968 1909396 1909468
-	1909594 1909595 1909598 1909860 1909861 1909869
-
-	* Multiple entries per line to conserve documentation space
-
-    If the "Long Distance if not an Allowed Prefix" toggle option is set to
-    "Yes", then any number that is NOT included in this list will be
-    considered long distance.
-
- 7. Use the "Long Distance Prefix List" sub-menu to set which SAME-AREA
-    prefixes will be considered long distance. If the "Long Distance if not
-    an Allowed Prefix" toggle option is set to "Yes", then this list is not
-    used. For example, in the 714 area code, 529 prefix, the following
-    714 prefixes are long distance (*):
-
-	241 258 259 265 285 418 432 433 434 435 436 437 438 479 480
-	505 513 531 540 541 542 543 544 545 546 547 549 550 554 556
-	557 558 560 564 565 566 567 568 569 571 573 641 647 648 662
-	664 665 667 668 669 691 708 730 731 751 754 755 775 832 834
-	835 836 838 839 850 953 954 957 966 967 972 973 977 979
-
-	* Multiple entries per line to conserve documentation space
-
- 8. Use the "Long Distance Calling Times" sub-menu to set the times on each day
-    when SCB is allowed to place long distance calls. All times are entered
-    in 24-hour format and ranges crossing midnight (e.g. 18:00 to 09:00) are
-    valid. Numbers included in the "Allowed Prefix List" will not be limited
-    to these calling times.
-
- 9. If you are a registered owner of SCB, be sure to enter your registration
-    number on the main menu.
-
-10. Hit ESC from the main SCB configuration menu and select "Yes" to save
-    the configuration file.
-
-
-Notes:
-=====
-
-All SCB activity is logged to the file SCB.LOG in the SCB directory in
-the format:
-
-	Node 7	     : Mon Sep 27 16:44:31 1993
-	User Name    : Digital Man
-	Voice Number : 714-529-6328
-	Modem Number : 5295313
-	Result	     : Verified
-
-Results 	Description
-------- 	-----------
-Hung up 	User hung up before or during validation process
-Refused 	User refused validation
-Long Dist	User is a long distance call and long distance is disallowed
-Invalid #	User entered a number that is in the trashcan file, less than
-		    minimum length, or begins with a disallowed number (0 or 1)
-No Init 	Modem could not be initialized
-No Connect	Modem could not connect to user's modem (possibly wrong #)
-Verified	User was called, modem connected, and password verified
-Bad Pass	User was called, modem connected, and incorrect password
-
-
-Customizations:
-==============
-
-The following files can be modified (optionally using Ctrl-A codes for color):
-
-SCB.MSG 	The opening screen for SCB
-REFUSED.MSG	Verification refused
-INSTRUCT.MSG	Instructions
-NO_ONE.MSG	Long distance numbers starting with 1 not allowed
-NO_ZERO.MSG	Long distance numbers starting with 0 not allowed
-LD_TIME.MSG	Not within allowed long distance callback time range
-TOOSHORT.MSG	Phone number is less than configured minimum number of digits
-PHONECAN.MSG	Phone number found in trashcan file
-VERIFIED.MSG	Displayed to users after verification
-
-
-Registration:
-============
-
-If you wish to order a registered copy of SCB at the same time as Synchronet,
-use the Synchronet ORDER.TXT file (in the SBBS\DOCS directory).
-
-If registering SCB after already purchasing a copy of Synchronet, call
-Digital Dynamics voice at 714-529-6328, Support BBS at 714-529-9525 (and use
-Domain Shopper), or complete the ORDER.TXT file in the SCB directory and mail
-or fax it to Digital Dynamics.
-
-/* End of SCB.DOC */
diff --git a/xtrn/scb/scb.msg b/xtrn/scb/scb.msg
deleted file mode 100644
index 617338c75d3cab422a30073429c9ce822744c7de..0000000000000000000000000000000000000000
--- a/xtrn/scb/scb.msg
+++ /dev/null
@@ -1,8 +0,0 @@
-ng    Synchronet Callback can be used to verify your modem phone number.
-If your modem phone number is verified, your access on the BBS may be 
-immediately upgraded or the sysop will be notified of the verification and your
-access may be upgraded later.
-
-    Some BBSs may not allow long distance verification calls.  If you are 
-not a local call from this BBS and it doesn't allow long distance calls,
-you will be notified of this when you start the verification procedure.
diff --git a/xtrn/scb/toolong.msg b/xtrn/scb/toolong.msg
deleted file mode 100644
index 079411abdeee7b5559aa0c98c49ee77f864f5980..0000000000000000000000000000000000000000
--- a/xtrn/scb/toolong.msg
+++ /dev/null
@@ -1,2 +0,0 @@
-Your phone number is too long to be valid.
-
diff --git a/xtrn/scb/tooshort.msg b/xtrn/scb/tooshort.msg
deleted file mode 100644
index e31e216680ed482057ce281bce6cd55d9e3195ed..0000000000000000000000000000000000000000
--- a/xtrn/scb/tooshort.msg
+++ /dev/null
@@ -1 +0,0 @@
-Your phone number is too short to be valid.
diff --git a/xtrn/scb/verified.msg b/xtrn/scb/verified.msg
deleted file mode 100644
index ae5b1c8f293eec75d0eee41bee30520749295c83..0000000000000000000000000000000000000000
--- a/xtrn/scb/verified.msg
+++ /dev/null
@@ -1,5 +0,0 @@
-
-ghYour number has been verified and your access upgraded. Please call back
-to use your upgraded security!
-
-p
\ No newline at end of file
diff --git a/xtrn/scb/whats.new b/xtrn/scb/whats.new
deleted file mode 100644
index 2945099c7fe7c0d220110fea7f2dc96da2239f09..0000000000000000000000000000000000000000
--- a/xtrn/scb/whats.new
+++ /dev/null
@@ -1,21 +0,0 @@
-What's new in SCB v1.20
-=======================
-
- o	Supports new communications routines, supporting UART, FOSSIL,
-	BIOS (PC BIOS), EBIOS (PS/2 BIOS), and DigiBoard support.
-
-If installing over existing SCB install, just update SCB*.EXE and SCB.DOC.
-
-
-What's new in SCB v1.12
-=======================
-
- o	Updated and more comprehensive documentation.
- o	New "Long Distance if not an Allowed Prefix" toggle option.
- o	If the user's expiration date is already set to the future, it will be
-	extended by the number of days in SCBCFG. Previously, expiration dates
-	would always be set to the current date plus the number of days set in
-	SCBCFG.
-
-If installing over existing SCB install, just update SCB*.EXE and SCB.DOC.
-
diff --git a/xtrn/sdk/xsdk.c b/xtrn/sdk/xsdk.c
deleted file mode 100644
index b61b049df52bd31813237f437418c6f43f4ef9ee..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdk.c
+++ /dev/null
@@ -1,2677 +0,0 @@
-/* xsdk.c */
-
-/* Synchronet External Program Software Development Kit	*/
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-/***************************** Revision History *****************************\
-
-			Initial version for use with Synchronet v1a r6
-	1.0�	
-			Added bgotoxy() macro
-			Added mnehigh and mnelow vars for control of the mnemonic colors
-			Added sys_nodes and node_num variables to xtrn_sdk.c
-			Added MAX_NODES to xtrn_sdk.h
-			Added printfile() function to xtrn_sdk.c
-			Added rputs() (Raw put string)
-			Added getstr() (Get string)
-			Added redrwstr() (Redraw string)
-			Added stripattr() (String attributes)
-			Added sys_op var and the reading from the xtrn.dat
-			Removed user_min and the reading from the xtrn.dat
-			Changed read_xtrn_dat() to initdata()
-			Added ctrl-break handler to xtrn_sdk
-			Changed xtrn.dat format (again), adding system operator,
-				guru name, user ml, tl, birthdate and sex.
-			Added username() function
-			Renamed xtrn_sdk.* to xsdk.* and xtrnvars.c to xsdkvars.c
-				and xtrndefs.h to xsdkdefs.h
-			Added fexist() function
-	1.0
-			Ctrl-p is now switched into ctrl-^ by SBBS
-			Fixed relative data_dir bug in username()
-	1.01
-			Added flength() function and lowered disk activity
-			Lowered MAX_CARDS from 20 to 10 and made the re-shuffling happen
-				less often.
-	1.02
-			Fixed bug in attr() for monochrome users
-	1.03
-			Made warning and timeout times variables (sec_warn and sec_timeout)
-			Added SYSOP macro
-			Made it so sysop won't get timeout
-			Added user's phone number to XTRN.DAT
-			Added modem and com port information to XTRN.DAT
-			Added ahtoul function
-			Changed getstr commands Ctrl-L to Ctrl-R and Ctrl-P to Ctrl-\
-	1.04
-			Added intercommunication between the external programs and users
-			on the BBS or other external programs written with XSDK.
-			Added rprintf() function
-			Made many changes to getstr() function
-	2.00
-			Added DESQview awareness
-			Removed difftime() function calls completely
-			Added ungetkey() function
-			Added memory address of last modem status register for com routines
-				so we can track DCD incase user hangs up.
-			Added checkline function that does the checking of DCD.
-			Added new bug-free fdelay() routine to replace TC's delay() that
-				crashes multi-taskers such as DESQview and Windows
-	2.01
-			Added external program name access for user listings.
-			Added last node to send message to remembering and defaulting.
-			Added MALLOC and FREE macros for memory model non-specific memory
-				allocation.
-	2.02
-			Added INTRSBBS.DAT support for Synchronet shrinking to run programs
-				written with XSDK (new with v1b rev 01).
-			Added user's main flags, transfer flags, exemptions, and
-				restrictions to XTRN.DAT
-			Added support for the NODE_PAGE action (paging for private chat)
-				when listing nodes (printnodedat()).
-			Added user expiration date support to XTRN.DAT
-	2.03
-			Fixed bug with com_base variable being messed up.
-			New messaging system supported (for v1b r2 and higher)
-				(putnmsg and getnmsg functions).
-	2.10
-			Added support for file retrieving node status display.
-			NOPEN collision notice only appears after 25 retries.
-	2.11
-			Changed getnmsg function to not use IXB files.
-			Changed getsmsg function to not re-open for truncate.
-			Added user address, location, and zip/postal code suppport.
-			Added support for local arrow keys, home, end, ins, and del.
-			Remote keys ^] (back one space) and ^BkSpc (del) supported now.
-			Added support for high-bit Ctrl-A codes (for cursor positioning)
-			Removed file locking check - slowed down initialization sometimes.
-			Change user_ml to user_level, removed user_tl, changed user_mf to
-				user_flags1, changed user_tf to user_flags2, and added
-				user_flags3 and user_flags4.
-			cls() now updates lncntr like it should have.
-			Added ctrl-break handler so that users can abort printfile()
-			If a ctrl-c is received by inkey, the aborted flag is set.
-			Removed fdelay from XSDK and replaced with mswait for better
-				multitasker performance
-	2.20
-			New mswait that support OS2/Windows, DOS Idle, and non-DV modes.
-			XTRN.DAT passes mode of mswait configured in node setup.
-	2.21
-			Added user's real name/company name (user_realname) to XTRN.DAT
-	2.22
-			Added usernumber() function to get user number from a user name.
-	2.23
-			DTE rate (com_rate) now a ulong (instead of uint) to allow 115.2K
-	2.24
-			New K_AUTODEL mode for getstr() function, to be used in conjunction
-				with the K_EDIT mode. Makes overwriting existing strings very
-				easy for users.
-			Supports intelligent timeslice APIs while waiting for a key with
-				getkey() and with getstr() if K_LOWPRIO mode is used.
-			Hitting Ctrl-C sets the 'aborted' variable to 1.
-			Time zone and daylight savings automatically initialized to 0.
-			Modem strings up to 63 chars in XTRN.DAT now supported.
-			Fixed 10 character zip code bug in XSDKVARS.C.
-			Node directories (node_dir) up to 127 chars now supported.
-			nopen() can now open DENYNONE if passed access O_DENYNONE.
-	2.30
-			Added support for the following Ctrl-A codes: ;,.<>[]A
-			Changed definitions of TAB, SP, etc. to hex
-	2.31
-			C restriction disallows users to use Ctrl-P.
-			T exemption disables "Time's up" message.
-			Added center() function for outputting centered lines of text.
-			Added auto-pause to cls() and outchar() functions when clearing
-				the screen and lncntr is greater than 1
-			Changed bstrlen() to not count control characters (CR,LF,TAB,etc)
-			XSDK is now Watcom C++ compatible (although SBJ.C and SBL.C aren't)
-			XSDK.H is now *.CPP compatible
-			Added support for Ctrl-AQ (reset pause) and Ctrl-AZ (premature EOF)
-	2.32
-			Change bstrlen(char *str) to bstrlen(uchar *str)
-			Fixed bug in getstr() when word-wrapping a line that contains
-				ctrl-a codes and the input string did not begin at column 1.
-			Added user_dce variable (initialized by initdata from XTRN.DAT)
-			Fixed printnodedat() to not show Waiting for call (M)
-			Fixed typo in C restriction Ctrl-P message.
-			Moved call of checkline() in getkey() to immediately abort when
-				user hangs-up, even when keys are in the input buffer.
-			Added setmode() call to initdata() to set stderr to binary mode
-			Changed putchar() to write() in outchar() to elminate LF to CRLF
-				expansion
-	2.33
-			Improved cls() routine for auto-pause feature.
-			Added get_term() automatic RIP and WIP terminal detection function.
-	2.34
-			Added exec_dir, text_dir, and temp_dir variables to XTRN.DAT
-				format and initdata() function.
-			Added _fullpath() calls to initdata() to fix dir paths.
-			Added sys_id (QWK ID) to XTRN.DAT format and initdat() func.
-			Added node_misc to XTRN.DAT format and initdata() function.
-			If NM_LOWPRIO (low priority string input) is toggled on in
-				node_misc, then time-slices are always given up during input.
-			XSDK is now Symantec C++ compatible
-	2.40
-			node_misc was being read as a decimal number (it's stored in
-				the XTRN.DAT as hex), thus causing time-slice APIs to not
-				function correctly.
-	2.41
-			Ctrl-T is now intercepted by inkey() and displays the time the
-				program was launched, the current time, time used, and time
-				left (similar to SBBS).
-			Users are now warned of their last 5 minutes available (like SBBS).
-	2.42
-			Added Microsoft/Borland 32-bit compiler compatibility
-			Added socket (Telnet) compatibility
-			Changed Ctrl-Minus (Insert key) to Ctrl-V
-			Changed Ctrl-V (Center text key) to Ctrl-L
-			Added support for telnet nodes (connection=0xffff)
-	3.00
-			Fixed problem with clear screen (form feed) in node messages.
-			checkline() now exits when the remote user disconnects on 32-bit 
-				programs. Use atexit() to add cleanup code.
-	3.01
-			Eliminated warnings in ctrl_a() when compiled with VC++ 6.0.
-			Added Linux/GCC support (xsdkwrap.c, xsdkwrap.h, and xsdkinet.h)
-	3.10	
-			Added COMPILER_DESC and PLATFORM_DESC macros to xsdkwrap.h
-			Added support for no local console (XSDK_MODE_NOCONSOLE)
-				- This is now the default mode when building 32-bit programs
-			Eliminated use of ungetch() in favor of ungetkey() - more secure
-	3.11	
-
-\****************************************************************************/
-
-#include "xsdk.h"
-
-#ifdef _WINSOCKAPI_
-WSADATA WSAData;		// WinSock data
-#endif
-
-char *xsdk_ver="3.11";
-ulong xsdk_mode=XSDK_MODE_NOCONSOLE;
-
-/****************************************************************************/
-/* This allows users to abort the listing of text by using Ctrl-C           */
-/****************************************************************************/
-int cbreakh(void)	/* ctrl-break handler */
-{
-	aborted=1;
-	return(1);		/* 1 to continue, 0 to abort */
-}
-
-/****************************************************************************/
-/* Performs printf() using bbs bputs function								*/
-/****************************************************************************/
-int bprintf(char *fmt, ...)
-{
-	va_list argptr;
-	char sbuf[1024];
-	int chcount;
-
-	va_start(argptr,fmt);
-	chcount=vsprintf(sbuf,fmt,argptr);
-	va_end(argptr);
-	bputs(sbuf);
-	return(chcount);
-}
-
-/****************************************************************************/
-/* Performs printf() using bbs rputs function								*/
-/****************************************************************************/
-int rprintf(char *fmt, ...)
-{
-	va_list argptr;
-	char sbuf[1024];
-	int chcount;
-
-	va_start(argptr,fmt);
-	chcount=vsprintf(sbuf,fmt,argptr);
-	va_end(argptr);
-	rputs(sbuf);
-	return(chcount);
-}
-
-/****************************************************************************/
-/* Outputs a NULL terminated string locally and remotely (if applicable) 	*/
-/****************************************************************************/
-void bputs(char *str)
-{
-	ulong l=0;
-
-	while(str[l] && !aborted) {
-		if(str[l]==1) {				/* ctrl-a */
-			ctrl_a(str[++l]);		/* skip the ctrl-a */
-			if(str[l]=='Z')         /* Ctrl-AZ marks premature end of file */
-				break;
-			l++; }					/* skip the attribute code */
-		else
-			outchar(str[l++]); }
-}
-
-/****************************************************************************/
-/* Outputs a NULL terminated string locally and remotely (if applicable) 	*/
-/* Does not process ctrl-a codes (raw output)								*/
-/* Max length of str is 64 kbytes											*/
-/****************************************************************************/
-void rputs(char *str)
-{
-	ulong l=0;
-
-	while(str[l])
-		outchar(str[l++]);
-}
-
-/****************************************************************************/
-/* Returns the number of characters in 'str' not counting ctrl-ax codes		*/
-/* or the null terminator													*/
-/****************************************************************************/
-int bstrlen(uchar *str)
-{
-	int i=0;
-
-	while(*str) {
-		if(*str<SP) {	/* ctrl char */
-			if(*str==1) /* ctrl-A */
-				str++;
-			else if(*str!=CR && *str!=LF && *str!=FF)
-				i++; }
-		else
-			i++;
-		if(!(*str))
-			break;
-		str++; }
-	return(i);
-}
-
-/****************************************************************************/
-/* Outputs the string 'str' centered for an 80 column display               */
-/* Automatically appends "\r\n" to output                                   */
-/****************************************************************************/
-void center(char *str)
-{
-	 int i,j;
-
-	j=bstrlen(str);
-	for(i=0;i<(80-j)/2;i++)
-		outchar(SP);
-	bputs(str);
-}
-
-#ifndef __16BIT__
-
-char	outbuf[5000];
-ulong	outbufbot=0;
-ulong	outbuftop=0;
-sem_t	output_sem;
-
-void output_thread(void* arg)
-{
-	int		i,len;
-	char	str[256];
-
-	sem_init(&output_sem,0,0);
-
-	while(client_socket!=INVALID_SOCKET) {
-		if(outbufbot==outbuftop) {
-			sem_init(&output_sem,0,0);
-			sem_wait(&output_sem);
-			continue; 
-		}
-
-		if(outbuftop>outbufbot)
-			len=outbuftop-outbufbot;
-		else
-			len=sizeof(outbuf)-outbufbot;
-		i=send(client_socket,outbuf+outbufbot,len,0);
-		if(i!=len) {
-			sprintf(str,"!XSDK Error %d (%d) sending on socket %d\n"
-				,i,ERROR_VALUE,client_socket);
-#ifdef _WIN32
-			OutputDebugString(str);
-#else
-			fprintf(stderr,"%s",str);
-#endif
-		}
-		outbufbot+=len;
-		if(outbufbot>=sizeof(outbuf))
-			outbufbot=0;
-	}
-}
-#endif
-
-/****************************************************************************/
-/* Outputs one character to the screen. Handles, pause, saving and			*/
-/* restoring lines, etc.													*/
-/****************************************************************************/
-void outchar(char ch)
-{
-
-#ifndef __16BIT__
-	if(client_socket!=INVALID_SOCKET) {
-		ulong	top=outbuftop+1;
-
-		if(top==sizeof(outbuf))
-			top=0;
-		if(top!=outbufbot) {
-			outbuf[outbuftop++]=ch;
-			if(outbuftop==sizeof(outbuf))
-				outbuftop=0;
-			sem_post(&output_sem);
-		}
-	}
-#endif
-
-	if(con_fp!=NULL)
-		write(fileno(con_fp),&ch,1);
-
-	if(ch==LF) {
-		lncntr++;
-		lbuflen=0;
-		tos=0; 
-	}
-	else if(ch==FF) {
-		if(lncntr>1) {
-			lncntr=0;
-			CRLF;
-			bpause(); 
-		}
-		lncntr=0;
-		lbuflen=0;
-		tos=1; 
-	}
-	else if(ch==BS) {
-		if(lbuflen)
-			lbuflen--; 
-	}
-	else {
-		if(!lbuflen)
-			latr=curatr;
-		if(lbuflen>=LINE_BUFSIZE) lbuflen=0;
-		lbuf[lbuflen++]=ch; 
-	}
-	if(lncntr==user_rows-1) {
-		lncntr=0;
-		bpause(); 
-	}
-}
-
-/****************************************************************************/
-/* Prints PAUSE message and waits for a key stoke							*/
-/****************************************************************************/
-void bpause(void)
-{
-	char	ch;
-	uchar	tempattrs=curatr,*msg="\1_\1r\1h[Hit a key] ";
-	int		i,j;
-
-	lncntr=0;
-	bputs(msg);
-	j=bstrlen(msg);
-	ch=getkey(K_UPPER);
-	for(i=0;i<j;i++)
-		bputs("\b \b");
-	attr(tempattrs);
-	if(ch=='N' || ch=='Q')
-		aborted=1;
-}
-
-/****************************************************************************/
-/* Prompts user for Y or N (yes or no) and CR is interpreted as a Y			*/
-/* Returns 1 for Y or 0 for N												*/
-/* Called from quite a few places											*/
-/****************************************************************************/
-char yesno(char *str)
-{
-	char ch;
-
-	bprintf("\1_\1b\1h%s (Y/n) ? \1w",str);
-	while(1) {
-		ch=getkey(K_UPPER);
-		if(ch=='Y' || ch==CR) {
-			bputs("Yes\r\n");
-			return(1); }
-		if(ch=='N' || aborted) {
-			bputs("No\r\n");
-			return(0); 
-		} 
-	}
-}
-
-/****************************************************************************/
-/* Prompts user for N or Y (no or yes) and CR is interpreted as a N			*/
-/* Returns 1 for N or 0 for Y												*/
-/* Called from quite a few places											*/
-/****************************************************************************/
-char noyes(char *str)
-{
-	char ch;
-
-	bprintf("\1_\1b\1h%s (y/N) ? \1w",str);
-	while(1) {
-		ch=getkey(K_UPPER);
-		if(ch=='N' || ch==CR || aborted) {
-			bputs("No\r\n");
-			return(1); }
-		if(ch=='Y') {
-			bputs("Yes\r\n");
-			return(0); 
-		} 
-	}
-}
-
-/****************************************************************************/
-/* Outputs a string highlighting characters preceeded by a tilde with the	*/
-/* color specified in mnehigh and the rest of the line is in color mnelow.	*/
-/* If the user doesn't have ANSI, it puts the character following the tilde */
-/* in parenthesis.															*/
-/****************************************************************************/
-void mnemonics(char *str)
-{
-	long l;
-
-	attr(mnelow);
-	l=0L;
-	while(str[l]) {
-		if(str[l]=='~' && str[l+1]) {
-			if(!(user_misc&ANSI))
-				outchar('(');
-			l++;
-			attr(mnehigh);
-			outchar(str[l]);
-			l++;
-			if(!(user_misc&ANSI))
-				outchar(')');
-			attr(mnelow); 
-		}
-		else
-			outchar(str[l++]); 
-	}
-	attr(LIGHTGRAY);
-}
-
-/****************************************************************************/
-/* If a key has been pressed, the ASCII code is returned. If not, 0 is		*/
-/* returned. Ctrl-P and Ctrl-U are intercepted here.						*/
-/****************************************************************************/
-char inkey(long mode)
-{
-	static in_ctrl_p;
-	uchar ch=0,hour,min,sec;
-	long tleft;
-	int i=0;
-	time_t now;
-
-#ifndef __16BIT__
-	char	str[256];
-	ulong	cnt=0;
-
-	if(client_socket!=INVALID_SOCKET) {
-		i=ioctlsocket(client_socket,FIONREAD,&cnt);
-		if(i) {
-			sprintf(str,"!XSDK Error %d (%d) checking readcnt on socket %d\n"
-				,i,ERROR_VALUE,client_socket);
-#ifdef _WIN32
-			OutputDebugString(str);
-#else
-			fprintf(stderr,"%s",str);
-#endif
-		}
-	}
-
-	if(i==0 && cnt) 
-		recv(client_socket,&ch,1,0);
-	else
-#endif
-
-	if(keybufbot!=keybuftop) {
-		ch=keybuf[keybufbot++];
-		if(keybufbot==KEY_BUFSIZE)
-			keybufbot=0; }
-	else if(!(xsdk_mode&XSDK_MODE_NOCONSOLE) && kbhit()) {
-		i=getch();
-#ifdef __unix__
-		if(i==LF) i=CR;	/* Enter key returns Ctrl-J on Unix! (ohmygod) */
-#endif
-		if(i==0 || i==0xE0) {			/* Local Alt or Function key hit */
-			i=getch();
-			switch(i) {
-				case 0x47:	/* Home - Same as Ctrl-B */
-					return(2);	/* ctrl-b beginning of line */
-				case 0x4b:		/* Left Arrow - same as ctrl-] */
-					return(0x1d);
-				case 0x4d:		/* Right Arrow - same as ctrl-f */
-					return(6);
-				case 0x48:		/* Up arrow - same as ctrl-^ */
-					return(0x1e);
-				case 0x50:		/* Down arrow - same as CR */
-					return(CR);
-				case 0x4f:	  /* End	  - same as Ctrl-E */
-					return(5);  /* ctrl-e - end of line */
-				case 0x52:	/* Insert */
-					return(0x1f);	/* ctrl-minus - insert mode */
-				case 0x53:	/* Delete */
-					return(0x7f);   /* ctrl-bkspc - del cur char */
-				}
-			return(0); } 
-		ch=i;
-	}
-
-	if(ch==0x10 || ch==0x1e) {	/* Ctrl-P or Ctrl-^ */
-		if(in_ctrl_p || !ctrl_dir[0])	/* keep from being recursive */
-			return(0);
-		in_ctrl_p=1;
-		SAVELINE;
-		CRLF;
-		nodemsg();
-		CRLF;
-		RESTORELINE;
-		lncntr=0;
-		in_ctrl_p=0;
-		return(0); }
-
-	if(ch==20) { /* Ctrl-T Time left online */
-		SAVELINE;
-		attr(LIGHTGRAY);
-		now=time(NULL);
-		checktimeleft();
-		CRLF;
-		bprintf("\r\nStart     : %.24s",ctime(&starttime));
-		bprintf("\r\nNow       : %.24s",ctime(&now));
-		i=now-starttime;
-		hour=(i/60)/60;
-		min=(i/60)-(hour*60);
-		sec=i-((min+(hour*60))*60);
-		bprintf("\r\nTime Used : %02u:%02u:%02u",hour,min,sec);
-		tleft=timeleft-(now-starttime);
-		hour=(tleft/60)/60;
-		min=(tleft/60)-(hour*60);
-		sec=tleft-((min+(hour*60))*60);
-		bprintf("\r\nTime Left : %02u:%02u:%02u\r\n\r\n",hour,min,sec);
-		RESTORELINE;
-		lncntr=0;
-		return(0); }
-
-	if(ch==21) { /* Ctrl-U Users online */
-		if(!ctrl_dir[0])
-			return(0);
-		SAVELINE;
-		CRLF;
-		whos_online(1);
-		CRLF;
-		RESTORELINE;
-		lncntr=0;
-		return(0); }
-
-#ifndef __16BIT__
-	if(ch==LF) 
-		ch=0;		/* Ignore LF of Telnet CR/LF sequence */
-#endif
-
-	if(ch==3)
-		aborted=1;
-	else if(aborted)
-		ch=3;
-
-	if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO|| node_misc&NM_LOWPRIO))
-		mswait(1);
-	return(ch);
-}
-
-/****************************************************************************/
-/* Waits for remote or local user to hit a key. Inactivity timer is checked */
-/* and hangs up if inactive for 4 minutes. Returns key hit, or uppercase of */
-/* key hit if mode&K_UPPER or key out of KEY BUFFER. Does not print key.	*/
-/****************************************************************************/
-char getkey(long mode)
-{
-	char	ch,warn=0;
-	long	tleft;
-	time_t	timeout,now;
-
-	aborted=lncntr=0;
-	timeout=time(NULL);
-	do {
-		checkline();
-		ch=inkey(mode);
-		now=time(NULL);
-		if(ch) {
-			if(mode&K_NUMBER && isprint(ch) && !isdigit(ch))
-				continue;
-			if(mode&K_ALPHA && isprint(ch) && !isalpha(ch))
-				continue;
-			if(ch==LF) continue;
-			if(mode&K_UPPER)
-				return(toupper(ch));
-			return(ch); 
-		}
-		checktimeleft();
-
-		tleft=timeleft-(now-starttime);
-		if((tleft/60)<(5-timeleft_warn)) {	/* Running out of time warning */
-			timeleft_warn=5-(tleft/60);
-			SAVELINE;
-			bprintf("\1n\1h\r\n\7\r\nYou only have \1r\1i%u\1n\1h minute%s "
-				"left.\r\n\r\n"
-				,((ushort)tleft/60)+1,(tleft/60) ? "s" : "");
-			RESTORELINE; 
-		}
-
-		if(now-timeout>=(time_t)sec_warn && !warn)		/* Inactivity warning */
-			for(warn=0;warn<5;warn++)
-				outchar(7);
-	} while(now-timeout<(time_t)sec_timeout);
-
-	bputs("\r\nInactive too long.\r\n");
-	exit(0);
-	return(0);	/* never gets here, but makes compiler happy */
-}
-
-/****************************************************************************/
-/* If remote user, checks DCD to see if user has hung up or not.			*/
-/****************************************************************************/
-void checkline(void)
-{
-#ifdef __16BIT__
-	if(com_port && !((*msr)&DCD)) exit(0);
-#else
-	char	str[256];
-	char	ch;
-	int		i;
-	fd_set	socket_set;
-	struct timeval timeout;
-
-	if(client_socket!=INVALID_SOCKET) {
-		FD_ZERO(&socket_set);
-		FD_SET(client_socket,&socket_set);
-		timeout.tv_sec=0;
-		timeout.tv_usec=100;
-
-		if((i=select(client_socket+1,&socket_set,NULL,NULL,&timeout))>0) {
-			if((i=recv(client_socket,&ch,1,MSG_PEEK))!=1) {
-				sprintf(str,"!XSDK Error %d (%d) checking state of socket %d\n"
-					,i,ERROR_VALUE,client_socket);
-	#ifdef _WIN32
-				OutputDebugString(str);
-	#else
-				fprintf(stderr,"%s",str);
-				fflush(stderr);
-	#endif
-				exit(0);
-			}
-		}
-	}
-#endif
-}
-
-/****************************************************************************/
-/* Waits for remote or local user to hit a key that is contained inside str.*/
-/* 'str' should contain uppercase characters only. When a valid key is hit, */
-/* it is echoed (upper case) and is the return value.						*/
-/* If max is non-zero and a number is hit that is not in str, it will be	*/
-/* returned with the high bit set. If the return of this function has the	*/
-/* high bit set (&0x8000), just flip the bit (^0x8000) to get the number.	*/
-/****************************************************************************/
-int getkeys(char *instr,int max)
-{
-	char	str[256];
-	uchar	ch,n=0;
-	int		i=0;
-
-	sprintf(str,"%.*s",sizeof(str)-1,instr);
-	strupr(str);
-	while(!aborted) {
-		ch=getkey(K_UPPER);
-		if(max && ch>0x7f)	/* extended ascii chars are digits to isdigit() */
-			continue;
-		if(ch && !n && (strchr(str,ch))) { 	/* return character if in string */
-			outchar(ch);
-			attr(LIGHTGRAY);
-			CRLF;
-			return(ch); 
-		}
-		if(ch==CR && max) {             /* return 0 if no number */
-			attr(LIGHTGRAY);
-			CRLF;
-			if(n)
-				return(i|0x8000);		/* return number plus high bit */
-			return(0); 
-		}
-		if(ch==BS && n) {
-			bputs("\b \b");
-			i/=10;
-			n--; 
-		}
-		else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
-			i*=10;
-			n++;
-			i+=ch&0xf;
-			outchar(ch);
-			if(i*10>max) {
-				attr(LIGHTGRAY);
-				CRLF;
-				return(i|0x8000); 
-			} 
-		}	 
-	}
-	return(0);
-}
-
-/****************************************************************************/
-/* Hot keyed number input routine.											*/
-/****************************************************************************/
-int getnum(int max)
-{
-	uchar ch,n=0;
-	int i=0;
-
-	while(1) {
-		ch=getkey(K_UPPER);
-		if(ch>0x7f)
-			continue;
-		if(ch=='Q') {
-			outchar('Q');
-			CRLF;
-			break;
-		}
-		else if(ch==3) {		/* ctrl-c */
-			CRLF;
-			break;
-		}
-		else if(ch==CR) {
-			CRLF;
-			return(i);
-		}
-		else if(ch==BS && n) {
-			bputs("\b \b");
-			i/=10;
-			n--;
-		}
-		else if(isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
-			i*=10;
-			n++;
-			i+=ch&0xf;
-			outchar(ch);
-			if(i*10>max) {
-				CRLF;
-				return(i);
-			}
-		}
-	}
-	return(-1);
-}
-
-/****************************************************************************/
-/* Waits for remote or local user to input a CR terminated string. 'length' */
-/* is the maximum number of characters that getstr will allow the user to 	*/
-/* input into the string. 'mode' specifies upper case characters are echoed */
-/* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */
-/* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */
-/* ^N non-destructive BS, ^V center line. Valid keys are echoed.			*/
-/****************************************************************************/
-int getstr(char *strout, size_t maxlen, long mode)
-{
-	size_t i,l,x,z;	/* i=current position, l=length, j=printed chars */
-					/* x&z=misc */
-	uchar ch,str1[256],str2[256],ins=0,atr;
-
-	if(mode&K_LINE && user_misc&ANSI) {
-		attr(LIGHTGRAY|HIGH|(BLUE<<4));  /* white on blue */
-		for(i=0;i<maxlen;i++)
-			outchar(SP);
-		bprintf("\x1b[%dD",maxlen); 
-	}
-	i=l=0;	/* i=total number of chars, j=number of printable chars */
-	if(wordwrap[0]) {
-		strcpy(str1,wordwrap);
-		wordwrap[0]=0; 
-	}
-	else str1[0]=0;
-	if(mode&K_EDIT)
-		strcat(str1,strout);
-	if(strlen(str1)>maxlen)
-		str1[maxlen]=0;
-	atr=curatr;
-	if(mode&K_AUTODEL && str1[0])
-		attr(BLUE|(LIGHTGRAY<<4));
-	rputs(str1);
-	if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && user_misc&ANSI)
-		bputs("\x1b[K");  /* destroy to eol */
-	i=l=strlen(str1);
-
-	if(mode&K_AUTODEL && str1[0]) {
-		ch=getkey(mode);
-		attr(atr);
-		if(isprint(ch) || ch==0x7f) {
-			for(i=0;i<l;i++)
-				bputs("\b \b");
-			i=l=0; 
-		}
-		else {
-			for(i=0;i<l;i++)
-				outchar(BS);
-			rputs(str1);
-			i=l; 
-		}
-		if(ch!=SP && ch!=TAB)
-			ungetkey(ch); 
-	}
-
-	while((ch=getkey(mode|K_GETSTR))!=CR && !aborted) {
-		switch(ch) {
-			case 1:	/* Ctrl-A for ANSI */
-				if(!(mode&K_MSG) || i>maxlen-3)
-					break;
-				if(ins) {
-					if(l<maxlen)
-						l++;
-					for(x=l;x>i;x--)
-						str1[x]=str1[x-1];
-					rprintf("%.*s",l-i,str1+i);
-					rprintf("\x1b[%dD",l-i);
-					if(i==maxlen-1)
-						ins=0; 
-				}
-				outchar(str1[i++]=1);
-				break;
-			case 2:	/* Ctrl-B Beginning of Line */
-				if(user_misc&ANSI && i) {
-					bprintf("\x1b[%dD",i);
-					i=0; 
-				}
-				break;
-			case 4:	/* Ctrl-D Delete word right */
-        		if(i<l) {
-					x=i;
-					while(x<l && str1[x]!=SP) {
-						outchar(SP);
-						x++; 
-					}
-					while(x<l && str1[x]==SP) {
-						outchar(SP);
-						x++; 
-					}
-					bprintf("\x1b[%dD",x-i);   /* move cursor back */
-					z=i;
-					while(z<l-(x-i))  {             /* move chars in string */
-						outchar(str1[z]=str1[z+(x-i)]);
-						z++; 
-					}
-					while(z<l) {					/* write over extra chars */
-						outchar(SP);
-						z++; 
-					}
-					bprintf("\x1b[%dD",z-i);
-					l-=x-i; 						/* l=new length */
-				}
-				break;
-			case 5:	/* Ctrl-E End of line */
-				if(user_misc&ANSI && i<l) {
-					bprintf("\x1b[%dC",l-i);  /* move cursor right one */
-					i=l; 
-				}
-				break;
-			case 6:	/* Ctrl-F move cursor forewards */
-				if(i<l && (user_misc&ANSI)) {
-					bputs("\x1b[C");   /* move cursor right one */
-					i++; 
-				}
-				break;
-			case 7:
-				if(!(mode&K_MSG))
-					break;
-				 if(ins) {
-					if(l<maxlen)
-						l++;
-					for(x=l;x>i;x--)
-						str1[x]=str1[x-1];
-					if(i==maxlen-1)
-						ins=0; 
-				 }
-				 if(i<maxlen) {
-					str1[i++]=7;
-					outchar(7); 
-				 }
-				 break;
-			case 14:	/* Ctrl-N Next word */
-				if(i<l && (user_misc&ANSI)) {
-					x=i;
-					while(str1[i]!=SP && i<l)
-						i++;
-					while(str1[i]==SP && i<l)
-						i++;
-					bprintf("\x1b[%dC",i-x); 
-				}
-				break;
-			case 0x1c:	  /* Ctrl-\ Previous word */
-				if(i && (user_misc&ANSI)) {
-					x=i;
-					while(str1[i-1]==SP && i)
-						i--;
-					while(str1[i-1]!=SP && i)
-						i--;
-					bprintf("\x1b[%dD",x-i); 
-				}
-				break;
-			case 18:	/* Ctrl-R Redraw Line */
-				redrwstr(str1,i,l,0);
-				break;
-			case TAB:
-				if(!(i%TABSIZE)) {
-            		if(ins) {
-						if(l<maxlen)
-							l++;
-						for(x=l;x>i;x--)
-							str1[x]=str1[x-1];
-						if(i==maxlen-1)
-							ins=0; 
-					}
-					str1[i++]=SP;
-					outchar(SP); 
-				}
-				while(i<maxlen && i%TABSIZE) {
-            		if(ins) {
-						if(l<maxlen)
-							l++;
-						for(x=l;x>i;x--)
-							str1[x]=str1[x-1];
-						if(i==maxlen-1)
-							ins=0; 
-					}
-					str1[i++]=SP;
-					outchar(SP); 
-				}
-				if(ins)
-					redrwstr(str1,i,l,0);
-				break;
-			case BS:
-				if(!i)
-					break;
-				i--;
-				l--;
-				if(i!=l) {				/* Deleting char in middle of line */
-					outchar(BS);
-					z=i;
-					while(z<l)	{		/* move the characters in the line */
-						outchar(str1[z]=str1[z+1]);
-						z++; 
-					}
-					outchar(SP);		/* write over the last char */
-					bprintf("\x1b[%dD",(l-i)+1); 
-				}
-				else
-					bputs("\b \b");
-				break;
-			case 12:	/* Ctrl-L 	Center line (used to be Ctrl-V) */
-				str1[l]=0;
-				l=bstrlen(str1);
-				for(x=0;x<(maxlen-l)/2;x++)
-					str2[x]=SP;
-				str2[x]=0;
-				strcat(str2,str1);
-				strcpy(strout,str2);
-				l=strlen(strout);
-				if(mode&K_MSG)
-					redrwstr(strout,i,l,K_MSG);
-				else {
-					while(i--)
-						bputs("\b");
-					bputs(strout);
-					if(mode&K_LINE)
-						attr(LIGHTGRAY); 
-				}
-				CRLF;
-				return(l);
-			case 23:	/* Ctrl-W   Delete word left */
-				if(i<l) {
-					x=i;							/* x=original offset */
-					while(i && str1[i-1]==SP) {
-						outchar(BS);
-						i--; 
-					}
-					while(i && str1[i-1]!=SP) {
-						outchar(BS);
-						i--; 
-					}
-					z=i;                            /* i=z=new offset */
-					while(z<l-(x-i))  {             /* move chars in string */
-						outchar(str1[z]=str1[z+(x-i)]);
-						z++; 
-					}
-					while(z<l) {					/* write over extra chars */
-						outchar(SP);
-						z++; 
-					}
-					bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
-					l-=x-i; 						/* l=new length */
-				}
-				else {
-            		while(i && str1[i-1]==SP) {
-						i--;
-						l--;
-						bputs("\b \b"); 
-					}
-					while(i && str1[i-1]!=SP) {
-						i--;
-						l--;
-						bputs("\b \b"); 
-					} 
-				}
-				break;
-			case 24:	/* Ctrl-X   Delete entire line */
-				while(i<l) {
-					outchar(SP);
-					i++; 
-				}
-				while(l) {
-					l--;
-					bputs("\b \b"); 
-				}
-				i=0;
-				break;
-			case 25:	/* Ctrl-Y	Delete to end of line */
-				if(user_misc&ANSI) {
-					bputs("\x1b[s\x1b[K\x1b[u");
-					l=i; 
-				}
-				break;
-			case 22:	/* Ctrl-V		Toggles Insert/Overwrite */
-				if(!(user_misc&ANSI))
-					break;
-				if(ins) {
-					ins=0;
-					redrwstr(str1,i,l,0); 
-				}
-				else if(i<l) {
-					ins=1;
-					bprintf("\x1b[s\x1b[%dC",80-i);         /* save pos  */
-					z=curatr;								/* and got to EOL */
-					attr(z|BLINK|HIGH);
-					outchar('�');
-					attr(z);
-					bputs("\x1b[u");   /* restore pos */
-				}
-				break;
-			case 0x1d:	/* Ctrl-]  Reverse Cursor Movement */
-				if(i && (user_misc&ANSI)) {
-					bputs("\x1b[D");   /* move cursor left one */
-					i--; 
-				}
-				break;
-			case 0x7f:	/* Ctrl-BkSpc (DEL) Delete current char */
-				if(i==l) {	/* Backspace if end of line */
-					if(i) {
-						i--;
-						l--;
-						bputs("\b \b");
-					}
-					break;
-				}
-				l--;
-				z=i;
-				while(z<l)	{		/* move the characters in the line */
-					outchar(str1[z]=str1[z+1]);
-					z++; 
-				}
-				outchar(SP);		/* write over the last char */
-				bprintf("\x1b[%dD",(l-i)+1);
-				break;
-			case ESC:
-				if(!(user_misc&ANSI))
-					break;
-				if((ch=getkey(0x8000))!='[') {
-					ungetkey(ch);
-					break; 
-				}
-				if((ch=getkey(0x8000))=='C') {
-					if(i<l) {
-						bputs("\x1b[C");   /* move cursor right one */
-						i++; 
-					} 
-				}
-				else if(ch=='D') {
-					if(i) {
-						bputs("\x1b[D");   /* move cursor left one */
-						i--; 
-					} 
-				}
-				else {
-					while(isdigit(ch) || ch==';' || isalpha(ch)) {
-						if(isalpha(ch)) {
-							ch=getkey(0);
-							break; 
-						}
-						ch=getkey(0); 
-					}
-					ungetkey(ch); 
-				}
-				break;
-			default:
-				if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
-					str1[i]=0;
-					if(ch==SP) {	/* don't wrap a space as last char */
-						strcpy(strout,str1);
-						if(stripattr(strout))
-							redrwstr(strout,i,l,K_MSG);
-						CRLF;
-						return(i); 
-					}
-					x=i-1;
-					z=1;
-					wordwrap[0]=ch;
-					while(str1[x]!=SP && x)
-						wordwrap[z++]=str1[x--];
-					if(x<(maxlen/2)) {
-						wordwrap[1]=0;	/* only wrap one character */
-						strcpy(strout,str1);
-						if(stripattr(strout))
-							redrwstr(strout,i,l,K_MSG);
-						CRLF;
-						return(i); 
-					}
-					wordwrap[z]=0;
-					while(z--) {
-						i--;
-						bputs("\b \b"); 
-					}
-					strrev(wordwrap);
-					str1[x]=0;
-					strcpy(strout,str1);
-					if(stripattr(strout))
-						redrwstr(strout,i,x,mode);
-					CRLF;
-					return(x); 
-				}
-				if(i<maxlen && ch>=SP) {
-					if(mode&K_UPRLWR)
-						if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
-							|| str1[i-1]=='.' || str1[i-1]=='_')))
-							ch=toupper(ch);
-						else
-							ch=tolower(ch);
-					if(ins) {
-						if(l<maxlen)	/* l<maxlen */
-							l++;
-						for(x=l;x>i;x--)
-							str1[x]=str1[x-1];
-						rprintf("%.*s",l-i,str1+i);
-						rprintf("\x1b[%dD",l-i);
-						if(i==maxlen-1) {
-							bputs("  \b\b");
-							ins=0; 
-						} 
-					}
-					str1[i++]=ch;
-					outchar(ch); 
-				} 
-			} /* switch */
-		if(i>l)
-			l=i;
-		if(mode&K_CHAT && !l)
-			return(0); 
-	}
-	if(i>l)
-		l=i;
-	str1[l]=0;
-	if(!aborted) {
-		strcpy(strout,str1);
-		if(stripattr(strout) || ins)
-			redrwstr(strout,i,l,K_MSG); 
-	}
-	else
-		l=0;
-	if(mode&K_LINE) attr(LIGHTGRAY);
-	if(!(mode&K_NOCRLF)) {
-		outchar(CR);
-		if(!(mode&K_MSG && aborted))
-			outchar(LF); 
-	}
-	return(l);
-}
-
-/****************************************************************************/
-/* Redraws str using i as current cursor position and l as length           */
-/****************************************************************************/
-void redrwstr(char *strin, int i, int l, long mode)
-{
-	char str[256],c;
-
-	sprintf(str,"%-*.*s",l,l,strin);
-	c=i;
-	while(c--)
-		outchar(BS);
-	if(mode&K_MSG)
-		bputs(str);
-	else
-		rputs(str);
-	if(user_misc&ANSI) {
-		bputs("\x1b[K");
-		if(i<l)
-			bprintf("\x1b[%dD",l-i); 
-	}
-	else {
-		while(c<79)	{ /* clear to end of line */
-			outchar(SP);
-			c++; 
-		}
-		while(c>l) { /* back space to end of string */
-			outchar(BS);
-			c--; 
-		} 
-	}
-}
-
-/****************************************************************************/
-/* Strips invalid Ctrl-Ax sequences from str                                */
-/* Returns number of ^A's in line                                           */
-/****************************************************************************/
-char stripattr(char *strin)
-{
-	uchar str[81];
-	uchar a,c,d,e;
-
-	e=strlen(strin);
-	for(a=c=d=0;c<e;c++) {
-		if(strin[c]==1) {
-			a++;
-			switch(toupper(strin[c+1])) {
-				case '-':	/* clear 		*/
-				case '_':	/* clear		*/
-				case 'B':	/* blue 	fg 	*/
-				case 'C':	/* cyan 	fg 	*/
-				case 'G':	/* green	fg 	*/
-				case 'H':	/* high 	fg 	*/
-				case 'I':	/* blink 	   	*/
-				case 'K':	/* black 	fg 	*/
-				case 'L':	/* cls         	*/
-				case 'M':	/* magenta  fg 	*/
-				case 'N':	/* normal      	*/
-				case 'P':	/* pause       	*/
-				case 'Q':   /* pause reset  */
-				case 'R':	/* red      fg 	*/
-				case 'W':	/* white    fg 	*/
-				case 'Y':	/* yellow   fg 	*/
-				case '0':	/* black 	bg 	*/
-				case '1':	/* red   	bg 	*/
-				case '2':	/* green 	bg 	*/
-				case '3':   /* brown	bg 	*/
-				case '4':	/* blue  	bg 	*/
-				case '5':   /* magenta 	bg 	*/
-				case '6':	/* cyan    	bg 	*/
-				case '7':	/* white   	bg 	*/
-					break;
-				default:
-					c++;
-					continue; 
-			} 
-		}
-		str[d++]=strin[c]; 
-	}
-	str[d]=0;
-	strcpy(strin,str);
-	return(a);
-}
-
-/***************************************************************************/
-/* Changes local and remote text attributes accounting for monochrome      */
-/***************************************************************************/
-void attr(int atr)
-{
-
-	if(!(user_misc&ANSI) || aborted)
-		return;
-	if(!(user_misc&COLOR)) {  /* eliminate colors if user doesn't have them */
-		if(atr&LIGHTGRAY)		/* if any bits set, set all */
-			atr|=LIGHTGRAY;
-		if(atr&(LIGHTGRAY<<4))
-			atr|=(LIGHTGRAY<<4);
-		if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4))
-			atr&=~LIGHTGRAY; }	/* if background is solid, forground is black */
-	if(curatr==atr) /* attribute hasn't changed. don't send codes */
-		return;
-
-	if((!(atr&HIGH) && curatr&HIGH)	|| (!(atr&BLINK) && curatr&BLINK)
-		|| atr==LIGHTGRAY) {
-		bprintf("\x1b[0m");
-		curatr=LIGHTGRAY; }
-
-	if(atr==LIGHTGRAY) {				 /* no attributes */
-		curatr=atr;
-		return; }
-
-	if(atr&BLINK) {						/* special attributes */
-		if(!(curatr&BLINK))
-			bprintf("\x1b[5m"); }
-	if(atr&HIGH) {
-		if(!(curatr&HIGH))
-			bprintf("\x1b[1m"); }
-
-	if((atr&0x7)==BLACK) {				/* foreground colors */
-		if((curatr&0x7)!=BLACK)
-			bprintf("\x1b[30m"); }
-	else if((atr&0x7)==RED) {
-		if((curatr&0x7)!=RED)
-			bprintf("\x1b[31m"); }
-	else if((atr&0x7)==GREEN) {
-		if((curatr&0x7)!=GREEN)
-			bprintf("\x1b[32m"); }
-	else if((atr&0x7)==BROWN) {
-		if((curatr&0x7)!=BROWN)
-			bprintf("\x1b[33m"); }
-	else if((atr&0x7)==BLUE) {
-		if((curatr&0x7)!=BLUE)
-			bprintf("\x1b[34m"); }
-	else if((atr&0x7)==MAGENTA) {
-		if((curatr&0x7)!=MAGENTA)
-			bprintf("\x1b[35m"); }
-	else if((atr&0x7)==CYAN) {
-		if((curatr&0x7)!=CYAN)
-			bprintf("\x1b[36m"); }
-	else if((atr&0x7)==LIGHTGRAY) {
-		if((curatr&0x7)!=LIGHTGRAY)
-			bprintf("\x1b[37m"); }
-
-	if((atr&0x70)==(BLACK<<4)) {		/* background colors */
-		if((curatr&0x70)!=(BLACK<<4))
-			bprintf("\x1b[40m"); }
-	else if((atr&0x70)==(RED<<4)) {
-		if((curatr&0x70)!=(RED<<4))
-			bprintf("\x1b[41m"); }
-	else if((atr&0x70)==(GREEN<<4)) {
-		if((curatr&0x70)!=(GREEN<<4))
-			bprintf("\x1b[42m"); }
-	else if((atr&0x70)==(BROWN<<4)) {
-		if((curatr&0x70)!=(BROWN<<4))
-			bprintf("\x1b[43m"); }
-	else if((atr&0x70)==(BLUE<<4)) {
-		if((curatr&0x70)!=(BLUE<<4))
-			bprintf("\x1b[44m"); }
-	else if((atr&0x70)==(MAGENTA<<4)) {
-		if((curatr&0x70)!=(MAGENTA<<4))
-			bprintf("\x1b[45m"); }
-	else if((atr&0x70)==(CYAN<<4)) {
-		if((curatr&0x70)!=(CYAN<<4))
-			bprintf("\x1b[46m"); }
-	else if((atr&0x70)==(LIGHTGRAY<<4)) {
-		if((curatr&0x70)!=(LIGHTGRAY<<4))
-			bprintf("\x1b[47m"); }
-
-	curatr=atr;
-}
-
-/****************************************************************************/
-/* Peform clear screen														*/
-/****************************************************************************/
-void cls(void)
-{
-	if(lncntr>1 && !tos) {
-		lncntr=0;
-		CRLF;
-		bpause();
-		while(lncntr && !aborted)
-			bpause(); }
-
-	if(user_misc&ANSI)
-		bputs("\x1b[2J\x1b[H");	/* clear screen, home cursor */
-	else 
-		outchar(FF);
-	tos=1;
-	lncntr=0;
-}
-
-/****************************************************************************/
-/* performs the correct attribute modifications for the Ctrl-A code			*/
-/****************************************************************************/
-void ctrl_a(char x)
-{
-	char atr=curatr;
-	int i;
-
-	if((uchar)x>=0x7f) {
-		if(user_misc&ANSI)
-			bprintf("\x1b[%uC",(uchar)x-0x7f);
-		else
-			for(i=0;i<(uchar)x-0x7f;i++)
-				outchar(SP);
-		return; }
-
-	switch(toupper(x)) {
-		case '-':								/* turn off all attributes if */
-			if(atr&(HIGH|BLINK|(LIGHTGRAY<<4)))	/* high intensity, blink or */
-				attr(LIGHTGRAY);				/* background bits are set */
-			break;
-		case '_':								/* turn off all attributes if */
-			if(atr&(BLINK|(LIGHTGRAY<<4)))		/* blink or background is set */
-				attr(LIGHTGRAY);
-			break;
-		case ',':   /* Delay 1/10 sec */
-			mswait(100);
-			break;
-		case ';':   /* Delay 1/2 sec */
-			mswait(500);
-			break;
-		case '.':   /* Delay 2 secs */
-			mswait(2000);
-			break;
-		case 'P':	/* Pause */
-			bpause();
-			break;
-		case 'Q':   /* Pause reset */
-			lncntr=0;
-			break;
-		case 'L':	/* CLS (form feed) */
-			cls();
-			break;
-		case '>':   /* CLREOL */
-			if(user_misc&ANSI)
-				bputs("\x1b[K");
-#if 0
-			else {
-				i=j=wherey();
-				while(i++<80)
-					outchar(SP);
-				while(j++<80)
-					outchar(BS); }
-#endif
-			break;
-		case '<':   /* Non-destructive backspace */
-			outchar(BS);
-			break;
-		case '[':   /* Carriage return */
-			outchar(CR);
-			break;
-		case ']':   /* Line feed */
-			outchar(LF);
-			break;
-		case 'A':   /* Ctrl-A */
-			outchar(1);
-			break;
-		case 'H': 	/* High intensity */
-			atr|=HIGH;
-			attr(atr);
-			break;
-		case 'I':	/* Blink */
-			atr|=BLINK;
-			attr(atr);
-			break;
-		case 'N': 	/* Normal */
-			attr(LIGHTGRAY);
-			break;
-		case 'R':
-			atr=(atr&0xf8)|RED;
-			attr(atr);
-			break;
-		case 'S':
-			nodesync();
-			break;
-		case 'G':
-			atr=(atr&0xf8)|GREEN;
-			attr(atr);
-			break;
-		case 'B':
-			atr=(atr&0xf8)|BLUE;
-			attr(atr);
-			break;
-		case 'W':	/* White */
-			atr=(atr&0xf8)|LIGHTGRAY;
-			attr(atr);
-			break;
-		case 'C':
-			atr=(atr&0xf8)|CYAN;
-			attr(atr);
-			break;
-		case 'M':
-			atr=(atr&0xf8)|MAGENTA;
-			attr(atr);
-			break;
-		case 'Y':
-			atr=(atr&0xf8)|BROWN;
-			attr(atr);
-			break;
-		case 'K':	/* Black */
-			atr=(atr&0xf8)|BLACK;
-			attr(atr);
-			break;
-		case '0':	/* Black Background */
-			atr=(atr&0x8f)|(uchar)(BLACK<<4);
-			attr(atr);
-			break;
-		case '1':	/* Red Background */
-			atr=(atr&0x8f)|(uchar)(RED<<4);
-			attr(atr);
-			break;
-		case '2':	/* Green Background */
-			atr=(atr&0x8f)|(uchar)(GREEN<<4);
-			attr(atr);
-			break;
-		case '3':	/* Yellow Background */
-			atr=(atr&0x8f)|(uchar)(BROWN<<4);
-			attr(atr);
-			break;
-		case '4':	/* Blue Background */
-			atr=(atr&0x8f)|(uchar)(BLUE<<4);
-			attr(atr);
-			break;
-		case '5':	/* Magenta Background */
-			atr=(atr&0x8f)|(uchar)(MAGENTA<<4);
-			attr(atr);
-			break;
-		case '6':	/* Cyan Background */
-			atr=(atr&0x8f)|(uchar)(CYAN<<4);
-			attr(atr);
-			break;
-		case '7':	/* White Background */
-			atr=(atr&0x8f)|(uchar)(LIGHTGRAY<<4);
-			attr(atr);
-			break; }
-}
-
-/****************************************************************************/
-/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
-/* number of times if the attempted file is already open or denying access  */
-/* for some other reason.	All files are opened in BINARY mode.			*/
-/****************************************************************************/
-int nopen(char *str, int access)
-{
-	char count=0;
-	int file,share;
-
-	if(access&SH_DENYNO) share=SH_DENYNO;
-	else if(access==O_RDONLY) share=SH_DENYWR;
-	else share=SH_DENYRW;
-	while(((file=sopen(str,O_BINARY|access,share))==-1)
-		&& errno==EACCES && count++<LOOP_NOPEN)
-		if(count>10)
-			mswait(50);
-	if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN)
-		bprintf("\r\nNOPEN COLLISION - File: %s Count: %d\r\n"
-			,str,count);
-	if(file==-1 && errno==EACCES)
-		bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-	return(file);
-}
-
-/****************************************************************************/
-/* Reads data from XTRN.DAT in the node directory and fills the appropriate */
-/* global variables.														*/
-/* Initializes starttime variable with current time.						*/
-/****************************************************************************/
-void initdata(void)
-{
-	char str[256],tmp[256];
-	int i;
-	FILE *stream;
-
-#ifdef _WINSOCKAPI_
-    WSAStartup(MAKEWORD(1,1), &WSAData);
-	client_socket=INVALID_SOCKET;
-#endif
-
-#ifdef __WATCOMC__
-	putenv("TZ=UCT0");
-	setvbuf(stdout,NULL,_IONBF,0);
-	setvbuf(stderr,NULL,_IONBF,0);
-#endif
-
-#ifdef __SC__
-    setvbuf(stdout,NULL,_IONBF,0);
-	con_fp=stdout;
-#else
-	con_fp=stderr;
-#endif
-
-#ifdef __16BIT__
-
-#if defined(__TURBOC__) || defined(__SC__)	/* Borland or Symantec */
-	ctrlbrk(cbreakh);
-#endif
-
-	if(setmode(fileno(con_fp),O_BINARY)==-1) {	 /* eliminate LF expansion */
-		printf("Can't set console output to BINARY\n");
-		exit(1); }
-#endif
-
-	sprintf(str,"%sXTRN.DAT",node_dir);
-	if((stream=fopen(str,"rt"))==NULL) {
-		printf("Can't open %s\r\n",str);
-		exit(1); }
-	fgets(str,81,stream);			/* username */
-	sprintf(user_name,"%.25s",str);
-	truncsp(user_name);
-	fgets(str,81,stream);			/* system name */
-	sprintf(sys_name,"%.40s",str);
-	truncsp(sys_name);
-	fgets(str,81,stream);			/* system operator */
-	sprintf(sys_op,"%.40s",str);
-	truncsp(sys_op);
-	fgets(str,81,stream);			/* system guru */
-	sprintf(sys_guru,"%.40s",str);
-	truncsp(sys_guru);
-
-	fgets(str,81,stream);			/* ctrl dir */
-	str[50]=0;
-	if(str[0]=='.')
-		sprintf(ctrl_dir,"%s%s",node_dir,str);
-	else
-		strcpy(ctrl_dir,str);
-	truncsp(ctrl_dir);
-	if(_fullpath(str,ctrl_dir,50))
-		strcpy(ctrl_dir,str);
-	backslash(ctrl_dir);
-
-	fgets(str,81,stream);			/* data dir */
-	if(str[0]=='.')
-		sprintf(data_dir,"%s%s",node_dir,str);
-	else
-		sprintf(data_dir,"%.40s",str);
-	truncsp(data_dir);
-	if(_fullpath(str,data_dir,50))
-		strcpy(data_dir,str);
-	backslash(data_dir);
-
-	fgets(str,81,stream);			/* total nodes */
-	sys_nodes=atoi(str);
-	fgets(str,81,stream);			/* current node */
-	node_num=atoi(str);
-	fgets(str,81,stream);			/* time left */
-	timeleft=atoi(str);
-	fgets(str,81,stream);			/* ANSI? (Yes, Mono, or No) */
-	user_misc=0;
-	if(str[0]=='Y')
-		user_misc|=(ANSI|COLOR);
-	else if(str[0]=='M')
-		user_misc|=ANSI;
-	fgets(str,81,stream);			/* screen lines */
-	user_rows=atoi(str);
-	fgets(str,81,stream);			/* credits */
-	user_cdt=atol(str);
-	fgets(str,81,stream);			/* level */
-	user_level=atoi(str);
-	fgets(str,81,stream);			/* was transfer level, left for compat. */
-	fgets(str,81,stream);			/* birthdate */
-	truncsp(str);
-	sprintf(user_birth,"%.8s",str);
-	fgets(str,81,stream);			/* sex */
-	user_sex=str[0];
-	fgets(str,81,stream);			/* user number */
-	user_number=atoi(str);
-	fgets(str,81,stream);			/* user phone number */
-	sprintf(user_phone,"%.12s",str);
-	truncsp(user_phone);
-	fgets(str,81,stream);			/* com port (0 if local or no modem) */
-	com_port=atoi(str);
-	fgets(str,81,stream);			/* com (UART) irq */
-	com_irq=atoi(str);
-	fgets(str,81,stream);			/* com (UART) base address in hex */
-	truncsp(str);
-	com_base=(uint)ahtoul(str);
-	fgets(str,81,stream);			/* com rate */
-	com_rate=(ulong)atol(str);
-	fgets(str,81,stream);			/* hardware flow control (Y/N) */
-	if(toupper(str[0])=='Y')
-		mdm_misc|=MDM_FLOWCTRL;
-	fgets(str,81,stream);			/* locked DTE rate (Y/N) */
-	if(toupper(str[0])=='Y')
-		mdm_misc|=MDM_STAYHIGH;
-	fgets(str,81,stream);			/* modem initialization string */
-	sprintf(mdm_init,"%.63s",str);
-	truncsp(mdm_init);
-	fgets(str,81,stream);			/* modem special init string */
-	sprintf(mdm_spec,"%.63s",str);
-	truncsp(mdm_spec);
-	fgets(str,81,stream);			/* modem terminal mode string */
-	sprintf(mdm_term,"%.63s",str);
-	truncsp(mdm_term);
-	fgets(str,81,stream);			/* modem dial string */
-	sprintf(mdm_dial,"%.63s",str);
-	truncsp(mdm_dial);
-	fgets(str,81,stream);			/* modem off-hook string */
-	sprintf(mdm_offh,"%.63s",str);
-	truncsp(mdm_offh);
-	fgets(str,81,stream);			/* modem answer string */
-	sprintf(mdm_answ,"%.63s",str);
-	truncsp(mdm_answ);
-	fgets(str,81,stream);			/* memory address of modem status register */
-	msr=(uint FAR16 *)atol(str);
-	if(!fgets(str,81,stream))		/* total number of external programs */
-		total_xtrns=0;
-	else
-		total_xtrns=atoi(str);
-	if(total_xtrns && (xtrn=(char **)MALLOC(sizeof(char *)*total_xtrns))==NULL) {
-		printf("Allocation error 1: %u\r\n",sizeof(char *)*total_xtrns);
-		exit(1); }
-	for(i=0;i<(int)total_xtrns;i++) {
-		fgets(str,81,stream);
-		truncsp(str);
-		if((xtrn[i]=(char *)MALLOC(strlen(str)+1))==NULL) {
-			printf("Allocation error 2 (%u): %u\r\n",i,strlen(str)+1);
-			exit(1); }
-		strcpy(xtrn[i],str); }
-	fgets(str,81,stream);			/* user's main flags */
-	sprintf(user_flags1,"%.26s",str);
-	fgets(str,81,stream);			/* user's xfer flags */
-	sprintf(user_flags2,"%.26s",str);
-	fgets(str,81,stream);			/* user's exemptions */
-	sprintf(user_exempt,"%.26s",str);
-	fgets(str,81,stream);			/* user's restrictions */
-	sprintf(user_rest,"%.26s",str);
-	fgets(str,81,stream);			/* user's expiration date */
-	truncsp(str);
-	user_expire=ahtoul(str);
-	str[0]=0;
-	fgets(str,81,stream);			/* user's address */
-	sprintf(user_address,"%.30s",str);
-	truncsp(user_address);
-	fgets(str,81,stream);			/* user's location (city, state) */
-	sprintf(user_location,"%.30s",str);
-	truncsp(user_location);
-	fgets(str,81,stream);			/* user's zip/postal code */
-	sprintf(user_zipcode,"%.10s",str);
-	truncsp(user_zipcode);
-	str[0]=0;
-	fgets(str,81,stream);
-	sprintf(user_flags3,"%.26s",str);
-	fgets(str,81,stream);
-	sprintf(user_flags4,"%.26s",str);
-	if(fgets(str,81,stream))		/* Time-slice API type */
-#ifdef __16BIT__ 
-		mswtyp=ahtoul(str);
-#else
-		;
-#endif
-	str[0]=0;
-	fgets(str,81,stream);
-	truncsp(str);
-	sprintf(user_realname,"%.25s",str);
-	str[0]=0;
-	fgets(str,81,stream);
-	user_dce=atol(str);
-
-	str[0]=0;
-	fgets(str,81,stream);			/* exec dir */
-	if(!str[0])
-		sprintf(exec_dir,"%s../exec/",ctrl_dir);
-	else {
-		if(str[0]=='.')
-			sprintf(exec_dir,"%s%s",node_dir,str);
-		else
-			sprintf(exec_dir,"%.50s",str); }
-	truncsp(exec_dir);
-	if(_fullpath(str,exec_dir,50))
-		strcpy(exec_dir,str);
-	backslash(exec_dir);
-
-	str[0]=0;
-	fgets(str,81,stream);			/* text dir */
-	if(!str[0])
-		sprintf(text_dir,"%s../text/",ctrl_dir);
-	else {
-		if(str[0]=='.')
-			sprintf(text_dir,"%s%s",node_dir,str);
-		else
-			sprintf(text_dir,"%.50s",str); }
-	truncsp(text_dir);
-	if(_fullpath(str,text_dir,50))
-		strcpy(text_dir,str);
-	backslash(text_dir);
-
-	str[0]=0;
-	fgets(str,81,stream);			/* temp dir */
-	if(!str[0])
-		sprintf(temp_dir,"%stemp/",node_dir);
-	else {
-		if(str[0]!=BACKSLASH && str[1]!=':')
-			sprintf(temp_dir,"%s%s",node_dir,str);
-		else
-			sprintf(temp_dir,"%.50s",str); }
-	truncsp(temp_dir);
-	if(_fullpath(str,temp_dir,50))
-		strcpy(temp_dir,str);
-	backslash(temp_dir);
-
-	str[0]=0;
-	fgets(str,81,stream);
-	sprintf(sys_id,"%.8s",str);
-
-	str[0]=0;
-	fgets(str,81,stream);
-	truncsp(str);
-	if(str[0])
-		node_misc=(uint)ahtoul(str);
-	else
-		node_misc=NM_LOWPRIO;
-
-#ifndef __16BIT__
-	str[0]=0;
-	fgets(str,81,stream);
-	client_socket=atoi(str);
-
-	if(client_socket!=INVALID_SOCKET) {
-
-#ifdef _WIN32
-		output_sem=CreateEvent(
-						 NULL	// pointer to security attributes
-						,TRUE	// flag for manual-reset event
-						,FALSE	// flag for initial state
-						,NULL	// pointer to event-object name
-						);
-		if(output_sem==NULL) {
-			printf("\r\n\7Error %d creating output_event\r\n",GetLastError());
-			exit(1);
-		}
-#else
-		sem_init(&output_sem,0,0);
-#endif
-		_beginthread(output_thread,0,NULL);
-	}
-#endif
-
-	fclose(stream);
-
-	sprintf(str,"%sINTRSBBS.DAT",node_dir);     /* Shrank to run! */
-	if(fexist(str)) {
-		if((stream=fopen(str,"rt"))==NULL) {
-			printf("Can't open %s\n",str);
-			exit(1); 
-		}
-		fgets(tmp,81,stream);					/* so get MSR address from file */
-		msr=(uint FAR16 *)atol(tmp);
-		fclose(stream);
-		remove(str); 
-	}
-
-	starttime=time(NULL);			/* initialize start time stamp */
-	wordwrap[0]=0;					/* set wordwrap to null */
-	mnehigh=LIGHTGRAY|HIGH; 		/* mnemonics highlight color */
-	mnelow=GREEN;					/* mnemonics normal text color */
-	sec_warn=180;					/* seconds till inactivity warning */
-	sec_timeout=300;				/* seconds till inactivity timeout */
-	tos=lncntr=0;					/* init topofscreen and linecounter to 0 */
-	lastnodemsg=0;					/* Last node to send message to */
-	aborted=0;                      /* Ctrl-C hit flag */
-	sysop_level=90; 				/* Minimum level to be considered sysop */
-	timeleft_warn=0;				/* Running out of time warning */
-
-	sprintf(str,"%s%s",ctrl_dir,"node.dab");
-	if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO))==-1) {
-		printf("\r\n\7Error opening %s\r\n",str);
-		exit(1); 
-	}
-
-	sprintf(str,"%suser/name.dat",data_dir);
-	if((i=nopen(str,O_RDONLY))==-1) {
-		printf("\r\n\7Error opening %s\r\n",str);
-		exit(1); 
-	}
-	memset(str,0,30);
-	read(i,str,26);
-	close(i);
-	if(str[25]==CR) 	/* Version 1b */
-		name_len=25;
-	else				/* Version 1a */
-		name_len=30;
-
-#ifdef __unix__
-	_termios_setup();
-#endif
-
-	if(xsdk_mode&XSDK_MODE_NOCONSOLE) {
-		con_fp=NULL;
-#ifdef _WIN32
-		FreeConsole();
-#endif
-	}
-
-	attr(LIGHTGRAY);				/* initialize color and curatr to plain */
-}
-
-/****************************************************************************/
-/* Automatic RIP & WIP terminal detection function. Sets RIP and WIP bits	*/
-/* in user_misc variable. Must be called AFTER initdat(), not before.		*/
-/****************************************************************************/
-void get_term(void)
-{
-	char str[128],ch;
-	int i;
-
-	bputs("\r\x1b[!_\x1b[0t_\r        \r");
-	mswait(500);
-	for(i=0;i<120;i++) {
-		ch=inkey(0);
-		if(!ch)
-			break;
-		mswait(1);
-		str[i]=ch; }
-	str[i]=0;
-	if(strstr(str,"RIPSCRIP"))
-		user_misc|=RIP;
-	if(strstr(str,"DC-TERM"))
-		user_misc|=WIP;
-}
-
-/****************************************************************************/
-/* Truncates white-space chars off end of 'str' and terminates at first tab */
-/****************************************************************************/
-void truncsp(uchar *str)
-{
-	char c;
-
-	str[strcspn(str,"\t")]=0;
-	c=strlen(str);
-	while(c && (uchar)str[c-1]<=SP) c--;
-	str[c]=0;
-}
-
-/****************************************************************************/
-/* Puts a backslash on path strings 										*/
-/****************************************************************************/
-void backslash(char *str)
-{
-    int i;
-
-	i=strlen(str);
-	if(i && str[i-1]!='\\' && str[i-1]!='/') {
-		str[i]=BACKSLASH; 
-		str[i+1]=0; 
-	}
-}
-
-
-/****************************************************************************/
-/* Checks the amount of time inside the external program against the amount */
-/* of time the user had left online before running the external program and */
-/* prints a message and exits the program if time has run out.				*/
-/****************************************************************************/
-void checktimeleft(void)
-{
-	if(!SYSOP && !strchr(user_exempt,'T') && time(NULL)-starttime>timeleft) {
-		bputs("\1_\n\1r\1hTime's up.\n");
-		exit(0);  }
-}
-
-/****************************************************************************/
-/* Prints a file remotely and locally, interpreting ^A sequences.			*/
-/* 'str' is the path of the file to print                                   */
-/****************************************************************************/
-void printfile(char *str)
-{
-	char *buf;
-	int file;
-	ulong length;
-
-	if(!tos)
-		CRLF;
-	if((file=nopen(str,O_RDONLY))==-1) {
-		bprintf("File not Found: %s\r\n",str);
-		return; }
-	length=filelength(file);
-	if((buf=MALLOC(length+1L))==NULL) {
-		close(file);
-		bprintf("\7\r\nPRINTFILE: Error allocating %lu bytes of memory for %s.\r\n"
-			,length+1L,str);
-		return; }
-	buf[read(file,buf,length)]=0;
-	close(file);
-	bputs(buf);
-	aborted=0;
-	FREE(buf);
-}
-
-/****************************************************************************/
-/* Returns a char pointer to the name of the user that corresponds to		*/
-/* usernumber. Takes value directly from database.							*/
-/****************************************************************************/
-char *username(uint usernumber)
-{
-	static	char name[26];
-	char	str[128];
-	int 	i,file;
-
-	strcpy(name,"UNKNOWN USER");
-	if(!data_dir[0])
-		return(name);
-	if(!usernumber) {
-		bputs("\7username: called with zero usernumber\r\n");
-		return(name); }
-	sprintf(str,"%suser/name.dat",data_dir);
-	if((file=nopen(str,O_RDONLY))==-1) {
-		bprintf("\7username: couldn't open %s\r\n",str);
-		return(name); }
-	if(filelength(file)<(long)(usernumber-1)*((long)name_len+2L)) {
-		close(file);
-		return(name); }
-	lseek(file,(long)(usernumber-1)*((long)name_len+2L),SEEK_SET);
-	read(file,name,25);
-	close(file);
-	for(i=0;i<25;i++)
-		if(name[i]==3)
-			break;
-	name[i]=0;
-	if(!name[0])
-		strcpy(name,"DELETED USER");
-	return(name);
-}
-
-/****************************************************************************/
-/* Returns the number of the user 'username' from the NAME.DAT file.        */
-/* If the username is not found, the function returns 0.					*/
-/****************************************************************************/
-uint usernumber(char *username)
-{
-	char str[128];
-	int i,file;
-	FILE *stream;
-
-	if(!data_dir[0])
-		return(0);
-	sprintf(str,"%suser/name.dat",data_dir);
-	if((file=nopen(str,O_RDONLY))==-1 || (stream=fdopen(file,"rb"))==NULL) {
-		if(file!=-1)
-			close(file);
-		bprintf("\7usernumber: couldn't open %s\r\n",str);
-		return(0); }
-	for(i=1;!feof(stream);i++) {
-		if(!fread(str,27,1,stream))
-			break;
-		str[25]=0;
-		truncsp(str);	/* chop of trailing EOTs and spaces */
-		if(!stricmp(str,username)) {
-			fclose(stream);
-			return(i); } }
-	fclose(stream);
-	return(0);
-}
-
-
-/****************************************************************************/
-/* Returns in 'string' a character representation of the number in l with   */
-/* commas. Maximum value of l is 4 gigabytes.								*/
-/****************************************************************************/
-char *ultoac(ulong l, char *string)
-{
-	char str[81];
-	char i,j,k;
-
-	sprintf(str,"%lu",l);
-	i=strlen(str)-1;
-	j=i/3+1+i;
-	string[j--]=0;
-	for(k=1;i>-1;k++) {
-		string[j--]=str[i--];
-		if(j>0 && !(k%3))
-			string[j--]=','; }
-	return(string);
-}
-
-/****************************************************************************/
-/* Converts an ASCII Hex string into a ulong								*/
-/****************************************************************************/
-ulong ahtoul(char *str)
-{
-	ulong l,val=0;
-
-	while((l=(*str++)|0x20)!=0x20)
-		val=(l&0xf)+(l>>6&1)*9+val*16;
-	return(val);
-}
-
-/****************************************************************************/
-/* Reads the data for node number 'number' into the structure 'node'        */
-/* from NODE.DAB															*/
-/* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
-/****************************************************************************/
-void getnodedat(int number, node_t *node, char lockit)
-{
-	int count=0;
-
-	if(nodefile<0)
-		return;
-	number--;	/* make zero based */
-	while(count<LOOP_NODEDAB) {
-		lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-		if(lockit
-			&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-			count++;
-			continue; }
-		if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-			break;
-		count++; }
-	if(count==LOOP_NODEDAB)
-		bprintf("\7Error unlocking and reading node.dab\r\n");
-}
-
-/****************************************************************************/
-/* Write the data from the structure 'node' into NODE.DAB  					*/
-/* getnodedat(num,&node,1); must have been called before calling this func  */
-/*          NOTE: ------^   the indicates the node record has been locked   */
-/****************************************************************************/
-void putnodedat(int number, node_t node)
-{
-	if(nodefile<0)
-		return;
-	number--;	/* make zero based */
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
-		unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-		bprintf("\7Error writing node.dab for node %u\r\n",number+1);
-		return; }
-	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-}
-
-/****************************************************************************/
-/* Checks for messages waiting for this node or interruption.				*/
-/****************************************************************************/
-void nodesync(void)
-{
-	node_t node;
-
-	if(!ctrl_dir[0])
-		return;
-	getnodedat(node_num,&node,0);
-
-	if(node.misc&NODE_MSGW)
-		getsmsg(user_number);		/* getsmsg clears MSGW flag */
-
-	if(node.misc&NODE_NMSG) 		/* getnmsg clears NMSG flag */
-		getnmsg();
-
-	if(node.misc&NODE_INTR)
-		exit(0);
-
-}
-
-/****************************************************************************/
-/* Displays the information for node number 'number' contained in 'node'    */
-/****************************************************************************/
-void printnodedat(int number, node_t node)
-{
-	char hour,mer[3],tmp[256];
-	int i;
-
-	attr(LIGHTGRAY|HIGH);
-	bprintf("Node %2d: ",number);
-	attr(GREEN);
-	switch(node.status) {
-		case NODE_WFC:
-			bputs("Waiting for call");
-			break;
-		case NODE_OFFLINE:
-			bputs("Offline");
-			break;
-		case NODE_NETTING:
-			bputs("Networking");
-			break;
-		case NODE_LOGON:
-			bputs("At logon prompt");
-			break;
-		case NODE_EVENT_WAITING:
-			bputs("Waiting for all nodes to become inactive");
-			break;
-		case NODE_EVENT_LIMBO:
-			bprintf("Waiting for node %d to finish external event",node.aux);
-			break;
-		case NODE_EVENT_RUNNING:
-			bputs("Running external event");
-			break;
-		case NODE_NEWUSER:
-			attr(GREEN|HIGH);
-			bputs("New user");
-			attr(GREEN);
-			bputs(" applying for access ");
-			if(!node.connection)
-				bputs("Locally");
-			else if(node.connection==0xffff)
-				bprintf("via telnet");
-			else
-				bprintf("at %ubps",node.connection);
-			break;
-		case NODE_QUIET:
-			if(!SYSOP) {
-				bputs("Waiting for call");
-				break; }
-		case NODE_INUSE:
-			attr(GREEN|HIGH);
-			if(node.misc&NODE_ANON && !SYSOP)
-				bputs("UNKNOWN USER");
-			else
-				bputs(username(node.useron));
-			attr(GREEN);
-			bputs(" ");
-			switch(node.action) {
-				case NODE_MAIN:
-					bputs("at main menu");
-					break;
-				case NODE_RMSG:
-					bputs("reading messages");
-					break;
-				case NODE_RMAL:
-					bputs("reading mail");
-					break;
-				case NODE_RSML:
-					bputs("reading sent mail");
-					break;
-				case NODE_RTXT:
-					bputs("reading text files");
-					break;
-				case NODE_PMSG:
-					bputs("posting message");
-					break;
-				case NODE_SMAL:
-					bputs("sending mail");
-					break;
-				case NODE_AMSG:
-					bputs("posting auto-message");
-					break;
-				case NODE_XTRN:
-					if(!node.aux)
-						bputs("at external program menu");
-					else {
-						bputs("running ");
-						i=node.aux-1;
-						if(i>=(int)total_xtrns || i<0 || !xtrn[i][0])
-							bputs("external program");
-						else
-							bputs(xtrn[i]); }
-					break;
-				case NODE_DFLT:
-					bputs("changing defaults");
-					break;
-				case NODE_XFER:
-					bputs("at transfer menu");
-					break;
-				case NODE_RFSD:
-					bprintf("retrieving from device #%d",node.aux);
-					break;
-				case NODE_DLNG:
-					bprintf("downloading");
-					break;
-				case NODE_ULNG:
-					bputs("uploading");
-					break;
-				case NODE_BXFR:
-					bputs("transferring bidirectional");
-					break;
-				case NODE_LFIL:
-					bputs("listing files");
-					break;
-				case NODE_LOGN:
-					bputs("logging on");
-					break;
-				case NODE_LCHT:
-					bprintf("in local chat with %s",sys_op);
-					break;
-				case NODE_MCHT:
-					if(node.aux) {
-						bprintf("in multinode chat channel %d",node.aux&0xff);
-						if(node.aux&0x1f00)  /* password */
-							outchar('*'); }
-					else
-						bputs("in multinode global chat channel");
-					break;
-				case NODE_PAGE:
-					bprintf("paging node %u for private chat",node.aux);
-					break;
-				case NODE_PCHT:
-					bprintf("in private chat with node %u",node.aux);
-					break;
-				case NODE_GCHT:
-					bprintf("chatting with %s",sys_guru);
-					break;
-				case NODE_CHAT:
-					bputs("in chat section");
-					break;
-				case NODE_TQWK:
-					bputs("transferring QWK packet");
-					break;
-				case NODE_SYSP:
-					bputs("performing sysop activities");
-					break;
-				default:
-					bputs(ultoa(node.action,tmp,10));
-					break;  }
-			if(!node.connection)
-				bputs(" locally");
-			else if(node.connection==0xffff)
-				bprintf(" via telnet");
-			else
-				bprintf(" at %ubps",node.connection);
-			if(node.action==NODE_DLNG) {
-				if((node.aux/60)>12) {
-					hour=(node.aux/60)-12;
-					strcpy(mer,"pm"); }
-				else {
-					if((node.aux/60)==0)    /* 12 midnite */
-						hour=12;
-					else hour=node.aux/60;
-					strcpy(mer,"am"); }
-				bprintf(" ETA %02d:%02d %s"
-					,hour,node.aux%60,mer); }
-			break; }
-	i=NODE_LOCK;
-	if(node.status==NODE_INUSE || SYSOP)
-		i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
-	if(node.misc&i) {
-		bputs(" (");
-		if(node.misc&(i&NODE_AOFF))
-			outchar('A');
-		if(node.misc&NODE_LOCK)
-			outchar('L');
-		if(node.misc&(i&(NODE_MSGW|NODE_NMSG)))
-			outchar('M');
-		if(node.misc&(i&NODE_POFF))
-			outchar('P');
-		outchar(')'); }
-	if(SYSOP && ((node.misc
-		&(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
-		|| node.status==NODE_QUIET)) {
-		bputs(" [");
-		if(node.misc&NODE_ANON)
-			outchar('A');
-		if(node.misc&NODE_INTR)
-			outchar('I');
-		if(node.misc&NODE_RRUN)
-			outchar('R');
-		if(node.misc&NODE_UDAT)
-			outchar('U');
-		if(node.status==NODE_QUIET)
-			outchar('Q');
-		if(node.misc&NODE_EVENT)
-			outchar('E');
-		if(node.misc&NODE_DOWN)
-			outchar('D');
-		outchar(']'); }
-	if(node.errors && SYSOP) {
-		attr(RED|HIGH|BLINK);
-		bprintf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' ); }
-	CRLF;
-}
-
-/****************************************************************************/
-/* Prints short messages waiting for 'usernumber', if any...				*/
-/* then deletes them.														*/
-/****************************************************************************/
-void getsmsg(int usernumber)
-{
-	char str[256], *buf;
-	int file;
-	long length;
-	node_t node;
-
-	if(!data_dir[0])
-		return;
-	sprintf(str,"%smsgs/%4.4u.msg",data_dir,usernumber);
-	if(flength(str)<1L) {
-		return; }
-	if((file=nopen(str,O_RDWR))==-1) {
-		bprintf("\7Error opening %s for read/write access\r\n",str);
-		return; }
-	length=filelength(file);
-	if((buf=MALLOC(length+1))==NULL) {
-		close(file);
-		bprintf("\7Error allocating %u bytes of memory for %s\r\n",length+1,str);
-		return; }
-	if(read(file,buf,length)!=length) {
-		close(file);
-		FREE(buf);
-		bprintf("\7Error reading %u bytes from %s\r\n",length,str);
-		return; }
-	chsize(file,0L);
-	close(file);
-	buf[length]=0;
-	getnodedat(node_num,&node,0);
-	if(node.action==NODE_MAIN || node.action==NODE_XFER) {
-		CRLF; }
-	if(node.misc&NODE_MSGW) {
-		getnodedat(node_num,&node,1);
-		node.misc&=~NODE_MSGW;
-		putnodedat(node_num,node); }
-	bputs(buf);
-	FREE(buf);
-}
-
-/****************************************************************************/
-/* Creates a short message for 'usernumber' than contains 'strin'			*/
-/****************************************************************************/
-void putsmsg(int usernumber, char *strin)
-{
-	char str[256];
-	int file,i;
-    node_t node;
-
-	if(!data_dir[0])
-		return;
-	sprintf(str,"%smsgs/%4.4u.msg",data_dir,usernumber);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-		bprintf("\7Error opening/creating %s for creat/append access\r\n",str);
-		return; }
-	i=strlen(strin);
-	if(write(file,strin,i)!=i) {
-		close(file);
-		bprintf("\7Error writing %u bytes to %s\r\n",i,str);
-		return; }
-	close(file);
-	for(i=1;i<=sys_nodes;i++) {		/* flag node if user on that msg waiting */
-		getnodedat(i,&node,0);
-		if(node.useron==(ushort)usernumber
-			&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
-			&& !(node.misc&NODE_MSGW)) {
-			getnodedat(i,&node,1);
-			node.misc|=NODE_MSGW;
-			putnodedat(i,node); } }
-}
-
-/****************************************************************************/
-/* Prints short messages waiting for this node, if any...					*/
-/****************************************************************************/
-void getnmsg(void)
-{
-	char str[256], *buf;
-	int file;
-	long length;
-	node_t thisnode;
-
-	if(!data_dir[0])
-		return;
-	getnodedat(node_num,&thisnode,1);
-	thisnode.misc&=~NODE_NMSG;			/* clear the NMSG flag */
-	putnodedat(node_num,thisnode);
-
-	sprintf(str,"%smsgs/n%3.3u.msg",data_dir,node_num);
-	if(flength(str)<1L) {
-		return; }
-	if((file=nopen(str,O_RDWR))==-1) {
-		printf("Couldn't open %s for read/write\r\n",str);
-		return; }
-	length=filelength(file);
-	if((buf=MALLOC(length+1))==NULL) {
-		close(file);
-		printf("Couldn't allocate %lu bytes for %s\r\n",length+1,str);
-		return; }
-	if(read(file,buf,length)!=length) {
-		close(file);
-		FREE(buf);
-		printf("Couldn't read %lu bytes from %s\r\n",length,str);
-		return; }
-	chsize(file,0L);
-	close(file);
-	buf[length]=0;
-
-	bputs(buf);
-	FREE(buf);
-}
-
-/****************************************************************************/
-/* Creates a short message for node 'num' than contains 'strin'             */
-/****************************************************************************/
-void putnmsg(int num, char *strin)
-{
-	char str[256];
-	int file,i;
-    node_t node;
-
-	if(!data_dir[0])
-		return;
-	sprintf(str,"%smsgs/n%3.3u.msg",data_dir,num);
-	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-		printf("Couldn't open %s for append\r\n",str);
-		return; }
-	i=strlen(strin);
-	if(write(file,strin,i)!=i) {
-		close(file);
-		printf("Error writing %u bytes to %s\r\n",i,str);
-		return; }
-	close(file);
-	getnodedat(num,&node,0);
-	if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-		&& !(node.misc&NODE_NMSG)) {
-		getnodedat(num,&node,1);
-		node.misc|=NODE_NMSG;
-		putnodedat(num,node); }
-}
-
-/****************************************************************************/
-/* This function lists users that are online.								*/
-/* If listself is true, it will list the current node.						*/
-/* Returns number of active nodes (not including current node). 			*/
-/****************************************************************************/
-int whos_online(char listself)
-{
-	int i,j;
-	node_t node;
-
-	if(!ctrl_dir[0])
-		return(0);
-	CRLF;
-	for(j=0,i=1;i<=sys_nodes;i++) {
-		getnodedat(i,&node,0);
-		if(i==node_num) {
-			if(listself)
-				printnodedat(i,node);
-			continue; }
-		if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
-			printnodedat(i,node);
-			if(!lastnodemsg)
-				lastnodemsg=i;
-			j++; } }
-	if(!j)
-		bputs("\1nNo other active nodes.\r\n");
-	return(j);
-}
-
-/****************************************************************************/
-/* Sending single line messages between nodes                               */
-/****************************************************************************/
-void nodemsg(void)
-{
-	char	line[256],buf[512];
-	int 	i;
-	node_t	thisnode;
-	node_t 	node;
-
-	if(!ctrl_dir[0])
-		return;
-	if(strchr(user_rest,'C')) {
-		bputs("You cannot send messages.\r\n");
-		return; }
-	getnodedat(node_num,&thisnode,0);
-	wordwrap[0]=0;
-	if(lastnodemsg) {
-		getnodedat(lastnodemsg,&node,0);
-		if(node.status!=NODE_INUSE)
-			lastnodemsg=0; }
-	if(!whos_online(0))
-		return;
-	bprintf("\r\n\1n\1gNumber of node to send message to, \1w\1hA\1n\1gll, "
-		"or \1w\1hQ\1n\1guit [%u]: \1w\1h",lastnodemsg);
-	i=getkeys("QA",sys_nodes);
-	if(i==-1)
-		return;
-	if(i&0x8000 || !i) {
-		if(!i)
-			i=lastnodemsg;
-		else {
-			i^=0x8000;
-			lastnodemsg=i; }
-		if(!i || i>sys_nodes)
-			return;
-		getnodedat(i,&node,0);
-		if(node.status!=NODE_INUSE && !SYSOP)
-			bprintf("\r\n\1_\1w\1hNode %d is not in use.\r\n",i);
-		else if(i==node_num)
-			bputs("\r\nThere's no need to send a message to yourself.\r\n");
-		else if(node.misc&NODE_POFF && !SYSOP)
-			bprintf("\r\n\1r\1h\1iDon't bug %s.\1n\r\n"
-				,node.misc&NODE_ANON ? "UNKNOWN USER"
-				: username(node.useron));
-		else {
-			bputs("\1_\1y\1hMessage: ");
-			if(!getstr(line,70,K_LINE))
-				return;
-			sprintf(buf
-				,"\7\1_\1w\1hNode %2d: \1g%s\1n\1g sent you a message:\r\n"
-				"\1w\1h\0014%s\1n\r\n"
-				,node_num
-				,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line);
-			putnmsg(i,buf); } }
-	else if(i=='A') {
-		bputs("\1_\1y\1hMessage: ");
-		if(!getstr(line,70,K_LINE))
-			return;
-		sprintf(buf
-			,"\7\1_\1w\1hNode %2d: \1g%s\1n\1g sent all nodes a message:\r\n"
-				"\1w\1h\0014%s\1n\r\n"
-			,node_num
-			,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line);
-		for(i=1;i<=sys_nodes;i++) {
-			if(i==node_num)
-				continue;
-			getnodedat(i,&node,0);
-			if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
-				&& (SYSOP || !(node.misc&NODE_POFF)))
-				putnmsg(i,buf); } }
-
-}
-
-/****************************************************************************/
-/* Puts a character into the input buffer									*/
-/****************************************************************************/
-void ungetkey(char ch)
-{
-
-	keybuf[keybuftop++]=ch;
-	if(keybuftop==KEY_BUFSIZE)
-		keybuftop=0;
-}
-
diff --git a/xtrn/sdk/xsdk.h b/xtrn/sdk/xsdk.h
deleted file mode 100644
index dbdf440b96aba9d3ca079e37a696dd97aeacc75d..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdk.h
+++ /dev/null
@@ -1,278 +0,0 @@
-/* xsdk.h */
-
-/* Synchronet XSDK function prototypes */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-
-#ifndef _XSDK_H
-#define _XSDK_H
-
-/*********************************************/
-/* Standard Borland/Turbo C/C++ Header Files */
-/*********************************************/
-#ifndef __unix__
-	#include <io.h>
-	#include <dos.h>
-	#include <share.h>
-	#include <conio.h>
-#endif
-#ifdef _WIN32
-	#include <windows.h>
-#endif
-#include <time.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#ifndef __FreeBSD__		/* FreeBSD uses stdlib.h for malloc() */
-	#include <malloc.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#define GLOBAL extern	/* turns XSDKVARS.C into a header file */
-#include "xsdkinet.h"
-#include "xsdkwrap.h"
-#include "xsdkvars.c"
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-extern char *xsdk_ver;	/* XSDK version number */
-extern ulong xsdk_mode;	/* XSDK mode bits */
-extern int mswtyp;		/* MSwait type */
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-
-/* Initialize Data
-	- Reads XTRN.DAT and initializes variables */
-void initdata(void);
-
-/* Get Terminal Type
-	- Detects RIP and WIP terminal compatibility */
-void get_term(void);
-
-/* BBS Print String
-	- Displays a string locally and remotely (with Ctrl-A codes) */
-void bputs(char *str);
-
-/* Raw Print String
-	- Oututs a string locally and remotely (verbatim) */
-void rputs(char *str);
-
-/* BBS Print Formatted
-	- Displays a formatted string locally and remotely (with Ctrl-A codes)
-	- printf() equivalent */
-int  bprintf(char *fmt, ...);
-
-/* Raw Print Formated
-	- Displays a formatted string locally and remotely (verbatim)
-	- printf() equivalent */
-int  rprintf(char *fmt, ...);
-
-/* BBS String Length
-	- Returns length of string, excluding Ctrl-A codes */
-int  bstrlen(uchar *str);
-
-/* Output character
-	- Displays a single character */
-void outchar(char ch);
-
-/* Mnemonics
-	- Display a string expanding ~letter combinations to command keys
-	- Automatically colorizes mnemonic letters or places them in parenthesis
-	  for non-ANSI users */
-void mnemonics(char *str);
-
-/* Pause prompt
-	- Displays [Hit a key] and waits for the user to hit a key */
-void bpause(void);
-
-/* Yes/no Question
-	- Displays a string with (Y/n) ? appended and waits for the user to hit
-	  'Y', 'N' or enter
-	- Returns 1 if the user hit 'Y' or enter
-	- Automatic colorization */
-char yesno(char *str);
-
-/* No/yes Question
-	- Displays a string with (y/N) ? appended and waits for the user to hit
-	  'Y', 'N' or enter
-	- Returns 1 if the user hit 'N' or enter */
-char noyes(char *str);
-
-/* Inbound Keystroke
-	- If the local or remote user has struck a key, this function returns the
-	  key, otherwise it returns 0
-	- Does not wait for a keystroke */
-char inkey(long mode);
-
-/* Get a Key
-	- Waits for the local or remote user to hit a valid key
-	- See K_* constants in XSDKDEFS.H for possible values of mode */
-char getkey(long mode);
-
-/* Get One of these Keys or a Number
-	- Waits for the user to hit a valid key or if max is non-zero, then enter
-	  a number not greater than max
-	- Hot-keyed input, automatically displays the struck key (in upper case)
-	  followed by CRLF
-	- If the user entered a number, the number is ORed with 0x8000 and returned
-	  you must XOR (or not) this bit to get the correct number */
-int  getkeys(char *str, int max);
-
-/* Get a Number
-	- Waits for the user to enter a number from 0 to max, 'Q' or ENTER
-	- Returns -1 if the user hit 'Q' or Ctrl-C
-	- Returns 0 if the user just hit ENTER */
-int  getnum(int max);
-
-/* Change Attribute
-	- Sends ANSI escape sequences (if user supports ANSI) to change color
-	- Valid color bits are defined in INCLUDE\CONIO.H */
-void attr(int atr);
-
-/* Clear Screen
-	- Clears local and remote screen (using ANSI if appropriate)
-	- Automatically pauses before clearing if lncntr is >1 */
-void cls(void);
-
-/* Process Ctrl-A Code
-	- Changes color or performs special Ctrl-A function */
-void ctrl_a(char x);
-
-/* Network Open
-	- Opens a file in DENYNONE or DENYWRITE mode, automatically retrying */
-int  nopen(char *str, int access);
-
-/* Truncate Space
-	- Removes white space characters from the end of a string */
-void truncsp(uchar *str);
-
-/* Adds Backslash
-	- Adds backslash to end of string if it doesn't exist */
-void backslash(char *str);
-
-/* Check Time Left
-	- Checks the amount of time the user has left and sets the timeleft
-	  variable
-	- Automatically exits if user runs out of time */
-void checktimeleft(void);
-
-/* Print File
-	- Displays contents of file (expanding Ctrl-A characters if appropriate) */
-void printfile(char *str);
-
-/* Get String
-	- Waits for the user to enter a string
-	- maxlen is the maximum length of the string
-	- See K_* constants in XSDKDEFS.H for possible values of mode */
-int  getstr(char *str, size_t maxlen, long mode);
-
-/* Redraw String
-	- Redisplays a string, mainly called by getstr() */
-void redrwstr(char *strin, int i, int l, long mode);
-
-/* Strip Invalid Ctrl-A codes */
-char stripattr(char *strin);
-
-/* Returns the name of the user number passed */
-char *username(uint usernumber);
-
-/* Returns the number of the user name passed */
-uint usernumber(char *username);
-
-/* Convert unsigned long to an ASCII string with commas */
-char *ultoac(ulong l, char *string);
-
-/* Convert an ASCII string of hex digits into an unsigned long */
-ulong ahtoul(char *str);
-
-/* Display status of node */
-void printnodedat(int number, node_t node);
-
-/* Checks to see if this node has been interrupted or any messages waiting */
-void nodesync(void);
-
-/* Writes the node information to disk */
-void putnodedat(int number, node_t node);
-
-/* Reads the node information from disk */
-void getnodedat(int number, node_t *node, char lockit);
-
-/* Writes a short message (telegram) for specified user number */
-void putsmsg(int usernumber, char *strin);
-
-/* Reads and displays short message for specified user number */
-void getsmsg(int usernumber);
-
-/* Writes a node message for specified node */
-void putnmsg(int num, char *strin);
-
-/* Reads and displays node message for current node */
-void getnmsg(void);
-
-/* Displays users online */
-int whos_online(char listself);
-
-/* Send a node-message (ctrl-P) */
-void nodemsg(void);
-
-/* Put a key into the keyboard buffer */
-void ungetkey(char ch);
-
-/* Check to see if the user has hung-up */
-void checkline(void);
-
-/* Display a line (with ctrl-A codes) centered on the screen */
-void center(char *str);
-
-#ifdef _MSC_VER
-int lock(int file, long offset, int size);
-int unlock(int file, long offset, int size);
-#endif
-
-#ifdef __cplusplus
-	}
-#endif
-
-
-#endif	/* Don't add anything after this #endif */
diff --git a/xtrn/sdk/xsdk.txt b/xtrn/sdk/xsdk.txt
deleted file mode 100644
index 9e1183e4db3c1e881b8f63cb8d64ba3920be7691..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdk.txt
+++ /dev/null
@@ -1,127 +0,0 @@
-	  Synchronet External Program Software Developer's Kit (XSDK)
-		  Version 3.11 - March 2001 - Rob Swindell
-
-
-What is it?
-===========
-
-The Synchronet XSDK is a software development kit for C/C++ programmers that
-are interested in writing external online programs (aka "doors") for
-Synchronet BBS Software (www.synchro.net). The XSDK consists of C source and
-header files that contain functions and variables that make writing an external
-program for Synchronet much easier than "from scratch".
-
-The Synchronet XSDK can be used to create 16-bit DOS programs supported by
-all versions of Synchronet and native 32-bit programs supported by Synchronet 
-Version 3.0 for Win32 and Linux.
-
-Programs written using the XSDK will automatically inherit the following
-features:
-
-o Reads Synchronet's XTRN.DAT drop file from the current node directory
-  without any required command line parameters (easy configuration)
-  initializing many user and system variables for the programmer to use
-
-o Automatically supports remote user I/O with dropped connection detection
-
-o Synchronet internode messaging (Ctrl-P), activity alerts, and node listings
-
-o Automatic terminal type detection
-
-o Intelligent Ctrl-A code expansion for Color/ANSI users
-
-o Automatic screen pausing based on screen length (optional)
-
-o 32-bit programs will default to no local console I/O (new in v3.11)
-
-
-Supported Compilers
-===================
-
-o All Borland 16-bit and 32-bit C/C++ compilers for DOS and Windows
-  e.g. Turbo C/C++, Borland C/C++, and Borland C++ Builder
-  See xtrn/sbl/sbl.bpr and xtrn/sbj/sbj.bpr for example BCB 5 XSDK projects
-
-o Microsoft Visual C++ Version 5 and 6
-  (earlier 32-bit versions should work too)
-  See xtrn/sbl/sbl.dsp and xtrn/sbj/sbj.dsp for example MSVC 6 XSDK projects
-
-o GNU Compiler Collection
-  (including Cygwin/MinGW for Win32)
-  See xtrn/sbl/Makefile.gnu and xtrn/sbj/Makefile.gnu for example XSDK projects
-
-o Watcom C/C++
-
-o Symantec C/C++
-
-o Other C/C++ compilers may be supported with slight modifications to the code
-  (please share your modifications with me: sysop@vert.synchro.net)
-
-
-How do I use it?
-================
-
-1. Copy the following files into the source directory for your project (or
-   copy them to and build them from your Synchronet XTRN\SDK directory):
-
-   xsdk.c
-   xsdk.h
-   xsdkvars.c
-   xsdkwrap.c -> New in XSDK v3.10
-   xsdkwrap.h -> New in XSDK v3.10
-   xsdkinet.h -> New in XSDK v3.10
-   xsdkdefs.h
-   mswaits.obj (16-bit compilers only)
-   mswaitl.obj (16-bit copmilers only)
-
-2. Add the following line towards the top of your main .c file:
-
-   #include "xsdk.h"
-
-3. Compile your main .c file to verify that you do not have any
-   incompatibilities with the contents of xsdk.h. If you receive any
-   compilation errors, you'll need to resolve these errors (possibly by
-   editing xsdk*.c or xsdk*.h) before you can continue.
-
-4. Add a call to the XSDK "initdata" function to your program's entry point
-   (typically main()). The XSDK "initdata" function will read in the BBS drop
-   file (XTRN.DAT) and initialize the appropriate variables. See xsdk.h for a
-   complete list of functions available to you and their descriptions.
-
-5. Somewhere after the call to initdata(), add the following line to your
-   code:
-
-   bprintf("XSDK v%s",xsdk_ver);
-
-   Note: You may also want to use the COMPILER_DESC and PLATFORM_DESC macros
-         (new in v3.11) to describe the compiler used and the target platform.
-
-6. Include xsdk.c, xsdkwrap.c and xsdkvars.c in your project or "make" file.
-
-7. If you are using a 16-bit compiler, you will need to include mswaits.obj
-   (for small memory models) or mswaitl.obj (for large memory models) in your
-   project's linked library/object list. This is the millisecond wait/
-   time-slice surrender library used by the 16-bit DOS version of Synchronet.
-
-8. Compile and link your project.
-
-
-Configuring Synchronet To Run Your Program
-==========================================
-
-Make sure you have the program configured (in SCFG) to create the XTRN.DAT
-drop file in the Node Directory.
-
-16-bit Programs
----------------
-16-bit XSDK programs must have "Intercept I/O Interrupts" set to "Yes".
-
-32-bit Programs
----------------
-32-bit XSDK programs are only supported by Synchronet version 3. To configure 
-a 32-bit program with Synchronet v3.0b, add the program's base filename to the
-OS/2 program list in SCFG (this will be replaced with a toggle option in the 
-extenral program configuration menu in the future).
-
-
-/* End of XSDK.TXT */
diff --git a/xtrn/sdk/xsdkdefs.h b/xtrn/sdk/xsdkdefs.h
deleted file mode 100644
index fe1f1d3cc5b61316115cd71f10163e278237d7e9..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdkdefs.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/* xsdkdefs.h */
-
-/* Synchronet XSDK constants, macros, and type definitions */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-#ifndef _XSDKDEFS_H
-#define _XSDKDEFS_H
-
-/**********/
-/* Macros */
-/**********/
-
-									/* Control characters */
-#define STX 	0x02				/* Start of text			^B	*/
-#define ETX 	0x03				/* End of text				^C	*/
-#define BS		0x08				/* Back space				^H	*/
-#define TAB 	0x09				/* Horizontal tabulation	^I	*/
-#define LF		0x0a				/* Line feed				^J	*/
-#define FF		0x0c				/* Form feed				^L	*/
-#define CR		0x0d				/* Carriage return			^M	*/
-#define ESC 	0x1b				/* Escape					^[	*/
-#define SP      0x20                /* Space                        */
-
-
-#define DCD    0x8000		/* Data carrier detect bit in msr			*/
-
-#define TABSIZE 	4		/* Tabs will expand to 4 chars upon input	*/
-
-#define SAVE_LINES	 4		/* Maximum number of lines to save			*/
-#define LINE_BUFSIZE 512    /* Size of line output buffer               */
-
-#define HIGH 8				/* High intensity attribute bit */
-
-							/* user_misc bits */
-#define ANSI	(1<<0)		/* user has ANSI capability */
-#define COLOR	(1<<1)		/* user has monochrome ANSI display */
-#define RIP 	(1<<2)		/* RIP compatible terminal detected */
-#define WIP 	(1<<3)		/* WIP compatible terminal detected */
-
-#ifndef MAX_PATH
-	#ifdef MAXPATHLEN
-		#define MAX_PATH MAXPATHLEN	/* clib.h */
-	#elif defined PATH_MAX
-		#define MAX_PATH PATH_MAX
-	#elif defined _MAX_PATH
-		#define MAX_PATH _MAX_PATH
-	#else
-		#define MAX_PATH 260		
-	#endif
-#endif
-
-#ifndef uchar				/* Short-hand for unsigned data types */
-#define uchar unsigned char
-#endif
-#ifndef uint
-#define uint unsigned int
-#endif
-#ifndef ushort
-#define ushort unsigned short
-#endif
-#ifndef ulong
-#define ulong unsigned long
-#endif
-
-									/* Valid bits for xsdk_mode			*/
-#define XSDK_MODE_NOCONSOLE	(1<<0)	/* No Local Console					*/
-
-							/* Bits in 'mode' for getkey and getstr     */
-#define K_UPPER		(1<<0)	/* Converts all letters to upper case 		*/
-#define K_UPRLWR    (1<<1)  /* Upper/Lower case automatically           */
-#define K_NUMBER    (1<<2)  /* Allow numbers only                       */
-#define K_WRAP	    (1<<3)  /* Allows word wrap							*/
-#define K_MSG		(1<<4)  /* Allows ANSI, ^N ^A ^G					*/
-#define K_SPIN      (1<<5)  /* Spinning cursor (same as SPIN)           */
-#define K_LINE      (1<<6)  /* Input line (inverse color)               */
-#define K_EDIT      (1<<7)  /* Edit string passed                       */
-#define K_CHAT		(1<<8)	/* In chat multi-chat 						*/
-#define K_NOCRLF    (1<<9)	/* Don't print CRLF after string input      */
-#define K_ALPHA     (1<<10) /* Only allow alphabetic characters         */
-#define K_AUTODEL	(1<<11) /* Auto-delete text (used with K_EDIT)		*/
-#define K_LOWPRIO	(1<<12) /* Low priority getstr() operation			*/
-#define K_GETSTR	(1<<13) /* getkey() called from getstr()			*/
-
-							/* Miscellaneous Modem Settings (mdm_misc)	*/
-#define MDM_FLOWCTRL (1<<0)	/* Use flow control with modem				*/
-#define MDM_STAYHIGH (1<<1) /* Stay at highest DTE rate                 */
-
-#define LOOP_NOPEN   50    	/* Retries before file access denied        */
-#define LOOP_NODEDAB 100	/* Retries on NODE.DAB locking/unlocking	*/
-
-#define MAX_NODES	250 	/* Maximum number of nodes					*/
-
-enum {								/* Node Status */
-	 NODE_WFC			        	/* Waiting for Call */
-	,NODE_LOGON                  	/* at logon prompt */
-	,NODE_NEWUSER         			/* New user applying */
-	,NODE_INUSE			 			/* In Use */
-	,NODE_QUIET			 			/* In Use - quiet mode */
-	,NODE_OFFLINE		 			/* Offline */
-	,NODE_NETTING		 			/* Networking */
-	,NODE_EVENT_WAITING				/* Waiting for all nodes to be inactive */
-	,NODE_EVENT_RUNNING				/* Running an external event */
-	,NODE_EVENT_LIMBO				/* Allowing another node to run an event */
-	};
-
-									/* Bit values for node.misc */
-#define	NODE_ANON	(1<<0)			/* Anonymous User */
-#define	NODE_LOCK	(1<<1)			/* Locked for sysops only */
-#define	NODE_INTR	(1<<2)			/* Interrupted - hang up */
-#define NODE_MSGW   (1<<3)			/* Message is waiting */
-#define NODE_POFF   (1<<4)        	/* Page disabled */
-#define NODE_AOFF	(1<<5)			/* Activity Alert disabled */
-#define NODE_UDAT	(1<<6)			/* User data has been updated */
-#define NODE_RRUN	(1<<7)			/* Re-run this node when log off */
-#define NODE_EVENT	(1<<8)			/* Must run node event after log off */
-#define NODE_DOWN	(1<<9)			/* Down this node after logoff */
-#define NODE_RPCHT	(1<<10) 		/* Reset private chat */
-#define NODE_NMSG   (1<<11)         /* Node message waiting (new way) */
-
-
-enum {								/* Node Action */
-	 NODE_MAIN						/* Main Prompt */
-	,NODE_RMSG			 			/* Reading Messages */
-	,NODE_RMAL						/* Reading Mail */
-	,NODE_SMAL			 			/* Sending Mail */
-	,NODE_RTXT			 			/* Reading G-Files */
-	,NODE_RSML			 			/* Reading Sent Mail */
-	,NODE_PMSG			 			/* Posting Message */
-	,NODE_AMSG			 			/* Auto-message */
-	,NODE_XTRN			  			/* Running External Program */
-	,NODE_DFLT			  			/* Main Defaults Section */
-	,NODE_XFER			   			/* Transfer Prompt */
-	,NODE_DLNG		    			/* Downloading File */
-	,NODE_ULNG			    		/* Uploading File */
-	,NODE_BXFR						/* Bidirectional Transfer */
-	,NODE_LFIL			    		/* Listing Files */
-	,NODE_LOGN			    		/* Logging on */
-	,NODE_LCHT			    		/* In Local Chat with Sysop */
-	,NODE_MCHT		     			/* In Multi-Chat with Other Nodes */
-	,NODE_GCHT			   			/* In Local Chat with Guru */
-	,NODE_CHAT			   			/* In Chat Section */
-	,NODE_SYSP		     			/* Sysop Activity */
-	,NODE_TQWK						/* Transferring QWK packet */
-	,NODE_PCHT						/* Private node-to-node chat */
-	,NODE_PAGE						/* Paging node for Private Chat */
-	,NODE_RFSD						/* Retrieving file from sequential dev */
-	};
-
-							/* Different bits in node_misc				*/
-#define NM_ANSALARM (1<<0)	/* Alarm locally on answer					*/
-#define NM_WFCSCRN  (1<<1)	/* Wait for call screen                     */
-#define NM_WFCMSGS	(1<<2)	/* Include total messages/files on WFC		*/
-#define NM_LCL_EDIT (1<<3)	/* Use local editor to create messages		*/
-#define NM_EMSOVL	(1<<4)	/* Use expanded memory of overlays			*/
-#define NM_WINOS2	(1<<5)	/* Use Windows/OS2 time slice API call		*/
-#define NM_INT28	(1<<6)	/* Make int 28 DOS idle calls				*/
-#define NM_NODV 	(1<<7)	/* Don't detect and use DESQview API        */
-#define NM_NO_NUM	(1<<8)	/* Don't allow logons by user number        */
-#define NM_LOGON_R	(1<<9)	/* Allow logons by user real name			*/
-#define NM_LOGON_P	(1<<10) /* Secure logons (always ask for password)	*/
-#define NM_NO_LKBRD (1<<11) /* No local keyboard (at all)				*/
-#define NM_SYSPW	(1<<12) /* Protect WFC keys and Alt keys with SY:	*/
-#define NM_NO_INACT (1<<13) /* No local inactivity alert/logoff 		*/
-#define NM_NOBEEP	(1<<14) /* Don't beep locally                       */
-#define NM_LOWPRIO	(1<<15) /* Always use low priority input			*/
-#define NM_7BITONLY (1L<<16) /* Except 7-bit input only (E71 terminals)  */
-
-#if !defined(__COLORS)
-#define __COLORS
-
-	enum COLORS {
-		BLACK,			/* dark colors */
-		BLUE,
-		GREEN,
-		CYAN,
-		RED,
-		MAGENTA,
-		BROWN,
-		LIGHTGRAY,
-		DARKGRAY,		/* light colors */
-		LIGHTBLUE,
-		LIGHTGREEN,
-		LIGHTCYAN,
-		LIGHTRED,
-		LIGHTMAGENTA,
-		YELLOW,
-		WHITE
-	};
-#endif
-
-#ifndef BLINK
-#define BLINK		128 /* blink bit */
-#endif
-
-#ifdef __WATCOMC__
-
-
-	#define ffblk find_t
-    #define findfirst(x,y,z) _dos_findfirst(x,z,y)
-	#define findnext(x) _dos_findnext(x)
-	#pragma aux mswait "_*"
-#endif
-
-/* Windows Types */
-#ifndef BYTE
-#define BYTE	uchar
-#endif
-#ifndef WORD
-#define WORD	ushort
-#endif
-#ifndef DWORD
-#define DWORD	ulong
-#endif
-#ifndef BOOL
-#define BOOL	int
-#endif
-#ifndef TRUE
-#define TRUE	1
-#define FALSE	0
-#endif
-#ifndef HANDLE
-#define HANDLE	void*
-#endif
-
-/****************************************************************************/
-/* MALLOC/FREE Macros for various compilers and environments				*/
-/* MALLOC is used for allocations of 64k or less							*/
-/* FREE is used to free buffers allocated with MALLOC						*/
-/* LMALLOC is used for allocations of possibly larger than 64k				*/
-/* LFREE is used to free buffers allocated with LMALLOC 					*/
-/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
-/* FAR16 is used to create a far (32-bit) pointer in 16-bit compilers		*/
-/* HUGE16 is used to create a huge (32-bit) pointer in 16-bit compilers 	*/
-/****************************************************************************/
-#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
-	#define __16BIT__
-	#define HUGE16 huge
-	#define FAR16 far
-	#if defined(__TURBOC__)
-		#define REALLOC(x,y) farrealloc(x,y)
-		#define LMALLOC(x) farmalloc(x)
-		#define MALLOC(x) farmalloc(x)
-		#define LFREE(x) farfree(x)
-		#define FREE(x) farfree(x)
-	#elif defined(__WATCOMC__)
-		#define REALLOC realloc
-		#define LMALLOC(x) halloc(x,1)	/* far heap, but slow */
-		#define MALLOC malloc			/* far heap, but 64k max */
-		#define LFREE hfree
-		#define FREE free
-	#else	/* Other 16-bit Compiler */
-		#define REALLOC realloc
-		#define LMALLOC malloc
-		#define MALLOC malloc
-		#define LFREE free
-		#define FREE free
-	#endif
-#else		/* 32-bit Compiler or Small Memory Model */
-	#define HUGE16
-	#define FAR16
-	#define REALLOC realloc
-	#define LMALLOC malloc
-	#define MALLOC malloc
-	#define LFREE free
-	#define FREE free
-#endif
-
-#define KEY_BUFSIZE 256
-
-#define CRLF  { outchar(CR); outchar(LF); }
-
-#define SYSOP (user_level>=sysop_level) /* Is current user sysop t/f macro	 */
-
-#define bgotoxy(x,y)	printf("\x1b[%d;%dH",y,x)   /* place the cursor at   */
-													/* location x,y via ANSI */
-
-#define SAVELINE		{ slatr[slcnt]=latr; \
-							sprintf(slbuf[slcnt<SAVE_LINES ? slcnt++ : slcnt] \
-							,"%.*s",lbuflen,lbuf); \
-							lbuflen=0; }
-#define RESTORELINE 	{ lbuflen=0; attr(slatr[--slcnt]); \
-							bputs(slbuf[slcnt]); }
-
-#define pause bpause	/* backwards compatibility with pre-3.1 XSDK */
-
-/************/
-/* Typedefs */
-/************/
-
-#ifdef _WIN32	/* necessary for compatibility with SBBS v2 */
-#pragma pack(push)
-#pragma pack(1)
-#endif
-
-#ifdef __GNUC__ 
-	#define _PACK __attribute__ ((packed))
-#else
-	#define _PACK
-#endif
-
-typedef struct _PACK {					/* Node information kept in NODE.DAB */
-	uchar	status,						/* Current Status of Node */
-			errors,						/* Number of Critical Errors */
-			action;						/* Action User is doing on Node */
-	ushort	useron,						/* User on Node */
-			connection,					/* Connection rate of Node */
-			misc,						/* Miscellaneous bits for node */
-			aux;						/* Auxillary word for node */
-	ulong	extaux;						/* Extended aux dword for node */
-            } node_t;
-
-#ifdef _WIN32
-#pragma pack(pop)		/* original packing */
-#endif
-
-#endif	/* Don't add anything after this endif */
diff --git a/xtrn/sdk/xsdkinet.h b/xtrn/sdk/xsdkinet.h
deleted file mode 100644
index 5c2f75ab97a336c38d7a290ed5eca02619cdf9c9..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdkinet.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* xsdkinet.h */
-
-/* Synchronet platform-specific Internet stuff */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-#ifndef _XSDKINET_H
-#define _XSDKINET_H
-
-/***************/
-/* OS-specific */
-/***************/
-#if defined _WIN32	|| defined __OS2__	/* Use WinSock */
-
-#include <winsock.h>	/* socket/bind/etc. */
-
-/* Let's agree on a standard WinSock symbol here, people */
-#ifndef _WINSOCKAPI_
-#define _WINSOCKAPI_	
-#endif
-
-#elif defined __unix__	/* Unix-variant */
-
-#ifdef __FreeBSD__
-#include <sys/types.h>	/* u_intXX_t */
-#endif
-
-#include <netdb.h>		/* gethostbyname */
-#include <netinet/in.h>	/* IPPROTO_IP */
-#include <sys/socket.h>	/* socket/bind/etc. */
-#include <sys/ioctl.h>	/* FIONBIO */
-#include <sys/time.h>	/* struct timeval */
-#include <arpa/inet.h>	/* inet_ntoa */
-#include <unistd.h>		/* close */
-#include <errno.h>		/* errno */
-
-#endif
-
-/**********************************/
-/* Socket Implementation-specific */
-/**********************************/
-#ifdef _WINSOCKAPI_
-
-#undef  EINTR
-#define EINTR			WSAEINTR
-#undef  ENOTSOCK
-#define ENOTSOCK		WSAENOTSOCK
-#undef  EWOULDBLOCK
-#define EWOULDBLOCK		WSAEWOULDBLOCK
-#undef  ECONNRESET
-#define ECONNRESET		WSAECONNRESET
-#undef  ECONNABORTED
-#define ECONNABORTED	WSAECONNABORTED
-
-#define s_addr			S_un.S_addr
-
-#define socklen_t		int
-
-#define ERROR_VALUE		WSAGetLastError()
-
-#else	/* BSD sockets */
-
-/* WinSock-isms */
-#define HOSTENT			struct hostent
-#define SOCKADDR_IN		struct sockaddr_in
-#define LINGER			struct linger
-#define SOCKET			int
-#define SOCKET_ERROR	-1
-#define INVALID_SOCKET  (SOCKET)(~0)
-#define closesocket		close
-#define ioctlsocket		ioctl
-#define ERROR_VALUE		errno
-
-#endif	/* __unix__ */
-
-#ifndef SHUT_RDWR
-#define SHUT_RDWR		2	/* for shutdown() */
-#endif
-
-#endif	/* Don't add anything after this line */
diff --git a/xtrn/sdk/xsdkvars.c b/xtrn/sdk/xsdkvars.c
deleted file mode 100644
index 9ffcccfadb1248a22166726a3199cbe6a6aede1b..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdkvars.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* xsdkvars.c */
-
-/* Synchronet XSDK global variables */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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 <time.h>
-#include <stdio.h>
-#include "xsdkinet.h"	/* SOCKET */
-#include "xsdkdefs.h"
-
-#ifndef GLOBAL
-#define GLOBAL
-#endif
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-/*******************************/
-/* Global Variable Definitions */
-/*******************************/
-GLOBAL char 	lncntr; 			/* Line counter */
-GLOBAL char 	tos;				/* Top of screen */
-GLOBAL uchar	curatr; 			/* Current attribute */
-GLOBAL char 	mnehigh,			/* Colors for mnemonics */
-				mnelow;
-GLOBAL uchar	sys_nodes,			/* Number of nodes on system */
-				node_num;			/* Current node number */
-GLOBAL ulong	node_misc;			/* Misc. node toggles */
-GLOBAL char 	sys_name[41],		/* System name */
-				sys_id[9],			/* System QWK ID */
-				sys_op[41], 		/* System operator name */
-				sys_guru[41];		/* System guru name */
-GLOBAL ushort	timeleft;			/* Time left in seconds */
-GLOBAL char 	ctrl_dir[128],		/* SBBS dirs */
-				data_dir[128],
-				node_dir[128],
-				exec_dir[128],
-				text_dir[128],
-				temp_dir[128];
-GLOBAL uint 	user_number;		/* User's number */
-GLOBAL char 	user_name[45],		/* User's name/alias */
-				user_misc,			/* User's misc settings */
-				user_rows,			/* User's rows per screen */
-				user_level, 		/* User's main level */
-				user_flags1[27],	/* User's flag set #1 */
-				user_flags2[27],	/* User's flag set #2 */
-				user_flags3[27],	/* User's flag set #3 */
-				user_flags4[27],	/* User's flag set #4 */
-				user_exempt[27],	/* User's exemptions */
-				user_rest[27],		/* User's restrictions */
-				user_sex,			/* User's sex */
-				user_birth[9],		/* User's birthday */
-				user_phone[13], 	/* User's phone number */
-				user_address[31],	/* User's address */
-				user_location[31],	/* User's location */
-				user_zipcode[11],	/* User's zip/postal code */
-				user_realname[26];	/* User's real name or company name */
-GLOBAL ulong	user_cdt,			/* User's credits */
-				user_dce;			/* User's DCE rate */
-GLOBAL time_t	user_expire;		/* User's expiration date */
-
-									/* COM port registers: */
-GLOBAL uint 	com_base,			/* COM base address */
-				com_irq;			/* irq line number	   */
-GLOBAL ulong	com_rate;			/* DTE rate in bps	   */
-GLOBAL char  	com_port;			/* Number of COM port  */
-
-									/* Modem command strings */
-GLOBAL char 	mdm_init[64],		/* Initialization */
-				mdm_spec[64],		/* Special Initialization */
-				mdm_term[64],		/* Terminal Initialization String */
-				mdm_dial[64],		/* Dial */
-				mdm_offh[64],		/* Off hook */
-				mdm_answ[64],		/* Answer */
-                mdm_misc;           /* Misc bits used for flags */
-
-GLOBAL time_t	starttime;			/* Start time-stamp */
-GLOBAL char 	wordwrap[81];		/* Wordwrap buffer */
-GLOBAL uint 	sec_warn,			/* Seconds till inactivity warning */
-				sec_timeout;		/* Seconds till disconnect */
-GLOBAL char 	timeleft_warn;		/* Minutes left warning */
-
-GLOBAL int		nodefile;			/* File descriptor for NODE.DAB */
-
-GLOBAL char 	slbuf[SAVE_LINES][LINE_BUFSIZE+1]; /* Saved for redisplay */
-GLOBAL char 	slatr[SAVE_LINES];	/* Starting attribute of each line */
-GLOBAL char 	slcnt;			/* Number of lines currently saved */
-GLOBAL char 	lbuf[LINE_BUFSIZE];/* Temp storage for each line output */
-GLOBAL int		lbuflen;		/* Number of characters in line buffer */
-GLOBAL char     latr;           /* Starting attribute of line buffer */
-GLOBAL uint 	inDV;			/* DESQview version if running under DV */
-GLOBAL int		keybuftop,keybufbot;	/* Keyboard input buffer pointers */
-GLOBAL char     keybuf[KEY_BUFSIZE];    /* Keyboard input buffer */
-GLOBAL uint FAR16 *msr;			/* Last modem status register contents */
-GLOBAL char 	**xtrn; 		/* List of external program names */
-GLOBAL uint 	total_xtrns;	/* Total number of external programs */
-GLOBAL uchar	lastnodemsg;	/* Last node to send a message to */
-GLOBAL uchar	name_len;		/* Length of name field in NAME.DAT */
-GLOBAL char 	aborted;		/* Aborted flag - if ctrl-c hit */
-GLOBAL char 	sysop_level;	/* Sysop Level */
-GLOBAL FILE 	*con_fp;		/* Console file pointer (stdout/stderr) */
-
-#ifndef __16BIT__	/* Sockets */
-
-GLOBAL SOCKET	client_socket;
-
-#endif
-
-#ifdef __cplusplus
-	}
-#endif
diff --git a/xtrn/sdk/xsdkwrap.c b/xtrn/sdk/xsdkwrap.c
deleted file mode 100644
index c929aa5a673239f7d61e9435ac05dbc169ed2db4..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdkwrap.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/* xsdkwrap.c */
-
-/* Synchronet XSDK system-call wrappers (compiler & platform portability) */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-/* OS-specific */
-#if defined(_WIN32)
-
-	#include <windows.h>	/* DWORD */
-
-#elif defined(__unix__)
-
-	#include <glob.h>       /* glob() wildcard matching */
-	#include <string.h>     /* strlen() */
-	#include <unistd.h>     /* getpid() */
-	#include <fcntl.h>      /* fcntl() file/record locking */
-	#include <stdlib.h>
-	#include <unistd.h>
-	#include <termios.h>
-	#ifdef __FreeBSD__
-	#include <sys/kbio.h>
-	#else
-	#include <sys/kd.h>
-	#endif
-	#include <sys/time.h>
-	#include <sys/types.h>
-	#include <signal.h>
-
-#endif
-
-/* ANSI */
-#include <sys/types.h>	/* _dev_t */
-#include <sys/stat.h>	/* struct stat */
-
-/* XSDK-specific */
-#include "xsdkdefs.h"	/* MAX_PATH */
-#include "xsdkwrap.h"	/* Verify prototypes */
-
-#ifdef _WIN32
-#define stat(f,s)	_stat(f,s)
-#define STAT		struct _stat
-#else
-#define STAT		struct stat
-#endif
-
-#ifdef __unix__
-
-/****************************************************************************/
-/* Wrapper for Win32 create/begin thread function							*/
-/* Uses POSIX threads														*/
-/****************************************************************************/
-#ifdef _POSIX_THREADS
-ulong _beginthread(void( *start_address )( void * )
-		,unsigned stack_size, void *arglist)
-{
-	pthread_t	thread;
-	pthread_attr_t attr;
-
-	pthread_attr_init(&attr);     /* initialize attribute structure */
-
-	/* set thread attributes to PTHREAD_CREATE_DETACHED which will ensure
-	   that thread resources are freed on exit() */
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-	if(pthread_create(&thread
-		,&attr	/* default attributes */
-		/* POSIX defines this arg as "void *(*start_address)" */
-		,(void *) start_address
-		,arglist)==0)
-		return((int) thread /* thread handle */);
-
-	return(-1);	/* error */
-}
-#else
-
-#error "Need _beginthread implementation for non-POSIX thread library."
-
-#endif
-
-/****************************************************************************/
-/* Convert ASCIIZ string to upper case										*/
-/****************************************************************************/
-char* strupr(char* str)
-{
-	char*	p=str;
-
-	while(*p) {
-		*p=toupper(*p);
-		p++;
-	}
-	return(str);
-}
-/****************************************************************************/
-/* Convert ASCIIZ string to lower case										*/
-/****************************************************************************/
-char* strlwr(char* str)
-{
-	char*	p=str;
-
-	while(*p) {
-		*p=tolower(*p);
-		p++;
-	}
-	return(str);
-}
-
-/****************************************************************************/
-/* Reverse chars in string													*/
-/****************************************************************************/
-char* strrev(char* str)
-{
-    char t, *i=str, *j=str+strlen(str);
-
-    while (i<j) {
-        t=*i; *(i++)=*(--j); *j=t;
-    }
-    return str;
-}
-
-/* This is a bit of a hack, but it works */
-char* _fullpath(char* absPath, const char* relPath, size_t maxLength)
-{
-	char *curdir = (char *) malloc(MAX_PATH+1);
-
-	if(curdir == NULL) {
-		strcpy(absPath,relPath);
-		return(absPath);
-	}
-
-    getcwd(curdir, MAX_PATH);
-    if(chdir(relPath)!=0) /* error, invalid dir */
-		strcpy(absPath,relPath);
-	else {
-		getcwd(absPath, maxLength);
-		chdir(curdir);
-	}
-	free(curdir);
-
-    return absPath;
-}
-
-/***************************************/
-/* Console I/O Stuff (by Casey Martin) */
-/***************************************/
-
-static struct termios current;				// our current term settings
-static struct termios original;				// old termios settings
-static struct timeval timeout = {0, 0};		// passed in select() call
-static fd_set inp;							// ditto
-static int beensetup = 0;					// has _termios_setup() been called?
-								
-
-/* Resets the termios to its previous state */
-void _termios_reset(void)
-{
-	tcsetattr(0, TCSANOW, &original);
-}
-
-/************************************************
-  This pair of functions handles Ctrl-Z presses
-************************************************/
-
-void _sighandler_stop(int sig)
-{
-    // clean up the terminal
-    _termios_reset();
-
-    // ... and stop
-	kill(getpid(), SIGSTOP);
-}
-
-void _sighandler_cont(int sig)
-{
-    // restore terminal
-	tcsetattr(0, TCSANOW, &current);
-}
-
-
-/* Prepares termios for non-blocking action */
-void _termios_setup(void)
-{
-	beensetup = 1;
-    
-	tcgetattr(0, &original);
-  
-	memcpy(&current, &original, sizeof(struct termios));
-	current.c_cc[VMIN] = 1;           // read() will return with one char
-	current.c_cc[VTIME] = 0;          // read() blocks forever
-	current.c_lflag &= ~ICANON;       // character mode
-    current.c_lflag &= ~ECHO;         // turn off echoing
-	tcsetattr(0, TCSANOW, &current);
-
-    // Let's install an exit function, also.  This way, we can reset
-    // the termios silently
-    atexit(_termios_reset);
-
-    // install the Ctrl-Z handler
-    signal(SIGSTOP, _sighandler_stop);
-    signal(SIGCONT, _sighandler_cont);
-}
-
-
-int kbhit(void)
-{
-	if(!isatty(0))
-		return(0);
-
-	// set up select() args
-	FD_ZERO(&inp);
-	FD_SET(0, &inp);
-
-	return select(1, &inp, NULL, NULL, &timeout);
-}
-
-int getch(void)
-{
-	char c;
-
-    if (!beensetup)
-    	// I hate to test for this every time, but this shouldn't be
-        // called that often anyway...
-    	_termios_setup();
-
-    // get a char out of stdin
-    read(0, &c, 1);
-
-    return c;
-}
-
-#endif // __unix__
-
-/**************/
-/* File Stuff */
-/**************/
-
-/****************************************************************************/
-/* Returns the length of the file in 'filename'                             */
-/****************************************************************************/
-long flength(char *filename)
-{
-	STAT st;
-
-	if(stat(filename, &st)!=0)
-		return(-1L);
-
-	return(st.st_size);
-}
-
-/****************************************************************************/
-/* Checks the file system for the existence of one or more files.			*/
-/* Returns TRUE if it exists, FALSE if it doesn't.                          */
-/* 'filespec' may contain wildcards!										*/
-/****************************************************************************/
-BOOL fexist(char *filespec)
-{
-#ifdef _WIN32
-
-	long	handle;
-	struct _finddata_t f;
-
-	if((handle=_findfirst(filespec,&f))==-1)
-		return(FALSE);
-
- 	_findclose(handle);
-
- 	if(f.attrib&_A_SUBDIR)
-		return(FALSE);
-
-	return(TRUE);
-
-#elif defined(__unix__)	/* portion by cmartin */
-
-	glob_t g;
-    int c;
-    int l;
-
-    // start the search
-    glob(filespec, GLOB_MARK | GLOB_NOSORT, NULL, &g);
-
-    if (!g.gl_pathc) {
-	    // no results
-    	globfree(&g);
-    	return FALSE;
-    }
-
-    // make sure it's not a directory
-	c = g.gl_pathc;
-    while (c--) {
-    	l = strlen(g.gl_pathv[c]);
-    	if (l && g.gl_pathv[c][l-1] != '/') {
-        	globfree(&g);
-            return TRUE;
-        }
-    }
-        
-    globfree(&g);
-    return FALSE;
-
-#else
-
-#warning "fexist() port needs to support wildcards!"
-
-	return(FALSE);
-
-#endif
-}
-
-#if defined(__unix__)
-
-/****************************************************************************/
-/* Returns the length of the file in 'fd'									*/
-/****************************************************************************/
-long filelength(int fd)
-{
-	STAT st;
-
-	if(fstat(fd, &st)!=0)
-		return(-1L);
-
-	return(st.st_size);
-}
-
-/* Sets a lock on a portion of a file */
-int lock(int fd, long pos, int len)
-{
-	int	flags;
- 	struct flock alock;
-
-	if((flags=fcntl(fd,F_GETFL))<0)
-		return -1;
-
-	if(flags==O_RDONLY)
-		alock.l_type = F_RDLCK; // set read lock to prevent writes
-	else
-		alock.l_type = F_WRLCK; // set write lock to prevent all access
-	alock.l_whence = L_SET;	  // SEEK_SET
-	alock.l_start = pos;
-	alock.l_len = len;
-
-	return fcntl(fd, F_SETLK, &alock);
-}
-
-/* Removes a lock from a file record */
-int unlock(int fd, long pos, int len)
-{
-	struct flock alock;
-
-	alock.l_type = F_UNLCK;   // remove the lock
-	alock.l_whence = L_SET;
-	alock.l_start = pos;
-	alock.l_len = len;
-	return fcntl(fd, F_SETLK, &alock);
-}
-
-/* Opens a file in specified sharing (file-locking) mode */
-int sopen(char *fn, int access, int share)
-{
-	int fd;
-	struct flock alock;
-
-	if ((fd = open(fn, access, S_IREAD|S_IWRITE)) < 0)
-		return -1;
-
-	if (share == SH_DENYNO)
-		// no lock needed
-		return fd;
-
-	alock.l_type = share;
-	alock.l_whence = L_SET;
-	alock.l_start = 0;
-	alock.l_len = 0;       // lock to EOF
-
-#if 0
-	/* The l_pid field is only used with F_GETLK to return the process 
-		ID of the process holding a blocking lock.  */
-	alock.l_pid = getpid();
-#endif
-
-	if (fcntl(fd, F_SETLK, &alock) < 0) {
-		close(fd);
-		return -1;
-	}
-
-	return fd;
-}
-
-#elif defined _MSC_VER || defined __MINGW32__
-
-#include <io.h>				/* tell */
-#include <stdio.h>			/* SEEK_SET */
-#include <sys/locking.h>	/* _locking */
-
-/* Fix MinGW locking.h typo */
-#if defined LK_UNLOCK && !defined LK_UNLCK
-	#define LK_UNLCK LK_UNLOCK
-#endif
-
-int lock(int file, long offset, int size) 
-{
-	int	i;
-	long	pos;
-   
-	pos=tell(file);
-	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
-	i=_locking(file,LK_NBLCK,size);
-	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
-	return(i);
-}
-
-int unlock(int file, long offset, int size)
-{
-	int	i;
-	long	pos;
-   
-	pos=tell(file);
-	if(offset!=pos)
-		lseek(file, offset, SEEK_SET);
-	i=_locking(file,LK_UNLCK,size);
-	if(offset!=pos)
-		lseek(file, pos, SEEK_SET);
-	return(i);
-}
-
-#endif	/* !Unix && (MSVC || MinGW) */
-
-/****************************************************************************/
-/* Return ASCII string representation of ulong								*/
-/* There may be a native GNU C Library function to this...					*/
-/****************************************************************************/
-#if !defined _MSC_VER && !defined __BORLANDC__
-char* ultoa(unsigned long val, char* str, int radix)
-{
-	switch(radix) {
-		case 8:
-			sprintf(str,"%lo",val);
-			break;
-		case 10:
-			sprintf(str,"%lu",val);
-			break;
-		case 16:
-			sprintf(str,"%lx",val);
-			break;
-		default:
-			sprintf(str,"bad radix: %d",radix);
-			break;
-	}
-	return(str);
-}
-#endif
diff --git a/xtrn/sdk/xsdkwrap.h b/xtrn/sdk/xsdkwrap.h
deleted file mode 100644
index af811ab268b217bdaacf73033e24bd205ae3efdd..0000000000000000000000000000000000000000
--- a/xtrn/sdk/xsdkwrap.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/* xsdkwrap.h */
-
-/* Synchronet XSDK system-call wrappers */
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.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 xtrn	*
- *																			*
- * 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.	*
- ****************************************************************************/
-
-#ifndef _XSDKWRAP_H
-#define _XSDKWRAP_H
-
-/*********************/
-/* Compiler-specific */
-/*********************/
-
-/* Compiler Description */
-#if defined(__BORLANDC__)
-
-	#define COMPILER_DESC(str) sprintf(str,"BCC %X.%02X" \
-		,__BORLANDC__>>8,__BORLANDC__&0xff);	
-
-#elif defined(_MSC_VER)
-
-	#define COMPILER_DESC(str) sprintf(str,"MSC %u", _MSC_VER);
-
-/***
-#elif defined(__GNUC__) && defined(__GLIBC__)
-
-	#define COMPILER_DESC(str) sprintf(str,"GCC %u.%02u (GLIBC %u.%u)" \
-		,__GNUC__,__GNUC_MINOR__,__GLIBC__,__GLIBC_MINOR__);
-***/
-
-#elif defined(__GNUC__)
-
-	#define COMPILER_DESC(str) sprintf(str,"GCC %u.%02u" \
-		,__GNUC__,__GNUC_MINOR__);
-
-#else /* Unknown compiler */
-
-	#define COMPILER_DESC(str) strcpy(str,"UNKNOWN COMPILER");
-
-#endif
-
-#if defined(__unix__)
-	#define BACKSLASH	'/'
-#else /* MS-DOS based OS */
-	#define BACKSLASH	'\\'
-#endif
-
-/* Target Platform Description */
-#if defined(_WIN32)
-	#define PLATFORM_DESC	"Win32"
-#elif defined(__OS2__)
-	#define PLATFORM_DESC	"OS/2"
-#elif defined(__MSDOS__)
-	#define PLATFORM_DESC	"DOS"
-#elif defined(__linux__)
-	#define PLATFORM_DESC	"Linux"
-#elif defined(__FreeBSD__)
-	#define PLATFORM_DESC	"FreeBSD"
-#elif defined(BSD)
-	#define PLATFORM_DESC	"BSD"
-#elif defined(__unix__)
-	#define PLATFORM_DESC	"Unix"
-#else
-	#warning "Need to describe target platform"
-	#define PLATFORM_DESC	"UNKNOWN"
-#endif
-
-#if defined(__unix__)
-
-	int kbhit(void);
-	int getch(void);
-	#define ungetch(x)	/* !need a wrapper for this */
-
-#else	/* DOS-Based */
-
-	#include <conio.h>
-
-#endif
-
-#if defined(_WIN32)
-
-	#include <io.h>				/* _sopen */
-	#include <sys/stat.h>		/* S_IREAD */
-	#include <fcntl.h>			/* O_BINARY */
-	#include <windows.h>		/* OF_SHARE_ */
-
-	#define sopen(f,o,s)		_sopen(f,o,s,S_IREAD|S_IWRITE)
-	#define close(f)			_close(f)
-							
-	#ifndef SH_DENYNO
-	#define SH_DENYNO			OF_SHARE_DENY_NONE
-	#define SH_DENYWR			OF_SHARE_DENY_WRITE
-	#define SH_DENYRW			OF_SHARE_EXCLUSIVE
-	#endif
-	#ifndef O_DENYNONE
-	#define O_DENYNONE			SH_DENYNO
-	#endif
-
-#elif defined(__unix__)
-
-	#include <fcntl.h>
-
-	#define O_BINARY	0		/* all files in binary mode on Unix */
-	#define O_DENYNONE  (1<<31)	/* req'd for Baja/nopen compatibility */
-
-	#define SH_DENYNO	2          // no locks
-	#define SH_DENYRW	F_WRLCK	   // exclusive lock
-	#define SH_DENYWR   F_RDLCK    // shareable lock
-
-	#define stricmp(x,y)		strcasecmp(x,y)
-	#define strnicmp(x,y,z)		strncasecmp(x,y,z)
-	#define chsize(fd,size)		ftruncate(fd,size)
-
-#endif
-
-#ifdef __unix__
-
-	#include <pthread.h>	/* POSIX threads and mutexes */
-	#include <semaphore.h>	/* POSIX semaphores */
-	unsigned long _beginthread(void( *start_address )( void * )
-		,unsigned stack_size, void *arglist);
-
-#elif defined(_WIN32)	
-
-	#include <process.h>	/* _beginthread() */
-
-	/* POSIX semaphores */
-	typedef HANDLE sem_t;
-	#define sem_init(psem,ps,v)			ResetEvent(*(psem))
-	#define sem_wait(psem)				WaitForSingleObject(*(psem),INFINITE)
-	#define sem_post(psem)				SetEvent(*(psem))
-	#define sem_destroy(psem)			CloseHandle(*(psem))
-
-	/* POIX mutexes */
-	typedef HANDLE pthread_mutex_t;
-	#define pthread_mutex_init(pmtx,v)	*(pmtx)=CreateMutex(NULL,FALSE,NULL)
-	#define pthread_mutex_lock(pmtx)	WaitForSingleObject(*(pmtx),INFINITE)
-	#define pthread_mutex_unlock(pmtx)	ReleaseMutex(*(pmtx))
-	#define	pthread_mutex_destroy(pmtx)	CloseHandle(*(pmtx))
-
-
-#elif defined(__MSDOS__)
-
-	/* No semaphores */
-
-#else
-
-	#warning "Need semaphore wrappers."
-
-#endif
-
-
-#if defined(_WIN32)
-
-	#define mswait(x)			Sleep(x)
-
-#elif defined(__OS2__)
-
-	#define mswait(x)			DosSleep(x)
-
-#elif defined(__unix__)
-
-	#define mswait(x)			usleep(x*1000)
-	#define _mkdir(dir)			mkdir(dir,0777)
-	#define _rmdir(dir)			rmdir(dir)
-	#define tell(fd)			lseek(fd,0,SEEK_CUR)
-
-	int		sopen(char *fn, int access, int share);
-	long	filelength(int fd);
-	char*	strupr(char* str);
-	char*	strlwr(char* str);
-
-	char*	strrev(char* str);
-	char*	_fullpath(char* absPath, const char* relPath
-								,size_t maxLength);
-
-#elif defined(__MSDOS__)
-
-	void mswait(int ms);	/* Wait a specific number of milliseconds */
-
-#else	/* Unsupported OS */
-
-	#warning "Unsupported Target: Need some macros of function prototypes here."
-
-#endif
-
-#ifndef BOOL
-	#define BOOL	int
-#endif
-#ifndef TRUE
-	#define TRUE	1
-	#define FALSE	0
-#endif
-
-/**************/
-/* Prototypes */
-/**************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if !defined(__BORLANDC__)
-	int	lock(int fd, long pos, int len);
-	int	unlock(int fd, long pos, int len);
-#endif
-
-#if !defined(_MSC_VER) && !defined(__BORLANDC__)
-	char*	ultoa(unsigned long val, char* str, int radix);
-#endif
-
-BOOL	fexist(char *filespec);
-long	flength(char *filename);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* Don't add anything after this line */
diff --git a/xtrn/smm/adult.que b/xtrn/smm/adult.que
deleted file mode 100644
index dd10f2f4c89cbb22d1a74be1d85364ef45a134eb..0000000000000000000000000000000000000000
--- a/xtrn/smm/adult.que
+++ /dev/null
@@ -1,93 +0,0 @@
-20
-How old were you when you lost your virginity?
-9
-1
-I still have it
-Younger than 12
-Between 12 and 14
-Between 15 and 16
-Between 17 and 18
-Between 19 and 20
-Between 21 and 25
-Between 25 and 30
-Older than 30
-How many sexual partners have you had?
-8
-1
-None
-Between 1 and 5
-Between 6 and 10
-Between 11 and 20
-Between 21 and 30
-Between 31 and 50
-Between 51 and 100
-More than 100
-When engaged in a relationship, how often do you prefer to have sex?
-8
-1
-Never
-At least once a day
-Between 4 and 6 times a week
-Between 1 and 3 times a week
-Between 1 and 3 times a month
-Between 6 and 11 times a year
-Between 1 and 5 times a year
-Less than once a year
-What form of sexually transmitted disease protection do you prefer?
-5
-1
-I don't know
-Abstinence
-No protection
-Male condoms
-Female condoms
-Do you enjoy oral sex?
-5
-1
-I don't know
-No
-Yes, giving
-Yes, receiving
-Yes, both giving and receiving
-Do you enjoy anal sex?
-5
-1
-I don't know
-No
-Yes, giving
-Yes, receiving
-Yes, both giving and receiving
-How often do you masturbate?
-8
-1
-At least once a day
-Between 4 and 6 times a week
-Between 1 and 3 times a week
-Between 1 and 3 times a month
-Between 6 and 11 times a year
-Between 1 and 5 times a year
-Less than once a year
-Never
-Do you reach orgasm (alone or with a partner)?
-5
-1
-I don't know
-Yes, always
-Yes, occasionally
-Yes, rarely
-No
-Have you had sexual partners of your same gender?
-6
-1
-I don't know
-Yes, always
-Yes, occasionally
-Yes, rarely
-No, but I'm curious
-No, never
-Do you shave your pubic area?
-3
-1
-Yes, all of it
-Yes, some of it
-No
diff --git a/xtrn/smm/appear.que b/xtrn/smm/appear.que
deleted file mode 100644
index b7b1b7ea02a51d80816883dc50d08d9f84bed505..0000000000000000000000000000000000000000
--- a/xtrn/smm/appear.que
+++ /dev/null
@@ -1,119 +0,0 @@
-8
-Do you wear any of the following?
-16
-16
-Eye glasses
-Partial beard (goatee, five o'clock shadow, etc.)
-Full beard
-Mustache
-Side burns
-Earring(s)
-Make-up
-Body piercing (nose, tongue, naval, eyebrow, etc.)
-Visible tatoos
-Covered tatoos
-Unnaturally colored/bleached hair (blue, purple, pink, etc.)
-Brades or dreds
-Pony tail
-Long fingernails
-Painted fingernails
-None of the above
-Larger than average or smaller than average attributes?
-16
-8
-Small eyes
-Large eyes
-Small ears
-Large ears
-Small nose
-Large nose
-Small breasts
-Large breasts
-Large arms
-Large legs
-Large hips/buttocks
-Thin-lips
-Thick-lips
-Thin eyebrows
-Thick eyebrows
-None of the above
-Do you have a sun-tan?
-5
-1
-No, I'm naturally dark
-No, but I will this summer
-No, I don't try to tan
-No, I always burn
-Yes
-Your (natural) complexion?
-9
-3
-Very dark
-Medium dark (olive)
-Light dark
-White
-Whiter than white (alabaster)
-Sparse freckles
-Dense freckles
-Mild acne
-Cystic acne
-Your hair (on your head)?
-16
-5
-Gone (bald)
-Thin (balding)
-Thinner than average
-Average thickness
-Thicker than average
-Feathered
-All one length
-Curly
-Wavy
-Straight
-Partially shaved
-Completely shaved
-Short length
-Medium length
-Long length
-Very long length
-Your teeth?
-11
-4
-Very white
-Average whiteness
-Slightly stained (smoke, coffee, etc.)
-Very stained (smoke, coffee, etc.)
-Very straight
-Average straightness
-Slightly crooked
-Very crooked
-Visible missing teeth
-Visible caps (gold or silver)
-Visible braces
-Your build?
-6
-1
-Thin, wirey
-Thin, but toned
-Average
-Chunky
-Stocky
-Muscle-bound
-Physical disabilities/deformities?
-14
-5
-Missing fingers
-Gimpy or missing limbs
-Scarred face
-Scarred arms or hands
-Mongloidian eyes
-Lazy/cross/cock-eyed
-Cleft pallette
-Paraplegic
-Quadriplegic
-Blind
-Deaf
-Mute
-Other
-None
-
diff --git a/xtrn/smm/basic.que b/xtrn/smm/basic.que
deleted file mode 100644
index aaf3634eb02a3553e5e2569e92c06b52b12cd9f6..0000000000000000000000000000000000000000
--- a/xtrn/smm/basic.que
+++ /dev/null
@@ -1,179 +0,0 @@
-17
-What is your religious belief?
-9
-1
-Christian
-Jewish
-Catholic
-Buddihst
-Muslim
-Mormon
-Jehovah's Witness
-Other
-None
-Do you participate in organized religion?
-3
-1
-Yes
-No
-Sometimes
-Do you smoke tobacco?
-5
-1
-Yes, daily
-Yes, occasionally
-Yes, I'm trying to quit
-No, I quit
-No, I never smoked tobacco regularly
-Do you use forms of nicotine other than tobacco (dip, snuff, etc)?
-5
-1
-Yes, daily
-Yes, occasionally
-Yes, I'm trying to quit
-No, I quit
-No, never
-Do you drink alcohol?
-6
-1
-Yes, daily
-Yes, occasionally
-Yes, but never enough to get drunk
-Yes, I'm trying to quit
-No, I quit
-No, I never drank
-Do you dance?
-7
-1
-Yes, professionally (exotic)
-Yes, professionally (tame)
-Yes, regularly
-Yes, occasionally
-Yes, rarely
-No, not recently
-No, not ever
-Favorite types of music?
-16
-16
-Easy Listening
-New Age
-Classical
-Classic Rock
-Heavy Metal
-Punk Rock
-Alternative
-Industrial
-Techno
-Pop
-Rap
-Disco
-Rhthym and Blues
-Jazz
-Folk
-Country and Western
-Completed education?
-7
-6
-Grade school
-High school
-Trade school
-College (Associate's)
-College (Bachelor's)
-College (Master's)
-None
-Are you currently enrolled in school?
-8
-1
-Yes, grade school
-Yes, high school
-Yes, trade school
-Yes, city college
-Yes, state college
-No, but I plan to return
-No, but I plan to start
-No, and I have no plans to
-Are you currently employed?
-4
-1
-Yes, full-time
-Yes, part-time
-No, but I'm seeking employment
-No, I don't need/want to work right now
-Are you financially independant?
-5
-1
-Yes
-No, I depend on my parent(s)
-No, I depend on other relative(s)
-No, I depend on my spouse
-No, I depend on a significant other
-Do you play sports?
-5
-1
-Yes, professionally
-Yes, frequently
-Yes, occasionally
-Yes, rarely
-No
-Do you do any recreational reading?
-4
-1
-Yes, frequently
-Yes, occasionally
-Yes, rarely
-No
-Favorite out-door activities?
-16
-16
-Water (swimming, skiing, surfing, etc.)
-Snow (skiing, boarding, ice skating, etc.)
-Hiking/camping/climbing
-Roller skating/blading
-Bicycling
-Running/jogging/walking
-Team sports (baseball, basketball, football, soccer, etc.)
-Racket sports (tennis, racquetball, badminton, etc.)
-Golf
-Shooting (firearms, archery, etc.)
-Off-road (motorcycles, ATVs, etc.)
-Sky diving/bungee jumping
-Gardening
-Fishing/hunting
-Horseback riding
-None of the above
-Favorite in-home activities?
-16
-16
-Painting/drawing/sculpting/etc.
-Sewing/weaving/etc.
-Cooking
-Writing
-Reading
-Playing a musical instrument/singing
-Playing video/computer games
-Playing card/board games
-Cleaning
-Computer programming/exploring
-BBS/E-mail/Internet communications
-CB/HAM/shortwave radio communications
-Electronics/chemistry/physics experiments
-Talking on the telephone
-Watching television
-Listening to music (CDs, records, tapes, radio, etc.)
-Do you have any children?
-6
-1
-Yes, three or more
-Yes, two
-Yes, one
-No, but definitely someday
-No, but possibly someday
-No, I don't ever want children
-What kind of relationship are you seeking?
-5
-5
-Platonic friendship (no intimacy)
-Dating (no commitment)
-Long term relationship (boyfriend/girlfriend/lover)
-Marriage
-None of the above
diff --git a/xtrn/smm/file_id.diz b/xtrn/smm/file_id.diz
deleted file mode 100644
index 5b423d7a3f4db10074039113ceb646dd2842a419..0000000000000000000000000000000000000000
--- a/xtrn/smm/file_id.diz
+++ /dev/null
@@ -1,7 +0,0 @@
-Synchronet Match Maker (BBS door) v2.10
-supports any DOOR.SYS or Synchronet BBS.
-Internationally networked profiles, 
-telegrams, wall, photographs, and more! 
-Developed by Digital Dynamics, makers of 
-Synchronet BBS Software. Perhaps the most 
-comprehensive match maker available.
diff --git a/xtrn/smm/list_hdr.asc b/xtrn/smm/list_hdr.asc
deleted file mode 100644
index 182a1298dd2ff79ae8d05de74f2ee8b7a2c8784e..0000000000000000000000000000000000000000
--- a/xtrn/smm/list_hdr.asc
+++ /dev/null
@@ -1,5 +0,0 @@
-nh���Marital Status or Orientation (Single, Married, Divorced, Widowed, etc)
-�ng��Race (White, Black, Hispanic, Indian, Middle Eastern, Asian, or Other)
-hw�ng�hc�Sex  m   �Eyes    y�Weight 
-w�ng�hc�bAge gHairm�  rHeighty�   ng�Location           cPhoto�hw�Name/Alias           mMatch�
-w�ng�hc� b�  g�   m�   r�    y�ng   �                        c�hw�m                          �
diff --git a/xtrn/smm/material.que b/xtrn/smm/material.que
deleted file mode 100644
index 2de521f0150f61b7dd4025f43ca153597b8150ef..0000000000000000000000000000000000000000
--- a/xtrn/smm/material.que
+++ /dev/null
@@ -1,91 +0,0 @@
-16
-Do you own a passenger vehicle?
-5
-1
-Yes, more than one
-Yes
-No, but I will soon
-No, and I don't know when/if I will
-No, I don't have a driver's license
-Do you own a recreational vehicle?
-2
-1
-Yes
-No
-Do you own a home (mortage counts)?
-4
-1
-Yes, more than one
-Yes
-No, I'm renting
-No
-Do you own furniture?
-3
-1
-Yes
-No, I'm renting
-No
-Do you own a computer?
-4
-1
-Yes, more than one
-Yes
-No, I'm renting
-No
-Do you have a savings account?
-2
-1
-Yes
-No
-Do you have a checking account?
-2
-1
-Yes
-No
-Do you have a credit card?
-3
-1
-Yes, more than one
-Yes
-No
-Do you have health insurance?
-2
-1
-Yes
-No
-Do you have life insurance?
-2
-1
-Yes
-No
-Do you have car insurance?
-2
-1
-Yes
-No
-Do you have an accountant?
-2
-1
-Yes
-No
-Do you have a maid?
-2
-1
-Yes
-No
-Do you own a swimming pool (i.e. in your backyard)?
-2
-1
-Yes
-No
-Do you own an acre or more of land?
-2
-1
-Yes
-No
-Do you own any stocks or bonds?
-2
-1
-Yes
-No
-
diff --git a/xtrn/smm/mb-e.asc b/xtrn/smm/mb-e.asc
deleted file mode 100644
index 2b612f78b2f06864bce8dbc5667aa911a9904393..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-e.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-An Extrovert is energized by people. A strong extrovert feels very much alone
-without lots of people around. E's tend to talk first & think later, know a
-lot of people, don't mind having a conversation while the TV is on, are
-approachable, don't consider the telephone to be an interruption, tend to 
-think out loud and use people as a sounding board for their ideas, need
-affirmation from friends about  who I am & how do I look. 
-About 75% of the population are type E.
diff --git a/xtrn/smm/mb-enfj.asc b/xtrn/smm/mb-enfj.asc
deleted file mode 100644
index 7dadc77fe75706a029dc3ce7ff44c9c4e806a044..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-enfj.asc
+++ /dev/null
@@ -1,134 +0,0 @@
-ENFJs in short:
-
-Responsive and responsible.  Generally feel real concern for what
-others think or want, and try to handle things with due regard for
-other person's feelings.  Can present a proposal or lead a group
-discussion with ease and tact.  Sociable, popular, sympathetic.
-Responsive to praise and criticism.
-
-About 5% of the population.
-
-Details about ENFJs:
-
-ENFJs are outstanding leaders of groups, both task groups and
-growth groups.  They have the charming characteristic of seeming to
-take for granted that they will be followed, never doubting that
-people will want to do what they suggest.  And, more often than
-not, people do, because this type of has unusual charisma.  ENFJs
-place a high value on cooperation from others and are most willing
-to cooperate themselves.
-
-Found in only about 5 percent of the general population, ENFJs
-place people as being of highest importance and priority.  As a
-result, ENFJs may find themselves feeling responsible for the
-feelings of others to an extent which places a burden on the
-relationship.
-
-An ENFJ communicates caring, concern, and a willingness to be
-involved.  Thus people turn to ENFJs for nurture and support, which
-an ENFJ is usually able to deliver.  At times, however, these kinds
-of demands can overwhelm ENFJs, who find at this point that they
-lack the skills to dissociate.  ENFJs do not seem able to turn away
-from these demands even when they become unreasonable.  Or, if
-forced to let go of the burden through sheer unavailability of time
-or energy, ENFJs experience a guilt all out of proportion to the
-realities of the commitment to the relationship.
-
-ENFJs are vulnerable to idealize interpersonal relationships,
-raising these relationships to a plane which seldom can sustain the
-realities of human nature.  Because of this tendency to raise
-interpersonal relations to the ideal, ENFJs may unwittingly
-overpower their friends, who believe that they cannot possibly live
-up to an ENFJ's perception of them.  The fact is, ENFJs are
-extraordinarily tolerant of others, seldom critical, and always
-trustworthy.
-
-ENFJs take communication for granted and believe that they are
-understood and that their communications are accepted.  Just as
-they themselves are accepting, so do they assume that others are
-the same.  When ENFJs find that their position or beliefs were not
-comprehended or accepted, they are surprised, puzzled, and
-sometimes hurt.  Fortunately, this does not happen with high
-frequency, as ENFJs have a remarkable fluency with language,
-especially in speech; they are particularly adept when
-communicating face-to-face as opposed to communicating in writing.
-
-They are influential, therefore, in groups, having no hesitation
-about speaking out, no matter how large or small the group may be.
-
-ENFJs have an unusual ability to relate to others with empathy,
-taking into themselves the characteristics, emotions, and beliefs
-of others.  This can pose a danger for ENFJs, they can
-unconsciously over-identify with others and pick up their burdens
-as if they were their own.  In the process, ENFJs may risk their
-own sense of identity.
-
-They have a natural ability to mimic because of this highly
-developed ability to empathize by interjection.  They are likely to
-be very concerned about the problems of those close to them, but
-they also may get as deeply involved in the problems of those not
-so close and may find themselves overextended emotionally.
-
-ENFJs would do well to follow their hunches, for their intuition
-tends to be well developed.  Decisions made purely on the basis of
-logic may not be so sound, and checking with a person who has a
-strong T preference might be at times advisable for the ENFJ.  In
-the framework of values, however, the ENFJ is on certain ground.
-Generally, they know what they prefer and can read other people
-with outstanding accuracy.  Seldom is an ENFJ wrong about the
-motivations or intents of another, hidden or not.
-
-ENFJs are socially adept and make excellent companions and mates.
-They also are deeply devoted to their children, yet tend not to be
-domineering to either the children or a mate.  In fact, the ENFJ is
-so even-tempered that he or she can be victimized by a mate who
-might have become more than demanding.
-
-ENFJ mates always try to please and feel personally responsible
-when home life does not go smoothly.  They are tireless in their
-efforts to see that it does, providing generously from available
-income, time and energy.  This dedication often exists, however,
-side by side with an ENFJ's dream of the perfect relationship - a
-characteristic of all NFs, but one which is particularly strong in
-an ENFJ.  Thus an ENFJ has that longing for the ideal which results
-in a vague dissatisfaction with whatever is in the way of
-relationships, mating as well as friendship.
-
-This longing for the perfect carries over into the careers of
-ENFJs, who experience some degree of restlessness whatever their
-jobs.  And, as with ENFPs, ENFJs have a wide range of occupations
-which offer success.
-
-Being verbally adept, ENFJs contribute to an unusual level when
-dealing with people, particularly face-to-face: the media, the
-ministry, and the stage and screen are populated with successful
-ENFJs.  They make superior therapists, charismatic teachers,
-excellent executives, and personalized executives.  Areas that
-would not permit utilization of the interaction talents of the
-ENFJs, for example, accounting, should be avoided; otherwise,
-almost any people-to-people occupation where personal, sustained
-contact is involved capitalizes on the personality of an ENFJ.
-
-ENFJs like to have things organized and settled.  They prefer to
-plan both work and social engagements ahead and tend to be
-absolutely reliable in honoring these commitments.  ENFJs are very
-much at home in complex situations which require the juggling of
-much data.  At the same time they can handle people with charm and
-concern.
-
-ENFJs are usually popular wherever they are.  Their ability to be
-comfortable either leading or following makes them easy to have
-around, whatever the situation.  A well-developed ENFJ group leader
-can provide, almost endlessly, activities for groups to play.  In
-some, this can amount to genius which other types find hard to
-emulate.  In this ability to organize without planning there is a
-certain, similarity to the ESFJ, but the latter acts more as a
-master of ceremonies than as a leader of groups.  The ESFJ is more
-of a recreational leader, who insures that each member has fun at a
-party and that the right things are expressed at social occasions,
-especially institutional social occasions such as weddings,
-funerals, parties, and the like.
-
-ENFJs, just like ESFJs, value harmonious human relations above all
-else; but ENFJs are not so easily crushed by indifference as are
-ESFJs and are more independent of others' valuations.
diff --git a/xtrn/smm/mb-enfp.asc b/xtrn/smm/mb-enfp.asc
deleted file mode 100644
index b8bcfdb153f8419529a418c96e59c5959015c9c7..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-enfp.asc
+++ /dev/null
@@ -1,157 +0,0 @@
-ENFPs in short:
-
-Warmly enthusiastic, high-spirited, ingenious, imaginative.  Able
-to do almost anything that interests them.  Quick with a solution
-for any difficulty and ready to help anyone with a problem.  Often
-rely on their ability to improvise instead of preparing in advance.
-Can usually find compelling reasons for whatever they want.
-
-About 5% of the population.
-
-Details on ENFPs:
-
-For ENFPs nothing occurs which does not have some significance, and
-they have an uncanny sense of the motivations of others.  This
-gives them a talent for seeing life as an exciting drama, pregnant
-with possibilities for both good and evil.  This type is found in
-only about 5 percent of the general population, but they have great
-influence because of their extraordinary impact on others.
-
-ENFPs strive toward the authentic, even when acting spontaneously,
-and this intent is usually communicated nonverbally to others, who
-find this characteristic attractive.  ENFPs, however, find their
-own efforts of authenticity and spontaneity always lacking, and
-tend to heap coals of fire on themselves, always berating
-themselves for being so conscious of self.
-
-ENFPs consider intense emotional experiences vital; when they have
-these, however, they are made uneasy by a sense of being there but
-with a part of themselves cut off.  They strive for congruency, but
-always see themselves in some danger of losing touch with their
-real feelings, which ENFPs possess in a wide range and variety.
-
-ENFPs exercise a continuous scanning of the external environment
-and nothing out of the ordinary is likely to escape their
-attention.  They are keen and penetrating observers and are capable
-of intense concentration on another individual while aware of what
-is going on about them.  Their attention is never passive or
-casual, never wandering, but always directed.
-
-At times, ENFPs find themselves interpreting events in terms of
-another's "hidden motive," giving special meaning to words or
-actions.  This interpretation tends to be negative and, more often
-than not, inaccurately negative.  In the process, an ENFP may find
-that he or she has introduced an unnecessary, toxic element into
-the relationship.
-
-While ENFPs are brilliantly perceptive, they can make serious
-mistakes in judgement, which works to their discomfort.  These
-mistakes derive from their tendency to focus on data which confirm
-their own biases.  They may be absolutely correct in their
-perceptions but wrong in their conclusions.
-
-Because they tend to be hypersensitive and hyperalert, they may
-suffer from muscle tension.  They live in readiness for
-emergencies; because they have this facility, they assume this is
-true for others.  They can become bored rather quickly with both
-situations and people, and resist repeating experiences.
-
-They enjoy the process of creating something - an idea or a project
-- but are not as interested in the follow-through.  They are
-typically enthusiastic, and this is contagious.  People get caught
-up and entranced by an ENFP.  Yet this type is marked with a fierce
-independence, repudiating any kind of subordination, either in
-themselves or in others in relation to them.
-
-They do tend to attribute more power to authority figures than is
-there and give over to these figures an ability to "see through"
-them - which also is not apt to be there.
-
-While ENFPs resist the notion of others becoming dependent or
-having power over them, their charisma draws followers who wish to
-be shown the way.  ENFPs constantly find themselves surrounded by
-others who look toward the ENFP for wisdom, inspiration, courage,
-leadership, and so on - an expectancy which, at times, weighs
-rather heavily on an ENFP.
-
-ENFPs are characteristically optimistic and are surprised when
-people and events do not turn out as anticipated.  Often their
-confidence in the innate goodness of fate and human nature is a
-self-fulfilling prophecy.
-
-ENFPs have a remarkable latitude in career choices and succeed in
-many fields.  As workers, they are warmly enthusiastic, high
-spirited, ingenious, imaginative, and can do almost anything that
-interests them.  They can solve most problems, particularly those
-dealing with people.  They are charming and at ease with
-colleagues; others enjoy their presence.
-
-ENFPs are outstanding in getting people together, and are good at
-initiating meetings and conferences, although not as talented at
-providing for the operational details of these events.  They enjoy
-inventing new ways of doing things, and their projects tend to
-become a cause, quickly becoming personalized.
-
-They are imaginative themselves, but can have difficulty picking up
-on ideas and projects initiated by others.  They must make these
-ideas and projects their own if ENFPs are to lend energy and
-interest.  Once people or projects become routine, ENFPs are likely
-to lose interest; what 'might be' is always more fascinating than
-'what is.'
-
-ENFPs make extensive use of their intuitive powers.  They usually
-have a wide range of personal and telephone contacts, expending
-energy in maintaining both career and personal relationships.
-
-ENFPs make excellent salespeople, advertising people, politicians,
-screen or play writers, and in general are attracted to the
-interpretive arts, particularly, character acting.
-People-to-people work is essential for ENFPs, who need the feedback
-of interaction with others.
-
-ENFPs may find it difficult to work within the constraints of an
-institution, especially in following rules, regulations, and
-standard operating procedures.  More frequently, institutional
-procedures and policies are targets to be challenged and bent by
-the will of an ENFP.  Colleagues and superiors sometimes find
-themselves in the position of having to accommodate and salvage.
-
-At times, ENFPs demonstrate impatience with others; they may get
-into difficulty in an organization by siding with its detractors,
-who find in an ENFP a sympathetic ear and a natural rescuer.  In
-occupational choice, ENFPs quickly become restless if the choice
-involves painstaking detail and follow-through over a period of
-time.  Variety in day-to-day operations and interactions best suits
-the talents of ENFPs, who need quite a bit of latitude in which to
-exercise their adaptive ingenuity.
-
-As mates, ENFPs tend to be charming, gentle, sympathetic, and
-nonconformist.  They are not likely to be interested in the
-less-inspired routines of daily maintenance and ever will be
-seeking new outlets for their inspirations.
-
-As parents, ENFPs are devoted to their children, shifting from a
-role of "friend in need rescuer" to stern authority figure.  They
-may not always be willing to enforce their impulsive
-pronouncements, but leave it to their mates to follow through.
-
-A mate of an ENFP can expect charming surprises: extravagant
-generosity punctuated by periods of frugality.  Independent actions
-regarding money on the part of an ENFP's mate are not ordinarily
-welcomed, and the mate may find him or herself in an embarrassing
-situation of having to return purchases.
-
-ENFPs generally are the ones in charge of the home, and a
-conflict-free home is desired, almost demanded.  When he or she is
-in charge of economic resources, the ENFPs may contain extravagant
-luxuries, while necessities may be missing.  They are not always
-interested in saving for the future and may be casual in giving
-consideration to such things as life insurance, savings accounts,
-and even a ready cash supply for mate and children.
-
-ENFPs are characteristic in their pursuit of the novel, their
-strong sense of the possible, and outstanding intuitive powers.  At
-the same time, they have warmth and fun with people and generally
-are unusually skilled in handling people.  Their extroverted role
-tends to be well developed, as is their capacity for the novel and
-the dramatic.
diff --git a/xtrn/smm/mb-entj.asc b/xtrn/smm/mb-entj.asc
deleted file mode 100644
index a37af1d7e69f038528b89029a41d5f8606f06317..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-entj.asc
+++ /dev/null
@@ -1,105 +0,0 @@
-ENTJs in short:
-
-Hearty, frank, decisive, leaders in activities.  Usually good in
-anything that requires reasoning and intelligent talk, such as
-public speaking.  Are usually well-informed and enjoy adding to
-their fund of knowledge.  May sometimes be more positive and
-confident than their experience in an area warrants.
-
-About 5% of the population.
-
-Details about ENTJs:
-
-If one word were used to capture ENTJ's style, it would be
-commandant.  The basic driving force and need of ENTJs is to lead,
-and from an early age they can be observed taking over groups. This
-type is found in approximately 5 percent of the total population.
-
-ENTJs have a strong urge to give structure wherever they are - to
-harness people to distant goals.  Their empirical, objective, and
-extroverted thinking may be highly developed; if this is the case,
-they use classification, generalization, summarization, adduction
-of evidence, and demonstration with ease.
-
-They resemble ESTJs in their tendency to establish plans for a
-task, enterprise, or organization, but ENTJs search more for policy
-and goals than for regulations and procedures.
-
-An ENTJ's introverted thinking (analysis and conservation) may be
-less well developed than the extroverted thinking processes, and
-the ENTJ leader may turn to an ENTP or INTP to provide this kind of
-input.  ENTJs are similar to INTJs except that the former places
-greater trust in empirical thought than in intuition; it is the
-ENTJs own intuitive sense of coherence, however, that augments and
-supports their empirical thinking.
-
-Although ENTJs are tolerant of established procedures, they can
-abandon any procedure when it can be shown to be indifferent to the
-goal it seemingly serves.  Inefficiency is especially rejected by
-ENTJs, and repetition of error causes them to become impatient. For
-the ENTJ, there must always be a reason for doing anything, and
-people's feelings usually are not sufficient reason.
-
-When in charge of an organization, ENTJs more than any other type
-desire (and generally have the ability) to visualize where the
-organization is going and seem able to communicate that vision to
-others.  They are the natural organization builders, and they
-cannot not lead.  They find themselves in command and sometimes are
-mystified as to how this happened.
-
-As administrators, ENTJs organize their units into a smooth
-functioning system, planning in advance, keeping both short-term
-and long-range objectives well in mind.  They seek and can see
-efficiency and effectiveness in personnel.  They prefer decisions
-to be based on impersonal data, want to work from well-thought-out
-plans, and like to use engineered operations - and they prefer that
-others follow suit.  ENTJs will support the policy of the
-organization and will expect others to do so.
-
-ENTJs will usually rise to positions of responsibility and enjoy
-being executives.  They are tireless in their devotion to their
-jobs and can easily block out other areas of life for the sake of
-work.  They will be able to reduce inefficiency, ineffectiveness,
-and aimless confusion, being willing to dismiss employees who
-perpetuate such behaviors.
-
-ENTJs tend to work in organizational structures of some sort, tend
-to be in charge administratively, and rise to top levels of
-responsibility, whether in the military, business, education, or
-government.
-
-ENTJs take charge of the home.  When the ENTJ is present, there
-will be little doubt as to who is in command.  Because their work
-is so important to them, however, they can become increasingly
-absent, especially if male.
-
-Male or female, ENTJs expect a great deal of their mates, who need
-to possess a strong personality of their own, a well-developed
-autonomy, many and varied interests, and a healthy self-esteem.  A
-career wife, however, may not be appealing to an ENTJ male, who is
-apt to view his home and family as a part of his professional
-background, a resource, and adjunct to his own career development.
-
-As a parent, an ENTJ will be thoroughly in charge, and the children
-will know what is expected of them - and will be expected to obey.
-When this does not occur, an ENTJ parent is not apt to make a
-scene; rather, there is likely to be a low-key, firm issuance of
-reprimand and a taking-for-granted of immediate obedience.
-
-While both mating and parenting are roles of importance to the
-ENTJ, they are to some degree preempted by the ENTJ's strong career
-interest.  The romantic dream and the quest for the ideal mate is
-usually not a characteristic of this type.
-
-ENTJs generally do, however, expect a home to be attractive,
-well-ordered, with meals served punctually and maintenance
-accomplished on schedule - all these in the service of the larger
-goal of creating a family system where children can be reared to be
-productive and healthy and establishing a devoted, harmonious
-relationship between man and woman.
-
-An ENTJ male might expect his mate to be active in civic and
-community affairs, to be socially sophisticated, and to be as
-well-educated as he.  The ENTJ female may find it difficult to
-select a mate who is not overwhelmed by her strong personality and
-will.
diff --git a/xtrn/smm/mb-entp.asc b/xtrn/smm/mb-entp.asc
deleted file mode 100644
index 4817854f1d243baddc38eb1a8359470a2327143d..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-entp.asc
+++ /dev/null
@@ -1,145 +0,0 @@
-ENTPs in short:
-
-Quick, ingenious, good at many things.  Stimulating company, alert
-and outspoken.  May argue for fun on either side of a question.
-Resourceful in solving new and challenging problems, but may
-neglect routine assignments.  Apt to turn to one new interest after
-another.  Skillful in finding logical reasons for what they want.
-
-About 5% of the population.
-
-Details about ENTPs:
-
-ENTPs wish to exercise their ingenuity in the world of people and
-things.  Found in about five out of every hundred people, ENTPs
-extrovert intuition; thus they deal imaginatively with social
-relationships as well as physical and mechanical relations.  They
-are very alert to what is apt to occur next, and always sensitive
-to possibilities.
-
-ENTPs are good at analysis, especially functional analysis, and
-have both a tolerance for and enjoyment of the complex.  Usually
-enthusiastic, ENTPs are apt to express interest in everything, and
-thus are a source of inspiration to others, who find themselves
-caught up by the ENTP's enthusiasm.  This type is delighted over
-many things and so is easy to please, often showing the
-effervescence of their NF counterpart, the ENFP.
-
-The ENTP is the most reluctant of all the types to do things in a
-particular manner just because that is the way things have always
-been done.  They characteristically have an eye for a better way,
-always on the lookout for new projects, new activities, new
-procedures.
-
-ENTPs are confident in the value of their pursuits and display a
-charming capacity to ignore the standard, the traditional, and the
-authoritative.  As a result of this open attitude, they often bring
-a fresh, new approach to their work and their lives.  The ENTP is a
-keen judge of the pragmatics of both the social and the mechanical,
-and may become expert at directing relationships between means and
-ends.
-
-Where the introverted NTP sees design as an end in itself, the
-extroverted NTP sees design as a 'means'; the end is the invention
-that works, the prototype that is replicatable.  Ideas are valuable
-when and only when they make possible actions and objects.  "It
-can't be done" is a challenge to an ENFP and elicits a reaction of
-"I can do it."
-
-They are not, however, the movers of mountains as are the INTJs.
-Rather, the faith of the ENTPs is in their ability to improvise
-something, and they display an unusual talent for rising to the
-expectancy of a situation.
-
-Superficially, ENTPs resemble ESTPs in their derring-do.  But the
-focus of the ENTP is on competency and the sense of power this
-gives, rather than on the feeling of freedom of action experienced
-by the ESTP.
-
-ENTPs can be fascinating conversationalists, able as they are to
-follow the complex verbalizations of others.  They may deliberately
-employ debate tactics to the disadvantage of their opponents, even
-when the "opponents" are close associates and valued friends.
-
-ENTPs are the most able of all types to maintain a one-up position
-with others.  They value adaptability and innovation and thus
-respond quickly and adeptly to another's shifting position.  They
-may even be several jumps ahead.
-
-The ENTP, talkative and motivating, is often the life of an
-enterprise.  The ENTP can be an entrepreneur and cleverly makes do
-with whatever or whoever is at hand, counting on ingenuity to solve
-problems as they arise, rather than carefully generating a detailed
-blueprint in advance.  A rough draft is all an ENTP needs to feel
-confident and ready to proceed into action, counting on the ability
-to improvise as a situation develops.
-
-Because of this tendency to depend on ingenuity and improvisation,
-they may neglect very necessary preparation at times.  After
-repeated failures in situations where improvising has met with
-defeat, the ENTP may develop ways of avoiding such situations as a
-substitute to thorough preparation.
-
-ENTPs can succeed in a variety of occupations, as long as the job
-does not involve too much humdrum routine.  At this point, they
-become restless.  If a project in which they are engaged is no
-longer challenging, they tend to lose interest in that project and
-fail to follow through - often to the discomfort of colleagues.
-
-Seldom are ENTPs conformists.  ENTPs enjoy outwitting the system
-and use rules and regulations within the system to win the game -
-whatever it may be.  They understand well the politics of
-institutions and deal with these realities very well, always aiming
-to understand the people within the system rather than to judge
-them.
-
-ENTPs are good at innovative projects and can administer them well
-if dull routine is not involved.  They usually are outstanding
-teachers, continuously devising new participative ways to make
-learning exciting for the students.
-
-As an employee, an ENTP may work against the system just for the
-joy of being one-up.  For ENTPs, to be taken-in, to be manipulated
-by another, is humiliating; this offends their joy in being masters
-of the art of one-upmanship.
-
-ENTPs are the natural engineers of human relationships and human
-systems.  Their good humor and optimistic outlook tend to be
-contagious, and people seek out their company.
-
-As mates, ENTPs tend to create a lively living environment.  They
-are gregarious, laugh easily and often, and are typically in good
-humor.
-
-Orderliness in the routines of daily living is not apt to inspire
-them; they usually solve this problem by mobilizing those around
-them.  Tom Sawyer illustrated this talent when he solved the
-problem of getting his Aunt Polly's fence whitewashed.  Life with
-ENTPs is likely to be a daring adventure; they can lead families
-into physical and economic dangers.  ENTPs improvise to remain
-unaware that they do not have the necessary knowledge of the
-situation to ward off such dangers.
-
-If the mate of an ENTP is not competitive, he or she is likely to
-find the one-up/one-down transactions somewhat wearing.  If the
-mate is competitive, the result might be conflict.
-
-Although usually good providers of economic necessities, ENTPs at
-times engage in brinkmanship with their careers, placing them in
-jeopardy and behaving as if unaware of the consequences; they may
-thus offer unnecessary challenges to those who have power over
-their professional success.  When challenges elicit negative
-responses from superiors, ENTPs are apt to react with delight at
-having an opportunity to improvise a solution to the crisis - and,
-more often than not, they succeed in doing so.
-
-ENTPs are likely to have all sorts of hobbies and to be experts in
-unexpected areas, but they are not apt to share these hobbies with
-their mates or children in the sense of teaching them.  In fact,
-ENTPs may be very inconsistent in the attention given to offspring.
-
-Usually, it is feast or famine.  ENTPs have a lively circle of
-friends and are interested in their ideas and activities.  They are
-usually easygoing, seldom critical or nagging.  At their worst,
-they can show undependable, fickle characteristics and may be
-easily discouraged.
diff --git a/xtrn/smm/mb-esfj.asc b/xtrn/smm/mb-esfj.asc
deleted file mode 100644
index c3801a37f6f07bf4b3b308a40146e9ee33cf69b9..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-esfj.asc
+++ /dev/null
@@ -1,118 +0,0 @@
-ESFJs in short:
-
-Warmhearted, talkative, popular, conscientious, born cooperators,
-active committee members.  Need harmony and may be good at creating
-it.  Always doing something nice for someone.  Work best with
-encouragement and praise.  Little interest in abstract thinking or
-technical subjects.  Main interest is in things that directly and
-visibly affect people's lives.
-
-About 13% of the population.
-
-Details about ESFJs:
-
-ESFJs, the most sociable of all the types, are energized by
-interactions with people, tending to idealize whatever or whoever
-they admire.  'Harmony' is a key to this type, which is represented
-in about 13 percent of the general population.
-
-ESFJs are the great nurturers of established institutions such as
-the home, the school, the church, and civic groups.  Wherever they
-go, they promote harmony and harmonious relationships.  They are
-outstanding hosts or hostesses, able to call people by name,
-usually after one introduction.  At a social gathering they can be
-observed attending to the needs of others, trying to insure that
-all are comfortable and involved.
-
-Social ties matter to the ESFJs, and their conversations often
-drift to the nostalgic recounting of past memories.  Traditions are
-developed, supported, and carefully observed by the ESFJ.
-
-ESFJs are hurt by indifference and need to be appreciated both for
-themselves and for the abundance, typically in the form of
-services, they give to others.  They are conscious of appearances
-and take the opinions of others regarding social standards very
-seriously.  Values in an ESFJ may take the form of 'shoulds' and
-'should nots' and may be freely expressed.  Conscientious and
-orderly, ESFJs may become restless when isolated from people.
-
-Career selection by ESFJs may lean toward service occupations.
-They have such outgoing personalities that they are outstanding at
-selling, being an invariable winner in sales contests.  They are
-apt to have seniority in any sales group within an organization.
-Observation of ESFJs at work in a sales transaction will
-demonstrate how this type personalizes the sale: The customer is
-not buying the product; he or she is buying personally from the
-ESFJ.
-
-This same characteristic causes ESFJs to be good in teaching,
-preaching, supervision, administration, coaching, and, in general,
-people-to-people jobs.  They seldom become a source of irritation
-to their superiors, for they respect and obey the rules and
-regulations, are duty and service oriented.  They are loyal to
-their bosses.
-
-ESFJs are likely to be aware of and enjoy discussing events and
-problems in the lives of their colleagues; but when conversations
-turn to abstractions of philosophy or science, the ESFJ may become
-restive.  Analysis of the complex - for example, an attempt to find
-an explanation of events through an analysis of principles - does
-not excite their interest, as it does the NTs.
-
-ESFJ mates have a set of values which contain clear 'shoulds' and
-'should-nots', and they expect their family to abide by these.
-They are conscientious about home responsibilities, are orderly
-about the home, and prefer that other occupants be the same.  They
-enjoy socializing and entertaining.
-
-ESFJs want family decisions settled efficiently and quickly and
-want family living routinized, scheduled, and correctly executed.
-They do not rebel against routine operations, and are devoted to
-the traditional values of home and hearth, respect their marriage
-vows, and are the most sympathetic of all types.
-
-They tend to be dependent on their mates and may marry to insure
-that they have a proper place in the social strata.  They enjoy the
-rituals in connected with serving of good food and beverages,
-thrive on festive occasions, respect and accumulate a goodly store
-of material possessions.  They take their role in the community
-seriously and are sensitive to the acknowledged, official
-decision-makers and identify with them.  They are aware of status,
-and often depend on higher authority as the source of opinions and
-attitudes.
-
-ESFJs wear their hearts on their sleeves and are outgoing in their
-emotional reactions.  They need to be needed, loved, and
-appreciated and may spend much energy reassuring themselves that
-this is the case.  They can become melancholy and depressed and
-even suicidal if they take the blame for whatever might be wrong in
-their institution or their personal relationships - as they are
-prone to do.
-
-ESFJs usually respect and revere their parents, and as children
-were responsive and obedient pupils.  They seem able to express the
-right feeling for a given situation.
-
-They are softhearted, sentimental, and usually observe with gusto
-and a flourish birthdays, anniversaries, and the like, making of
-the event a delightful, important occasion.  At the same time,
-however, ESFJs can cause others undue tension by expressing
-anticipations of gloom and doom, exhibiting a bent toward the
-pessimistic that can be contagious.  They need to control their
-fears that the worst is sure to happen and suppress their tendency
-toward crepe-hanging and anticipating disasters.
-
-The children of an ESFJ are seen as an extension of the family, and
-all they do reflects on the ESFJ.  If things do not go well, the
-SFJ may be critical, even carping toward his or her mate and
-children.
-
-This type may marry alcoholics or others who are particularly
-needy.  If a female ESFJ is married to a mate who is not a good
-provider, she can become nagging and brood over a comparison of her
-possessions and status with that of others.
-
-ESFJs, male or female, live in terms of people and things rather
-than in terms of ideas and principles.  They enjoy the process of
-decision-making, particularly when focus is on the 'usefulness' of
-things and people.
diff --git a/xtrn/smm/mb-esfp.asc b/xtrn/smm/mb-esfp.asc
deleted file mode 100644
index 633ade2c9b416ce9e7b14a820623ffb6516b9c96..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-esfp.asc
+++ /dev/null
@@ -1,89 +0,0 @@
-ESFPs in short:
-
-Outgoing, easygoing, accepting, friendly, enjoy everything and make
-things more fun others by their enjoyment.  Like sports and making
-things.  Know what's going and join in eagerly.  Find remembering
-facts easier than mastering theories.  Are best in situations that
-need sound common sense and practical ability with people as well
-as with things.
-
-About 13% of the population.
-
-Details about ESFPs:
-
-ESFPs radiate attractive warmth and optimism.  Smooth, witty,
-charming, clever, voluble, and open to the environment - this
-describes ESFPs who, like ESTPs, represent about 13 percent of the
-general population.  They are great fun to be with and are the most
-generous of all the types.  'Performer' would be the word which
-best describes an ESFP.
-
-ESFPs will avoid being alone and seek the company of others
-whenever possible.  ESFPs easily find company, for others are
-usually highly entertained by the presence of an ESFP.  ESFPs love
-excitement and create it wherever they are.  Their joy of living is
-contagious and generally they wear happy faces.  Often outstanding
-conversationalists, their flowing banter is amusing in its wit.
-
-ESFPs have an air of sophistication and are likely to be dressed in
-the latest fashion, displaying an enjoyment of all the good things
-of life: dress, food, physical comfort, and happy times.  ESFPs
-create a mood of "eat, drink, and be merry" wherever they go, and
-around them life can have a continual party-like atmosphere of
-gaiety.
-
-ESFPs make exciting, if somewhat unpredictable mates, which may
-give quieter type mates some anxiety and tension from living on the
-edge of adventure.  The home of an ESFP is likely to be filled with
-people all having a good time.  Problems will not be allowed to
-make their appearance.  The ESFP accomplishes this by taking an
-attitude of "walking by the graveyard whistling," refusing to
-recognize doom and gloom.
-
-ESFPs can be generous to a fault.  What is theirs is yours, and
-what is yours is yours still.  They give assistance to one and all
-without expectation of a return, just as they love freely without
-expecting something in return.  ESFPs seem to view life as an
-eternal cornucopia from which flows an endless supply of pleasures
-that require no effort on their part to insure.
-
-ESFPs' talent for enjoying life can make them more subject to
-temptations than are other types.  They are inclined to be
-impulsive, and thus both male and female ESFPs are vulnerable to
-psychological seduction, if not physical seduction, with an ESFP
-giving in easily and agreeably to the demands of others.  As a
-parent, the ESFP will be entertaining, a friend, and a source of
-fun and excitement.  When there is sickness, or trouble, however,
-ESFPs may become impatient and may want to absent themselves.
-
-ESFPs' tolerance for anxiety is the lowest of all types.  Anxiety
-is avoided by ignoring the dark side of a situation as long as
-possible.  They are inclined to be somewhat self-indulgent, but,
-rather than make an outward show of resistance or make waves, ESFPs
-will give apparent compliance - and then go their own way to what
-they enjoy.
-
-ESFPs prefer active jobs and should not be given lonely, solitary
-assignments.  Outstanding in public relations, they love working
-with people.  Decisions are made with personal warmth, based on
-personal reference or reference to significant others.  This type
-relies on their personal experiences and generally show good common
-sense.
-
-The gregarious sociability and adaptability of ESFPs make them a
-source of warmth to others.  They do not mind telephone or personal
-interruptions and are verbally facile in both situations.  They can
-be counted on to have accurate data about the people around them,
-gaining these data through effortless and continuous observations.
-
-ESFPs are not deeply interested in scholastic pursuits, wanting
-knowledge only for immediate utility.  They avoid science and
-engineering, gravitate toward business, and are adept at selling,
-particularly selling tangibles.
-
-They can be effective in education, especially elementary school
-teaching, and can enjoy nursing for its drama.  They are good at
-working with people in crisis, a facility, which often leads ESFPs
-into social work.  They also enjoy entertaining people and are thus
-drawn to the performing arts, thriving on the excitement of being
-in the limelight.
diff --git a/xtrn/smm/mb-estj.asc b/xtrn/smm/mb-estj.asc
deleted file mode 100644
index a58f235e23972f61f097e6ed7999204b4af43eae..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-estj.asc
+++ /dev/null
@@ -1,70 +0,0 @@
-ESTJs in short:
-
-Practical, realistic, matter-of-fact, with a natural head for
-business or mechanics.  Not interested in subjects they see no use
-for, but can apply themselves when necessary.  Like to organize and
-run activities.  May make good administrators, especially if they
-remember to consider others' feelings and points of view.
-
-About 13% of the population.
-
-Details about ESTJs:
-
-ESTJs are very much in touch with the external environment.  They
-know their community and usually are pillars of strength.  The best
-adjective to describe ESTJs would be 'responsible.'  They represent
-about 13 percent of the general population.
-
-ESTJs are outstanding at organizing procedures and in detailing
-rules and regulations.  They like to see things done correctly.
-They tend to be impatient with those who do not carry out
-procedures with sufficient attention to those details, prescribed
-by those with the most experience, that will get the job done
-right.
-
-ESTJs are comfortable in evaluating others and tend to judge how a
-person is doing in terms of standard operating procedures.  They
-may, at times, be abrupt with those who do not follow the rules
-correctly.  ESTJs are realistic, matter-of-fact, and more curious
-about new devices and processes than about new principles and
-theories.
-
-ESTJs generally are loyal to their institutions, work, and
-community and make excellent, faithful mates and parents.  They see
-where their duty lies and are not likely to shirk the doing of that
-duty, even when this requires considerable sacrifice on their part.
-
-They frequently rise to positions of responsibility in their jobs,
-in the community, and in their religious affiliations.  They very
-often belong to several civic clubs and support them both through
-steady attendance and through their spoken attitudes.  ESTJs
-themselves are punctual and expect others to be also.
-
-ESTJs may not always be responsive to points of view and emotions
-of others and may have a tendency to jump to conclusions too
-quickly at times.  They may not always be willing to listen
-patiently to opposing views; they are especially vulnerable to this
-tendency when in positions of authority.  They may need to make
-special effort to remain open to input from others who are
-dependent on them - their children, spouses, and employees.
-
-ESTJs are so in tune with the established, time-honored
-institutions and ways of behaving within those institutions that
-they cannot understand those who might wish to abandon or radically
-change those institutions.  They follow routines well at home and
-at work, tending to have a place for everything and wanting
-everything in its place.  They are usually neat and orderly at work
-and at play.
-
-They approach human relations through traditions and rituals,
-promoting harmony and contentment in their relationships through
-creating well-worked-out routines and procedures.  Family
-traditions have meaning for ESTJs, and they willingly participate
-in observing these.  They enjoy opportunities to see friends,
-former colleagues, and relatives at functions such as retirement
-dinners, annual picnics, Thanksgiving gatherings, and weddings.
-
-ESTJs are relatively easy to get to know; they do not tend to
-confuse people by sending double messages.  They are dependable and
-consistent, and what they seem to be is what they are.
-
diff --git a/xtrn/smm/mb-estp.asc b/xtrn/smm/mb-estp.asc
deleted file mode 100644
index e8c8c956fe9f53f729444e80eff0fbb5a5567459..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-estp.asc
+++ /dev/null
@@ -1,119 +0,0 @@
-ESTPs in short:
-
-Matter-of-fact, do not worry or hurry, enjoy whatever comes along.
-Tend to like mechanical things and sports, with friends on the
-side.  May be a bit blunt or insensitive.  Adaptable, tolerant,
-generally conservative in values.  Dislike long explanations.  Are
-best with real things that can be worked, handled, taken apart or
-put together.
-
-About 13% of the population.
-
-Details about ESTPs:
-
-ESTPs are men and women of action.  When someone of this
-personality is present, things begin to happen.  The lights come
-on, the music plays, the game begins.  And a game it is for the
-ESTP, The outstanding entrepreneur, the international diplomat, the
-conciliator, and the negotiator 'par excellence.'
-
-Approximately 13 percent of the general population are of this
-extroverted, sensing, thinking, perceiving type, and if only one
-adjective could be used to describe ESTPs 'resourceful' would be an
-apt choice.
-
-Life is never dull around ESTPs.  Their attractive, friendly style
-has a theatrical flourish which makes even the most routine,
-mundane event seem exciting.  ESTPs usually know the location of
-the best restaurants, and headwaiters are likely to call them by
-name.  ESTPs are socially sophisticated, suave, and urbane and are
-master manipulators of the external environment.
-
-ESTPs are uncanny at observing people's motivations, somehow
-hypersensitive to minimal nonverbal cues which other types might
-miss.  And they are masters at using these observations to "sell"
-the "client."  The eye of the ESTP is ever on the eye of the
-beholder, and all actions are directed toward this audience.
-
-Witty, clever, and fun, ESTPs seem to possess an unusual amount of
-empathy, when in fact this is not the case; rather, they are so
-acutely aware of minimal signals from others that they are usually
-several jumps ahead in anticipation of another's position.  And
-ESTPs can use information gained to the ends they have in mind -
-apparently with nerves of steel, engaging in what seems to others
-to be suicidal brinkmanship.  Other types may find this exhausting,
-but ESTPs are exhilarated by working close to the edge of disaster.
-
-ESTPs are ruthless pragmatists and often offer the ends as
-justification for whatever means they see as necessary -
-regrettable, perhaps, but necessary.  Usually, however, ESTPs do
-not care to justify actions, but prefer instead to get on to the
-next action.
-
-ESTPs are outstanding as initiators of enterprises that bring
-people together to negotiate.  They make invaluable itinerant
-administrators who can pull troubled companies or institutions out
-of the red very quickly, and with style!
-
-They can sell an idea or project in a way no other type can, but
-won't follow through on the tedious administrative details of a
-project.  This characteristic often causes ESTPs to be
-unappreciated for the extraordinary talents they have, for people
-lose sight of the idea contributed and focus on the details left
-undone, becoming critical of ESTPs' weaknesses rather than
-appreciating their strength.
-
-Few enterprises which are institutionally based use ESTPs as they
-should be used.  When they strike out on their own, however, they
-do not always succeed, for their unwillingness to bother with
-follow-up details may cause an otherwise excellent project to fail.
-ESTPs need to be sure they have someone who will take care of
-follow-up if at all possible.
-
-If the promotional, entrepreneurial capabilities of ESTPs are used
-to constructive ends, an institution is fortunate for their
-presence.
-
-If their desire for excitement is not met constructively, however,
-these energies may be channeled into destructive, antisocial
-activities such as those of the confidence rackets -
-counterfeiting, bad-check artistry, safe-cracking, and swindling. A
-movie of the early 1970's which caught this use of the ESTP's
-talent was The Sting.
-
-ESTPs live in the immediate moment and as mates lend excitement -
-and unpredictability - to the relationship.  The ESTP mate is
-usually extremely attentive in public and smooth in social rituals.
-They carry on amusing repartee, and laughter surrounds them as they
-recount from their endless supply of clever jokes and stories.
-
-Charm radiates from ESTPs.  Nothing is too good for their friends,
-although family responsibilities may, at times, be given second
-priority.  The ESTP's mate may in time come to feel like an object
-- the female a chattel and the male a negotiable commodity.  Deep
-commitments do not always occur in the lives of ESTPs, although
-they are always popular and know many, many people by name.
-
-Relationships usually are conditional, and the condition is the
-consideration of what the ESTP has to gain  from the relationship.
-Anything gained, however, is shared freely and generously with the
-mate.  The unexpected gift, the impulsive trip to Paris, the
-extravagant surprise at Christmas - all these an ESTP brings to a
-mate.  Fun, excitement, laughter, and that element of
-unpredictability are characteristic of their relationship.
-
-The ESTPs have a low tolerance for anxiety and are apt to avoid or
-leave situations that are consistently filled with interpersonal
-tensions.  ESTPs are usually somewhat of a mystery to their mates
-and to others.  Few people comprehend this unique personality.
-
-ESTPs themselves understand well the maxim, "He who travels
-fastest, travels alone."  Still, ESTPs are not likely to be lonely
-for long.
-
-ESTPs meet life with a hearty appetite for the good things of the
-world, searching out excitement, perhaps as a warrior, an athlete,
-an adventurer, or as a professional gambler, but always seeking the
-thrill of courting Lady Luck in one fashion or another.  A theme of
-seeking excitement through taking of risks runs through the lives
-of ESTPs.
diff --git a/xtrn/smm/mb-f.asc b/xtrn/smm/mb-f.asc
deleted file mode 100644
index 49cec2c04674a129e55f92a69445efb9fd231c59..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-f.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-The Feeler tends toward subjective & social values, personal feelings, 
-harmony, intimacy, sympathy and devotion. The F overextends himself to meet
-others needs, enjoys serving people, tends to retract statements that offend
-others, asks himself 'how will this affect the people involved'.
-The feeler feels the thinker has ice in his veins.
-The population is equally divided between Ts and Fs, although more men tend
-to be Thinkers & more women tend to be Feelers.
diff --git a/xtrn/smm/mb-fp.asc b/xtrn/smm/mb-fp.asc
deleted file mode 100644
index cdc07cb81e34bdf64acbbb1968a2db2161de9bce..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-fp.asc
+++ /dev/null
@@ -1 +0,0 @@
-You should never have a party without an FP.
diff --git a/xtrn/smm/mb-i.asc b/xtrn/smm/mb-i.asc
deleted file mode 100644
index 8ff52b2d3e61ef668e0123b8e7e6f0e0bf8c6e62..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-i.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-An Introvert gets his energy from inside himself and needs his own space for 
-recharging his batteries. An Introvert is drained by being around people.
-I is perceived as a good listener, tends to be shy, likes to share occasions
-with a few close friends, doesn't like interruptions, is suspicious if people 
-are too complimentary, gets irritated if people repeat what has already been
-said. 'I' tends to consider - then speak, An 'I' is reluctant to reveal himself
-and may resist taking this test for fear of being exposed, but can complete 
-the test in a short time without carefully considering & weighing each 
-question. About 25% of the population are type I.
diff --git a/xtrn/smm/mb-infj.asc b/xtrn/smm/mb-infj.asc
deleted file mode 100644
index 73e1893f97ed90c324ce71ca53b6cea9830a5e98..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-infj.asc
+++ /dev/null
@@ -1,144 +0,0 @@
-INFJs in short:
-
-Succeed by perseverance, originality and desire to do whatever is
-needed or wanted.  Put their best efforts into their work.  Quietly
-forceful, conscientious, concerned for others.  Respected for their
-firm principles.  Likely to be honored and followed for their clear
-convictions as to how best to serve the common good.
-
-About 1% of the population.
-
-Details about INFJs:
-
-INFJs focus on possibilities, think in terms of values, and come
-easily to decisions.  The small number of this type (1 percent) is
-regrettable, since INFJs have an unusually strong drive to
-contribute to the welfare of others and genuinely enjoy helping
-their fellow men.  This type has great depth of personality; they
-are themselves complicated, and can understand and deal with
-complex issues and people.
-
-It is an INFJ who is likely to have visions of human events past,
-present, or future.  If a person demonstrates an ability to
-understand psychic phenomenon better than most others, this person
-is likely to be an INFJ.
-
-Characteristically, INFJs have strong empathetic abilities and can
-be aware of another's emotions or intents even before that person
-is conscious of these.  This can take the form of feeling the
-distress or illnesses of others to an extent which is difficult for
-other types.  INFJs can intuit good and evil in others, although
-they seldom can tell how they came to know.  Subsequent events tend
-to bear them out, however.
-
-INFJs are usually good students, achievers who exhibit an
-unostentatious creativity.  They take their work seriously and
-enjoy academic activity.  They can exhibit qualities of
-over-perfectionism and put more into a task than perhaps is
-justified by the nature of the task.  They generally will not be
-visible leaders, but will quietly exert influence behind the
-scenes.
-
-INFJs are hard to get to know.  They have an unusually rich inner
-life, but they are reserved and tend not to share their reactions
-with those they trust.  Because of their vulnerability through a
-strong facility to interject, INFJs can be hurt rather easily by
-others, which, perhaps, is at least one reason they tend to be
-private people.  People who have known an INFJ for years may find
-sides emerging which come as a surprise.  Not that INFJs are
-inconsistent; they are very consistent and value integrity.  But
-they have convoluted, complex personalities which sometimes puzzle
-even them.
-
-INFJs like to please others and tend to contribute their best
-efforts in all situations.  They prefer and enjoy agreeing with
-others, and find conflict disagreeable and destructive.  What is
-known as ESP is likely found in an INFJ.
-
-INFJs have vivid imaginations exercised both as memory and
-intuition, and this can amount to genius, resulting at times in an
-INFJs being seen as mystical.  This unfettered imagination often
-will enable this person to compose complex and often aesthetic
-works of arts such as music, mathematical systems, poems, plays,
-and novels.  In a sense the INFJ is the most poetic of all the
-types.  INFJs can have uncanny communications with certain
-individuals at a distance.
-
-INFJs often select liberal arts as a college major and opt for
-occupations which involve interacting with people, but on a
-one-to-one basis.  For example, the general practitioner in
-medicine might be an INFJ, or the psychiatrist or psychologist.  As
-with all NFs, the ministry holds attraction, although the INFJ must
-develop an extroverted role here which requires a great deal of
-energy.
-
-INFJs may be attracted to writing as a profession, and often they
-use language which contains an unusual degree of imagery.  They are
-masters of the metaphor, and both their verbal and written
-communications tend to be elegant and complex.  Their great talent
-for language usually is directed toward people, describing people
-and writing to communicate with people in a personalized way. INFJs
-who write comment often that they write with a particular person in
-mind; writing to a faceless abstract audience leaves them
-uninspired.
-
-INFJs make outstanding individual therapists who have the ability
-to get in touch with the archetypes of their patients in a way some
-other types do not.  The INFJs are also the most vulnerable of all
-types to the eruptions of their own archetypal material.  As
-therapists, INFJs may choose counseling, clinical psychology, or
-psychiatry, or may choose to teach in these fields.  Writing about
-these professions often intrigues an INFJ.
-
-Whatever their choice, they generally are successful in these
-fields because of their great personal warmth, their enthusiasm,
-their insight, their depth of concentration, their originality, and
-their organizational skills can all be brought into play.
-
-At work as well as socially, INFJs are highly sensitive in their
-handling of others and tend to work well in an organizational
-structure.  They have a capacity for working at jobs which require
-solitude and concentration, but also do well when in contact with
-people, providing the human interaction is not superficial.
-
-INFJs enjoy problem-solving and can understand and use human
-systems creatively and humanistically.  As employees and employers,
-INFJs are concerned with people's feelings and are able to provide
-in themselves a barometer of the feelings of individuals and groups
-within the organization.  INFJs listen well and are  willing and
-able to consult and cooperate with others.  Once a decision is
-made, they work to implement it.
-
-INFJs are usually good at public relations and themselves have good
-interpersonal relations.  They value staff harmony and want an
-organization to run smoothly and pleasantly, themselves making
-every effort to contribute to that end.
-
-They are crushed by too much criticism and can have their feelings
-hurt rather easily.  They respond to praise and use approval as a
-means of motivating others, just as they, the INFJs, are motivated
-by approval.  If they are subject to a hostile, unfriendly working
-condition or to constant criticism, they tend to lose confidence,
-become unhappy and immobilized, and finally become physically ill.
-
-As mates INFJs are devoted to their spouses, but may not always be
-open to physical approaches.  They tend to be physically
-demonstrative at times, but wish to choose when, which is when they
-are in the mood.  This may be quite confusing to an extroverted
-mate.
-
-Often an INFJs expressions of affection will be subtle, taking a
-humorous, unexpected turn.  INFJs need and want harmony in their
-home and find constant conflict, overt or covert, extremely
-destructive to their psyches.  Their friendship circle is likely to
-be small, deep, and longstanding.
-
-As parents, INFJs usually are fiercely devoted.  A female INFJ,
-particularly, is linked to her children in a way different from the
-other types: with almost a psychic symbiosis.  This deep bond can
-create an overdependency that can be unhealthy for both mother and
-child.  At the same time, INFJs tend to be good friends with their
-children, while firm in discipline.  They usually are concerned
-about the comfort of a home and most especially the comfort,
-physical health, and emotional well-being of both mates and
-children.
diff --git a/xtrn/smm/mb-infp.asc b/xtrn/smm/mb-infp.asc
deleted file mode 100644
index f99ff2b82f182c82526befe1da89b7e53bbebdba..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-infp.asc
+++ /dev/null
@@ -1,118 +0,0 @@
-INFPs in short:
-
-Full of enthusiasms and loyalties, but seldom talk of these until
-they know you well.  Care about learning, ideas, language, and
-independent projects of their own.  Tend to undertake too much,
-then somehow get it done.  Friendly, but often too absorbed in what
-they are doing to be sociable.  Little concerned with possessions
-or physical surroundings.
-
-About 1% of the population.
-
-Details about INFPs:
-
-INFPs present a calm, pleasant face to the world and are seen as
-reticent and even shy.  Although they demonstrate a cool reserve
-toward others, inside they are anything but distant.  They have a
-capacity for caring which is not always found in other types.  They
-care deeply - indeed passionately - about a few special persons or
-cause.  One word that captures this type is 'idealistic'.  At
-times, this characteristic leaves them feeling isolated, especially
-since INFPs are found in only 1 percent of the general population.
-
-INFPs have a profound sense of honor derived from internal values.
-The INFP is the Prince or Princess of mythology, the King's
-champion, Defender of the Faith, and guardian of the castle.  Sir
-Galahad and Joan of Arc are male and female prototypes of an INFP.
-To understand INFPs their cause must be understood, for they are
-willing to make unusual sacrifices for someone or something
-believed in.
-
-INFPs seek unity in their lives, unity of body and mind, emotions
-and intellect.  They often have a subtle tragic motif running
-through their lives, but others seldom detect this inner minor key.
-The deep commitment of INFPs to the positive and the good causes
-them to be alert to the negative and the evil, which can take the
-form of a fascination with the profane.  Thus INFPs may live a
-paradox, drawn toward purity and unity but looking over the
-shoulder toward the sullied and desecrated.  When INFPs believe
-that they have yielded to an impure temptation, they may be given
-to acts of self-sacrifice in atonement.  The atonement, however, is
-within the INFP, who does not feel compelled to make public the
-issue.
-
-INFPs prefer the valuing process over the purely logical.  They
-respond to the beautiful versus the ugly, the good versus the bad,
-and the moral versus the immoral.  Impressions are gained in a
-fluid, global, diffused way.  Metaphors and similes come naturally
-but may be strained.
-
-INFPs have a gift of interpreting symbols, as well as creating
-them, and thus often write in lyric fashion.  They may demonstrate
-a tendency to take deliberate liberties with logic.  Unlike the NT,
-they see logic as something optional.
-
-INFPs also may, at times, assume an unwarranted familiarity with a
-domain, because their global, impressionistic way of dealing with
-reality may have failed to register a sufficient number of details
-for mastery.  INFPs may have difficulty thinking in terms of a
-conditional framework; they see things as either real or fancied,
-and are impatient with the hypothetical.
-
-At work, INFPs are adaptable, welcome new ideas and new
-information, are well aware of people and their feelings, and
-relate well to most, albeit with some psychological distance.
-INFPs dislike telephone interruptions and work well alone, as well
-as with others.  They are patient with complicated situations, but
-impatient with routine details.  They can make errors of fact, but
-seldom of values.  Their career choices may be toward the ministry,
-missionary work, college teaching, psychiatry, architecture,
-psychology - and away from business.
-
-They seem willing and usually are able to apply themselves
-scholastically to gain the necessary training for professional
-work, often doing better in college than in high school.  They have
-a natural interest in scholarly activities and demonstrate, as do
-other NFs, a remarkable facility for languages.  Often they hear a
-calling to go forth into the world to help others; they seem
-willing to make the necessary personal sacrifices involved in
-responding to that call, even if it means asking others to do
-likewise.
-
-INFPs can make outstanding novelists and character actors, for they
-able to efface their own personalities in their portrayal of a
-character in a way other types cannot.
-
-As mates, INFPs have a deep commitment to their pledges.  They like
-to live in harmony and may go to great lengths to avoid constant
-conflict.  They are sensitive to the feelings of others and enjoy
-pleasing those they care for.  They may find it difficult to
-reconcile a romantic, idealized concept of conjugal life with the
-realities of everyday living with another person.
-
-At times, INFPs may seem fearful of exuberant attainment, afraid
-that current advances may have to be paid for with later
-sacrifices.  The devil is sure to get his due if the INFP
-experiences too freely of success, or beauty, or health, or wealth,
-or knowledge.  And thus, INFPs guard against giving way to relaxing
-in the happiness of mating.  They may have difficulty in expressing
-affection directly, but communicate interest and affection
-indirectly.
-
-For INFPs, their home is their castle.  As parents, they are fierce
-in protection of their home and family and are devoted to the
-welfare of family members.  They have a strong capacity for
-devotion, sympathy, and adaptability in their relationships, and
-thus are easy to live with.  They are loyal to their family and,
-although they may dream of greener pastures, they soon locate the
-nettles.  The almost preconscious conviction that pleasure must be
-paid for with pain can cause a sense of uneasiness in the family
-system of an INFP, who may transmit an air of being ever-vigilant
-against invasion.
-
-In the routine rituals of daily living, INFPs tend to be compliant
-and may even prefer having decisions made on their behalf - until
-their value system is violated!  Then INFPs dig in their heels and
-will not budge from ideals.  Life with an INFP will go gently along
-for long periods, until an ideal is struck and violated.  Then an
-INFP will resist and insist.
diff --git a/xtrn/smm/mb-intj.asc b/xtrn/smm/mb-intj.asc
deleted file mode 100644
index 18d1d03349d4806f6721f8a2e97282ff4ea8eb89..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-intj.asc
+++ /dev/null
@@ -1,169 +0,0 @@
-INTJs in short:
-
-Usually have original minds and great drive for their own ideas and
-purposes.  In fields that appeal to them, they have a fine power to
-organize a job and carry it through with or without help.
-Skeptical, critical, independent, determined, often stubborn.  Must
-learn to yield less important points in order to win the most
-important.
-
-About 1% of the population.
-
-Details about INTJs:
-
-INTJs are the most self-confident of all the types, having
-"self-power" awareness.  Found in about 1 percent of the general
-population, the INTJs live in an introspective reality,  focusing
-on possibilities, using thinking in the form of empirical logic,
-and preferring that events and people serve some positive use.
-Decisions come naturally to the INTJs; once a decision is made,
-INTJs are at rest.  INTJs look to the future rather than the past,
-and a word which captures the essence of INTJs is 'builder' - a
-builder of systems and the applier of theoretical models.
-
-To INTJs, authority based on position, rank, title, or publication
-has absolutely no force.  This type is not likely to succumb to the
-magic of slogans, watchwords, or shibboleths.  If an idea or
-position makes sense to an INTJ, it will be adopted; if it doesn't,
-it won't, regardless of who took the position or generated the
-idea.  As with the INTP, authority per se does not impress the
-INTJ.
-
-INTJs do, however, tend to conform to rules if they are useful, not
-because they believe in them, or because they make sense, but
-because of their unique view of reality.  They are the supreme
-pragmatists, who see reality as something which is quite arbitrary
-and made up.  Thus it can be used as a tool - or ignored.
-
-Reality is quite malleable and can be changed, conquered, or
-brought to a heel.  Reality is a crucible for the refining of
-ideas, and in this sense, INTJs are the most theoretical of all the
-types. An INTJ sees reality as the pawn of ideas: No idea is too
-farfetched to be entertained.  INTJs are natural brainstormers,
-always open to new concepts, and, in fact, aggressively seeking
-them.
-
-INTJs manipulate the world of theory as if on a gigantic chess
-board, always seeking strategies and tactics that have high payoff.
-In their penchant for logic, the INTJs resemble the INTPs.  The
-logic of an INTJ, however, is not confined to the expressibly
-logical.  Unlike INTPs, INTJs need only to have a vague, intuitive
-impression of the unexpressed logic of a system to continue surely
-on their way.  Things need only 'seem' logical; this is entirely
-sufficient.
-
-Moreover, they always have a keen eye for the consequences of the
-application of new ideas or positions.  They can be quite ruthless
-in the implementation of systems, seldom counting personal cost in
-terms of time and energy.  Theories which cannot be made to work
-are quickly discarded by the INTJs.
-
-To understand INTJs, their way of dealing with reality rather than
-their way of dealing with ideas should be observed closely.  Their
-conscious thought is extroverted and empirical.  Hence, they are
-better at generalizing, classifying, summarizing, adducing
-evidence, proving and demonstrating than are the INTPs.
-
-The INTJs are somewhat less at home with pure reason, that is,
-systemic logic, where principles are explicit.  In this respect
-they resemble the ENTJs.  The INTJs, rather than using deductive
-logic, use their intuition to grasp coherence.
-
-INTJs have a drive to completion, always with an eye to long-term
-consequences.  Ideas seem to carry their own force for INTJs,
-although they subject every idea to the test of usefulness.
-
-Difficulties are highly stimulating to INTJs, who love responding
-to a challenge that requires creativity.  Those personality traits
-lead INTJs to occupations where theoretical models can be
-translated into actuality.  They build data and human systems
-wherever they work if given even a slight opportunity.  They can be
-outstanding in scientific research and also outstanding as
-executives who generate a plethora of implementations of ideas.
-
-Teamed with an INTP who is the architect of systems, the INTJ
-provides a dimension to an organization which insures that the work
-of the INTP does not gather dust on library shelves.
-
-INTJs can be very single-minded at times; this can be either a
-weakness or a strength in their careers, for they can ignore the
-points of view and wishes of others.  INTJs usually rise to
-positions of responsibility, for they work long and hard and steady
-in their pursuit of goals, sparing neither time nor effort on their
-part or that of their colleagues and employees.
-
-INTJs live to see systems translated into substance; an INTP, by
-way of contrast, is content to design the system.  In both, these
-types, however, coherence is the master.  Both internal and
-external consistency are important, and if an INTJ finds that he or
-she is in a working situation where overlapping functions,
-duplication of effort, inefficient paper flow, and waste of human
-and material resources abound, the INTJ cannot rest until an effort
-is made to correct the situation.  Cost-effectiveness is a concept
-which has a strong imperative for INTJs, who frequently select
-occupations in engineering, particularly human engineering.
-
-They also can be found in the physical sciences, in roles which
-require development, such as curriculum building, and, in general,
-any job which requires the creation and application of technology
-to complex areas.
-
-Fellow workers of INTJs often feel as if the INTJ can see right
-through them, and often believe that the INTJ finds them wanting.
-This tendency of people to feel transparent in the presence of the
-INTJ often results in relationships which have psychological
-distance.  Thus colleagues find the INTJ apparently unemotional
-and, at times, cold and dispassionate.  Because of their tendency
-to drive others as hard as themselves, INTJs often seem demanding
-and difficult to satisfy.
-
-INTJs are high achievers in school and on the job.  On the job,
-they take the goals of the institution seriously and continually
-strive to respond to these goals.  They make dedicated, loyal
-employees whose loyalties are directed toward the system, rather
-than toward individuals within the system.  So as the people of an
-institution come and go, the INTJs have little difficulty - unlike
-the NFs, who have their loyalties involved more with persons than
-offices.
-
-INTJs ordinarily tend to verbalize the positive and eschew comments
-of a negative nature; they are more interested in moving an
-institution forward than commiserating about mistakes of the past.
-
-As mates, INTJs want harmony and order in the home and in
-relationships.  They are the most independent of all the types.
-They will trust their intuitions about others when making choices
-of friends and mates, even in the face of contradictory evidence
-and pressures applied by others.
-
-The emotions of an INTJ are hard to read, and neither male nor
-female INTJ is apt to express emotional reactions.  At times, both
-will seem cold, reserved, and unresponsive, while in fact INTJs are
-almost hypersensitive to signals of rejection from those for whom
-they care.
-
-In social situations, INTJs may also be unresponsive and may
-neglect to observe small rituals designed to put others at their
-ease.  For example, INTJs may communicate that time is wasted if
-used for idle dialogue, and thus people receive a sense of hurry
-from an INTJ which is not always intended.  In their interpersonal
-relationships, INTJs are usually better in a working situation than
-in recreational situations.  They do not enjoy physical contact
-except with a chosen few.
-
-As parents, INTJs are dedicated and single-minded in their
-devotion: Their children are a major focus in life.  They are
-supportive of their children and tend to allow them to develop in
-directions of their own choosing.  INTJs usually are firm and
-consistent in their discipline and rarely care to repeat directions
-given to children - or others.
-
-Being the most independent of all the types, they have a strong
-need for autonomy; indifference or criticism from people in general
-does not particularly bother INTJs, if they believe that they are
-right.  They also have a strong need for privacy.
-
-The most important preference of an INTJ is 'intuition', but this
-is seldom seen.  Rather, the function of 'thinking' is used to deal
-with the world and with people.  INTJs are vulnerable in the
-emotional area and may make serious mistakes here.
diff --git a/xtrn/smm/mb-intp.asc b/xtrn/smm/mb-intp.asc
deleted file mode 100644
index 97594584b51cc919a9a4f7e051f459220aa97e14..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-intp.asc
+++ /dev/null
@@ -1,118 +0,0 @@
-INTPs in short:
-
-Quiet, reserved, impersonal.  Enjoy especially theoretical or
-scientific subjects.  Logical to the point of hairsplitting.
-Usually interested mainly in ideas, with little liking for parties
-or small talk.  Tend to have sharply defined interests.  Need
-careers where some strong interest can be used and useful.
-
-About 1% of the population.
-
-Details on INTPs:
-
-INTPs exhibit the greatest precision in thought and language of all
-the types; they tend to see the distinctions and inconsistencies in
-thought and language instantaneously.  The one word which captures
-the unique style of INTPs is 'architect' - the architect of ideas
-and systems as well as the architect of edifices.  This type is
-found in only 1 percent of the population and therefore is not
-encountered as frequently as some of the other types.
-
-INTPs detect contradictions in statements no matter how distant in
-space or time the contradictory statements were produced.  The
-intellectual scanning of INTPs has a principled quality; that is,
-INTPs search for whatever is relevant and pertinent to the issue at
-hand.  Consequently, INTPs can concentrate better than any other
-type.
-
-Authority derived from office, position, or wide acceptance does
-not impress INTPs.  External authority per se is irrelevant.  INTPs
-abhor redundancy and incoherence.
-
-Possessing a desire to understand the universe, an INTP is
-constantly looking for natural law.  Curiosity concerning these
-keys to the universe is a driving force in this type.
-
-INTPs prize intelligence in themselves and in others, but can
-become intellectual dilettantes as a result of their need to amass
-ideas, principles, or understanding of behavior.  And once they
-know something, it is remembered.
-
-INTPs can become obsessed with analysis.  Once caught up in a
-thought process that thought process seems to have a will of its
-own for INTPs, and they persevere until the issue is comprehended
-in all its complexity.  They can be intellectual snobs and may show
-impatience at times with others less endowed intellectually.  This
-quality, INTPs find, generates hostility and defensive behaviors on
-the part of others, who may describe an INTP as arrogant.
-
-For INTPs, the world exists primarily to be understood.  Reality is
-trivial, a mere arena for proving ideas.  It is essential that the
-universe is understood and that whatever is stated about the
-universe is stated correctly, with coherence and without
-redundancy.  This is the INTP's final purpose.  It matters not
-whether others understand or accept his or her truths.
-
-The INTP is the logician, the mathematician, the philosopher, the
-scientist; any pursuit requiring architecture of ideas intrigues
-this type.
-
-INTPs should not, however, be asked to work out the implementation
-of application of their models to the real world.  The INTP is the
-architect of a system and leaves it to others to be the builder and
-the applicator.  Very often, therefore, the INTP's work is not
-credited to him or her.  The builder and the applier gains fame and
-fortune, while the INTP's name remains obscure.  Appreciation of an
-INTP's theoretical work frequently comes posthumously - or the work
-may never be removed from library shelves at all and thus lost.
-
-INTPs tend not to be writers or to go into sales work.  They are,
-however, often excellent teachers, particularly for advanced
-students, although INTPs do not always enjoy much popularity, for
-they can be hard taskmasters.
-
-They are not good at clerical tasks and are impatient with routine
-details.  They prefer to work quietly, without interruption, and
-often alone.  If an organization is to use the talents of an INTP
-appropriately, the INTP must be given an efficient support staff
-who can capture ideas as they emerge and before the INTP loses
-interest and turns to another idea.
-
-INTPs take their mating relationship seriously and usually are
-faithful and devoted - albeit preoccupied at times.  They are not
-likely to welcome constant social activity or disorganization in
-the home.
-
-In all probability, the mate of an INTP will initiate and manage
-the social life.  If left to his or her own devices, the INTP mate
-will retreat into the world of books and emerge only when physical
-needs become imperative.
-
-INTPs are, however, willing, compliant, and easy to live with,
-although somewhat forgetful of appointments, anniversaries, and the
-rituals of daily living - unless reminded.  They may have
-difficulty expressing their emotions verbally, and the mate of an
-INTP may believe that he/she is somewhat taken for granted.
-
-As a parent, the INTP is devoted; they enjoy children and are
-serious about their upbringing.  The home of an INTP parent is
-usually calm, low-key in discipline, but well run and ordered.
-
-INTPs deal with the environment primarily through intuition, and
-their strongest quality, the thinking function, remains relatively
-hidden except in close associations.  Therefore, INTPs are often
-misunderstood, seen as difficult to know, and seldom perceived at
-their true level of competency.
-
-They are inclined to be shy except with close friends, and their
-reserve is difficult to penetrate.  They are very adaptable until
-one of their principles is violated.  Then INTPs are not adaptable
-at all!
-
-They may have difficulty in being understood by others because they
-tend to think in a complicated fashion and want to be precise,
-never redundant in their communications.
-
-Because their feeling qualities may be underdeveloped, they may be
-insensitive to the wants and wishes of others, often quiet unaware
-of the existence of these wants and wishes.
diff --git a/xtrn/smm/mb-intro.asc b/xtrn/smm/mb-intro.asc
deleted file mode 100644
index bdd60da67d3464895750139400e8d345bc9425f1..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-intro.asc
+++ /dev/null
@@ -1,18 +0,0 @@
-nyhThe Myers-Briggs Personality Test nc
-
-The test you are about to take is titled, "hThe Keirsey Temperament Sorternc".
-
-There are no "right" or "wrong" answers to the questions in this inventory.
-Your answers will help show how you like to look at things and how you like to
-go about deciding things.  Knowing your own preferences and learning about
-other people's can help you understand where your special strengths are, what
-kind of work you might enjoy and be successful doing, and how people with
-different preferences can relate to each other and be valuable to society.
- 
-Read each question carefully and indicate your answer by typing 'A', 'B' or
-'C' for cannot decide.
-
-Do not think too long about any question.
-
-The test consists of 70 questions.
-
diff --git a/xtrn/smm/mb-isfj.asc b/xtrn/smm/mb-isfj.asc
deleted file mode 100644
index c59d1d4a1930ac18c7ee6a63731e95fd0fe8c72c..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-isfj.asc
+++ /dev/null
@@ -1,116 +0,0 @@
-ISFJs in short:
-
-Quiet, friendly, responsible and conscientious.  Work devotedly to
-meet their obligations.  Lend stability to any project or group.
-Thorough, painstaking, accurate.  May need time to master technical
-subjects, as their interests are usually not technical.  Patient
-with detail and routine.  Loyal, considerate, concerned with how
-other people feel.
-
-About 6% of the population.
-
-Details about ISFJs:
-
-Six out of every hundred people are ISFJs.  Here the primary is to
-be of service and to minister to individual needs.  ISFJs carry a
-sense of history, a sense of continuity with past events and
-relationships.  Traditions and the conservation of resources are
-highly valued.
-
-The least hedonistic of all types, ISFJs believe work is good, play
-must be earned.  ISFJs are willing to work long, long hours.  When
-they undertake a task, it will be completed if at all humanly
-possible.
-
-Adhering to an established way of doing things and doing them well
-is valued and respected.  The efficiency and effectiveness of an
-established procedure is not often questioned.  Procedures dictated
-by handbooks are law.  If others violate or ignore these standard
-operating procedures, ISFJs are annoyed and irritated, although
-they may not always display this reaction.  Usually, such
-irritation is turned inward and may be experienced as fatigue and
-muscle tension.
-
-ISFJs are super-dependable and seldom are happy working in
-situations where rules are constantly changing.  Their major need
-to be of service to others leads them into occupations such as
-nursing, teaching, secretarial work, medical practice (especially
-general practice), librarian work, and middle-management
-administrative jobs.
-
-They relate well to people who need them, for example, the sick,
-the ignorant, students, and the "boss."  Much satisfaction comes to
-them when they are taking care of the needs of another and they
-render the service gently and helpfully.  When the recipient is no
-longer in need, the relationship may change its character, the ISFJ
-becoming disinterested.
-
-They enjoy assisting the downtrodden and can handle better than
-other types servility of others.  If a situation calls for such
-behavior on their part, they will show "due respect."
-
-ISFJs have an extraordinary sense of responsibility and an
-outstanding talent for executing routines which call for repeated,
-sequential procedures; for example, ISFJs make extraordinary
-secretaries, highly efficient nurses, and dedicated teachers.
-Speculation and theory do not intrigue ISFJs, who would rather
-leave the less practical matters to others while remaining
-themselves practical and down-to-earth.
-
-ISFJs tend to be devoted and loyal to a boss and tend to identify
-personally rather than institutionally.  They expect others,
-including the boss, to follow procedures and are distressed and
-embarrassed when people do not behave as they are supposed to
-behave.
-
-ISFJs often seem to feel personally responsible for seeing to it
-that people in an institution or business carry out established
-rules and routines.  They often are aware of status given by
-titles, environment, offices, and the like and can use this to
-advantage.
-
-They are aware of the value of material resources and abhor the
-squandering or misuse of these resources.  To save, to put
-something aside against an unpredictable future, to prepare for
-emergencies - these are important actions.
-
-ISFJs may experience some discomfort when placed in positions of
-authority over others and may tend to try to do everything
-themselves rather than insist that others do their jobs.  As a
-result, ISFJs are frequently overworked.
-
-ISFJs are devoted to mate and family and usually are excellent
-homemakers.  The home of an ISFJ is likely to be well kept inside
-and out.  Interior and exterior are meticulously maintained and
-appointed in the traditional manner.
-
-As a parent, the ISFJ expects children to conform to the rules of
-society and has a feeling of personal responsibility to see to it
-that these rules are honored.
-
-An ISFJ is apt to find the putting on of airs as offensive and
-tends to prefer modest, quiet friends rather than more boisterous
-ones.  For the ISFJ, people should behave according to their
-position in life, and the ISFJ may be annoyed by others who act
-either above or below their social or economic station.
-
-The ISFJ female often displays a flair for making the interior of
-the home attractive in a time-honored style, provides attractive,
-nourishing meals, and maintains the environment in a neat and
-orderly state.  To the ISFJ male and female, the home territory is
-important to own and to preserve.
-
-While ISFJs are super-dependable, they may be fascinated by and
-attracted to the irresponsible, the lush, the glutton.  Many ISFJs
-marry alcoholics and then proceed to conduct a rescue-rejection
-game without end, with the rescuing phase taking the guise of an
-attempt to reform.  Occasionally an ISFJ mother may reveal a
-tendency to find humor in the "waywardness" of a son, while raising
-her daughters to respect traditions and to do the Right Thing at
-the Right Time - always.
-
-ISFJs are frequently misunderstood and undervalued.  Their
-contributions often are taken for granted, and the ISFJ as well is
-often taken for granted.  This can cause an ISFJ to harbor feelings
-of resentment, and this bottled up emotion can gnaw inwardly,
-causing the ISFJ much undeserved suffering.
diff --git a/xtrn/smm/mb-isfp.asc b/xtrn/smm/mb-isfp.asc
deleted file mode 100644
index 4b9b4d322b01c9f64fde08c362edddc48c7c3784..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-isfp.asc
+++ /dev/null
@@ -1,166 +0,0 @@
-ISFPs in short:
-
-Retiring, quietly friendly, sensitive, kind, modest about their
-abilities.  Shun disagreements, do not force their opinions or
-values on others.  Usually do not care to lead but are often loyal
-followers.  Often relaxed about getting things done, because they
-enjoy the present moment and do not want to spoil it by undue haste
-or exertion.
-
-About 5% of the population.
-
-Details about ISFPs:
-
-Although all SPs (Sensuous Performers) are artisans in their
-nature, they usually do not pursue their artistry with the same
-devotion and adornment as the ISFP.  For whatever reason, the ISFP
-seems more inclined to the "fine arts" than the other SPs; so when
-an especially gifted composer, painter, or dancer shows up, he or
-she, more frequently than not, possesses the character of an ISFP.
-Beethoven, Toscanini, Rembrandt, and Nijinski, as shown by
-typohistorical research, were clear-cut ISFPs.
-
-But the ISFP temperament is very difficult to observe, even in the
-great artists, and so ISFP is probably the most misunderstood of
-all the types.
-
-A major source of misunderstanding is the tendency of ISFPs not to
-express themselves directly, but through action.  If they find a
-medium of expression, some art form, then the character is
-expressed in some degree in the medium.  If not, it simply doesn't
-come out, and no one knows them, this social reticence making the
-character all but invisible.
-
-Of course, in those rare cases where remarkable skill is achieved,
-such as in the virtuoso, ISFPs become celebrities, but their nature
-is still far from visible.  Harpo Marx, a brilliant comedic actor,
-may well be seen as a prototype, in his simultaneous celebrity and
-mute invisibility.
-
-On close observation, these relatively infrequent SPs (5 percent of
-the population is ISFP, as compared to 15 percent ESFP) are just as
-hedonistic and impulsive as the other SPs.  Here is no NF search
-for significance, nor for that matter any fascination with science
-(NT) or commerce (SJ).
-
-ISFPs live Epicurean lives in the here and now, and as gracefully
-as possible.  They do not plan and prepare.  Submergence in their
-artistry is not preparation for something later; rather they
-experience intensely, now.  ISFPs do not wait, for to wait is to
-see their impulse wither and die; they want and value their
-impulses and see them as the center of their lives.
-
-Nor are ISFPs devoted or committed to artful play; rather they are
-caught, as by a magnet or a whirlwind.  So then the long hours of
-"practice" the virtuoso "gives" to artistry is not practice at all
-and it is not given; it is doing and it is taken from the (willing)
-ISFP by the performance itself.  The act is ISFP's master, not the
-reverse, so we must abandon any notion of ISFPs as careful and
-devoted planners and of dutiful preparation and rehearsal.  They
-paint, or sing, or toot, or dance, or run, or skate, or pot, or
-whatever, simply because must: the mountain is climbed 'because it
-is there'.
-
-Because the ISFP is always caught up, so to speak, in whatever
-actions are underway, rather than practicing toward some distant
-goal, there is no question of the ISFP noticing fatigue, pain, or
-danger.  They are usually quite oblivious to the accompaniments of
-many of their favorite activities.  It is not that ISFPs are inured
-to them as much as it is that, wholly engaged by an action, they
-simply do not notice them.  In this ISFP is similar to other SPs
-and different from all other types.
-
-ISFP, like other SPs, has a special kind of intelligence.  Please
-recall that intelligence is defined in this book as doing things
-well under varying circumstances.  This particular category of
-intelligence might be called "artisan concretized."  Such talent
-differs from that possessed by NFs, NTs, and SJs (granting of
-course, that they too have their own unique and inherent
-abilities).  This artisan concretization somehow keeps the ISFP
-more closely in touch with the very real.
-
-While the ISTP is attuned to the tool, so to speak, the ISFP is
-attuned to color, line, texture, shading - touch, motion, seeing,
-and hearing in harmony.  The senses of the ISFP seem more keenly
-tuned than those of others.  Rembrandt could almost taste colors so
-great was his discrimination.  Toscanini could hear a single false
-note in the most complex operatic-orchestral score, and Hemingway's
-words tasted and smelled and felt the waves.  This extreme
-concreteness and specificity seems to come naturally to the ISFP
-and is embedded "in the warp and woof of the man's make."
-
-The social side of the ISFP character must not be eclipsed by the
-more spectacular performances some of this group are capable of.
-The ISFP has to be the kindest of all the types with no near
-competitors.  This kindness is unconditional.  Here is sympathy, of
-which we are all capable, carried to its most extreme form.  The
-ISFP is especially sensitive to the pain and suffering of others
-and, like St.  Francis of Assisi, with sympathetic impulsivity
-gives freely to the sufferer.
-
-ISFP is usually not interested in developing facility in speaking,
-writing, or conversation.  Speech, after all, is abstract, not
-concrete, ISFPs preferring to have their fingers on the pulse of
-life.  That pulse must be felt - by touch, in the muscles, in the
-eyes, in the ears.
-
-This insistence on the senses being so closely attuned to reality
-can, in some ISFPs, occasion a breach with language, and language
-becomes a barrier to smooth interpersonal relations.  So ISFPs are
-sometimes seen by others as reserved and private, tending to give
-up rather easily in their attempts to express themselves verbally.
-
-But this reluctant speech is not so much a lack of ability as it is
-disinterest.  Hemingway broke that barrier, a splendid instance of
-an ISFP entering the world of words and making apparent
-inarticulateness into art, changing the face of 20th Century
-literature.
-
-The number of great artisans who, upon investigation, were found
-clearly to have been ISFPs, is truly awesome.  The other SPs seem
-to have contributed far fewer masters to the fine arts.  Gaugin and
-Puccini, both ESTPs, were in this sense exceptional.  Music and the
-dance seems almost the province of ISFP, and surely investigation
-will show many of the great athletes come from this group.
-
-Of course, all ISFPs have not been and need not be artisans in the
-narrow sense of the word.  Art, broadly conceived, is any action
-the next move of which is a free variable, and it is art thus
-conceived that is the forte of SPs in general and the ISFP in
-particular.
-
-Thus ISFPs have a lot of leeway in choice of occupation, especially
-if they do not drop out of school early (most SPs do, since the
-school offers little that is of interest to them or that challenges
-their special brand of intelligence).  It is a sad day indeed when
-the ISFP chooses work wherein the operations are fixed by rule or
-necessity and not free.  To be happy and productive the ISFP must
-choose variable actions and be rewarded for doing them.
-
-Finally, in many ISFPs may be found an instinctive longing for the
-natural, the pastoral, the bucolic.  They are quite at home in the
-wilds, and nature seems to welcome them.  Some have a remarkable
-way with animals, even wild animals, almost as if there were a bond
-of mutual sympathy and trust.  In some instances a similar bond may
-be seen between the ISFP and young children, instant and unstudied.
-
-Perhaps the most important thing to understand about ISFPs is that
-they are SPs, with much in common with ESFPs especially, often
-resembling ISTPs, and even sharing some traits with the seemingly
-very different ESTP.
-
-To summarize this commonality with other SPs, ISFPs may be seen as
-optimistic and cheerful; egalitarian, fraternal, and insubordinate;
-tending to ward off obligation, duty, confinement, and fetters; a
-lover of freedom, easily bored, wanting excitement, risk, chance,
-and tests of luck; uncomplicated in motivation, trusting,
-receptive, generous, and in every sense of the word a spender
-rather than a saver.
-
-ISFPs are misunderstood not only because they are retiring,
-reserved, and even self-effacing, but because the Jungians have
-cast them as "introverted feeling types," and therefore very much
-like the INFPs.  Watch a few thoroughgoing ISFPs and you'll find
-they have very little in common with INFPs.  Other types are
-reminded to guard against the natural tendency to project their own
-traits of character onto the silent ISFP.
diff --git a/xtrn/smm/mb-istj.asc b/xtrn/smm/mb-istj.asc
deleted file mode 100644
index 399af67a1bde56e24327c2d24847a2ff999eba25..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-istj.asc
+++ /dev/null
@@ -1,121 +0,0 @@
-ISTJs in short:
-
-Serious, quiet, earn success by concentration and thoroughness.
-Practical, orderly, matter-of-fact, logical, realistic, and
-dependable.  See to it that everything is well organized.  Take
-responsibility.  Make up their own minds as to what should be
-accomplished and work toward it steadily, regardless of protests or
-distractions.
-
-About 6% of the population.
-
-Details about ISTJs:
-
-ISTJs are characterized by decisiveness in practical affairs, are
-the guardians of time-honored institutions, and, if only one
-adjective could be selected, 'dependable' would best describe this
-type which represents about 6 percent of the general population.
-The word of ISTJs is their bond, and they experience great
-uneasiness by thoughts of a bankrupt nation, state, institution, or
-family.
-
-Whether at home or at work, this type is rather quiet and serious.
-ISTJs are extraordinary persevering and dependable.  The thought of
-dishonoring a contract would appall a person of this type.  When
-they give their word, they give their honor.
-
-ISTJs can be counted on to conserve the resources of the
-institution they serve and bring to their work a practical point of
-view.  They perform their duties without flourish or fanfare;
-therefore, the dedication they bring to their work can go unnoticed
-and unappreciated.
-
-ISTJ's interest in thoroughness, details, justice, practical
-procedures, and smooth flow of personnel and material leads this
-type to occupations where these preferences are useful.
-
-For example, ISTJs make excellent bank examiners, auditors,
-accountants, or tax examiners.  Investments in securities are
-likely to interest this type, particularly investments in blue chip
-securities, ISTJs are not likely to take chances with their own or
-others' money.
-
-ISTJs can handle difficult, detailed figures and make sense of
-them.  They communicate a message of reliability and stability,
-which often makes them excellent supervisors of, for example, a
-ward of a hospital, a library, or a business operation.
-
-They would be capable of handling the duties of a mortician, a
-legal secretary, or a law researcher.  High school teachers of
-business, home economics, physical education, and the physical
-sciences, are ISTJs, as are top-ranking officers of the Women's
-Army Corps.  Often this type seem to have ice in their veins, for
-people fail to see an ISTJ's vulnerability to criticism.
-
-ISTJs are patient with their work and with procedures within an
-institution, although not always patient with the individual goals
-of people in that institution.  ISTJs will see to it that resources
-are delivered when and where they are supposed to be; materiel will
-be in the right place at the right time.  And ISTJs would prefer
-that this be the case with people, too.
-
-As a husband or wife, the ISTJ is a pillar of strength.  Just as
-this type honors business contracts, so do they honor the marriage
-contract.  Loyal and faithful mates, they take responsibilities to
-children and mate seriously, giving lifelong commitment to these.
-'Duty' is a word the ISTJ understands.
-
-The male ISTJ sees himself as the breadwinner of a family, although
-he can accept a working wife - as long as responsibilities to
-children are not shirked.  The male ISTJ's concept of masculinity
-is patriarchal, and both female and male ISTJs make steady,
-dependable partners.  The female ISTJ may abandon the frivolous for
-the sensible and may not always deepen her sensuality.
-
-As parents, ISTJs are consistent in handling children, and the
-rules of family are made clear.  A rebellious, nonconformist child
-may have a difficult time, however, with an ISTJ parent - and vice
-versa.  As a child, the ISTJ is apt to be obedient and a source of
-pleasure to parents and teachers.
-
-Although ISTJs are outstandingly practical and sensible, they can
-marry people who are thoroughly irresponsible, with the marriage
-developing into a relationship more parent-to-child than
-adult-to-adult.
-
-The ISTJ fluctuates from being rescuer to reformer of the wayward
-mate.  The marriage then becomes a lifelong game: On one side,
-there is Irresponsibility, Promise of Reform, Brief Period of
-Reform, and Irresponsibility again;  on the ISTJ's part, the cycle
-is Disapproval, Rescue, Scolding, Forgiveness, Acceptance of
-Promise To Do Better, and on and on.
-
-This pattern often is seen when an ISTJ marries an alcoholic and
-enters a life of care taking punctuated by periods of anger and
-rejection.  Somehow, although ISTJs can accept periodic fickleness
-and selfishness in significant others, they do not see this kind of
-behavior as acceptable in themselves.
-
-ISTJs have a distaste for and distrust of fanciness in speech,
-dress, or home.  The ostentatious is abhorred, and a neat, orderly,
-and functional home and work environment is preferred.  Durability
-of furnishings are of primary concern, esthetics given slim
-consideration.  The clothes of an ISTJ tend to be practical and
-durable rather than in the latest style or luxurious.  "No
-nonsense" in both food and clothes seem characteristic of this type
-who tend not to be attracted by exotic foods, beverages, or places.
-
-The male ISTJ may enjoy stag, men-only parties and use a different
-sort of language when only men are present.  The yearly hunting or
-fishing trip as a male ritual is often a part of recreation for an
-ISTJ.  More than the female, the ISTJ male is apt to be involved in
-community service organizations that transmit traditional values to
-the young, such as Boy Scouting.  They understand and appreciate
-the contributions these groups make in preserving the national
-heritage.
-
-Along with the SJs, the ISTJ takes particular delight in festive
-occasions held in the context of rituals, for example, weddings,
-holiday feasts, and birthdays.  At work, the ISTJ is apt to see the
-holiday office party as a necessary nuisance and would be likely to
-participate and enjoy these events.
diff --git a/xtrn/smm/mb-istp.asc b/xtrn/smm/mb-istp.asc
deleted file mode 100644
index 6341a59e448c4715865140cc49099481e64b4b54..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-istp.asc
+++ /dev/null
@@ -1,191 +0,0 @@
-ISTPs in short:
-
-Cool-onlookers - quiet, reserved, observing and analyzing life with
-detached curiosity and unexpected flashes of original humor.
-Usually interested in impersonal principles, cause and effect, how
-and why mechanical things work.  Exert themselves no more than they
-think necessary, because any waste of energy would be inefficient.
-
-About 13% of the population.
-
-Details about ISTPs:
-
-Just as impulsive as other SPs, the ISTP's life is artful action -
-and action is end in itself.  Action for the ISTP is more
-gratifying if it is born of impulse rather than purpose.  If the
-action is in the service of an end or aim, let the aim look out for
-itself; it cannot be allowed to influence execution.  The act is
-self-directed, self-leading, containing its own imperatives which
-cannot be suborned to mere rules, regulations, or laws.
-
-ISTPs are egalitarian and can be fiercely loyal to "brothers." They
-can also be fiercely insubordinate seeing hierarchy and authority
-as unnecessary and even superfluous.  It is not so much a matter of
-going against regulations as it is simply ignoring them.
-
-The ISTP must do his or her own thing, free to vary each next move.
-And ISTPs are, or want to be, proud of their ability to make the
-next move skillfully.
-
-ISTPs are often fearless, risking themselves more than other types,
-despite (even frequent) injury.  Of all the types, ISTPs are most
-likely to pit themselves, or their technique, against chance, odds,
-or fate.  They thrive on excitement; they crave some excitement
-each day, in the form of fast motion - racing, sky diving, or
-surfing, for instance.  This hunger for action makes them much more
-subject to boredom than any other type, their urge driving them to
-a faster pace.  Strangely, however, they are not bored while doing
-their thing, even though there may be long stretches when nothing
-happens, as during travel, surfing, hunting, or fishing.
-
-The ISTP nature is most easily seen in their mastery of tools,
-tools of any kind, from microscopic drill to supersonic jet.  From
-an early age, they are drawn to tools as to a magnet; they must
-manipulate them, and tools fall into their hands demanding use.
-Many pilots knew by the age of five that they were going to be
-pilots.
-
-ISTPs tend to take up activities that allow them to use tools;
-driving, steering, operating.  And if given a tool, whether scalpel
-or earth mover, is operated with a precision that defies belief,
-that operator is likely an ISTP.  Others use tools, of course, but
-not with the virtuosity of the ISTP.
-
-Indeed, we must call ISTP's the tool artisans, for they above all
-others command the tool and bend it to their impulse.  But again,
-ISTPs - personified in Michaelangelo and Leonardo - work (or
-better, play) with their tools on personal impulse and not on
-schedule.  If an externally imposed schedule coincides with
-impulse, fine; if not, so much the worse for the schedule.
-
-One tool especially attractive to the ISTP is the weapon.  Should
-ISTPs turn against society (for whatever reason), they wield their
-weapons with lethal genius to support their rejection.  The hit man
-of today, the gunslinger of the American West, and the duelist of
-18th Century Europe, may be seen as virtuosos of precision
-homicide.
-
-Hit man, gunslinger, and duelist alike took pride in their prowess.
-Fortunately, they face their own kind in battle, the good warriors
-of the land: soldier, marshal, police, intelligence agent.  This is
-not to say that all warriors, good or bad, are ISTPs, or that ISTPs
-are all weapons experts; rather that the weapon virtuoso is more
-frequently ISTP than not.
-
-ISTPs also play on impulse, taking off at any time just because
-they "feel like it."  (We are advised not to try to stop the ISTP
-who "feels like" doing something.)  The neurosurgeon does crop
-dusting on the side and rides a motorcycle to the airport, and the
-financier goes on a hunting trip in the middle of an audit (i.e.,
-SJ scrutiny).  There can be no end to the ways ISTPs seek thrills
-in play.
-
-Although they may have the appearance of loners in their work, they
-nonetheless hang around their own kind in play.  The climbers,
-racers, flyers, hunters, and in general, movers flock together. The
-companionship is mediated through the tool, and conversation is
-sparse and terse.
-
-Like the ISFPs, ISTPs communicate through action, and show little
-interest in developing verbal skills.  Indeed, this lack of
-interest in communication may be mistaken for what well meaning but
-misguided medics and educators call "learning disability" or
-"dyslexia," both preposterous notions when meant as explanations.
-Let ISFPs get near a tool of any complexity and power and see how
-fast they pass up everybody in 'learning' to use it and how precise
-their 'lexicon' in talking of its features.
-
-Despite their egalitarianism, insubordination, and love of freedom,
-they can be leaders, even great ones.  But they must be "up front,"
-sword in hand, leading the charge.  That is to say, ISTPs can be
-very successful as battle leaders, for instance, no matter how
-large or small the force under their command.  Their supreme
-realism, timing, and sense of expediency allows them to seize the
-moment and fully exploit whatever resources can be gotten (theirs
-or others) and capitalize on deficits and mistakes of their
-opponent.
-
-Theirs is an expediency or exploitative leadership, based on a
-special kind of intelligence which may be called artistic
-concreteness.  Yes, for the ISTP battle leader, combat is an art,
-an intellectual game, not in the sense of strategy (that is for
-NTs), but rather using whatever is at hand to defeat the other with
-the least injury.
-
-Battle leaders are duellists.  Patton was such a leader, and we
-must credit Marshall (an NTJ strategist) for seeing beneath that
-flamboyant, impulsive, insubordinate, and reckless exterior a
-peerless warrior.  The same credit goes to Grant (another NTJ) for
-selecting Sheridan (STP), and to Hitler (ENFJ) for selecting Rommel
-(ISTP).  Patton, Sheridan, and Rommel were cut from the same cloth
-and showed the same artistic espionage and rapier-like tactics.
-
-Glory is a pre-20th Century concept better understood by the ISTP
-than by others.  Or at least the ISTP is more interested in it than
-most others.  In battle there is glory, for it is in battle that
-one can exercise one's lethal skills with positive sanction.
-
-The Seven Samurai were glorified and so have been duellists down
-through the ages.  Foss, Boyington, Fonck, and von Richtoffen, all
-virtuosos of the winged machine gun, are still glorified heroes.
-But there are hundreds of warriors just like them in nature.  One
-can test one's mettle in lethal duel, there's glory in it, as the
-film The Great Waldo Pepper showed most poetically.
-
-The education and intelligence of the ISTP is worth special
-comment.  Possessed of artisan intelligence, ISTP is not in the
-least interested in the clerical, interpretive, and "science"
-curricula that abound in the 20th Century school.  The other SPs,
-equally bored by the school, will at least act as if they're trying
-to learn, but not ISTP.  ISTP will stare coldly into the eyes of
-the teacher and not even say no.  No amount of cajoling, bribing,
-rewarding, punishing, or threat will get them to do their school
-work.
-
-School work, quite apart from being irrelevant to the talents of
-SPs, is, after all, mere preparation for something the ISTPs figure
-they're never going to do anyway.  SPs do not wish to prepare - for
-anything - and ISTPs are careful to make this clear to their
-would-be instructors.
-
-What is there to 'do', 'now', that is 'worthwhile'?  ISTP will not
-sit still (literally) for the trivial fare dished out
-(sanctimoniously, in the eyes of the ISTP).  Most seem to agree
-that ISTPs "should" do their school work.  But why? The arguments
-are piddling and incoherent, warranting the scorn they get from the
-unshakable ISTP.
-
-ISTPs are not "minimally brain damaged," or "hyperactive," or
-"dyslexic"; they are active, and they are stubbornly insistent upon
-getting to do, in school, some things that allow them to test their
-intelligence and their mettle.  Name-calling and pill-pushing won't
-change them, other than destroying their self confidence and
-perhaps creating a stimulant addict now and then.  Give them a
-tool-centered curriculum and watch their speed.
-
-Behaviorally the ISTP is more like the ESTP than any other type,
-and the older they get, the greater the resemblance.  When young,
-ISTPs may look very much like ISFPs, but as their confidence and
-pride increase this resemblance recedes.  Jungians think ISTPs are
-just like INTPs with only minor differences, but this is based on
-the definition of ISTPs as "introverted thinking types."
-
-INTPs are logicians, philologists, and architects in the way they
-think, but ISTPs are completely disinterested in these pursuits.
-Even a cursory observation of a few clear-cut ISTPs will show how
-striking the contrast, and how trivial the resemblance.
-
-Still, the most important thing about the ISTPs is their
-commonality with other SPs.  We might think that there would be
-some resemblance to the ISTJ, having as they do, "IST" in common.
-but no, their behavior is antithetical in almost every dimension of
-comparison.  One is pessimistic while the other optimistic; one is
-parental, the other, fraternal; one saves, the other spends; one
-believes in rules, the other is instinctual insubordinate and
-recalcitrant to rules; and so on.
-
-ISTPs have infinitely more in common with the very different ESFP
-than they do with any NT or SJ; besides the above, their mood is
-one of good cheer, they are loyal to their equals, they want no
-obligations, duties, or confining promises, are uncomplicated in
-their desires, and are trusting, receptive, and generous.
diff --git a/xtrn/smm/mb-j.asc b/xtrn/smm/mb-j.asc
deleted file mode 100644
index 92c1cb6cbfb6de7c2ba943db5b7873a9b221b40f..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-j.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-The Judgement type tends toward planning, goal setting, deciding, and
-getting-things-done. Once the J makes a decision he tends to be fixed and
-inflexible. The J finds himself always waiting for others - who are always
-late; thinks that if everyone would do what they are supposed to, the world
-would be a better place, has a personal schedule for the day, and gets 
-frustrated when the schedule is interrupted, doesn't like surprises, keeps
-lists, thrives on order, likes to finish-the-job.
-J creates an environment that is structured, scheduled, ordered, planned,
-and controlled; is decisive, deliberate.
-J's plan their work and work their plan.
-The population is equally divided between Js and Ps.
diff --git a/xtrn/smm/mb-n.asc b/xtrn/smm/mb-n.asc
deleted file mode 100644
index 3347e8fb90085b5856e368ae99d31c076274ae2d..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-n.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-The iNtuitive type gets his information from within himself, tends to favor
-hunches, bases his decisions on possibilities, is innovative, imaginative. 
-An N tends to think about several things at once, finds future possibilities
-more intriguing than frightening, thinks 'boring details' is a redundancy,
-believes time is relative, likes to figure out how things work, is prone to
-puns & word games, thinks in terms of general directions rather than specific
-steps. About 25% of the population are type N.
diff --git a/xtrn/smm/mb-nf.asc b/xtrn/smm/mb-nf.asc
deleted file mode 100644
index 988b822688f39d23feb96c153e37df7762741872..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-nf.asc
+++ /dev/null
@@ -1,22 +0,0 @@
-The purpose of life for an NF is to find his purpose in life. NF is self in
-search of self & has difficulty understanding what seem to be the false goals
-of others. Search for identity, meaning, & actualization. Believes his real
-self is somewhat less than what it should be. Desires to be genuine,
-transparent; without masks or game-playing. Life is a drama; each encounter
-is pregnant with becoming. Very sensitive to non-verbal communication.
-Relationships can fall into a pattern of generous investment of energy followed
-by disappointment in what-could-have-been. Tend to be writers, poets, musicians
-teachers, counselors, actors; excellent communicators; gift of helping people 
-grow; strong empathy. Good at appearing to be what the beholder wants to see.
-Seeks greater intensity in relationships, seeks elusive intimacy. At once both
-the audience and the actor. Often has difficulty putting limits on time & 
-energy spent at work. Seeks perfection; and is often disappointed. Tends to
-romanticize experience. Hunger for relationships.
-NF strengths are a capacity for working with people & drawing out their best,
-being articulate & persuasive, a strong desire to help others, and the ability
-to affirm others freely & easily.
-As a manager, NF has difficulty being firm, tends to give workers too much
-leeway. As mate, NF has a deep need to give & receive affection and avoid 
-conflict. As a teacher, NF makes each student feel important & cared about.
-Desire to please & comfortable with theory makes NF an excellent student.
-About 12% of the population.
diff --git a/xtrn/smm/mb-nt.asc b/xtrn/smm/mb-nt.asc
deleted file mode 100644
index 0b6ebfbf443cf8cabaf91305b0be804a4e9a5ac7..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-nt.asc
+++ /dev/null
@@ -1,32 +0,0 @@
-NT often feel like aliens in a world of SPs and SJs. The NT has a hunger for
-understanding, control & power; not over people as much as over things. 
-Basic drives are for competence, abilities, skills, ingenuity. Loves doing
-things well. Addicted to storing up wisdom & acquiring intelligence. Has
-more interest in figuring things out than actually doing them. Self critical
-and self doubt to the point of paralysis. Perfectionist, tense, compulsive,
-fear-of-failure. Doesn't accept the conventional wisdom. Tries to lift others
-to his own exaggerated levels of competence and can be arrogant with those
-who choose not to see the complexity of his chosen area. His arrogance causes
-others to withhold their reactions for fear of being labeled 'stupid' and
-isolates him from the people around him. His speech tends to be terse, 
-compact, logical, precise. Wastes few words. Doesn't like to state the obvious.
-Passion for knowing. Tends to seek complicated & exacting profession; engineer,
-mathematics, philosophy. Enjoys building systems, developing models, exploring
-ideas. Tends to be straightforward in dealing with others; others find him
-cold, remote, detached & enigmatic. Vulnerable to all-work-and-no-play.
-Enjoys playing with words, paradox, bad puns. Tends to focus on the future;
-the past is dead & gone. Is humiliated when others witness his errors.
-Not sensitive to emotions of others, capable of biting sarcasm.
-NT strengths are the ability to see the big picture, a talent for systems
-planning, insight into the internal logic & principles of systems, and the
-ability to speak & write clearly.
-As managers, NT is the strategic planner; as mate NT is more interested in
-intellectualizing feeling & emotions than in experiencing them; As parent
-NT provides a role model that is impossible to live up to; as teacher, NT
-clarity & precision can be both exciting & intimidating to students, but 
-they can bore their students by working a point to death; in finances, NT
-probably has a plan, but at the same time is comfortable with high risk
-ventures.
-NT chooses clothes for comfort & utility, doesn't pay much attention to
-fashion.
-About 12% of the population.
diff --git a/xtrn/smm/mb-p.asc b/xtrn/smm/mb-p.asc
deleted file mode 100644
index 2cccc090a00033d51af214107930556be35cbcf3..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-p.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-The Perceptive type tends toward plan-as-you-go, flexibility, open-ended
-tentative agreements, and letting-life-unfold. P is easily distracted, loves
-to explore the unknown, doesn't plan tasks, depends on last-minute-spurts to
-meet deadlines, doesn't believe neatness counts, enjoys creativity, trys to turn
-work into play, doesn't like to be pinned down, tends toward non-judgemental
-statements. 'P' must generate alternatives for everything.
-Likes to keep his options open, but not always - it all depends.
-
-The population is equally divided between Js and Ps.
diff --git a/xtrn/smm/mb-s.asc b/xtrn/smm/mb-s.asc
deleted file mode 100644
index ef399f5634c69606dcc546f40685a54234a7538c..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-s.asc
+++ /dev/null
@@ -1,11 +0,0 @@
-The Sensor gets his information from external events; tends to be practical,
-base his decisions on experience, is down to earth, and notices details.
-An S prefers specific answers to specific questions, would rather DO something
-rather than think about it, likes to concentrate on the task at hand, likes
-tasks with tangible results, prefers facts to theories, thinks 'fantasy' is
-a dirty word, prefers clear/complete plans to vague guidelines, are very
-literal in use of words, very much a 'show me' person. An S may resist
-taking this test & quickly get bored with it because it is not practical
-and doesn't have an immediate application. S will take a long time to take
-this test, reading every question carefully.
-About 75% of the population are type S.
diff --git a/xtrn/smm/mb-sj.asc b/xtrn/smm/mb-sj.asc
deleted file mode 100644
index 78fc2553399dba0e0faa9a13f6739138c38a5405..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-sj.asc
+++ /dev/null
@@ -1,16 +0,0 @@
-The SJ exists to belong and be useful to his social group. A giver, provider,
-caretaker, parent; feels uncomfortable in a dependent role. Duty oriented,
-desires to serve, very aware of what-should-be-done. Is comfortable with
-obligations. Has a strong work ethic & desire for hierarchy & rule & order.
-Pessimistic, spends much energy in preparing for the future. Tradition &
-heritage are important. Has a keen sense for detecting ingratitude & lack of
-appreciation. Drawn to institutions; banking, teaching, government, service.
-Strong desire to conserve & store-up-for-the-future. Obligation to serve
-often overrides the fact that he is already overburdened. Backbone of society.
-SJ strengths are administration, dependability, ability to take charge.
-Home & hearth are cornerstones of SJ marriages, ritual & tradition is 
-important. SJ makes very clear who is the parent & what is expected of 
-children. As teacher SJ places high importance on neatness & punctuality.
-SJ's are the money - and moneyed - people of the world. Prefers classic,
-durable clothes. 60% of public school teachers are SJ.
-About 38% of the population.
diff --git a/xtrn/smm/mb-sp.asc b/xtrn/smm/mb-sp.asc
deleted file mode 100644
index 76882d4822516e5c46a7b13af950fcb6b25aca05..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-sp.asc
+++ /dev/null
@@ -1,20 +0,0 @@
-The SP must be free & will not be tied down with responsibility. Eat, drink &
-be merry, for tomorrow we die. In Aesop's fable of the ant & the grasshopper,
-the SP is the grasshopper. SP has the urge for impulsive action-for-right-now 
-rather than practicing for some future event. Waiting is the same as death.
-Likes diversity & trying new things. Easy come easy go. Not goal oriented.
-Yet the SP shows long endurance; He wouldn't climb a mountain to get to the
-top, but for the thrill of every moment. Gravitates toward jobs where action
-is involved. Tends to be fraternal & loyal to his equals. Master of the grand
-gesture, but not of the small important acts or words. Capable of abruptly
-abandoning his path & striking out in a completely different direction.
-Optimistic, libertarian, social equality. Compulsion to perform.
-SP strengths are practicality, adept problem solving skills, resourcefulness.
-As manager, SP is excellent in a crisis - and is not above creating a crisis
-to give him a sense of purpose. As mate, enjoys intensity & a thrill a minute.
-As teachers, are best at practical-vocational, tend to shy away from 
-theoretical or abstract. Not good at lesson plans. Dealing with money, SP is
-the original high roller. Not good at academics, poor spellers, least likely
-of all the types to receive a college degree.
-Chooses clothes for IMPACT.
-About 38% of the population.
diff --git a/xtrn/smm/mb-t.asc b/xtrn/smm/mb-t.asc
deleted file mode 100644
index b6d430d8b14021b716077a1097b23fc8210ec6cd..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-t.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-The Thinker tends toward logic, reason, laws, policy, principals, justice,
-and impersonal decisions. The T tends to favor critical analysis, stay calm
-& objective when others panic, enjoy proving their point, would rather be
-right than liked, remember facts better than faces.
-The thinker thinks the feeler is fuzzybrained.
-The population is equally divided between Ts and Fs, although more men tend
-to be Thinkers & more women tend to be Feelers.
diff --git a/xtrn/smm/mb-tj.asc b/xtrn/smm/mb-tj.asc
deleted file mode 100644
index a5c3dbeca2f99c0b95b65a0702a632ad7cb587b5..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-tj.asc
+++ /dev/null
@@ -1 +0,0 @@
-60 % of the world's managers are TJ.
diff --git a/xtrn/smm/mb-type.asc b/xtrn/smm/mb-type.asc
deleted file mode 100644
index efd263b45fe7c01c4eea68ee4a6e40cfa1efe6d4..0000000000000000000000000000000000000000
--- a/xtrn/smm/mb-type.asc
+++ /dev/null
@@ -1,20 +0,0 @@
-yhMyers-Briggs Personality Types:nc
-
-The first letter of the personality type indicates how you are energized
-(hEncxtroversion or hIncntroversion).
-
-The second letter of the personality type indicates how you obtain information
-for your decisions (hSncensation or ihNnctuition).
-
-The third letter of the personality type measures your preference to operate
-from your head to your heart (hTnchinking or hFnceeling).
-
-The fourth letter of the personality type indicates how you like to order your
-life (hJncudging or hPncerception).
-
-An asterisk (h*nc) in any of your letter positions indicates you are equally
-divided between the two personality tendancies.
-
-From here you can read definitions of letter combinations (types):
-hEnc, hInc, hSnc, hNnc, hTnc, hFnc, hJnc, hPnc, hTJnc, hSPnc, hSJnc, hNTnc, hNFnc, hENFPnc, hENFJnc, hENTPnc, hENTJnc, hESFPnc, hESFJnc,
-hESTPnc, hESTJnc, hINFPnc, hINFJnc, hINTPnc, hINTJnc, hISFPnc, hISFJnc, hISTPnc, and hISTJnc.
diff --git a/xtrn/smm/mb-type.que b/xtrn/smm/mb-type.que
deleted file mode 100644
index 987d79d569596870372afd7bab47c819ab32259e..0000000000000000000000000000000000000000
Binary files a/xtrn/smm/mb-type.que and /dev/null differ
diff --git a/xtrn/smm/purity-1.asc b/xtrn/smm/purity-1.asc
deleted file mode 100644
index 773f53d0a268533ae5d004bc9ae8940b4dc8aad3..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-1.asc
+++ /dev/null
@@ -1,16 +0,0 @@
-Section 1:  Platonic Relations.  19 Questions.
-
-For this section, if you are mostly a:
-
-         - heterosexual, then your partner in deed, often referred to
-                         by the word "someone" or "partner", is to be someone
-                         of the OPPOSITE gender.
-
-         - homosexual, then your partner in deed, often referred to by the
-                         word "someone" or "partner", is to be someone of
-                         YOUR OWN gender.
-
-         - 50-50 confirmed bisexual, then your partner in deed, often
-                         referred to by the word "someone" or "partner", is to
-                         be someone of the OPPOSITE gender.
- 
diff --git a/xtrn/smm/purity-2.asc b/xtrn/smm/purity-2.asc
deleted file mode 100644
index b69f67e1b615f499890f2a8a87ef1beca4e19c8d..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-2.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-Section 2:  Auto-erotica and Mono-sexualism.  51 Questions.
-
-     Although this section is termed Auto-erotica and mono-sexualism, the
-     events herein still count even if you are with someone else at the time.
-     It was so named because these activities, like the harp, (and the
-     porcelain goddess) are predominantly solo events.
- 
diff --git a/xtrn/smm/purity-3.asc b/xtrn/smm/purity-3.asc
deleted file mode 100644
index 5c33111569d7280eac84a367aba80fe63c414e57..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-3.asc
+++ /dev/null
@@ -1,2 +0,0 @@
-Section 3:  Legislative Misfits and Other Ethical Matters.  61 Questions.
- 
diff --git a/xtrn/smm/purity-4.asc b/xtrn/smm/purity-4.asc
deleted file mode 100644
index 37289ae749fe509a0af279ca5d89a1ba95f27f36..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-4.asc
+++ /dev/null
@@ -1,2 +0,0 @@
-Section 4:  Drugs.  43 Questions.
- 
diff --git a/xtrn/smm/purity-5.asc b/xtrn/smm/purity-5.asc
deleted file mode 100644
index 14d44dda2ceaa5d8f6d2c288d9d7d740a1ff3818..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-5.asc
+++ /dev/null
@@ -1,16 +0,0 @@
-Section 5:  Non Platonic Relations.  63 Questions.
-
-For this section, it you are mostly a:
-
-         - heterosexual, then your partner in deed, often referred to by
-                         the word "someone" or "partner", is someone of the
-                         OPPOSITE gender.
-
-         - homosexual, then your partner in deed, often referred to by the
-                         word "someone" or "partner", is to be someone of
-                         your OWN gender.
-
-         - 50-50 confirmed bisexual, then your partner in deed, often referred
-                         to by the word "someone" or "partner", is to be
-                         someone of the OPPOSITE gender.
- 
diff --git a/xtrn/smm/purity-6.asc b/xtrn/smm/purity-6.asc
deleted file mode 100644
index 3531a8ef778a37285eadbc69629b43a49bd368d3..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-6.asc
+++ /dev/null
@@ -1,18 +0,0 @@
-Section 6:  Non Primary Choice Relations.  39 questions.
-
-      This section of the test deals with whether you have done things with
-      people whom you may not be altogether comfortable, therefore in this
-      section of the test, if you are mostly a:
-
-         - heterosexual, then your partner in deed, often referred to by the
-                         word "someone" or "partner", is to be someone of your
-                         OWN gender.
-
-         - homosexual, then your partner in deed, often referred to by the
-                         word "someone" or "partner", is someone of the
-                         OPPOSITE gender.
-
-         - 50-50 confirmed bisexual, then your partner in deed, often
-                         referred to by the word "someone" or "partner", is to
-                         be someone of your OWN gender.
- 
diff --git a/xtrn/smm/purity-7.asc b/xtrn/smm/purity-7.asc
deleted file mode 100644
index 4cf23745bc29143dfd1c9ccc8977cc76b99a5e02..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-7.asc
+++ /dev/null
@@ -1,8 +0,0 @@
-Section 7:  Alternate Choices.  26 questions.
-
-      For any of the questions in this section, a yes answer is in order if it
-      is something that you do as an alternative to other sexual gratifications
-      or as an aid and/or in conjunction with other means of sexual
-      gratification.  In other words, have you done it in a serious basis?
-      Trying it a few times to see what it's like does not count.
- 
diff --git a/xtrn/smm/purity-8.asc b/xtrn/smm/purity-8.asc
deleted file mode 100644
index bad4ef2b31a91350ab10dcbbefd9966e1c76dc6e..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-8.asc
+++ /dev/null
@@ -1,7 +0,0 @@
-Section 8:  Group Sexual Relations.  27 questions.
-
-      This section relates to what you have or have not done.  Accordingly, the
-      group of people of which we are speaking are of both genders.  In
-      questions where groups of people are concerned, there must be at least
-      one person in the group who is of the opposite gender.
- 
diff --git a/xtrn/smm/purity-9.asc b/xtrn/smm/purity-9.asc
deleted file mode 100644
index 85a257e743f874233e8ec6a35211d1d1e8ed1041..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-9.asc
+++ /dev/null
@@ -1,6 +0,0 @@
-Section 9:  Non sentient objects.  62 questions.
-
-      This section measures your kinkiness.  Therefore, the questions apply to
-      actions and events which occurred while you were alone, as well as those
-      which occurred while you were with someone else.
- 
diff --git a/xtrn/smm/purity-a.asc b/xtrn/smm/purity-a.asc
deleted file mode 100644
index 3218f28900d925e24603aaf83b5ac584c7cc0c5d..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-a.asc
+++ /dev/null
@@ -1,5 +0,0 @@
-Section 10:  Locality.  33 questions.
-
-This  section  tries  to  figure  out how many places you have done it. It
-applies only to those situations in which you were with someone else.
- 
diff --git a/xtrn/smm/purity-b.asc b/xtrn/smm/purity-b.asc
deleted file mode 100644
index ad61bbf6c6ad4f79cbc523232493cc16824e89e5..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity-b.asc
+++ /dev/null
@@ -1,2 +0,0 @@
-Section 11:  Style.  76 questions.
- 
diff --git a/xtrn/smm/purity.100 b/xtrn/smm/purity.100
deleted file mode 100644
index c97b56bea11a7bd40fdf3adfd7c99c4de4744912..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity.100
+++ /dev/null
@@ -1,100 +0,0 @@
-Had a date
-Been out on a date past 4 am
-Had a blind date
-Kissed a MOS
-Been french kissed
-Kissed a MOS in the horizontal position
-French kissed three or more MOS's in 24 hours
-Kissed a MOS in the last three months
-Necked for more than 2 hours consecutively
-Slow danced cheek-to-cheek
-Had an alcoholic drink
-Been drunk
-Driven while under the influence of alcohol or drugs
-Had a lapse of memory due to drinking or drugs
-Used alcohol or drugs to lower a MOS's resistance
-Smoked tobacco
-Smoked pot or hashish
-Used a stronger drug
-Taken 4 or more "recreational" drugs within 24 hours
-Read a pornographic book or magazine
-Seen a pornographic movie
-Seen a stripper
-Been arrested
-Been convicted of a crime
-Had an erection/clitoral erection
-Had an orgasm
-Had an orgasm in a dream
-Fondled a MOS's ass
-Caressed a MOS's thigh
-Fondled a breast or had your breast fondled
-Wrestled with a MOS
-Showered, bathed, jacuzzied, or saunaed with a MOS
-Gone coed skinny-dipping
-Gone through the motions of intercourse while fully clothed
-Spent the night in a MOS's room
-Slept in the same bed with a MOS
-Seen a naked post-pubescent MOS
-Been seen naked by a MOS after puberty
-Undressed or been undressed by a MOS
-Kissed a MOS on the breast or been kissed on the breast
-Fondled a MOS's genitals or had your genitals fondled by a MOS
-Had an orgasm due to manipulation by a MOS
-Kissed a MOS on the thigh
-Engaged in cunnilingus
-Engaged in fellatio
-Had sexual intercourse at a parents house while they were home
-Engaged in definitely sexual activity on the first date
-Masturbated
-Masturbated to a picture
-Masturbated with another person in the room
-Watched another person masturbate
-Been caught masturbating
-Simulated intercourse with an inanimate object
-Committed an act of voyeurism
-Committed an act of exhibitionism
-Massaged or been massaged by a MOS
-Unintentionally interrupted a couple in a significant state of undress
-Participated in a tickle orgy, gross out, truth or dare, etc.
-Experimented sexually before puberty
-Purchased contraceptives in a drug store
-Had sexual intercourse
-Had sexual intercourse more than 10 times
-Had sexual intercourse continuously for 1/2 hour
-Had sexual intercourse within the last 3 months
-Had sexual intercourse 3 or more times in 1 night
-Had sexual intercourse in 3 or more positions
-Had sexual intercourse in a car
-Had sexual intercourse using a condom
-Done sixty-nine
-Had sexual intercourse outdoors
-Had sexual intercourse with 3 different people
-Had sexual intercourse with a virgin
-Had sexual intercourse during menstruation
-Had sexual intercourse without using birth control
-Had sexual intercourse with 2 MOSs in 24 hours
-Had sexual intercourse in a public place
-Described a sexual experience to a separate party
-Committed statutory rape
-Been the object of travel or traveled 100 miles or more for sexual activity
-Impregnated a woman or been pregnant
-Arranged or had an abortion
-Displaced a roommate by staying with a MOS for 1 or more nights
-Shacked up with a MOS for a month or more
-Tasted semen
-Been propositioned by a prostitute or pimp
-Accepted
-Had anal intercourse
-Been tested for V.D. due to reasonable suspicion
-Had V.D.
-Picked up a strange MOS for sexual purposes
-Engaged in group sex
-Engaged in sadism or masochism for sexual enjoyment
-Been propositioned by a member of the same sex
-Accepted a proposition by a member of the same sex
-Been masturbated by a member of the same sex
-Been orally stimulated by a member of the same sex
-Committed incest
-Fondled a pre-pubescent MOS
-Engaged in transvestitism for sexual enjoyment
-Committed bestiality
diff --git a/xtrn/smm/purity.500 b/xtrn/smm/purity.500
deleted file mode 100644
index 5f389c7ea827353afce460ace6278b9e0af58297..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity.500
+++ /dev/null
@@ -1,511 +0,0 @@
-*PURITY-1.ASC
-Kissed a friend or stranger as a friendly gesture
-Held hands with someone
-Had a date
-Had a date past 1 a.m.
-Dated someone on a regular basis
-Picked someone up
-Been picked up
-Gone steady
-Slow danced
-Had the symptoms of Russian fingers (rushin' fingers)
-Had the symptoms of Roman hands (roamin' hands)
-Shared a bed with someone without anything steamy happening
-Given a back or neck rub or massage with no ulterior motive
-Used tickling as a pick-up get-to-know-you-better routine
-Directly asked someone if they were a virgin
-Used physical strength as a get-to-know-you-better routine
-Secretly lusted after someone without that person knowing
-Dropped subtle hints to someone hoping they would pick up on it
-Written anonymous 'love letters' to someone
-*PURITY-2.ASC
-Had an arousing dream  (Wet dreams and the like.)
-Been sexually aroused
-Uttered/muttered/yelled/screamed obscenities
-Fantasized about your instructor or teacher
-Fantasized about your lawyer, doctor, nurse, psychiatrist
-Fantasized about someone you know personally but not closely
-Fantasized about anyone and masturbated at the same time
-Read or bought pornographic periodicals
-Ever had a subscription to pornographic periodicals
-Read sexually explicit literature
-Gone skinny dipping alone
-Made obscene phone calls
-Phoned up any recorded phone sex numbers
-Phoned up any live phone sex numbers
-Stuffed your bra or stuffed your pants
-Shaved your genital pubic hair
-Shaved your genital pubic hair on a fairly regular basis
-Colored or bleached your genital pubic hair
-Shaved or shaped your genital pubic hair in a particular design
-Masturbated
-Masturbated at least five times in one twenty-four hour period
-Masturbated on a fairly regular basis of no less than once a week
-Masturbated where you could have been discovered
-Masturbated out in the wilds or in nature
-Masturbated to orgasm
-Masturbated while reading sexually explicit materials
-Masturbated while driving a *moving* land vehicle
-Masturbated while on the phone
-Masturbated while in a bathroom of the opposite sex
-Masturbated while watching an R or X-rated show
-Seen any burlesque show (Rocky Horror counts)
-Been to a peep show
-Been to a private showing of a pornographic movie
-Seen a pornographic movie in a theater
-Walked around in your room/apartment/house/habitation in nude
-Walked around in a public or semi-public area bottomless
-Bought blatant sexual objects
-Owned any erotic art pieces
-Written your own fantasies for masturbatory purposes
-Sculpted erotic/obscene artworks in food
-Eaten any erotic food items  (Chocolate tits, banana dicks)
-Sculpted erotic/obscene artworks in soap, wood, etc
-Made an X- or R-rated snowman or snowwoman
-Tasted your own orgasmic liquids
-Inserted your finger into your rectum
-Used ben-wa balls or anal beads
-Performed oral sex on yourself
-Willingly urinated on your garments while wearing them
-Willingly urinated on any part of your body
-Willingly defecated on your garments while wearing them
-Willingly defecated on yourself
-*PURITY-3.ASC
-Administered a whole Purity Test or in the process
-Taken Purity Tests of any versions more than 5 times
-Lied on any previous Purity Tests
-Exaggerated about any sexual experiences
-Gone to (or escorted someone to) a Planned Parenthood Clinic
-Broken your word, promise, or vow
-Lied to someone at someone else's request
-Lied about your sexual preference in order to avoid a date
-Written graffitti
-Plagiarized
-Shoplifted
-Stolen
-Made out a check that bounced
-Used someone else's credit card without their knowledge
-Committed breaking and entering
-Seen a snuff film
-Read someone else's diary without their knowledge or consent
-Searched someone's room without their knowledge or consent
-Told someone that you loved them when you did not
-Told someone that you loved them just for sex
-Fantasized about someone else while having sex
-Intentionally listened in on other people having sex
-Used alcohol to lower someone else's inhibitions for sex
-Used drugs to lower someone else's inhibitions for sex
-Drugged someone without their knowledge and/or consent
-Forced someone into having intimate physical relations with you
-Had dates with more than one person in the same night
-Gone steady with two or more people at the same time(secret)
-Gone steady with two or more people at the same time(known)
-Urinated on someone else intentionally	(Piss fights!)
-Urinated in object that was not designed for such purpose
-Urinated anywhere other than commonly accepted piss hole
-Urinated from higher than the fifth floor or off a bridge
-Defecated anywhere other accepted shit hole
-Stored any excretia in a refrigerator/oven
-Stored evacuated excretia in your room/apartment
-Entered a bathroom of the opposite sex- unaccompanied
-Mooned or flashed someone from the front
-Farted (audibly) in mixed company
-Streaked/flashed or exposed yourself in public
-Streaked/flashed or exposed yourself at a formal gathering
-Been arrested  (Picture taken and all)
-Received money to have sex or mutual masturbation with someone
-Given money to have sex mutual masturbation with someone
-Thought you might be or might have caused someoneto be pregnant
-Bought a home pregnancy test
-Bought condoms
-Borrowed/stolen/taken birth control devices from someone else
-Had or given someone an unwanted pregnancy
-Lied about being pregnant or about having made someone pregnant
-Had sex while either you or your partner were under age
-Thought you had VD
-Had VD of any sort (VD/STD's/the clap/crabs/herpes/etc.)
-Had an AIDS test due to reasonable suspicion or imagination
-Given a sympathy fuck
-Initiated sex with someone for the sake of sex only
-Willingly committed incest
-Committed adultery
-Bought lingerie/undergarments of the opposite sex
-Stolen the underwear of someone you knew not for joke
-Intentionally taken a stranger's underwear
-*PURITY-4.ASC
-Had an alcoholic drink
-Been intoxicated
-Thrown up from having drunk too much alcohol
-Passed out due to having drunk too much alcohol
-Forgotten events that occurred while you were drunk
-Smoked tobacco	(cigarette/pipe/cigar/hookah)
-Chewed tobacco	(snuff)
-Bought controlled/illicit drugs in violation of the law
-Sold or re-sold controlled/illicit substances
-Taken stimulants
-Taken depressants excluding alcohol
-Inhaled nitrous oxide while not visiting a dentist
-Inhaled anything containing butyl nitrate
-Used a commercial aphrodisiac
-Taken valium
-Smoked marijuana/sensemilia
-Smoked marijuana/sensemilia more than four times
-Eaten marijuana/sensemilia
-Eaten marijuana or sensemilia more than four times
-Taken opiate in any form
-Taken opiate in any form more than twice
-Used cocaine
-Used cocaine more than four times
-Injected any drugs into your body other than medical
-Injected any illegal drug into your body more than twice
-Taken Ecstasy/X
-Taken PCP
-Taken PCP more than twice
-Taken LSD-25, peyote or psilocybin
-Taken LSD/peyote or psilocybin more than twice
-Taken LSD more than six times
-Deliberately injured yourself so as to obtain medication
-Played any games in which drugs were the prize
-Gone to class or work while under the influence of drugs
-Mixed drugs (alcohol counts)
-Sold possessions in order to obtain drugs
-Had sex while under the influence of nitrous
-Had an orgasm while under the influence of nitrous
-Had sex while under the influence of cocaine
-Had sex while under the influence of marijuana/sensemilia
-Had sex while under the influence of Ecstasy/X
-Had sex while under the influence of LSD/peyote or psilocybin
-Had sex while under the influence with a unknowing partner
-*PURITY-5.ASC
-Propositioned someone for necking or petting
-Propositioned someone for sex/oral sex or mutual masturbation
-Pinched or patted someone else's buttocks
-French kissed
-Been kissed below the neck but not including arms or hands
-Kissed someone else below the neck not including arms or hands
-Necked
-Petted above the waist
-Petted below the waist
-Kissed on the first date
-Necked on the first date
-Petted above the waist on the first date
-Petted below the waist on the first date
-Given a hickey
-Received a hickey
-Worn specific clothes for the purpose of hiding hickeys
-Fondled or stroked someone else's clothed legs
-Fondled or stroked someone else's bare legs
-Fondled or stroked someone else's frontal chest/torso region
-Had your frontal chest/torso region fondled or stroked
-Been involved with pelvic thrusting while fully clothed
-Had your fingers licked or sucked
-Had your ear or ear region licked/sucked, or nibbled
-Licked, breathed onto, sucked, or nibbled an ear or ear region
-Licked or sucked someone else's finger(s)
-Fondled someone who was asleep
-Given a back massage with ulterior motives
-Given a back massage that led to something steamier
-Seen someone completely nude when under good light conditions
-Been seen nude by someone else under good lighting conditions
-Been in someone's company while both were completely nude
-Bathed or showered with someone
-Let someone else wash you when you were capable of doing it
-Gone skinny dipping in mixed company
-Been involved with the fondling of a woman's clothed breast
-Been involved with the fondling of a woman's bare breast
-Licked, sucked, or nibbled on someone else's nipple
-Had your nipple licked, sucked, or nibbled upon
-Petted/fondled or otherwise handled someone's covered genitals
-Had your covered genitals petted/fondled or handled
-Petted/fondled or otherwise handled someone's bare genitals
-Had your bare genitals petted/fondled or otherwise handled
-Had an orgasm while petting
-Given your partner an orgasm while petting
-Given finger scratch marks
-Received finger scratch marks
-Drawn blood by scratching during sex
-Drawn blood by biting during sex
-Given or received *scars* from scratches or bites during sex
-Performed oral sex
-Received oral sex
-Swallowed semen, or licked female liquids off of fingers
-Done sixty-nine
-Performed mutual masturbation
-Had sex  (No need for orgasm; penetration counts.)
-Had sex on the first date
-Had sex without the use of birth control devices
-Had sex with a virgin  (Not yourself.)
-Had sex with someone whose name you did not know
-Had sex with someone whose face you never saw
-Had sex with someone with a 20 year age difference
-Had sex with someone not of your own race
-Had sex with a religious officiary
-*PURITY-6.ASC
-Held hands or otherwise displayed public affection
-Kissed someone on the lips
-French kissed someone
-Necked
-Petted
-Received manual sex
-Given manual sex
-Received oral sex
-Given oral sex
-Had sex
-Had sex with a virgin  (not yourself.)
-Had sex with someone with age difference of more than 20 years
-Had anal sex
-Been involved in fist-fucking
-Done 69  (simultaneous oral sex.)
-Propositioned someone for sex, oral sex, or mutual masturbation
-Yielded willingly to a proposition from someone for sex/oral sex
-Had sex with someone whose name you didn't know
-Had sex with someone whose face you never saw
-Been a participant in a who's-physically-better-equipped contest
-Been a judge in a contest such as above
-Gave money or favors for sex, oral sex, or mutual masturbation
-Received money or favors for sex/oral sex or mutual masturbation
-Fondled someone who was asleep
-Attempted to seduce someone
-Allowed yourself to be seduced
-Had an orgasm while petting
-Gave your partner an orgasm while petting
-Had an orgasm at all
-Had sex/oral sex or mutual masturbation with more than 10 people
-Stroked or fondled the clothed legs of someone
-Stroked or fondled the bare legs of someone
-Stroked or fondled the clothed chest/torso region of someone
-Stroked or fondled the bare chest/torso region of someone
-Fondled or handled the clothed genitals of someone else
-Stroked/fondled or handled the bare genitals of someone else
-Had sex/mutual masturbation with someone not of your own race
-Been in a menage-a-trois of people of the same sex
-Been involved in group sex/with all participants of the same sex
-*PURITY-7.ASC
-Been decidedly heterosexual
-Been decidedly homosexual
-Been decidedly bisexual
-Practiced bestiality (avec les animaux)
-Practiced transvesticism
-Practiced sadism
-Practiced masochism
-Practiced bondage
-Practiced domination
-Practiced submission
-Practiced sodomy (anal intercourse)
-Practiced cocrophilia (a marked interest in excrement)
-Practiced frotteurism
-Practiced infantilism(a dependency on diapers)
-Practiced klismaphilia (a dependency on being given an enema)
-Practiced necrophilia (copulation with a corpse)
-Practiced mysophilia (a dependency on something soiled)
-Practiced scoptophilia ( as in voyeurism)
-Practiced urophilia (being responsive to urine )
-Practiced role-playing
-Owned an underwear collection of underwear not belonging to you
-Been a foot fetishist to any degree
-Been a leather fetishist to any degree
-Been a rubber/latex fetishist to any degree
-Been a voyeur
-Been an exhibitionist
-Listened to dirty jokes in mixed company
-*PURITY-8.ASC
-Told dirty jokes in mixed company
-Discussed masturbation
-Watched a porn movie in mixed company
-Watched a porn movie with your own or someone else's parents
-Played a game which may require you or others to disrobe
-Played a game which may require you to perform action on others
-Been in contact with more than one person while all were nude
-Had oral sex with more than 10 people (not nec. at one time)
-Had sex with more than 10 people  (not necessarily at one time)
-Had sex with more than 1 person in a 24 hour period
-Had sex with both genders in a 24 hour period
-Been in a menage-a-trois (MFM OR FMF)
-Walked in on others having sex (oops) and then joined in
-Had sex or oral sex with a person and his/her parent
-Had sex/mutual masturbation, with a person and his/her sibling
-Been involved in a two (or more) in one
-Been involved in a gang bang
-Been in a circle of fuck
-Been in a 69 circle
-Been to a (cooking, baby, Wesson) oil party
-Played naked Twister [tm] (with or without oil)
-Participated in a hetro orgy or been involved in group sex
-Participated in a bisexual orgy or group sex
-Propositioned a person or group of people for group sex
-Been propositioned for group sex
-Participated in a fuck-a-thon
-*PURITY-9.ASC
-Used a foreign object or something for masturbation
-Masturbated using the aid of food
-Eaten the food used in masturbation after masturbation
-Eaten a lab dissection
-Inserted food into your or someone else's anus
-Eaten food after it was extracted from your or someone's anus
-Received an enema for a purpose other than medical
-Received an enema consisting on a non-normal enema solution
-Actually measured your own or someone else's penis
-Used a mechanical device in aiding or replacing masturbation
-Used a feather or other device for the purpose of tickling
-Used tickling as a form of *arousal*
-Used ice for sexual purposes
-Used ice for something frozen as a dildo
-Used a strap-on dildo or male extension sheath
-Used whipped cream for sexual purposes
-Used hot/melted wax for sexual purposes
-Had sex in front of or under a mirror
-Put food on your partner's body, and then eaten it
-Used household syrup/etc or any like substance for sex purposes
-Used ropes, cuffs or any other such device for bondage purposes
-Used a whip, cat-o-nine-tails, or something similar for pain
-Worn edible underwear/lingerie
-Eaten edible underwear/lingerie off of someone
-Worn a leather or rubber suit
-Worn diapers for a sexual or masturbatory purpose
-Been diapered by someone else for a sex or masturbatory purpose
-Used a ball gag or other manufactured gag
-Worn a collar and/or leash
-Been completely tied down (spreadeagled, hogtied, etc.)
-Tied someone down completely
-Had sex while you or your partner was tied up
-Used nipple clips (clothespins count)
-Pierced a part of your body other than your ears or nose
-Found a prepubescent child sexually attractive/arousing
-Had sexual contact of any kind with a prepubescent child
-Used an inflatable doll
-Humped an inanimate object like a pillow, banana, etc
-Had sex or oral sex with a dead person
-Inserted a small animal or creature into your rectum
-Had sex or oral sex with your (dead) dinner animal
-Watched animals having sex
-Been aroused by the sight of animals having sex
-Attempted to have sex with a live animal, but failed
-Had sex/oral sex or (mutual) masturbation with smallish animal
-Had sex/oral sex or masturbation with domesticated farm animal
-Mutilated or killed any living animal for your pleasures
-Had sex with a live animal  (Any size.)
-Received oral sex from a live animal  (Any size.)
-Gave oral sex to a live animal	(Any size.)
-Had sex or (mutual) masturbation with a animal more than once
-Had sex or masturbation with an animal in presence of others
-Cross dressed in the *undergarments* of the opposite sex
-Cross dressed in presence of others
-Stuffed your pants or bra while you were cross-dressed
-Had your head inserted into a urinal or toilet bowl willingly
-Worn groinal underwear on your head  (Panties/jock-strap/etc.)
-Inserted a  piece of groinal underwear into your mouth
-Deliberately sniffed or smelled a piece of groinal underwear
-Been gagged with someone's underwear  (not your own)
-Played in or with shit
-Worn or used a used condom or feminine hygiene contraption
-*PURITY-A.ASC
-Necked or petted in a place of religion
-Had sex or been involved in a place of religion
-Necked or petted in a place of the dead (mortuary)
-Had sex or been involved in oral sex in a place of the dead
-Necked or petted in a contraption of the dead (hearse/etc)
-Had sex in a contraption of the dead
-Had sex in/on a construction site (house, office, etc.)
-Necked or petted in a vehicle of LESS  THAN 30,000 pounds net
-Had sex in a vehicle of LESS THAN 30,000 pounds net
-Necked or petted in a vehicle of MORE THAN 30,000 pounds net
-Had sex in a vehicle of MORE THAN 30,000 pounds net
-Had sex in a land-based, non road dependant vehicle
-Necked in a water, manual powered vehicular transport medium
-Petted in a water/wind or prop driven transport medium
-Had sex in a water/wind driven transport MORE THAN 80 feet
-Had sex or oral sex in an aircraft
-Had sex in a household room other than a bedroom
-Had sex on the floor (but not the roof)
-Had sex on any furniture that is indoors but not a bed or table
-Had sex telephone booth, voting booth/etc
-Had sex in an elevator, people-mover, escalator, dumbwaiter
-Had sex up a tree but not in a tree house or similar structure
-Had sex in a suspension device of some kind (hammock)
-Had sex on the roof of a building in excess of 5 floors
-Had sex within the confines of a hedge, bush/etc
-Had sex, oral sex, or mutual masturbation in the snow
-Had sex in a place with the ambient temperature below freezing
-Had sex in a place where you could have been discovered
-Had sex in a water-filled bathtub, hot tub/etc
-Had sex, oral sex, or mutual masturbation in a body of water
-Had sex on the beach
-Had sex or mutual masturbation in a bathroom of the opposite sex
-Gone to a motel for the sole purpose of having sex
-*PURITY-B.ASC
-Watched while someone else masturbated
-Been watched while masturbating
-Orgasmed on somebody
-Orgasmed in somebody (male) or in you (female)
-Had more than one person orgasm on you at once
-Used  a penis as a leash or bludgeoning device
-Been involved in oxygen deprivation for sexual enhancement
-Willingly made video tapes or  pictures taken while having sex
-Physically watched others having sex
-Watched your partner of choice having sex with someone else
-Taken pictures of your partner having sex with someone else
-Willingly made audio recordings while having sex
-Talked dirty while having sex, oral sex, or mutual masturbation
-Intentionally made more noise than necessary while having sex
-Intentionally made 'animal' noises during sex
-Had a pet walk over you or your partner while during sex
-Had a general emergency arise while you were steeped in sex
-Had your sexual technique/style/skill openly praised by someone
-Taken nude pictures of someone else
-Had nude pictures of you taken
-Placed a personal ad
-Answered a personal ad
-Been involved in breast fucking  (The Hawaiian Muscle Fuck)
-Participated in fist-fucking  (see 'Caligula')
-Shaved someone's pubic hair (or had yours) as part of sex
-Had sex for more than three hours in a single session of sex
-Been bruised during sex, oral sex, or mutual masturbation
-Bruised someone else during sex, oral sex, or mutual masturbation
-Been injured during sex, oral sex, or mutual masturbation
-Orgasmed more than three times in one session of sex
-Had sex so many times or for so long that one involved runs dry
-Disturbed other people by making excessive noise during sex
-Had sex or received oral sex while you were driving
-Had sex doggie fashion
-Had sex in the female superior position
-Had sex sitting up
-Had sex standing up
-Had sex upside-down
-Gone through several sexual positions without need for re-entry
-Fallen asleep during sex
-Woken up to someone having sex with you
-Had sex while one person was passed out or unconscious
-Given or received a hickey on your upper inner thigh
-Been on the receiving of anal sex
-Been on the ramming end of anal sex (a dildo counts)
-Had sex more than 10 times with 1 person
-Had sex more than 5 times in a 24 hour period
-Had sex more than 10 times in a 24 hour period
-Had sex while someone other than your partner was watching
-Had sex while one or both were playing a musical instrument
-Performed oral sex after intercourse without washing or douching
-Kissed your partner on the lips after oral sex without rinsing
-Inflicted pain during sex
-Been involved in cunnilingus during the woman's period
-Had sex during the woman's period
-Foot masturbated someone
-Been foot masturbated
-Tongue bathed someone
-Been tongue bathed
-Licked or sucked on someone else's feet and/or toes
-Had your feet and/or toes licked or sucked by someone else
-Licked someone's anus
-Licked someone's anus while they were defecating
-Performed oral sex while the person was urinating
-Drank your own urine
-Tasted or drank someone else's urine
-Drank/drained an entire bladder-full of someone else's urine
-Drank human blood
-Tasted someone else's nasal mucous
-Been involved in a golden shower
-Swallowed your partner's orgasmic secretions
-Used the Purity Test as a checklist of things you could do
-Ever done something for purpose of lowering your Purity score
-Bought/read books to enhance sexual technique
-Participated in Purity Testing with an ulterior motive
-Become interested in person after hearing their Purity score
diff --git a/xtrn/smm/purity.asc b/xtrn/smm/purity.asc
deleted file mode 100644
index 3aae420c0007303289cce4c9a9ae8ef84d580b1d..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity.asc
+++ /dev/null
@@ -1,31 +0,0 @@
-nch                            THE UNISEX, OMNISEXUAL
-
-y                            P U R I T Y    T E S T
-nc_______________________________________________________________________________
-
-                   rhiWARNINGnrh: THIS TEST MAY EASILY OFFEND YOU
-
-chInstructions for Use:
-nc
-This is a fairly long test consisting of hone hundred questionsnc.  It starts out
-tame and gets progressively worse (or better, depending on your viewpoint).
-
-hDefinitions
-nc
-Any references to hMOSnc are references to a hMncember of the hOncpposite hSncex.
-
-All questions in this test pertain to events that have happened to you
-subsequent to your weaning and babyhood/infancy.  Anything that may have
-happened before that time is considered not standing and void.
-
-The term mutual masturbation refers to someone masturbating you AND/OR you
-masturbating someone else, not exclusively both at the same time.
-
-We would also like to define having sex in the homosexual case; homosexual sex
-has occurred when both partners are of the same sex and one of the partners has
-an orgasm while there is some contact between the genitals of both partners.
-
-We would now like to bring to your attention that there is no passing nor
-failing score.  Therefore, one really shouldn't worry too much about getting a
-high score...  even if you do get giggled at for the rest of your life.
-
diff --git a/xtrn/smm/purity.que b/xtrn/smm/purity.que
deleted file mode 100644
index c97b56bea11a7bd40fdf3adfd7c99c4de4744912..0000000000000000000000000000000000000000
--- a/xtrn/smm/purity.que
+++ /dev/null
@@ -1,100 +0,0 @@
-Had a date
-Been out on a date past 4 am
-Had a blind date
-Kissed a MOS
-Been french kissed
-Kissed a MOS in the horizontal position
-French kissed three or more MOS's in 24 hours
-Kissed a MOS in the last three months
-Necked for more than 2 hours consecutively
-Slow danced cheek-to-cheek
-Had an alcoholic drink
-Been drunk
-Driven while under the influence of alcohol or drugs
-Had a lapse of memory due to drinking or drugs
-Used alcohol or drugs to lower a MOS's resistance
-Smoked tobacco
-Smoked pot or hashish
-Used a stronger drug
-Taken 4 or more "recreational" drugs within 24 hours
-Read a pornographic book or magazine
-Seen a pornographic movie
-Seen a stripper
-Been arrested
-Been convicted of a crime
-Had an erection/clitoral erection
-Had an orgasm
-Had an orgasm in a dream
-Fondled a MOS's ass
-Caressed a MOS's thigh
-Fondled a breast or had your breast fondled
-Wrestled with a MOS
-Showered, bathed, jacuzzied, or saunaed with a MOS
-Gone coed skinny-dipping
-Gone through the motions of intercourse while fully clothed
-Spent the night in a MOS's room
-Slept in the same bed with a MOS
-Seen a naked post-pubescent MOS
-Been seen naked by a MOS after puberty
-Undressed or been undressed by a MOS
-Kissed a MOS on the breast or been kissed on the breast
-Fondled a MOS's genitals or had your genitals fondled by a MOS
-Had an orgasm due to manipulation by a MOS
-Kissed a MOS on the thigh
-Engaged in cunnilingus
-Engaged in fellatio
-Had sexual intercourse at a parents house while they were home
-Engaged in definitely sexual activity on the first date
-Masturbated
-Masturbated to a picture
-Masturbated with another person in the room
-Watched another person masturbate
-Been caught masturbating
-Simulated intercourse with an inanimate object
-Committed an act of voyeurism
-Committed an act of exhibitionism
-Massaged or been massaged by a MOS
-Unintentionally interrupted a couple in a significant state of undress
-Participated in a tickle orgy, gross out, truth or dare, etc.
-Experimented sexually before puberty
-Purchased contraceptives in a drug store
-Had sexual intercourse
-Had sexual intercourse more than 10 times
-Had sexual intercourse continuously for 1/2 hour
-Had sexual intercourse within the last 3 months
-Had sexual intercourse 3 or more times in 1 night
-Had sexual intercourse in 3 or more positions
-Had sexual intercourse in a car
-Had sexual intercourse using a condom
-Done sixty-nine
-Had sexual intercourse outdoors
-Had sexual intercourse with 3 different people
-Had sexual intercourse with a virgin
-Had sexual intercourse during menstruation
-Had sexual intercourse without using birth control
-Had sexual intercourse with 2 MOSs in 24 hours
-Had sexual intercourse in a public place
-Described a sexual experience to a separate party
-Committed statutory rape
-Been the object of travel or traveled 100 miles or more for sexual activity
-Impregnated a woman or been pregnant
-Arranged or had an abortion
-Displaced a roommate by staying with a MOS for 1 or more nights
-Shacked up with a MOS for a month or more
-Tasted semen
-Been propositioned by a prostitute or pimp
-Accepted
-Had anal intercourse
-Been tested for V.D. due to reasonable suspicion
-Had V.D.
-Picked up a strange MOS for sexual purposes
-Engaged in group sex
-Engaged in sadism or masochism for sexual enjoyment
-Been propositioned by a member of the same sex
-Accepted a proposition by a member of the same sex
-Been masturbated by a member of the same sex
-Been orally stimulated by a member of the same sex
-Committed incest
-Fondled a pre-pubescent MOS
-Engaged in transvestitism for sexual enjoyment
-Committed bestiality
diff --git a/xtrn/smm/que.lst b/xtrn/smm/que.lst
deleted file mode 100644
index 95018ef15d5c40f4492698eb705092733f0d5aa3..0000000000000000000000000000000000000000
--- a/xtrn/smm/que.lst
+++ /dev/null
@@ -1,12 +0,0 @@
-BASIC
-Basic Personality
-0
-APPEAR
-Appearance
-0
-MATERIAL
-Material
-0
-ADULT
-Adult Sexuality
-18
diff --git a/xtrn/smm/smm.can b/xtrn/smm/smm.can
deleted file mode 100644
index 503ab7da423f090b526c1ca28cef26a0e5dcc34c..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm.can
+++ /dev/null
@@ -1,4 +0,0 @@
-l
-p
-digital man
-fuck
diff --git a/xtrn/smm/smm.cfg b/xtrn/smm/smm.cfg
deleted file mode 100644
index 334011d05ec08c4f055ec6ce0adfe6da12461542..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm.cfg
+++ /dev/null
@@ -1,22 +0,0 @@
-18
-15
-0
-
-
-
-
-0
-0
-30
-1
-
-0
-0
-0
-0
-0
-%!dsz portx %u,%i sz %f
-0
-
-
-90
diff --git a/xtrn/smm/smm.doc b/xtrn/smm/smm.doc
deleted file mode 100644
index 37939ac6251347c2c5170880f9ab1ec4995ef654..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm.doc
+++ /dev/null
@@ -1,594 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-     Synchronet Match Maker  Version 2.10  Copyright 1996 Digital Dynamics
-     -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-	       "Perhaps the most comprehensive Match Maker ever."
-
-
-Synchronet Installation (if you are using Synchronet BBS Software)
-==================================================================
-
-Synchronet Match Maker (SMM) comes pre-installed in Synchronet BBS v2.1 and
-later. If match maker has been pre-installed in your system, see the file
-UPGRADE.DOC for details on installing a newer version over an older version
-(upgrading).
-
-Create the following sub-directory off of your main Synchronet directory
-(e.g. C:\SBBS):
-
-XTRN\SMM	(The XTRN directory should already exist)
-
-(example: C:\SBBS\XTRN\SMM)
-
-Copy the files included in the archive or on the floppy disk into this
-directory. The DEMO and registered versions of this program are identical.
-The registration number must be obtained from Digital Dynamics and entered
-into the Match Maker configuration program (SMMCFG) to convert the DEMO into
-a registered copy.
-
-Licenses for registered use of Synchronet Match Maker are sold separately from
-Synchronet BBS Software. Once a registration number has been issued, no refunds
-or returns of Synchronet Match Maker will be accepted.
-
-Run SCFG (Synchronet Configuration Program) and add the Match Maker to one
-of your External Program Sections and configure as follows:
-
-	����������������������������������������������������������ͻ
-	�		   Synchronet Match Maker		   �
-	����������������������������������������������������������͹
-	� �Name 		      Synchronet Match Maker	   �
-	� �Internal Code	      SMM			   �
-	� �Start-up Directory	      ..\XTRN\SMM		   �
-	� �Command Line 	      smm			   �
-	� �Clean-up Command Line				   �
-	� �Multiple Concurrent Users  Yes			   �
-	� �Intercept I/O Interrupts   No  <-- Important 	   �
-	� �Swap BBS out of Memory     Yes			   �
-	� �Modify User Data	      Yes			   �
-	� �Execute on Event	      No			   �
-	� �BBS Drop File Type	      Synchronet      XTRN.DAT	   �
-	� �Place Drop File In	      Node Directory		   �
-	����������������������������������������������������������ͼ
-
-If you wish to have old profile entries and wall writings automatically deleted
-from your match maker, you will need to run the SMMUTIL program periodically to
-remove profiles that haven't been updated in a certain number of days
-(specified on the SMMUTIL command line). To set up a timed event in SCFG->
-External Programs->Timed Events for SMMUTIL:
-
-    ��������������������������������������������������������������������ͻ
-    �			      SMMUTIL Timed Event			 �
-    ��������������������������������������������������������������������͹
-    � �Internal Code		       SMMUTIL				 �
-    � �Start-up Directory	       ..\XTRN\SMM			 �
-    � �Command Line		       smmutil 90 7 > SMMSTATS.TXT	 �
-    � �Execution Node		       1				 �
-    � �Execution Days		       Sun Mon Tue Wed Thu Fri Sat	 �
-    � �Execution Time		       00:00				 �
-    � �Requires Exclusive Execution    Yes				 �
-    � �Force Users Off-line For Event  No				 �
-    ��������������������������������������������������������������������ͼ
-
-This would have SMMUTIL remove all profiles that haven't been updated in the
-past 90 days and all wall writings older than 7 days.
-
-It will also create the file SMMSTATS.TXT in your XTRN\SMM directory with
-detailed statistics on the demographics of the current SMM profile database.
-You may want to make this file available for download or as a viewable bulletin
-on your BBS.
-
-If you are currently on DOVE-Net or FidoNet and you carry the "Synchronet Data"
-(SYNCDATA) message area and wish to link your match maker database with other
-BBSs through this message area, set up the following two Timed Events in SCFG:
-
-    ��������������������������������������������������������������������ͻ
-    �			      SMB2SMM Timed Event			 �
-    ��������������������������������������������������������������������͹
-    � �Internal Code		       SMB2SMM				 �
-    � �Start-up Directory	       ..\XTRN\SMM			 �
-    � �Command Line		       smb2smm %jsubs\syncdata smm.dab	 �
-    � �Execution Node		       1				 �
-    � �Execution Days		       Sun Mon Tue Wed Thu Fri Sat	 �
-    � �Execution Time		       00:00				 �
-    � �Requires Exclusive Execution    No				 �
-    � �Force Users Off-line For Event  No				 �
-    ��������������������������������������������������������������������ͼ
-
-    ��������������������������������������������������������������������ͻ
-    �			      SMM2SMB Timed Event			 �
-    ��������������������������������������������������������������������͹
-    � �Internal Code		       SMM2SMB				 �
-    � �Start-up Directory	       ..\XTRN\SMM			 �
-    � �Command Line		       smm2smb smm.dab %jsubs\syncdata	 �
-    � �Execution Node		       1				 �
-    � �Execution Days		       Sun Mon Tue Wed Thu Fri Sat	 �
-    � �Execution Time		       00:00				 �
-    � �Requires Exclusive Execution    No				 �
-    � �Force Users Off-line For Event  No				 �
-    ��������������������������������������������������������������������ͼ
-
-Change "syncdata" in the above examples to the internal code you have used
-for the "Synchronet Data" echo. Also, if you are not running v2.1+ of
-Synchronet, you must specify the full path to the DATA directory instead of
-using the %j. If your "Synchronet Data" echo is stored on a different
-drive or in a different directory than SBBS, then you must specify that drive
-and path on the above command lines.
-
-To get your match maker database active immediately, you may want to reset
-your message pointers for the "Synchronet Data" echo on your hub BBS. If
-using QWKnet, you would accomplish this by posting the message in the
-"Synchronet Data" echo on your BBS to "SBBS" with a title of "RESET". The
-message body does not matter.
-
-Swapping
---------
-If you get memory allocation errors during the execution of any of the above
-event command lines, add that program name to your Global Swap List in SCFG.
-
-DOOR.SYS BBS Installation (if you are using BBS software OTHER than Synchronet)
-===============================================================================
-
-Your BBS software must be able to create the industry standard DOOR.SYS drop
-file (35 lines or more). If you wish to charge credits for specific match maker
-functions (adding profile, sending telegrams, etc) your BBS software must be
-able to READ BACK in the modified DOOR.SYS drop file (e.g. GAP BBS software).
-Credits are read from line 31 of the DOOR.SYS file (in K) and credits used
-while in SMM are written to line 30 of the DOOR.SYS (in K) and total credits
-after adjustment (in K) are written back to line 31 of the DOOR.SYS. Since the
-DOOR.SYS format only supports one set of flags (line 23), flag set 1 will be
-the only valid flag set to use for the security options in SMMCFG (i.e. flag
-sets 2-4 will not be used).
-
-Create a directory for Synchronet Match Maker (SMM) and copy all the files
-into it (example: C:\BBS\DOORS\SMM).
-
-Copy the files included in the archive or on the floppy disk into this
-directory. The DEMO and registered versions of this program are identical.
-The registration number must be obtained from Digital Dynamics and entered
-into the Match Maker configuration program (SMMCFG) to convert the DEMO into
-a registered copy.
-
-Once a registration number has been issued, no refunds or returns of Synchronet
-Match Maker will be accepted.
-
-If you are running a multinode BBS, you will need to have the DOOR.SYS created
-in a separate directory for each node (i.e. NOT the directory where SMM has
-been installed). This will prevent drop file collisions if two users enter SMM
-at the same time. The complete path to the DOOR.SYS must be specified on the
-command line, so each node must have a different path specified. Example:
-
-Node 1 Command Line:	SMM C:\BBS\NODE1\DOOR.SYS
-Node 2 Command Line:	SMM C:\BBS\NODE2\DOOR.SYS
-
-SHARE must be loaded in your CONFIG.SYS or AUTOEXEC.BAT for SMM to function
-(in single node or multinode environments).
-
-If non-standard IRQs or I/O addresses are used, they must be specified on the
-SMM command line using the Command Line Options. IRQs 2-15 are fully supported.
-Shared IRQs are not supported in UART mode.
-
-16550 FIFO buffered UARTs are detected and enabled.
-
-DTE rates up to 115200 baud are supported (higher with proprietary hardware).
-
-Command Line Options:
-====================
-
-Command line options override the values (if present) in the DOOR.SYS file.
-No command line options are required when used with Synchronet BBS software.
-
-	/P#	Set the COM port (0=local only) (normally not necessary)
-
-		Example: /P1 to specify COM1
-			 /P0 to specify no COM port (local use)
-
-	/C#	Set the COM port type or I/O (D:DigiBoard, F:FOSSIL, E:EBIOS)
-
-		Example: /CF to specify FOSSIL
-			 /C3e8 to specify I/O address 3e8 (hexadecimal)
-
-	/I#	Set the COM port IRQ or channel (only required if non-standard)
-
-		Example: /I5 to specify IRQ 5
-			 /I0 to specify FOSSIL/Digi Channel 0
-
-	/R#	Set the COM port DTE rate (normally not necessary)
-
-		Example: /R57600 to specify a DTE rate of 57600 baud
-
-	/T#	Set time-slice APIs supported (default: DESQview if detected)
-
-		Example: /T1 to use INT28 time-slice API
-			 /T2 to use Win/OS2 time-slice API
-			 /T4 to disable DESQview detection and time-slice API
-
-If a user name is specified on the command line, that user's profile will be
-automatically looked up and displayed.
-
-	Example (Synchronet): SMM JOHN DOE
-
-	Example (non-Synchronet): SMM C:\BBS\NODE1\DOOR.SYS JOHN DOE
-
-The current directory MUST be the directory where SMM has been installed
-(e.g. C:\BBS\DOORS\SMM) when SMM is executed. Some non-Synchronet BBS packages
-may require a batch file to change drive and/or directory before running SMM
-and may require the same batch file re-load the BBS software. Example:
-
-	@ECHO OFF
-	CD \BBS\DOORS\SMM
-	SMM \BBS\NODE1\DOOR.SYS
-	REM The following may not be necessary with some BBS packages
-	CD \BBS\NODE1
-	BBS
-
-Configuration
-=============
-
-SMMCFG
-------
-SMMCFG.EXE is used to modify your SMM.CFG (Configuration) file. Hitting the F1
-key will display a help page on the currently selected menu or option.
-
-	����������������������������������������������������������ͻ
-	�	    Synchronet Match Maker Configuration	   �
-	����������������������������������������������������������͹
-	� �System Name				    MY BBS	   �
-	� �Wall Security...					   �
-	� �Profile Database Security... 			   �
-	� �Credit Cost for Adding Profile	    0k		   �
-	� �Credit Cost for Sending Telegram	    0k		   �
-	� �Credit Cost for Writing on the Wall	    0k		   �
-	� �Credit Cost for Reading Questionnaire    0k		   �
-	� �Minimum Level to Send Telegrams	    0		   �
-	� �Minimum Level to Read Questionnaires     0		   �
-	� �Sysop Level				    90		   �
-	� �Minor Segregation (Protection) Age	    Disabled	   �
-	� �Auto-Update Profiles 		    30		   �
-	� �Notify User of Activity		    1		   �
-	� �Use Metric System			    No		   �
-	� �Zmodem Send Command			    %!dsz portx %u,�
-	� �Local Photo Viewer			    dvpeg %f	   �
-	� �Registration Number			    UNREGISTERED   �
-	����������������������������������������������������������ͼ
-
-System Name
------------
-The most important option in this program is your System Name (BBS Name). If
-you are running Synchronet BBS Software, this option does not have to be set
-here (it is automatically passed to SMM in the XTRN.DAT drop file from
-Synchronet). If it is set, it will override the name specified in SCFG->System
-->BBS Name.
-
-If you have registered SMM for non-Synchronet BBS Software, this option must be
-set to the exact BBS name you registered SMM for (not case sensitive).
-
-Once you have setup SMM and your BBS users have entered their profiles, it is
-important that you DO NOT change your BBS name, or you will lose those
-profiles (and likely upset your users). If you are networking your match maker
-database with other BBSs, it is important that you do not have the same System
-Name as another BBS in the network. Only the first 25 characters of the BBS
-name are used and every BBS in an SMM network must have a unique BBS name. Your
-System Name (configured in SMMCFG) does not have to match your actual BBS name
-(as configured in your BBS software). This allows you to change your System
-Name for match maker networks where your real BBS name is already in use.
-
-Profile Database Security
--------------------------
-	�����������������������������������������������ͻ
-	�	    Profile Database Security		�
-	�����������������������������������������������͹
-	� �Minimum User Age to Add Profile	     15 �
-	� �Minimum User Age to Take Purity Test      18 �
-	� �Minimum Security Level to Add Profile     30 �
-	� �Required Flags (Set 1) to Add Profile	�
-	� �Required Flags (Set 2) to Add Profile	�
-	� �Required Flags (Set 3) to Add Profile	�
-	� �Required Flags (Set 4) to Add Profile	�
-	�����������������������������������������������ͼ
-
-The Profile Database Security sub-menu allows you to define who can add
-profiles by security level, age, and flags as well as the minimum age for
-the purity test. Flag sets 2-4 are used only with Synchronet BBS software.
-
-Minimum Levels
---------------
-From the SMMCFG main menu you can change the minimum levels required to
-send telegrams, write on the wall, read questionnaires, and perform sysop
-functions.
-
-Minor Segregation (Protection) Age
-----------------------------------
-This option separates all users into Minors (those users below the specified
-age) and Adults (those users at or above the specified age). When this option
-is used, adults cannot see minors' profiles or send them telegrams (and vice
-versa). This feature does not keep adult users on other non-segregated
-networked BBSs from sending telegrams to minors on your BBS (or minors on other
-BBSs from sending telegrams to adults on your BBS) - this can lead to confusion
-among users receiving telegrams from users that don't appear to be in the
-database (due to segregation on your system). This option is disabled by
-default.
-
-Auto-Update Profiles
---------------------
-This option allows you to change the number of days between automatic
-profile updates across a match maker network. Normally a user's profile will
-not be sent out across the network unless the user makes a change to their
-profile. This option allows you to have their profile automatically sent
-every so many days as long as the user is active in the match maker (enters
-the match maker and uses it). This is useful for keeping profile databases
-up-to-date across the network as new systems come online. Setting this option
-to 0 disables this feature. The default value (30) should be fine for most
-configurations.
-
-Notify User of Activity
------------------------
-This is the number of the user who will be notified of match maker activity
-(profiles added, telegrams sent, wall writings, etc). Normally this option will
-be set to 1 (for user #1, the sysop). Setting this option to 0 disables this
-feature.
-
-Use Metric System
------------------
-If you want all heights and weights to be displayed in centimeters and
-kilograms instead of inches and pounds, set this option to "Yes". Since all
-measurements are internally stored in inches and pounds, those (English)
-measurements are the most accurate. Some measurements may change slightly
-when converting from metric to English and back.
-
-Zmodem Send Command
--------------------
-This is the command line to execute to send a file via Zmodem to the remote
-user. The default command line (%!dsz portx %u,%i sz %f) should work for most
-system configurations (assuming DSZ is in your Synchronet EXEC directory or
-DOS search path and using UART serial ports on all nodes). The percent codes
-in the command line are called "Command Line Specifiers" and are explained
-later in this document.
-
-Local Photo Viewer
-------------------
-This is the command line to execute to view photos when running SMM locally.
-The percent codes in the command line are called "Command Line Specifiers" and
-are explained later in this document.
-
-Command Line Specifiers
------------------------
-%A	User name
-%B	Baud (DTE) Rate
-%C	Connect (DCE) Rate
-%F	File path
-%G	Temp directory (blank if non-SBBS)
-%I	UART IRQ Line
-%J	DATA directory (blank if non-SBBS)
-%K	CTRL directory (blank if non-SBBS)
-%N	Node Directory (blank if non-SBBS)
-%O	Sysop's name
-%P	COM Port
-%Q	System QWK ID (blank if non-SBBS)
-%R	Users Screen Rows
-%S	File Spec
-%T	Time left in seconds
-%U	UART I/O Address (in hex)
-%W	Time-slice API type
-%Z	TEXT Directory (blank if non-SBBS)
-%!	EXEC Directory (blank if non-SBBS)
-%#	Node number
-%*	Node number (zero padded to three digits)
-%$	Credits
-%%	%% for percent sign
-%1	User number
-%2	User number (zero padded to two digits)
-%3	User number (zero padded to three digits)
-%4	etc..
-
-SMM.CAN
--------
-
-The trash can file (SMM.CAN) can be used to specify a list of words or word
-combinations (one word or word combination per line) that will not be allowed
-in user information and wall entries.
-
-QUE.LST
--------
-
-The questionnaire list file (QUE.LST) can be edited with any ASCII text editor.
-The following is the stock QUE.LST containing the four stock questionnaires.
-
-BASIC
-Basic Personality
-0
-APPEAR
-Appearance
-0
-MATERIAL
-Material
-0
-ADULT
-Adult Sexuality
-18
-
-For each questionnaire, a code (up to eight valid DOS filename chars),
-a description (up to 25 chars), and minimum age are specified. A maximum
-of five questionnaires can be configured. If you are linked to the Synchronet
-Data echo, it is suggested you leave the four stock questionnaires intact
-(unmodified). If you change any of these questionnaires, you MUST change the
-code to something other than "BASIC, APPEAR, MATERIAL, or ADULT" as these codes
-are reserved specifically for the stock questionnaires. If you are not linked
-to the Synchronet Data echo, you can modify and remove any questionnaires you
-wish and use whatever code you wish except "PURITY" and "MB-TYPE" as these
-questionnaire names are specifically reserved by the Match Maker.
-
-The questionnaires are stored in files with the code for the name and .QUE
-as the file extension (e.g. BASIC.QUE, APPEAR.QUE, MATERIAL.QUE, etc).
-
-*.QUE Format
-------------
-
-A: First line is total number of questions (max: 20).
-   All lines following are question and answers groups.
-
-B: Each group starts with the actual question (max: 79 characters).
-
-C: The next line in the group consists of the total number of answers
-   (max: 16).
-
-D: The next line consists of the maximum number of answers this user can select
-   for this question.
-
-E: A single line for each answer (total answers from line C).
-
-F: Repeat lines B-E for each question (total questions from line A).
-
-Special Questionnaire Files
----------------------------
-
-Two questionnaire files (MB-TYPE.QUE and PURITY.QUE) are unique in that they
-don't follow the above format at all and should need no modification.
-
-The MB-TYPE.QUE is used for the Myers-Briggs personality test and is a pretty
-standard questionnaire. The files MB-*.ASC are descriptions of the various
-personality types. The file MB-INTRO.ASC is displayed before the test and
-MB-TYPE.ASC is displayed when seeking descriptions of the various types.
-
-The PURITY.QUE is used for the purity test and the format is simply one
-"Have you ever" question per line. The default PURITY.QUE is a 100 question
-test of an adult nature. An optional 500 question purity test is also included
-as PURITY.500. To use this test in place of the 100 question version, copy
-PURITY.500 to PURITY.QUE. The 100 question version is also included as
-PURITY.100 as a back-up, in case you want to return to the 100 question
-version. The PURITY*.ASC files are displayed before and during the testing
-procedure.
-
-Sysop Commands
-==============
-
-From the Match Maker main menu, the sysop (any user with sysop security level)
-can use the (D)elete command to remove any profile from the database. Profiles
-can be undeleted with the '*' command (available only to sysops).
-
-When viewing profiles, sysops are shown the user name, number, and system
-name at the top of the profile. Normal users are not shown this information
-to maintain the anonymity of the users in the database.
-
-Hitting '!' will display a list of all networked BBSs that have contributed to
-the current profile database. If you see your BBS name in the list, either
-someone else is using the same BBS name as you (which is bad), or something has
-gone wrong in your network and you should contact Digital Dynamics to remedy
-the situation immediately. If someone else is using the exact same BBS name
-(not considering upper/lower case differences), one of you must change your BBS
-name by at least one character or you will definitely have problems with your
-users' Match Maker profiles and telegrams.
-
-Hitting '\' will rebuild the database index. If your database is corrupted,
-you should down all your nodes and use SMMUTIL instead of this command. If
-your SMM.IXB file disappears or becomes out-of-sync with your SMM.DAB file
-(which is unlikely to occur), you can use this command to quickly recreate
-it.
-
-Photographs
-===========
-
-You may use the included ADDPHOTO.EXE utility to import photographs into your
-local match maker database. The current directory must be the directory where
-SMM is installed when ADDPHOTO is run. The usage is:
-
-ADDPHOTO filename.ext user_number system_name
-
-where filename.ext is the path, filename, and extension of the photograph file
-to import (preferably, but not necessarily, a JPEG file with a .JPG extension).
-User_number is the user's number and system_name is the name of the system the
-user created their profile on.
-
-ADDPHOTO will create a directory called PHOTO off of the directory where SMM
-is installed (e.g. C:\SBBS\XTRN\SMM\PHOTO or C:\BBS\DOORS\SMM\PHOTO) and move
-the photograph file into this directory (changing the name, but leaving the
-extension (e.g. JPG, GIF, TIF, etc) intact.
-
-Example:
-
-		ADDPHOTO JAMIEFAR.JPG 1 M.A.S.H BBS
-
-The DELPHOTO.EXE utility is used to remove photographs from your local match
-maker database. The usage is:
-
-DELPHOTO user_number system_name
-
-Example:
-		DELPHOTO 1 M.A.S.H BBS
-
-The LSTPHOTO.EXE utility may be used to create a list of all users with photos
-in your local match maker database.
-
-Example:
-		LSTPHOTO > PHOTO.LST
-
-PHOTO.ZIP
----------
-You can optionally, zip (using PKZIP) all the files in the PHOTO directory
-into a file called PHOTO.ZIP (in the SMM directory) and delete them from the
-PHOTO directory (to save disk space). When the photo is viewed or downloaded
-from SMM, it will be automatically extracted from the PHOTO.ZIP into the PHOTO
-directory (PKUNZIP.EXE must be in your DOS search path or your Synchronet
-EXEC directory). The ADDPHOTO utility will not automatically add new images to
-the PHOTO.ZIP (if you wish to use that storage method). Also, the files will
-not be automatically deleted from the PHOTO directory after download/viewing
-in SMM. This is so that popular image files will not have to be extracted each
-time. You may wish to periodically re-zip and delete the PHOTO directory
-(perhaps with an event) to preserve disk space.
-
-SYNCDATA Echo
--------------
-If your match maker is linked (via DOVE-Net or FidoNet) to the SYNCDATA echo,
-you do not need a scanner or the ADDPHOTO utility to get your users' photos
-into the database. Simply have your users send their photos along with your
-full and correct BBS name, their user number, and a xerox-copy of a current
-formal photo-ID (to verify identity only, IDs will not be scanned and all
-ID information will remain completely confidential) to Digital Dynamics.
-
-The photos must have a 2 inch square drawn around the area to be scanned. The
-photos will be scanned and distributed in JPEG format (with monthly
-redistribution) on the SYNCDATA echo by Digital Dynamics. This service is
-available to all users of SMM free of charge (this free offer _may_ expire
-on Feb 14th, 1996).
-
-Digital Dynamics reserves the right to refuse to scan and distribute any
-photos for any reason. Nudity or vulgarities will not be allowed.
-
-Photos and IDs included with a self-addressed _stamped_ enveloped will be
-returned.
-
-DEMO Version
-============
-
-The unregistered "DEMO" version of Synchronet Match Maker will not allow
-users to send Telegrams to other users in the database (through the
-message network), write on the Match Maker wall, or read other users'
-questionnaires.
-
-To register your copy of Synchronet Match Maker, complete the ORDER.TXT form
-included in this archive/directory and send it to Digital Dynamics, or call
-714-529-6328 (voice) or 714-529-9525 (BBS) to order with a credit card for
-faster processing.
-
-/* End of SMM.DOC */
diff --git a/xtrn/smm/smm_help.asc b/xtrn/smm/smm_help.asc
deleted file mode 100644
index c969ab434c583892813e19e505d1801208d2a3b4..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm_help.asc
+++ /dev/null
@@ -1,27 +0,0 @@
-yhOverall Match (General Explanation):nc
-
-The overal match is a highly refined algorithm used to compute a percentage of 
-preference match between a user and a prospective mate. The user's preferences
-are weighed more heavily than those of the prospective mate. More specific
-preferences will result in a higher match percentage potential and a wider
-range of match percentages. More vague preferences will result in a rather
-narrow range of match percentages, so it is best to keep your "hideal matenc" 
-in mind when completing the preferred mate sections of your profile and
-questionnaires.
-
-yhGlobal Database:nc
-
-If your sysop has taken the steps to link this profile database with the 
-international hSyncDatanc network, your profile will be automatically included
-in this global database for users on other BBSs around the world to view. The 
-profiles you see in this database may very well be users in other counties, 
-states, or countries and you can view their information here and communicate
-with them via hTelegramnc using this program.
-
-yhCredits:nc
-
-hPurity Test                     ncOriginal version from MIT's Baker House.
-
-hMyers-Briggs Type Indicator     ncAdapted from the book "Please Understand Me"
-				by David Keirsey and Marilyn Bates
-
diff --git a/xtrn/smm/smm_logo.asc b/xtrn/smm/smm_logo.asc
deleted file mode 100644
index c60c944dfc74384bdf6b04a08c09052ee0472738..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm_logo.asc
+++ /dev/null
@@ -1,3 +0,0 @@
-              nhrn h7������������������������������������������������n hr
-              n k7nk7 nk7Find your mate or just a date, electronically! n hr
-              nhrn hk7������������������������������������������������n hrn
diff --git a/xtrn/smm/smm_main.asc b/xtrn/smm/smm_main.asc
deleted file mode 100644
index b453ada7f35f8c3dd8a0d094f263283b686a7c32..0000000000000000000000000000000000000000
--- a/xtrn/smm/smm_main.asc
+++ /dev/null
@@ -1,9 +0,0 @@
-� nk7������������������������������������������������������������������0
-� 7  b[hRnb7] Read Profiles               [hHnb7] Help/Info                   hk�0
-� 7  nb7[hLnb7] List Profiles               [hMnb7] Myers-Briggs Types          hk�0
-� 7  nb7[hUnb7] Update Your Profile         [hPnb7] Toggle Screen Pause         hk�0
-� 7  nb7[hDnb7] Delete Your Profile         [hTnb7] Read Telegrams              hk�0
-� 7  nb7[hNnb7] Scan for New Profiles       [hSnb7] Send Telegrams              hk�0
-� 7  nb7[hGnb7] Go to a Specific Profile    [hVnb7] Visit the Wall              hk�0
-� 7  nb7[hFnb7] Find Text in Profiles       [hOnb7] Log-off (Hang-up)           hk�0
-� nk7�h������������������������������������������������������������������n
diff --git a/xtrn/smm/upgrade.doc b/xtrn/smm/upgrade.doc
deleted file mode 100644
index be87c35f6229bc64df1869b8e140df213115ec87..0000000000000000000000000000000000000000
--- a/xtrn/smm/upgrade.doc
+++ /dev/null
@@ -1,241 +0,0 @@
-Upgrading from Synchronet Match Maker 
--------------------------------------
-
-If you are a registered owner of SMM and upgrading from v1.10 or earlier,
-you'll need to optain your registration number from Digital Dynamics by calling
-voice at 714-529-6328. You will need to have your Synchronet registration
-number and control code on hand when you call.
-
-The most important change (in upgrading to v2.0) is to change "Intercept
-I/O Interrupts" in SCFG from "Yes" to "No". Example:
-
-	����������������������������������������������������������ͻ
-	�		   Synchronet Match Maker		   �
-	����������������������������������������������������������͹
-	� �Name 		      Synchronet Match Maker	   �
-	� �Internal Code	      SMM			   �
-	� �Start-up Directory	      ..\XTRN\SMM		   �
-	� �Command Line 	      smm			   �
-	� �Clean-up Command Line				   �
-	� �Multiple Concurrent Users  Yes			   �
-	� �Intercept I/O Interrupts   No  <-- Important 	   �
-	� �Swap BBS out of Memory     Yes			   �
-	� �Modify User Data	      Yes			   �
-	� �Execute on Event	      No			   �
-	� �BBS Drop File Type	      Synchronet      XTRN.DAT	   �
-	� �Place Drop File In	      Node Directory		   �
-        ����������������������������������������������������������ͼ
-
-The only files you need to update when converting from v2.01/2.02 to v2.10 are:
-
-SMM.DOC 	Sysop Documentation (v2.10)
-SMM.EXE 	Match Maker Program (v2.10)
-SMMCFG.EXE	Match Maker Configuration Program (v2.10)
-SMMUTIL.EXE	Repair/Maintenance Program (v2.01)
-
-The only files you need to update when converting from v2.00 to v2.10 are:
-
-SMM.DOC 	Sysop Documentation (v2.10)
-SMMCFG.EXE	Match Maker Configuration Program (v2.10)
-SMMUTIL.EXE	Repair/Maintenance Program (v2.01)
-SMB2SMM.EXE	Import Program (v2.01)
-SMM2SMB.EXE	Export Program (v2.01)
-ADDPHOTO.EXE	Import Photographs locally (v1.01)
-DELPHOTO.EXE	Delete Photographs locally (v1.00)
-LSTPHOTO.EXE	List Profiles with Photographs (v1.00)
-
-The only files you need to update when converting from v1.x to v2.0 are:
-
-*.EXE		Executables
-*.DOC		Documentation
-LIST_HDR.ASC	Condensed Listing Header
-
-If upgrading from v1.00 or v1.10, you will also need to update the following
-files:
-
-SMM_MAIN.ASC	Main Menu
-SMM_HELP.ASC	Help Screen (if upgrading from v1.00)
-PURITY.ASC	Purity Explanation (if upgrading from v1.00)
-
-New in version 2.10
-~~~~~~~~~~~~~~~~~~~
-o Minor segregation (protection) now supported. This option separates all users
-  into Adults and Minors (configurable separation age), disallowing adults to
-  see minors' profiles or send them telegrams (and vice versa)
-o Minimum Age to access the wall now configurable in SMMCFG
-o XSDK v2.42 feature: Ctrl-T now displays current time, time used, and time
-  left (similar to SBBS)
-o XSDK v2.42 feature: User is now warned on each of their last 5 minutes left
-
-New in version 2.02a
-~~~~~~~~~~~~~~~~~~~~
-o Fixed bug in SMM.EXE when using DOOR.SYS (non-Synchronet BBSs)
-
-New in version 2.02
-~~~~~~~~~~~~~~~~~~~
-o Low priority input now correctly supported (for giving up multitasker time
-  slices even while accepting string input from the user) - this was an
-  indirect bug fix in XSDK v2.41 most notably effecting OS/2 systems
-o "Searching..." text now displayed before possibly long searches to indicate
-  to the user the system is not crashed
-o Sysop text searches now search user real names, system names and user numbers
-  in addition to the normal user-viewable text fields
-
-New in version 2.01
-~~~~~~~~~~~~~~~~~~~
-o New DELPHOTO.EXE utility to delete photos from the database
-o New LSTPHOTO.EXE utility to create a list of all profiles with attached
-  photos
-o SMB2SMM/SMM2SMB updated to detect and not import/export corrupted profiles
-o ADDPHOTO 1.01 now copies (instead of renames/moves) photo image files
-o SMB2SMM no longer deletes existing photo if CRC error detected on new photo
-o Wall security level (configured in SMMCFG) now correctly keeps users below
-  that level from writing on the wall
-o FOSSIL channel number automatically determined by subtracting 1 from the
-  COM port number (e.g. COM 1 is FOSSIL/Digi channel 0)
-  /I command line switch may be used to set non-standard channel
-o New SMM, SMMCFG, and SMMUTIL fix 25 character BBS name limit
-o SMMUTIL (v2.00) now removes old photos (tallys photos and networked profiles)
-
-New in version 2.00
-~~~~~~~~~~~~~~~~~~~
-o Optionally reads from and writes to DOOR.SYS drop file
-  (for compatibility with other [non-Synchronet] BBS programs)
-o MSG, UTI, and possibly JAM message base import/export utilities will be
-  available soon (for match maker networking with non-SMB compatible BBSs)
-o Optional command line switches for com port configuration and time-slice APIs
-  (for non-standard COM ports with other BBS programs)
-o Photographs (in any size or format) can be added to the database locally
-  (with Zmodem download and local viewing)
-o Photographs are automatically imported from the SYNCDATA echo with SMB2SMM
-  (other match maker networks will need to use their own distribution methods)
-o System name separately configurable in SMMCFG (to work around duplicate BBS
-  names in a match maker network)
-o Metric measurements (centimeters and kilograms) can be enabled in SMMCFG
-o Sysop level defined in SMMCFG (no longer hard-coded at level 90)
-o Low priority input supported (based on SCFG Node toggle option if Synchronet,
-  automatically enabled with other BBS programs)
-o Trailing spaces from user names are automatically removed
-
-New in version 1.31
-~~~~~~~~~~~~~~~~~~~
-o Ability to specify a user to search for on the command line
-  displays extended profile on the user and then exits (just "SMM user name")
-o Messages can now be sent from Digital Dynamics to you (sysops, users, or
-  both) inside SMM (not telegrams, but similar) to inform sysops and users of
-  Match Maker progressions/news. All messages have pre-determined expiration
-  dates and will automatically disappear when the date is reached. Sysop-only
-  messages can be deleted immediately after they are read if the sysop wishes.
-  Special ONE-time messages are displayed to users only once, while others
-  may be displayed each time they enter SMM. (SMB2SMM v1.30 required)
-o New SMMUTIL (v1.15) fixes 4095 user limitation.
-
-New in version 1.30
-~~~~~~~~~~~~~~~~~~~
-o Ability to send telegrams directly from condensed user listings
-o Wall new-scans now correctly scan by date/time imported instead of the
-  date/time written (must use SMB2SMM 1.22, SMM2SMB 1.12, and SMMUTIL 1.14)
-o Condensed Wall listings now clear the screen between each screen-full
-  (faster screen draws) with a prompt allowing the user to read a profile,
-  send a telegram, move backwards through the wall writings, or quit at the
-  bottom of each screen-full (more intuitive and convenient)
-o Extended Wall listings now display wall writing in magenta if the author
-  is female, green if the author is male (instant gender recognition)
-  wall writings who can't be found in the database
-o Extended Wall listings allow sending telegrams directly (without reading
-  profile first) and moving backwards through the wall writings
-o Extended Wall listings stay on current wall writing after reading profile
-  or sending telegram
-o XSDK v2.33 fixes problem with flashing screen loops when a user hangs up
-  with keys in the modem buffer
-o XSDK v2.33 fixes problem with sending double carriage returns at the end
-  of each line (making captures difficult)
-o Fixed problem with selecting races above E
-o If the sysop hits '!' from the main menu, all systems connected to the
-  database are listed
-o When reading a user's questionnaire, (P)revious and (Q)uit commands are now
-  available on the pause prompt
-o Updated sysop documentation
-
-New in version 1.22
-~~~~~~~~~~~~~~~~~~~
-o New option for those seeking "any-sex non-romantic friendly matches" allows
-  matches with both romantic/intimate mates and non-romantic mates (friends)
-o When displaying long user information, preference ranges (age, weight, etc)
-  and specifics (hair color, marital status, etc) are high intensity (bright
-  colors) if the preferencees are considered requirements by the user
-o The Wall was revamped to allow new-scans for new writings since a specific
-  date only and optional display of extended user information allowing reading
-  of questionnaires and sending of telegrams
-o Wall writings will now disallow any text in SMM.CAN (same as user aliases
-  profiles, etc.)
-
-New in version 1.21
-~~~~~~~~~~~~~~~~~~~
-o Credits can be charged or given for reading questionnaires
-o New WALL inside Match Maker for public discussion
-o Credits can be charged or given for writing on the wall
-o Minimum level can be specified to allow writing on the wall
-o SMM2SMB v1.11 now creates unique profile messages that won't be deleted by
-  duplicate message checking
-o SMM2SMB v1.11 and SMB2SMM v1.21 read/write wall writings from message base
-o SMMUTIL v1.11 now allows command line specification of maximum wall writing
-  age before auto-deletion
-o Telegrams and Profile Personal Text no longer word wrap on last line (bugfix)
-o Telegrams now ask to Save (Y/n) when completed to allow last minute abort
-
-New in version 1.20
-~~~~~~~~~~~~~~~~~~~
-o DEMO and registered versions use the same executable files, unlocked with
-  registration number obtained from Digital Dynamics (entered in SMMCFG)
-o Minimum level can be specified to allow the sending of telegrams
-o Minimum level can be specified to allow the reading of questionnaires
-o Sysops deleting their own profile, will not have to exit and re-enter
-  before SMM will report their profile does not exist
-o Match Maker telegrams are stored in SMM and users are notified via BBS
-  telegram of newly received SMM telegrams
-o Users can read awaiting telegrams and send telegrams from the SMM main menu
-o New customizable main menu (SMM_MAIN.ASC)
-o (W)rite Profile command changed to (U)pdate Profile, although 'W' can still
-  be used
-o When sending telegrams, the destination user's detail is displayed to prevent
-  users from sending telegrams to a wrong user (with the same name)
-o Automatically corrects user sex when not set to (M)ale or (F)emale
-o Questionnaire answers are aligned so they can be visually compared easily
-o SMMUTIL v1.10 generates statistics, run "SMMUTIL > stats.txt" to create file
-  for display on your BBS
-
-New in version 1.10
-~~~~~~~~~~~~~~~~~~~
-o New configuration program (SMMCFG) instead of editing SMM.CFG with an
-  ASCII editor.
-o Optional trash can file for keeping users from using profanity in profiles
-  and users names.
-o SMB2SMM will not import profiles if the user age is less than you have
-  specified in SMMCFG for minimum user age.
-o SMB2SMM will not import profiles that contains words found in your TRASH.CAN
-  file (if it exists).
-o When listing profiles in SMM, you can go backwards to previous screens and
-  read profiles directly from the listing. The (R)ead profile key automatically
-  puts the user with the highest percentage on the current screen in the
-  user name field.
-o User's can enter "Non-disclosed" for their yearly income, by hitting ENTER
-  when asked.
-o User's can specify if they REQUIRE their matches to fall within certain
-  ranges or REQUIRE specific features.
-o Profile screens were condensed to get all information on one page whenever
-  possible.
-o SMMUTIL will scan for duplicate profiles or if specified, delete profiles
-  that haven't been updated in a certain number of days. SMMUTIL also
-  automatically condenses the data file, removing any deleted profiles and
-  rebuilds the index file.
-o Users can be charged credits or given credits for adding profiles and
-  sending telegrams. If a user adds a profile and then deletes it, the credit
-  charges are reversed.
-o Auto-update feature will automatically re-hatch a users entry into the
-  Global Database after a certain number of days, if the user is active in
-  the match maker but hasn't made any profile changes.
-o Sysop can be notified automatically of added profiles and sent telegrams
-  from the match maker
-
-/* End of UPGRADE.DOC */